/* * Copyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */ #include // Caricature of folly::basic_fbstring without the union between small // and medium/large data representations, and with an explicit field // for category_ instead of bitmasking part of the data value. // ref: // https://github.com/facebook/folly/blob/72850c2ebfb94d87bea74d89fcf79f3aaa91a627/folly/FBString.h enum category { small = 0, // ignore small strings for now medium = 1, large = 2, }; void* checkedMalloc(size_t size) { void* ptr = malloc(size); if (ptr == nullptr) { exit(1); } return ptr; } struct LikeFBString { int category_; char* buffer_; size_t size_; unsigned int* refcount_; LikeFBString() {} LikeFBString(const LikeFBString& src) { category_ = src.category(); switch (src.category_) { case medium: copyMedium(src); break; case large: copyLarge(src); break; default: exit(2); } } ~LikeFBString() { if (category() == medium) { free(buffer_); } else { decr_ref_count(); } } void copySmall(const LikeFBString& src) {} void copyMedium(const LikeFBString& src) { buffer_ = (char*)checkedMalloc(src.size_); size_ = src.size_; } void copyLarge(const LikeFBString& src) { buffer_ = src.buffer_; size_ = src.size_; refcount_ = src.refcount_; *refcount_ = *refcount_ + 1; } int category() const { return category_; } void decr_ref_count() { if (*refcount_ <= 0) { exit(1); } *refcount_ = *refcount_ - 1; if (*refcount_ == 0) { free(buffer_); } } }; void copy_fbstring(LikeFBString& s) { // this might alias the underlying buffers if the string is large in // that case the destruction of t does not de-allocate its buffer // but pulse might think it does if it fails to remember which // category t belongs to and follows impossibly control flow LikeFBString t = s; } void pass_to_copy_ok() { LikeFBString s; copy_fbstring(s); }