summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Derek Mauro <dmauro@google.com>2022-11-01 11:12:34 -0700
committerGravatar Copybara-Service <copybara-worker@google.com>2022-11-01 11:13:10 -0700
commit2b403ec754ec342311720467277c346e413e3438 (patch)
tree8fac980ef218fea582908f42ab77b2ec885548db
parentd819278ab70ee5e59fa91d76a66abeaa106b95c9 (diff)
Cord: Avoid leaking a node if SetExpectedChecksum() is called on an
empty cord twice in a row. PiperOrigin-RevId: 485367641 Change-Id: I6605ff25acbcef7c40b68e15a8888076a2da63be
-rw-r--r--absl/strings/cord.cc1
-rw-r--r--absl/strings/cord_test.cc12
2 files changed, 13 insertions, 0 deletions
diff --git a/absl/strings/cord.cc b/absl/strings/cord.cc
index 57082c5f..92822c05 100644
--- a/absl/strings/cord.cc
+++ b/absl/strings/cord.cc
@@ -857,6 +857,7 @@ inline absl::string_view Cord::InlineRep::FindFlatStartPiece() const {
void Cord::SetExpectedChecksum(uint32_t crc) {
auto constexpr method = CordzUpdateTracker::kSetExpectedChecksum;
if (empty()) {
+ contents_.MaybeRemoveEmptyCrcNode();
CordRep* rep = CordRepCrc::New(nullptr, crc);
contents_.EmplaceTree(rep, method);
} else if (!contents_.is_tree()) {
diff --git a/absl/strings/cord_test.cc b/absl/strings/cord_test.cc
index 9a72f7be..a4fa8955 100644
--- a/absl/strings/cord_test.cc
+++ b/absl/strings/cord_test.cc
@@ -2856,6 +2856,12 @@ TEST_P(CordTest, ExpectedChecksum) {
EXPECT_EQ(c1.ExpectedChecksum().value_or(0), 12345);
EXPECT_EQ(c1, base_value);
+ // Test that setting an expected checksum again doesn't crash or leak
+ // memory.
+ c1.SetExpectedChecksum(12345);
+ EXPECT_EQ(c1.ExpectedChecksum().value_or(0), 12345);
+ EXPECT_EQ(c1, base_value);
+
// CRC persists through copies, assignments, and moves:
absl::Cord c1_copy_construct = c1;
EXPECT_EQ(c1_copy_construct.ExpectedChecksum().value_or(0), 12345);
@@ -2968,6 +2974,12 @@ TEST_P(CordTest, ChecksummedEmptyCord) {
EXPECT_EQ(c1, "");
EXPECT_TRUE(c1.empty());
+ // Test that setting an expected checksum again doesn't crash or leak memory.
+ c1.SetExpectedChecksum(12345);
+ EXPECT_EQ(c1.ExpectedChecksum().value_or(0), 12345);
+ EXPECT_EQ(c1, "");
+ EXPECT_TRUE(c1.empty());
+
// CRC persists through copies, assignments, and moves:
absl::Cord c1_copy_construct = c1;
EXPECT_EQ(c1_copy_construct.ExpectedChecksum().value_or(0), 12345);