Commit 8c13c0b9 authored by Philip Pronin's avatar Philip Pronin Committed by Sara Golemon

fix a few bugs in FBString

Summary:
* `push_back()` fails for medium strings of zero capacity if not linked
with jemalloc (see added test),
* we incorrectly initiliaze capacity when acquire mallocated string
(forgot about null terminator).

Test Plan: fbconfig --allocator=malloc folly/test:fbstring_test_using_jemalloc && fbmake runtests_opt

@override-unit-failures

Reviewed By: tudorb@fb.com

FB internal diff: D1012196
parent 796bfa80
...@@ -445,22 +445,24 @@ public: ...@@ -445,22 +445,24 @@ public:
} }
// Snatches a previously mallocated string. The parameter "size" // Snatches a previously mallocated string. The parameter "size"
// is the size of the string, and the parameter "capacity" is the size // is the size of the string, and the parameter "allocatedSize"
// of the mallocated block. The string must be \0-terminated, so // is the size of the mallocated block. The string must be
// data[size] == '\0' and capacity >= size + 1. // \0-terminated, so allocatedSize >= size + 1 and data[size] == '\0'.
// //
// So if you want a 2-character string, pass malloc(3) as "data", pass 2 as // So if you want a 2-character string, pass malloc(3) as "data",
// "size", and pass 3 as "capacity". // pass 2 as "size", and pass 3 as "allocatedSize".
fbstring_core(Char *const data, const size_t size, fbstring_core(Char * const data,
const size_t capacity, const size_t size,
const size_t allocatedSize,
AcquireMallocatedString) { AcquireMallocatedString) {
if (size > 0) { if (size > 0) {
assert(capacity > size); assert(allocatedSize >= size + 1);
assert(data[size] == '\0'); assert(data[size] == '\0');
// Use the medium string storage // Use the medium string storage
ml_.data_ = data; ml_.data_ = data;
ml_.size_ = size; ml_.size_ = size;
ml_.capacity_ = capacity | isMedium; // Don't forget about null terminator
ml_.capacity_ = (allocatedSize - 1) | isMedium;
} else { } else {
// No need for the memory // No need for the memory
free(data); free(data);
...@@ -604,7 +606,7 @@ public: ...@@ -604,7 +606,7 @@ public:
smartRealloc( smartRealloc(
ml_.data_, ml_.data_,
ml_.size_ * sizeof(Char), ml_.size_ * sizeof(Char),
ml_.capacity() * sizeof(Char), (ml_.capacity() + 1) * sizeof(Char),
capacityBytes)); capacityBytes));
writeTerminator(); writeTerminator();
ml_.capacity_ = (capacityBytes / sizeof(Char) - 1) | isMedium; ml_.capacity_ = (capacityBytes / sizeof(Char) - 1) | isMedium;
...@@ -696,7 +698,7 @@ public: ...@@ -696,7 +698,7 @@ public:
} else { } else {
sz = ml_.size_; sz = ml_.size_;
if (sz == capacity()) { // always true for isShared() if (sz == capacity()) { // always true for isShared()
reserve(sz * 3 / 2); // ensures not shared reserve(1 + sz * 3 / 2); // ensures not shared
} }
} }
assert(!isShared()); assert(!isShared());
......
...@@ -1130,9 +1130,15 @@ TEST(FBString, testFixedBugs) { ...@@ -1130,9 +1130,15 @@ TEST(FBString, testFixedBugs) {
std::swap(str, str); std::swap(str, str);
EXPECT_EQ(1337, str.size()); EXPECT_EQ(1337, str.size());
} }
{ // D1012196, --allocator=malloc
fbstring str(128, 'f');
str.clear(); // Empty medium string.
fbstring copy(str); // Medium string of 0 capacity.
copy.push_back('b');
EXPECT_GE(copy.capacity(), 1);
}
} }
TEST(FBString, testHash) { TEST(FBString, testHash) {
fbstring a; fbstring a;
fbstring b; fbstring b;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment