@@ -365,14 +365,27 @@ Status CastBuffer(const std::shared_ptr<DataType>& in_type,
365365}
366366
367367template <typename FromType, typename ToType>
368- Status StaticCastBuffer (const Buffer& input, const int64_t length, MemoryPool* pool,
368+ Status StaticCastBuffer (const Buffer& input, int64_t length, MemoryPool* pool,
369+ const uint8_t * null_bitmap,
370+ const compute::CastOptions& cast_options,
369371 std::shared_ptr<Buffer>* out) {
370372 ARROW_ASSIGN_OR_RAISE (auto result, AllocateBuffer (sizeof (ToType) * length, pool));
371373
372374 auto in_values = reinterpret_cast <const FromType*>(input.data ());
373375 auto out_values = reinterpret_cast <ToType*>(result->mutable_data ());
376+
377+ constexpr FromType kMin = std::numeric_limits<ToType>::min ();
378+ constexpr FromType kMax = std::numeric_limits<ToType>::max ();
379+
374380 for (int64_t i = 0 ; i < length; ++i) {
375- *out_values++ = static_cast <ToType>(*in_values++);
381+ FromType value = *in_values++;
382+ // Skip overflow check for null values
383+ bool is_null = (null_bitmap != nullptr ) && !bit_util::GetBit (null_bitmap, i);
384+ if (!is_null && !cast_options.allow_int_overflow && (value < kMin || value > kMax )) {
385+ return Status::Invalid (" Integer value " , value, " out of bounds for int" ,
386+ sizeof (ToType) * 8 , " conversion at index " , i);
387+ }
388+ *out_values++ = static_cast <ToType>(value);
376389 }
377390 *out = std::move (result);
378391 return Status::OK ();
@@ -496,16 +509,17 @@ inline Status NumPyConverter::ConvertData<Date32Type>(std::shared_ptr<Buffer>* d
496509 // separately here from int64_t to int32_t, because this data is not
497510 // supported in compute::Cast
498511 if (date_dtype->meta .base == NPY_FR_D) {
499- // TODO(wesm): How pedantic do we really want to be about checking for int32
500- // overflow here?
501- Status s = StaticCastBuffer<int64_t , int32_t >(**data, length_, pool_, data);
502- RETURN_NOT_OK (s);
512+ // Downcast from int64 to int32 with overflow checking
513+ const uint8_t * null_bitmap_ptr = null_bitmap_ ? null_bitmap_->data () : nullptr ;
514+ RETURN_NOT_OK ((StaticCastBuffer<int64_t , int32_t >(**data, length_, pool_,
515+ null_bitmap_ptr, cast_options_,
516+ data)));
503517 } else {
504518 ARROW_ASSIGN_OR_RAISE (input_type, NumPyDtypeToArrow (dtype_));
505519 if (!input_type->Equals (*type_)) {
506520 // The null bitmap was already computed in VisitNative()
507- RETURN_NOT_OK (CastBuffer (input_type, *data, length_, null_bitmap_, null_count_,
508- type_ , cast_options_, pool_, data));
521+ RETURN_NOT_OK ((StaticCastBuffer< int64_t , int32_t >(
522+ **data, length_, pool_, null_bitmap_ptr , cast_options_, data) ));
509523 }
510524 }
511525 } else {
0 commit comments