diff --git a/riegeli/bytes/reader.cc b/riegeli/bytes/reader.cc index 2f269d2e..7afe85b6 100644 --- a/riegeli/bytes/reader.cc +++ b/riegeli/bytes/reader.cc @@ -89,11 +89,10 @@ bool Reader::ReadSlow(size_t length, char* dest) { return true; } -bool Reader::ReadSlow(size_t length, char* dest, size_t* length_read) { +bool Reader::ReadSlow(size_t length, char* dest, size_t& length_read) { RIEGELI_ASSERT_LT(available(), length) << "Failed precondition of Reader::ReadSlow(char*): " "enough data available, use Read(char*) instead"; - if (length_read == nullptr) return ReadSlow(length, dest); const Position pos_before = pos(); const bool read_ok = ReadSlow(length, dest); RIEGELI_ASSERT_GE(pos(), pos_before) @@ -101,12 +100,12 @@ bool Reader::ReadSlow(size_t length, char* dest, size_t* length_read) { RIEGELI_ASSERT_LE(pos() - pos_before, length) << "Reader::ReadSlow(char*) read more than requested"; if (ABSL_PREDICT_FALSE(!read_ok)) { - *length_read = IntCast(pos() - pos_before); + length_read = IntCast(pos() - pos_before); return false; } RIEGELI_ASSERT_EQ(pos() - pos_before, length) << "Reader::ReadSlow(char*) succeeded but read less than requested"; - *length_read = length; + length_read = length; return true; } @@ -114,27 +113,26 @@ bool Reader::ReadSlow(size_t length, std::string& dest) { RIEGELI_ASSERT_LT(available(), length) << "Failed precondition of Reader::ReadSlow(string&): " "enough data available, use Read(string&) instead"; - RIEGELI_ASSERT_LE(length, dest.max_size() - dest.size()) + RIEGELI_CHECK_LE(length, dest.max_size() - dest.size()) << "Failed precondition of Reader::ReadSlow(string&): " "string size overflow"; const size_t dest_pos = dest.size(); ResizeStringAmortized(dest, dest_pos + length); size_t length_read; - if (ABSL_PREDICT_FALSE(!ReadSlow(length, &dest[dest_pos], &length_read))) { + if (ABSL_PREDICT_FALSE(!ReadSlow(length, &dest[dest_pos], length_read))) { dest.erase(dest_pos + length_read); return false; } return true; } -bool Reader::ReadSlow(size_t length, std::string& dest, size_t* length_read) { +bool Reader::ReadSlow(size_t length, std::string& dest, size_t& length_read) { RIEGELI_ASSERT_LT(available(), length) << "Failed precondition of Reader::ReadSlow(string&): " "enough data available, use Read(string&) instead"; RIEGELI_ASSERT_LE(length, dest.max_size() - dest.size()) << "Failed precondition of Reader::ReadSlow(string&): " "string size overflow"; - if (length_read == nullptr) return ReadSlow(length, dest); const Position pos_before = pos(); const bool read_ok = ReadSlow(length, dest); RIEGELI_ASSERT_GE(pos(), pos_before) @@ -142,15 +140,22 @@ bool Reader::ReadSlow(size_t length, std::string& dest, size_t* length_read) { RIEGELI_ASSERT_LE(pos() - pos_before, length) << "Reader::ReadSlow(string&) read more than requested"; if (ABSL_PREDICT_FALSE(!read_ok)) { - *length_read = IntCast(pos() - pos_before); + length_read = IntCast(pos() - pos_before); return false; } RIEGELI_ASSERT_EQ(pos() - pos_before, length) << "Reader::ReadSlow(string&) succeeded but read less than requested"; - *length_read = length; + length_read = length; return true; } +bool Reader::ReadSlowWithSizeCheck(size_t length, Chain& dest) { + RIEGELI_CHECK_LE(length, std::numeric_limits::max() - dest.size()) + << "Failed precondition of Reader::ReadAndAppend(Chain&): " + "Chain size overflow"; + return ReadSlow(length, dest); +} + bool Reader::ReadSlow(size_t length, Chain& dest) { RIEGELI_ASSERT_LT(UnsignedMin(available(), kMaxBytesToCopy), length) << "Failed precondition of Reader::ReadSlow(Chain&): " @@ -170,14 +175,21 @@ bool Reader::ReadSlow(size_t length, Chain& dest) { return true; } -bool Reader::ReadSlow(size_t length, Chain& dest, size_t* length_read) { +bool Reader::ReadSlowWithSizeCheck(size_t length, Chain& dest, + size_t& length_read) { + RIEGELI_CHECK_LE(length, std::numeric_limits::max() - dest.size()) + << "Failed precondition of Reader::ReadAndAppend(Chain&): " + "Chain size overflow"; + return ReadSlow(length, dest, length_read); +} + +bool Reader::ReadSlow(size_t length, Chain& dest, size_t& length_read) { RIEGELI_ASSERT_LT(UnsignedMin(available(), kMaxBytesToCopy), length) << "Failed precondition of Reader::ReadSlow(Chain&): " "enough data available, use Read(Chain&) instead"; RIEGELI_ASSERT_LE(length, std::numeric_limits::max() - dest.size()) << "Failed precondition of Reader::ReadSlow(Chain&): " "Chain size overflow"; - if (length_read == nullptr) return ReadSlow(length, dest); const Position pos_before = pos(); const bool read_ok = ReadSlow(length, dest); RIEGELI_ASSERT_GE(pos(), pos_before) @@ -185,12 +197,12 @@ bool Reader::ReadSlow(size_t length, Chain& dest, size_t* length_read) { RIEGELI_ASSERT_LE(pos() - pos_before, length) << "Reader::ReadSlow(Chain&) read more than requested"; if (ABSL_PREDICT_FALSE(!read_ok)) { - *length_read = IntCast(pos() - pos_before); + length_read = IntCast(pos() - pos_before); return false; } RIEGELI_ASSERT_EQ(pos() - pos_before, length) << "Reader::ReadSlow(Chain&) succeeded but read less than requested"; - *length_read = length; + length_read = length; return true; } @@ -259,6 +271,13 @@ inline bool ReadSlowToCord(Reader& src, size_t length, DependentCord& dest) { } // namespace +bool Reader::ReadSlowWithSizeCheck(size_t length, absl::Cord& dest) { + RIEGELI_CHECK_LE(length, std::numeric_limits::max() - dest.size()) + << "Failed precondition of Reader::ReadAndAppend(Cord&): " + "Cord size overflow"; + return ReadSlow(length, dest); +} + bool Reader::ReadSlow(size_t length, absl::Cord& dest) { RIEGELI_ASSERT_LT(UnsignedMin(available(), kMaxBytesToCopy), length) << "Failed precondition of Reader::ReadSlow(Cord&): " @@ -269,14 +288,21 @@ bool Reader::ReadSlow(size_t length, absl::Cord& dest) { return ReadSlowToCord(*this, length, dest); } -bool Reader::ReadSlow(size_t length, absl::Cord& dest, size_t* length_read) { +bool Reader::ReadSlowWithSizeCheck(size_t length, absl::Cord& dest, + size_t& length_read) { + RIEGELI_CHECK_LE(length, std::numeric_limits::max() - dest.size()) + << "Failed precondition of Reader::ReadAndAppend(Cord&): " + "Cord size overflow"; + return ReadSlow(length, dest, length_read); +} + +bool Reader::ReadSlow(size_t length, absl::Cord& dest, size_t& length_read) { RIEGELI_ASSERT_LT(UnsignedMin(available(), kMaxBytesToCopy), length) << "Failed precondition of Reader::ReadSlow(Cord&): " "enough data available, use Read(Cord&) instead"; RIEGELI_ASSERT_LE(length, std::numeric_limits::max() - dest.size()) << "Failed precondition of Reader::ReadSlow(Cord&): " "Cord size overflow"; - if (length_read == nullptr) return ReadSlow(length, dest); const Position pos_before = pos(); const bool read_ok = ReadSlow(length, dest); RIEGELI_ASSERT_GE(pos(), pos_before) @@ -284,12 +310,12 @@ bool Reader::ReadSlow(size_t length, absl::Cord& dest, size_t* length_read) { RIEGELI_ASSERT_LE(pos() - pos_before, length) << "Reader::ReadSlow(Cord&) read more than requested"; if (ABSL_PREDICT_FALSE(!read_ok)) { - *length_read = IntCast(pos() - pos_before); + length_read = IntCast(pos() - pos_before); return false; } RIEGELI_ASSERT_EQ(pos() - pos_before, length) << "Reader::ReadSlow(Cord&) succeeded but read less than requested"; - *length_read = length; + length_read = length; return true; } @@ -309,11 +335,10 @@ bool Reader::CopySlow(Position length, Writer& dest) { return dest.Write(data); } -bool Reader::CopySlow(Position length, Writer& dest, Position* length_read) { +bool Reader::CopySlow(Position length, Writer& dest, Position& length_read) { RIEGELI_ASSERT_LT(UnsignedMin(available(), kMaxBytesToCopy), length) << "Failed precondition of Reader::CopySlow(Writer&): " "enough data available, use Copy(Writer&) instead"; - if (length_read == nullptr) return CopySlow(length, dest); const Position pos_before = pos(); const bool copy_ok = CopySlow(length, dest); RIEGELI_ASSERT_GE(pos(), pos_before) @@ -321,12 +346,12 @@ bool Reader::CopySlow(Position length, Writer& dest, Position* length_read) { RIEGELI_ASSERT_LE(pos() - pos_before, length) << "Reader::CopySlow(Writer&) read more than requested"; if (ABSL_PREDICT_FALSE(!copy_ok)) { - *length_read = pos() - pos_before; + length_read = pos() - pos_before; return false; } RIEGELI_ASSERT_EQ(pos() - pos_before, length) << "Reader::CopySlow(Writer&) succeeded but read less than requested"; - *length_read = length; + length_read = length; return true; } @@ -371,23 +396,22 @@ bool Reader::ReadSomeSlow(size_t max_length, char* dest) { return true; } -bool Reader::ReadSomeSlow(size_t max_length, char* dest, size_t* length_read) { +bool Reader::ReadSomeSlow(size_t max_length, char* dest, size_t& length_read) { RIEGELI_ASSERT_LT(available(), max_length) << "Failed precondition of Reader::ReadSomeSlow(char*): " "enough data available, use ReadSome(char*) instead"; - if (length_read == nullptr) return ReadSomeSlow(max_length, dest); const Position pos_before = pos(); const bool read_ok = ReadSomeSlow(max_length, dest); RIEGELI_ASSERT_GE(pos(), pos_before) << "Reader::ReadSomeSlow(char*) decreased pos()"; RIEGELI_ASSERT_LE(pos() - pos_before, max_length) << "Reader::ReadSomeSlow(char*) read more than requested"; - *length_read = IntCast(pos() - pos_before); + length_read = IntCast(pos() - pos_before); if (!read_ok) { - RIEGELI_ASSERT_EQ(*length_read, 0u) + RIEGELI_ASSERT_EQ(length_read, 0u) << "Reader::ReadSomeSlow(char*) failed but read some"; } else { - RIEGELI_ASSERT_GT(*length_read, 0u) + RIEGELI_ASSERT_GT(length_read, 0u) << "Reader::ReadSomeSlow(char*) succeeded but read none"; } return read_ok; @@ -424,23 +448,22 @@ bool Reader::ReadSomeSlow(size_t max_length, std::string& dest) { } bool Reader::ReadSomeSlow(size_t max_length, std::string& dest, - size_t* length_read) { + size_t& length_read) { RIEGELI_ASSERT_LT(available(), max_length) << "Failed precondition of Reader::ReadSomeSlow(string&): " "enough data available, use ReadSome(string&) instead"; - if (length_read == nullptr) return ReadSomeSlow(max_length, dest); const Position pos_before = pos(); const bool read_ok = ReadSomeSlow(max_length, dest); RIEGELI_ASSERT_GE(pos(), pos_before) << "Reader::ReadSomeSlow(string&) decreased pos()"; RIEGELI_ASSERT_LE(pos() - pos_before, max_length) << "Reader::ReadSomeSlow(string&) read more than requested"; - *length_read = IntCast(pos() - pos_before); + length_read = IntCast(pos() - pos_before); if (!read_ok) { - RIEGELI_ASSERT_EQ(*length_read, 0u) + RIEGELI_ASSERT_EQ(length_read, 0u) << "Reader::ReadSomeSlow(string&) failed but read some"; } else { - RIEGELI_ASSERT_GT(*length_read, 0u) + RIEGELI_ASSERT_GT(length_read, 0u) << "Reader::ReadSomeSlow(string&) succeeded but read none"; } return read_ok; @@ -460,23 +483,22 @@ bool Reader::ReadSomeSlow(size_t max_length, Chain& dest) { return ReadAndAppend(UnsignedMin(max_length, available()), dest); } -bool Reader::ReadSomeSlow(size_t max_length, Chain& dest, size_t* length_read) { +bool Reader::ReadSomeSlow(size_t max_length, Chain& dest, size_t& length_read) { RIEGELI_ASSERT_LT(UnsignedMin(available(), kMaxBytesToCopy), max_length) << "Failed precondition of Reader::ReadSomeSlow(Chain&): " "enough data available, use ReadSome(Chain&) instead"; - if (length_read == nullptr) return ReadSomeSlow(max_length, dest); const Position pos_before = pos(); const bool read_ok = ReadSomeSlow(max_length, dest); RIEGELI_ASSERT_GE(pos(), pos_before) << "Reader::ReadSomeSlow(Chain&) decreased pos()"; RIEGELI_ASSERT_LE(pos() - pos_before, max_length) << "Reader::ReadSomeSlow(Chain&) read more than requested"; - *length_read = IntCast(pos() - pos_before); + length_read = IntCast(pos() - pos_before); if (!read_ok) { - RIEGELI_ASSERT_EQ(*length_read, 0u) + RIEGELI_ASSERT_EQ(length_read, 0u) << "Reader::ReadSomeSlow(Chain&) failed but read some"; } else { - RIEGELI_ASSERT_GT(*length_read, 0u) + RIEGELI_ASSERT_GT(length_read, 0u) << "Reader::ReadSomeSlow(Chain&) succeeded but read none"; } return read_ok; @@ -497,23 +519,22 @@ bool Reader::ReadSomeSlow(size_t max_length, absl::Cord& dest) { } bool Reader::ReadSomeSlow(size_t max_length, absl::Cord& dest, - size_t* length_read) { + size_t& length_read) { RIEGELI_ASSERT_LT(UnsignedMin(available(), kMaxBytesToCopy), max_length) << "Failed precondition of Reader::ReadSomeSlow(Cord&): " "enough data available, use ReadSome(Cord&) instead"; - if (length_read == nullptr) return ReadSomeSlow(max_length, dest); const Position pos_before = pos(); const bool read_ok = ReadSomeSlow(max_length, dest); RIEGELI_ASSERT_GE(pos(), pos_before) << "Reader::ReadSomeSlow(Cord&) decreased pos()"; RIEGELI_ASSERT_LE(pos() - pos_before, max_length) << "Reader::ReadSomeSlow(Cord&) read more than requested"; - *length_read = IntCast(pos() - pos_before); + length_read = IntCast(pos() - pos_before); if (!read_ok) { - RIEGELI_ASSERT_EQ(*length_read, 0u) + RIEGELI_ASSERT_EQ(length_read, 0u) << "Reader::ReadSomeSlow(Cord&) failed but read some"; } else { - RIEGELI_ASSERT_GT(*length_read, 0u) + RIEGELI_ASSERT_GT(length_read, 0u) << "Reader::ReadSomeSlow(Cord&) succeeded but read none"; } return read_ok; @@ -544,25 +565,24 @@ bool Reader::CopySomeSlow(size_t max_length, Writer& dest) { } bool Reader::CopySomeSlow(size_t max_length, Writer& dest, - size_t* length_read) { + size_t& length_read) { RIEGELI_ASSERT_LT(UnsignedMin(available(), kMaxBytesToCopy), max_length) << "Failed precondition of Reader::CopySomeSlow(Writer&): " "enough data available, use CopySome(Writer&) instead"; - if (length_read == nullptr) return CopySomeSlow(max_length, dest); const Position pos_before = pos(); const bool copy_ok = CopySomeSlow(max_length, dest); RIEGELI_ASSERT_GE(pos(), pos_before) << "Reader::CopySomeSlow(Writer&) decreased pos()"; RIEGELI_ASSERT_LE(pos() - pos_before, max_length) << "Reader::CopySomeSlow(Writer&) read more than requested"; - *length_read = IntCast(pos() - pos_before); + length_read = IntCast(pos() - pos_before); if (!copy_ok) { if (dest.ok()) { - RIEGELI_ASSERT_EQ(*length_read, 0u) + RIEGELI_ASSERT_EQ(length_read, 0u) << "Reader::CopySomeSlow(Writer&) failed but read some"; } } else { - RIEGELI_ASSERT_GT(*length_read, 0u) + RIEGELI_ASSERT_GT(length_read, 0u) << "Reader::CopySomeSlow(Writer&) succeeded but read none"; } return copy_ok; @@ -581,25 +601,24 @@ bool Reader::ReadOrPullSomeSlow(size_t max_length, bool Reader::ReadOrPullSomeSlow(size_t max_length, absl::FunctionRef get_dest, - size_t* length_read) { + size_t& length_read) { RIEGELI_ASSERT_GT(max_length, 0u) << "Failed precondition of Reader::ReadOrPullSomeSlow(): " "nothing to read, use ReadOrPullSome() instead"; RIEGELI_ASSERT_EQ(available(), 0u) << "Failed precondition of Reader::ReadOrPullSomeSlow(): " "some data available, use ReadOrPullSome() instead"; - if (length_read == nullptr) return ReadOrPullSomeSlow(max_length, get_dest); const Position pos_before = limit_pos(); const bool read_ok = ReadOrPullSomeSlow(max_length, get_dest); RIEGELI_ASSERT_GE(pos(), pos_before) << "Reader::ReadOrPullSomeSlow() decreased pos()"; RIEGELI_ASSERT_LE(pos() - pos_before, max_length) << "Reader::ReadOrPullSomeSlow() read more than requested"; - *length_read = IntCast(pos() - pos_before); + length_read = IntCast(pos() - pos_before); if (!read_ok) { - RIEGELI_ASSERT_EQ(*length_read, 0u) + RIEGELI_ASSERT_EQ(length_read, 0u) << "Reader::ReadOrPullSomeSlow() failed but read some"; - } else if (*length_read == 0) { + } else if (length_read == 0) { RIEGELI_ASSERT_GT(available(), 0u) << "Reader::ReadOrPullSomeSlow() succeeded but " "read none and pulled none"; diff --git a/riegeli/bytes/reader.h b/riegeli/bytes/reader.h index 00318cf0..ab0df5d6 100644 --- a/riegeli/bytes/reader.h +++ b/riegeli/bytes/reader.h @@ -607,31 +607,36 @@ class Reader : public Object { // `ReadSomeSlow(absl::Cord&)`: // `dest->size() < std::numeric_limits::max()` virtual bool ReadSlow(size_t length, char* dest); - bool ReadSlow(size_t length, char* dest, size_t* length_read); + bool ReadSlow(size_t length, char* dest, size_t& length_read); bool ReadSlow(size_t length, std::string& dest); - bool ReadSlow(size_t length, std::string& dest, size_t* length_read); + bool ReadSlow(size_t length, std::string& dest, size_t& length_read); + bool ReadSlowWithSizeCheck(size_t length, Chain& dest); virtual bool ReadSlow(size_t length, Chain& dest); - bool ReadSlow(size_t length, Chain& dest, size_t* length_read); + bool ReadSlowWithSizeCheck(size_t length, Chain& dest, size_t& length_read); + bool ReadSlow(size_t length, Chain& dest, size_t& length_read); + bool ReadSlowWithSizeCheck(size_t length, absl::Cord& dest); virtual bool ReadSlow(size_t length, absl::Cord& dest); - virtual bool ReadSlow(size_t length, absl::Cord& dest, size_t* length_read); + bool ReadSlowWithSizeCheck(size_t length, absl::Cord& dest, + size_t& length_read); + bool ReadSlow(size_t length, absl::Cord& dest, size_t& length_read); virtual bool CopySlow(Position length, Writer& dest); - bool CopySlow(Position length, Writer& dest, Position* length_read); + bool CopySlow(Position length, Writer& dest, Position& length_read); virtual bool CopySlow(size_t length, BackwardWriter& dest); bool ReadSomeSlow(size_t max_length, char* dest); - bool ReadSomeSlow(size_t max_length, char* dest, size_t* length_read); + bool ReadSomeSlow(size_t max_length, char* dest, size_t& length_read); bool ReadSomeSlow(size_t max_length, std::string& dest); - bool ReadSomeSlow(size_t max_length, std::string& dest, size_t* length_read); + bool ReadSomeSlow(size_t max_length, std::string& dest, size_t& length_read); bool ReadSomeSlow(size_t max_length, Chain& dest); - bool ReadSomeSlow(size_t max_length, Chain& dest, size_t* length_read); + bool ReadSomeSlow(size_t max_length, Chain& dest, size_t& length_read); bool ReadSomeSlow(size_t max_length, absl::Cord& dest); - bool ReadSomeSlow(size_t max_length, absl::Cord& dest, size_t* length_read); + bool ReadSomeSlow(size_t max_length, absl::Cord& dest, size_t& length_read); bool CopySomeSlow(size_t max_length, Writer& dest); - bool CopySomeSlow(size_t max_length, Writer& dest, size_t* length_read); + bool CopySomeSlow(size_t max_length, Writer& dest, size_t& length_read); virtual bool ReadOrPullSomeSlow(size_t max_length, absl::FunctionRef get_dest); bool ReadOrPullSomeSlow(size_t max_length, absl::FunctionRef get_dest, - size_t* length_read); + size_t& length_read); // Implementation of the slow part of `ReadHint()`. // @@ -797,22 +802,25 @@ inline bool Reader::Read(size_t length, char* dest, size_t* length_read) { if (length_read != nullptr) *length_read = length; return true; } - return ReadSlow(length, dest, length_read); + if (length_read != nullptr) return ReadSlow(length, dest, *length_read); + return ReadSlow(length, dest); } inline bool Reader::Read(size_t length, std::string& dest, size_t* length_read) { - RIEGELI_CHECK_LE(length, dest.max_size()) + RIEGELI_ASSERT_LE(length, dest.max_size()) << "Failed precondition of Reader::Read(string&): " "string size overflow"; if (ABSL_PREDICT_TRUE(available() >= length)) { + // `std::string::assign()` checks for size overflow. dest.assign(cursor(), length); move_cursor(length); if (length_read != nullptr) *length_read = length; return true; } dest.clear(); - return ReadSlow(length, dest, length_read); + if (length_read != nullptr) return ReadSlow(length, dest, *length_read); + return ReadSlow(length, dest); } inline bool Reader::Read(size_t length, Chain& dest, size_t* length_read) { @@ -823,7 +831,8 @@ inline bool Reader::Read(size_t length, Chain& dest, size_t* length_read) { if (length_read != nullptr) *length_read = length; return true; } - return ReadSlow(length, dest, length_read); + if (length_read != nullptr) return ReadSlow(length, dest, *length_read); + return ReadSlow(length, dest); } inline bool Reader::Read(size_t length, absl::Cord& dest, size_t* length_read) { @@ -834,49 +843,62 @@ inline bool Reader::Read(size_t length, absl::Cord& dest, size_t* length_read) { return true; } dest.Clear(); - return ReadSlow(length, dest, length_read); + if (length_read != nullptr) return ReadSlow(length, dest, *length_read); + return ReadSlow(length, dest); } inline bool Reader::ReadAndAppend(size_t length, std::string& dest, size_t* length_read) { - RIEGELI_CHECK_LE(length, dest.max_size() - dest.size()) + RIEGELI_ASSERT_LE(length, dest.max_size() - dest.size()) << "Failed precondition of Reader::ReadAndAppend(string&): " "string size overflow"; if (ABSL_PREDICT_TRUE(available() >= length)) { + // `std::string::append()` checks for size overflow. dest.append(cursor(), length); move_cursor(length); if (length_read != nullptr) *length_read = length; return true; } - return ReadSlow(length, dest, length_read); + if (length_read != nullptr) return ReadSlow(length, dest, *length_read); + return ReadSlow(length, dest); } inline bool Reader::ReadAndAppend(size_t length, Chain& dest, size_t* length_read) { - RIEGELI_CHECK_LE(length, std::numeric_limits::max() - dest.size()) + RIEGELI_ASSERT_LE(length, std::numeric_limits::max() - dest.size()) << "Failed precondition of Reader::ReadAndAppend(Chain&): " "Chain size overflow"; if (ABSL_PREDICT_TRUE(available() >= length && length <= kMaxBytesToCopy)) { + // `Chain::Append()` checks for size overflow. dest.Append(absl::string_view(cursor(), length)); move_cursor(length); if (length_read != nullptr) *length_read = length; return true; } - return ReadSlow(length, dest, length_read); + // Check the size before calling virtual `ReadSlow(Chain&)`. + if (length_read != nullptr) { + return ReadSlowWithSizeCheck(length, dest, *length_read); + } + return ReadSlowWithSizeCheck(length, dest); } inline bool Reader::ReadAndAppend(size_t length, absl::Cord& dest, size_t* length_read) { - RIEGELI_CHECK_LE(length, std::numeric_limits::max() - dest.size()) - << "Failed precondition of Reader::ReadAndAppend(Cord&): " - "Cord size overflow"; - if (ABSL_PREDICT_TRUE(available() >= length && length <= kMaxBytesToCopy)) { + if (ABSL_PREDICT_TRUE( + available() >= length && length <= kMaxBytesToCopy && + // `absl::Cord::Append()` does not check for size overflow. + length <= std::numeric_limits::max() - dest.size())) { dest.Append(absl::string_view(cursor(), length)); move_cursor(length); if (length_read != nullptr) *length_read = length; return true; } - return ReadSlow(length, dest, length_read); + // Check the size in case it would overflow in the fast path. and also before + // calling virtual `ReadSlow(absl::Cord&)`. + if (length_read != nullptr) { + return ReadSlowWithSizeCheck(length, dest, *length_read); + } + return ReadSlowWithSizeCheck(length, dest); } inline bool Reader::Copy(Position length, Writer& dest, Position* length_read) { @@ -886,7 +908,8 @@ inline bool Reader::Copy(Position length, Writer& dest, Position* length_read) { if (length_read != nullptr) *length_read = length; return dest.Write(data); } - return CopySlow(length, dest, length_read); + if (length_read != nullptr) return CopySlow(length, dest, *length_read); + return CopySlow(length, dest); } inline bool Reader::Copy(size_t length, BackwardWriter& dest) { @@ -921,7 +944,10 @@ inline bool Reader::ReadSome(size_t max_length, char* dest, if (length_read != nullptr) *length_read = max_length; return true; } - return ReadSomeSlow(max_length, dest, length_read); + if (length_read != nullptr) { + return ReadSomeSlow(max_length, dest, *length_read); + } + return ReadSomeSlow(max_length, dest); } inline bool Reader::ReadSome(size_t max_length, std::string& dest, @@ -934,7 +960,10 @@ inline bool Reader::ReadSome(size_t max_length, std::string& dest, return true; } dest.clear(); - return ReadSomeSlow(max_length, dest, length_read); + if (length_read != nullptr) { + return ReadSomeSlow(max_length, dest, *length_read); + } + return ReadSomeSlow(max_length, dest); } inline bool Reader::ReadSome(size_t max_length, Chain& dest, @@ -947,7 +976,10 @@ inline bool Reader::ReadSome(size_t max_length, Chain& dest, if (length_read != nullptr) *length_read = max_length; return true; } - return ReadSomeSlow(max_length, dest, length_read); + if (length_read != nullptr) { + return ReadSomeSlow(max_length, dest, *length_read); + } + return ReadSomeSlow(max_length, dest); } inline bool Reader::ReadSome(size_t max_length, absl::Cord& dest, @@ -960,7 +992,10 @@ inline bool Reader::ReadSome(size_t max_length, absl::Cord& dest, return true; } dest.Clear(); - return ReadSomeSlow(max_length, dest, length_read); + if (length_read != nullptr) { + return ReadSomeSlow(max_length, dest, *length_read); + } + return ReadSomeSlow(max_length, dest); } inline bool Reader::ReadAndAppendSome(size_t max_length, std::string& dest, @@ -972,7 +1007,10 @@ inline bool Reader::ReadAndAppendSome(size_t max_length, std::string& dest, if (length_read != nullptr) *length_read = max_length; return true; } - return ReadSomeSlow(max_length, dest, length_read); + if (length_read != nullptr) { + return ReadSomeSlow(max_length, dest, *length_read); + } + return ReadSomeSlow(max_length, dest); } inline bool Reader::ReadAndAppendSome(size_t max_length, Chain& dest, @@ -985,7 +1023,10 @@ inline bool Reader::ReadAndAppendSome(size_t max_length, Chain& dest, if (length_read != nullptr) *length_read = max_length; return true; } - return ReadSomeSlow(max_length, dest, length_read); + if (length_read != nullptr) { + return ReadSomeSlow(max_length, dest, *length_read); + } + return ReadSomeSlow(max_length, dest); } inline bool Reader::ReadAndAppendSome(size_t max_length, absl::Cord& dest, @@ -998,7 +1039,10 @@ inline bool Reader::ReadAndAppendSome(size_t max_length, absl::Cord& dest, if (length_read != nullptr) *length_read = max_length; return true; } - return ReadSomeSlow(max_length, dest, length_read); + if (length_read != nullptr) { + return ReadSomeSlow(max_length, dest, *length_read); + } + return ReadSomeSlow(max_length, dest); } inline bool Reader::CopySome(size_t max_length, Writer& dest, @@ -1010,7 +1054,10 @@ inline bool Reader::CopySome(size_t max_length, Writer& dest, if (length_read != nullptr) *length_read = max_length; return dest.Write(data); } - return CopySomeSlow(max_length, dest, length_read); + if (length_read != nullptr) { + return CopySomeSlow(max_length, dest, *length_read); + } + return CopySomeSlow(max_length, dest); } inline bool Reader::ReadOrPullSome(size_t max_length, @@ -1021,7 +1068,10 @@ inline bool Reader::ReadOrPullSome(size_t max_length, if (length_read != nullptr) *length_read = 0; return true; } - return ReadOrPullSomeSlow(max_length, get_dest, length_read); + if (length_read != nullptr) { + return ReadOrPullSomeSlow(max_length, get_dest, *length_read); + } + return ReadOrPullSomeSlow(max_length, get_dest); } inline void Reader::ReadHint(size_t min_length, size_t recommended_length) {