2727#include " arrow/buffer.h"
2828#include " arrow/status.h"
2929#include " arrow/util/bit_util.h"
30- #include " arrow/util/int_util_overflow.h"
3130#include " arrow/util/bitmap_generate.h"
3231#include " arrow/util/bitmap_ops.h"
32+ #include " arrow/util/int_util_overflow.h"
3333#include " arrow/util/macros.h"
3434#include " arrow/util/ubsan.h"
3535#include " arrow/util/visibility.h"
@@ -114,8 +114,8 @@ class ARROW_EXPORT BufferBuilder {
114114 // jemalloc, but significantly better performance when using the system
115115 // allocator. See ARROW-6450 for further discussion
116116 int64_t doubled;
117- if (ARROW_PREDICT_FALSE (internal::AddWithOverflow (current_capacity, current_capacity,
118- &doubled))) {
117+ if (ARROW_PREDICT_FALSE (
118+ internal::AddWithOverflow (current_capacity, current_capacity, &doubled))) {
119119 return new_capacity;
120120 }
121121 return std::max (new_capacity, doubled);
@@ -274,21 +274,12 @@ class TypedBufferBuilder<
274274 }
275275
276276 Status Append (const T* values, int64_t num_elements) {
277- if (ARROW_PREDICT_FALSE (num_elements < 0 )) {
278- return Status::Invalid (" Append: negative number of elements" );
279- }
280277 int64_t num_bytes;
281- if (ARROW_PREDICT_FALSE (internal::MultiplyWithOverflow (
282- num_elements, static_cast <int64_t >(sizeof (T)), &num_bytes))) {
283- return Status::CapacityError (" Append: size overflow" );
284- }
278+ ARROW_RETURN_NOT_OK (ElementsToBytes (" Append" , num_elements, &num_bytes));
285279 return bytes_builder_.Append (reinterpret_cast <const uint8_t *>(values), num_bytes);
286280 }
287281
288282 Status Append (const int64_t num_copies, T value) {
289- if (ARROW_PREDICT_FALSE (num_copies < 0 )) {
290- return Status::Invalid (" Append: negative number of copies" );
291- }
292283 ARROW_RETURN_NOT_OK (Reserve (num_copies));
293284 UnsafeAppend (num_copies, value);
294285 return Status::OK ();
@@ -318,38 +309,20 @@ class TypedBufferBuilder<
318309 }
319310
320311 Status Resize (const int64_t new_capacity, bool shrink_to_fit = true ) {
321- if (ARROW_PREDICT_FALSE (new_capacity < 0 )) {
322- return Status::Invalid (" Resize: negative capacity" );
323- }
324312 int64_t num_bytes;
325- if (ARROW_PREDICT_FALSE (internal::MultiplyWithOverflow (
326- new_capacity, static_cast <int64_t >(sizeof (T)), &num_bytes))) {
327- return Status::CapacityError (" Resize: capacity overflow" );
328- }
313+ ARROW_RETURN_NOT_OK (ElementsToBytes (" Resize" , new_capacity, &num_bytes));
329314 return bytes_builder_.Resize (num_bytes, shrink_to_fit);
330315 }
331316
332317 Status Reserve (const int64_t additional_elements) {
333- if (ARROW_PREDICT_FALSE (additional_elements < 0 )) {
334- return Status::Invalid (" Reserve: negative additional_elements" );
335- }
336318 int64_t num_bytes;
337- if (ARROW_PREDICT_FALSE (internal::MultiplyWithOverflow (
338- additional_elements, static_cast <int64_t >(sizeof (T)), &num_bytes))) {
339- return Status::CapacityError (" Reserve: size overflow" );
340- }
319+ ARROW_RETURN_NOT_OK (ElementsToBytes (" Reserve" , additional_elements, &num_bytes));
341320 return bytes_builder_.Reserve (num_bytes);
342321 }
343322
344323 Status Advance (const int64_t length) {
345- if (ARROW_PREDICT_FALSE (length < 0 )) {
346- return Status::Invalid (" Advance: negative length" );
347- }
348324 int64_t num_bytes;
349- if (ARROW_PREDICT_FALSE (internal::MultiplyWithOverflow (
350- length, static_cast <int64_t >(sizeof (T)), &num_bytes))) {
351- return Status::CapacityError (" Advance: size overflow" );
352- }
325+ ARROW_RETURN_NOT_OK (ElementsToBytes (" Advance" , length, &num_bytes));
353326 return bytes_builder_.Advance (num_bytes);
354327 }
355328
@@ -374,14 +347,8 @@ class TypedBufferBuilder<
374347 // / only for memory allocation).
375348 Result<std::shared_ptr<Buffer>> FinishWithLength (int64_t final_length,
376349 bool shrink_to_fit = true ) {
377- if (ARROW_PREDICT_FALSE (final_length < 0 )) {
378- return Status::Invalid (" FinishWithLength: negative final length" );
379- }
380350 int64_t num_bytes;
381- if (ARROW_PREDICT_FALSE (internal::MultiplyWithOverflow (
382- final_length, static_cast <int64_t >(sizeof (T)), &num_bytes))) {
383- return Status::CapacityError (" FinishWithLength: final length overflow" );
384- }
351+ ARROW_RETURN_NOT_OK (ElementsToBytes (" FinishWithLength" , final_length, &num_bytes));
385352 return bytes_builder_.FinishWithLength (num_bytes, shrink_to_fit);
386353 }
387354
@@ -393,6 +360,20 @@ class TypedBufferBuilder<
393360 T* mutable_data () { return reinterpret_cast <T*>(bytes_builder_.mutable_data ()); }
394361
395362 private:
363+ // Convert a number of elements to a number of bytes, erroring out on
364+ // negative element counts and byte size overflow.
365+ static Status ElementsToBytes (const char * operation, int64_t num_elements,
366+ int64_t * num_bytes) {
367+ if (ARROW_PREDICT_FALSE (num_elements < 0 )) {
368+ return Status::Invalid (operation, " : negative number of elements" );
369+ }
370+ if (ARROW_PREDICT_FALSE (internal::MultiplyWithOverflow (
371+ num_elements, static_cast <int64_t >(sizeof (T)), num_bytes))) {
372+ return Status::CapacityError (operation, " : byte size overflow" );
373+ }
374+ return Status::OK ();
375+ }
376+
396377 BufferBuilder bytes_builder_;
397378};
398379
@@ -503,7 +484,7 @@ class TypedBufferBuilder<bool> {
503484 internal::AddWithOverflow (bit_length_, additional_elements, &min_length))) {
504485 return Status::CapacityError (" Reserve: capacity overflow" );
505486 }
506- return Resize (min_length, false );
487+ return Resize (BufferBuilder::GrowByFactor (bit_length_, min_length) , false );
507488 }
508489
509490 Status Advance (const int64_t length) {
@@ -534,6 +515,9 @@ class TypedBufferBuilder<bool> {
534515 // / only for memory allocation).
535516 Result<std::shared_ptr<Buffer>> FinishWithLength (int64_t final_length,
536517 bool shrink_to_fit = true ) {
518+ if (ARROW_PREDICT_FALSE (final_length < 0 )) {
519+ return Status::Invalid (" FinishWithLength: negative final length" );
520+ }
537521 const auto final_byte_length = bit_util::BytesForBits (final_length);
538522 bytes_builder_.UnsafeAdvance (final_byte_length - bytes_builder_.length ());
539523 bit_length_ = false_count_ = 0 ;
0 commit comments