X-Git-Url: http://plrg.eecs.uci.edu/git/?a=blobdiff_plain;f=folly%2FFBString.h;h=6f5ea13194978aad661e2227f6fcc34e90ba8d26;hb=cb5272724fbe18e937bbe8bb8a0a279027255032;hp=e00194babfe8d542b4c5e0f1e1bca8150fe99a28;hpb=91199bbe0faa08c417dc9fae5911e80b34870e92;p=folly.git diff --git a/folly/FBString.h b/folly/FBString.h index e00194ba..6f5ea131 100644 --- a/folly/FBString.h +++ b/folly/FBString.h @@ -105,6 +105,10 @@ #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wshadow" +// FBString cannot use throw when replacing std::string, though it may still +// use std::__throw_* +#define throw FOLLY_FBSTRING_MAY_NOT_USE_THROW + #ifdef _LIBSTDCXX_FBSTRING namespace std _GLIBCXX_VISIBILITY(default) { _GLIBCXX_BEGIN_NAMESPACE_VERSION @@ -113,21 +117,26 @@ namespace folly { #endif // Different versions of gcc/clang support different versions of -// the address sanitizer attribute. +// the address sanitizer attribute. Unfortunately, this attribute +// has issues when inlining is used, so disable that as well. #if defined(__clang__) -# if __has_attribute(__no_address_safety_analysis__) -# define FBSTRING_DISABLE_ADDRESS_SANITIZER \ - __attribute__((__no_address_safety_analysis__)) -# elif __has_attribute(__no_sanitize_address__) -# define FBSTRING_DISABLE_ADDRESS_SANITIZER \ - __attribute__((__no_sanitize_address__)) -# else -# define FBSTRING_DISABLE_ADDRESS_SANITIZER +# if __has_feature(address_sanitizer) +# if __has_attribute(__no_address_safety_analysis__) +# define FBSTRING_DISABLE_ADDRESS_SANITIZER \ + __attribute__((__no_address_safety_analysis__, __noinline__)) +# elif __has_attribute(__no_sanitize_address__) +# define FBSTRING_DISABLE_ADDRESS_SANITIZER \ + __attribute__((__no_sanitize_address__, __noinline__)) +# endif # endif -#elif defined (__GNUC__) && (__GNUC__ == 4) && (__GNUC_MINOR__ >= 8) +#elif defined (__GNUC__) && \ + (__GNUC__ == 4) && \ + (__GNUC_MINOR__ >= 8) && \ + __SANITIZE_ADDRESS__ # define FBSTRING_DISABLE_ADDRESS_SANITIZER \ - __attribute__((__no_address_safety_analysis__)) -#else + __attribute__((__no_address_safety_analysis__, __noinline__)) +#endif +#ifndef FBSTRING_DISABLE_ADDRESS_SANITIZER # define FBSTRING_DISABLE_ADDRESS_SANITIZER #endif @@ -300,7 +309,7 @@ private: */ template class fbstring_core { public: - fbstring_core() { + fbstring_core() noexcept { // Only initialize the tag, will set the MSBs (i.e. the small // string size) to zero too ml_.capacity_ = maxSmallSize << (8 * (sizeof(size_t) - sizeof(Char))); @@ -354,7 +363,7 @@ public: assert(memcmp(data(), rhs.data(), size() * sizeof(Char)) == 0); } - fbstring_core(fbstring_core&& goner) { + fbstring_core(fbstring_core&& goner) noexcept { if (goner.category() == isSmall) { // Just copy, leave the goner in peace new(this) fbstring_core(goner.small_, goner.smallSize()); @@ -423,7 +432,7 @@ public: assert(memcmp(this->data(), data, size * sizeof(Char)) == 0); } - ~fbstring_core() { + ~fbstring_core() noexcept { auto const c = category(); if (c == isSmall) { return; @@ -436,22 +445,24 @@ public: } // Snatches a previously mallocated string. The parameter "size" - // is the size of the string, and the parameter "capacity" is the size - // of the mallocated block. The string must be \0-terminated, so - // data[size] == '\0' and capacity >= size + 1. + // is the size of the string, and the parameter "allocatedSize" + // is the size of the mallocated block. The string must be + // \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 - // "size", and pass 3 as "capacity". - fbstring_core(Char *const data, const size_t size, - const size_t capacity, + // So if you want a 2-character string, pass malloc(3) as "data", + // pass 2 as "size", and pass 3 as "allocatedSize". + fbstring_core(Char * const data, + const size_t size, + const size_t allocatedSize, AcquireMallocatedString) { if (size > 0) { - assert(capacity > size); + assert(allocatedSize >= size + 1); assert(data[size] == '\0'); // Use the medium string storage ml_.data_ = data; ml_.size_ = size; - ml_.capacity_ = capacity | isMedium; + // Don't forget about null terminator + ml_.capacity_ = (allocatedSize - 1) | isMedium; } else { // No need for the memory free(data); @@ -595,7 +606,7 @@ public: smartRealloc( ml_.data_, ml_.size_ * sizeof(Char), - ml_.capacity() * sizeof(Char), + (ml_.capacity() + 1) * sizeof(Char), capacityBytes)); writeTerminator(); ml_.capacity_ = (capacityBytes / sizeof(Char) - 1) | isMedium; @@ -687,7 +698,7 @@ public: } else { sz = ml_.size_; if (sz == capacity()) { // always true for isShared() - reserve(sz * 3 / 2); // ensures not shared + reserve(1 + sz * 3 / 2); // ensures not shared } } assert(!isShared()); @@ -1009,7 +1020,7 @@ private: public: // C++11 21.4.2 construct/copy/destroy - explicit basic_fbstring(const A& a = A()) { + explicit basic_fbstring(const A& a = A()) noexcept { } basic_fbstring(const basic_fbstring& str) @@ -1017,7 +1028,8 @@ public: } // Move constructor - basic_fbstring(basic_fbstring&& goner) : store_(std::move(goner.store_)) { + basic_fbstring(basic_fbstring&& goner) noexcept + : store_(std::move(goner.store_)) { } #ifndef _LIBSTDCXX_FBSTRING @@ -1075,7 +1087,7 @@ public: assign(il.begin(), il.end()); } - ~basic_fbstring() { + ~basic_fbstring() noexcept { } basic_fbstring& operator=(const basic_fbstring& lhs) { @@ -1101,7 +1113,7 @@ public: } // Move assignment - basic_fbstring& operator=(basic_fbstring&& goner) { + basic_fbstring& operator=(basic_fbstring&& goner) noexcept { if (FBSTRING_UNLIKELY(&goner == this)) { // Compatibility with std::basic_string<>, // C++11 21.4.2 [string.cons] / 23 requires self-move-assignment support. @@ -1782,7 +1794,9 @@ public: const size_type nsize) const { if (!nsize) return pos; auto const size = this->size(); - if (nsize + pos > size) return npos; + // nsize + pos can overflow (eg pos == npos), guard against that by checking + // that nsize + pos does not wrap around. + if (nsize + pos > size || nsize + pos < pos) return npos; // Don't use std::search, use a Boyer-Moore-like trick by comparing // the last characters first auto const haystack = data(); @@ -2416,6 +2430,7 @@ struct hash< ::folly::fbstring> { #endif // _LIBSTDCXX_FBSTRING #undef FBSTRING_DISABLE_ADDRESS_SANITIZER +#undef throw #undef FBSTRING_LIKELY #undef FBSTRING_UNLIKELY