diff --git a/td/telegram/UpdatesManager.cpp b/td/telegram/UpdatesManager.cpp index 5bac3c7c..476230a3 100644 --- a/td/telegram/UpdatesManager.cpp +++ b/td/telegram/UpdatesManager.cpp @@ -187,7 +187,7 @@ void UpdatesManager::fill_gap(void *td, const char *source) { string UpdatesManager::get_state() const { char buff[1024]; - StringBuilder sb({buff, sizeof(buff)}); + StringBuilder sb(MutableSlice{buff, sizeof(buff)}); sb << "UpdatesManager is in state "; switch (state_.type) { case State::Type::General: diff --git a/tdnet/td/net/HttpHeaderCreator.h b/tdnet/td/net/HttpHeaderCreator.h index ffde46f9..96144d71 100644 --- a/tdnet/td/net/HttpHeaderCreator.h +++ b/tdnet/td/net/HttpHeaderCreator.h @@ -16,26 +16,26 @@ namespace td { class HttpHeaderCreator { public: static constexpr size_t MAX_HEADER = 4096; - HttpHeaderCreator() : sb_({header_, MAX_HEADER}) { + HttpHeaderCreator() : sb_(MutableSlice{header_, MAX_HEADER}) { } void init_ok() { - sb_ = StringBuilder({header_, MAX_HEADER}); + sb_ = StringBuilder(MutableSlice{header_, MAX_HEADER}); sb_ << "HTTP/1.1 200 OK\r\n"; } void init_get(Slice url) { - sb_ = StringBuilder({header_, MAX_HEADER}); + sb_ = StringBuilder(MutableSlice{header_, MAX_HEADER}); sb_ << "GET " << url << " HTTP/1.1\r\n"; } void init_post(Slice url) { - sb_ = StringBuilder({header_, MAX_HEADER}); + sb_ = StringBuilder(MutableSlice{header_, MAX_HEADER}); sb_ << "POST " << url << " HTTP/1.1\r\n"; } void init_error(int code, Slice reason) { - sb_ = StringBuilder({header_, MAX_HEADER}); + sb_ = StringBuilder(MutableSlice{header_, MAX_HEADER}); sb_ << "HTTP/1.1 " << code << " " << reason << "\r\n"; } void init_status_line(int http_status_code) { - sb_ = StringBuilder({header_, MAX_HEADER}); + sb_ = StringBuilder(MutableSlice{header_, MAX_HEADER}); sb_ << "HTTP/1.1 " << http_status_code << " " << get_status_line(http_status_code) << "\r\n"; } void add_header(Slice key, Slice value) { diff --git a/tdutils/td/utils/OptionsParser.h b/tdutils/td/utils/OptionsParser.h index d9d6ccfc..0820e31b 100644 --- a/tdutils/td/utils/OptionsParser.h +++ b/tdutils/td/utils/OptionsParser.h @@ -58,7 +58,7 @@ class OptionsParser { return -1; #else char buff[1024]; - StringBuilder sb({buff, sizeof(buff)}); + StringBuilder sb(MutableSlice{buff, sizeof(buff)}); for (auto &opt : options_) { CHECK(opt.type != Option::OptionalArg); sb << opt.short_key; diff --git a/tdutils/td/utils/StringBuilder.cpp b/tdutils/td/utils/StringBuilder.cpp index 0a6ecbce..86dfdf87 100644 --- a/tdutils/td/utils/StringBuilder.cpp +++ b/tdutils/td/utils/StringBuilder.cpp @@ -65,10 +65,16 @@ bool StringBuilder::reserve_inner(size_t size) { if (!use_buffer_) { return false; } - //TODO: check size_t oveflow + size_t old_data_size = current_ptr_ - begin_ptr_; + if (size >= std::numeric_limits::max() - reserved_size - old_data_size - 1) { + return false; + } size_t need_data_size = old_data_size + size; size_t old_buffer_size = end_ptr_ - begin_ptr_; + if (old_buffer_size >= (std::numeric_limits::max() - reserved_size) / 2 - 2) { + return false; + } size_t new_buffer_size = (old_buffer_size + 1) * 2; if (new_buffer_size < need_data_size) { new_buffer_size = need_data_size; @@ -77,13 +83,14 @@ bool StringBuilder::reserve_inner(size_t size) { new_buffer_size = 100; } new_buffer_size += reserved_size; - auto new_buffer_ = std::make_unique(new_buffer_size); - std::memcpy(new_buffer_.get(), begin_ptr_, old_data_size); - buffer_ = std::move(new_buffer_); + auto new_buffer = std::make_unique(new_buffer_size); + std::memcpy(new_buffer.get(), begin_ptr_, old_data_size); + buffer_ = std::move(new_buffer); begin_ptr_ = buffer_.get(); current_ptr_ = begin_ptr_ + old_data_size; end_ptr_ = begin_ptr_ + new_buffer_size - reserved_size; - CHECK(end_ptr_ > begin_ptr_); + CHECK(end_ptr_ > current_ptr_); + CHECK(static_cast(end_ptr_ - current_ptr_) >= size); return true; } @@ -136,7 +143,7 @@ StringBuilder &StringBuilder::operator<<(long long unsigned int x) { } StringBuilder &StringBuilder::operator<<(FixedDouble x) { - if (unlikely(!reserve())) { + if (unlikely(!reserve(std::numeric_limits::max_exponent10 + x.precision + 4))) { return on_error(); } diff --git a/tdutils/td/utils/StringBuilder.h b/tdutils/td/utils/StringBuilder.h index fb655dd8..1ee97156 100644 --- a/tdutils/td/utils/StringBuilder.h +++ b/tdutils/td/utils/StringBuilder.h @@ -19,16 +19,15 @@ namespace td { class StringBuilder { public: explicit StringBuilder(MutableSlice slice, bool use_buffer = false) - : begin_ptr_(slice.begin()) - , current_ptr_(begin_ptr_) - , end_ptr_(slice.end() - reserved_size) - , use_buffer_(use_buffer) { + : begin_ptr_(slice.begin()), current_ptr_(begin_ptr_), use_buffer_(use_buffer) { if (slice.size() <= reserved_size) { auto buffer_size = reserved_size + 100; buffer_ = std::make_unique(buffer_size); begin_ptr_ = buffer_.get(); current_ptr_ = begin_ptr_; end_ptr_ = begin_ptr_ + buffer_size - reserved_size; + } else { + end_ptr_ = slice.end() - reserved_size; } } diff --git a/tdutils/test/json.cpp b/tdutils/test/json.cpp index deca81a7..5559e2ce 100644 --- a/tdutils/test/json.cpp +++ b/tdutils/test/json.cpp @@ -34,7 +34,7 @@ static void decode_encode(string str, string result = "") { TEST(JSON, array) { char tmp[1000]; - StringBuilder sb({tmp, sizeof(tmp)}); + StringBuilder sb(MutableSlice{tmp, sizeof(tmp)}); JsonBuilder jb(std::move(sb)); jb.enter_value().enter_array() << "Hello" << -123; ASSERT_EQ(jb.string_builder().is_error(), false); @@ -44,7 +44,7 @@ TEST(JSON, array) { } TEST(JSON, object) { char tmp[1000]; - StringBuilder sb({tmp, sizeof(tmp)}); + StringBuilder sb(MutableSlice{tmp, sizeof(tmp)}); JsonBuilder jb(std::move(sb)); auto c = jb.enter_object(); c << std::tie("key", "value"); @@ -58,7 +58,7 @@ TEST(JSON, object) { TEST(JSON, nested) { char tmp[1000]; - StringBuilder sb({tmp, sizeof(tmp)}); + StringBuilder sb(MutableSlice{tmp, sizeof(tmp)}); JsonBuilder jb(std::move(sb)); { auto a = jb.enter_array(); diff --git a/tdutils/test/misc.cpp b/tdutils/test/misc.cpp index 5cf5b362..aacebf5a 100644 --- a/tdutils/test/misc.cpp +++ b/tdutils/test/misc.cpp @@ -494,12 +494,12 @@ TEST(Misc, full_split) { } TEST(Misc, StringBuilder) { - auto small = std::string{"abcdefghij"}; - auto big = std::string(1000, 'a'); + auto small_str = std::string{"abcdefghij"}; + auto big_str = std::string(1000, 'a'); using V = std::vector; for (auto use_buf : {false, true}) { for (size_t initial_buffer_size : {0, 1, 5, 10, 100, 1000, 2000}) { - for (auto test : {V{small}, {small, big, big, small}, {big, small, big}}) { + for (auto test : {V{small_str}, V{small_str, big_str, big_str, small_str}, V{big_str, small_str, big_str}}) { std::string buf(initial_buffer_size, '\0'); td::StringBuilder sb(buf, use_buf); std::string res;