This is an automated email from the ASF dual-hosted git repository.

kou pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/arrow.git


The following commit(s) were added to refs/heads/main by this push:
     new d0919579cb GH-50075: [C++][Gandiva] fix buffer overrun in to_hex 
int32/int64 (#50076)
d0919579cb is described below

commit d0919579cbdd37549ba163c0d61843f04bac92cd
Author: metsw24-max <[email protected]>
AuthorDate: Fri Jun 26 06:32:26 2026 +0530

    GH-50075: [C++][Gandiva] fix buffer overrun in to_hex int32/int64 (#50076)
    
    ### Rationale for this change
    
    `to_hex_int64` and `to_hex_int32` in 
`cpp/src/gandiva/precompiled/string_ops.cc` allocate the arena buffer with the 
bare hex-digit count (16 and 8 bytes) but pass that size + 1 as the `snprintf` 
bound. For any full-width value (`to_hex(-1::bigint)` -> `FFFFFFFFFFFFFFFF`, 
`INT64_MIN`, `INT32_MIN`, ...) `snprintf` writes all digits plus the trailing 
NUL, one byte past the end of the allocation. `gdv_fn_context_arena_malloc` 
returns exactly the requested bytes, so the NUL corrupts the ad [...]
    
    ### What changes are included in this PR?
    
    Allocate one extra byte in both functions so the allocation matches the 
`snprintf` bound, the same fix as GH-49752 applied to the identical pattern in 
`hash_utils.cc`.
    
    ### Are these changes tested?
    
    Yes. The existing `TestToHexInt64` / `TestToHexInt32` cases already 
exercise the full-width path (`INT64_MIN`, `INT32_MIN`, -1) and run clean under 
ASAN with this change. Output behaviour is unchanged.
    
    ### Are there any user-facing changes?
    
    No.
    
    **This PR contains a "Critical Fix".** It fixes a one-byte out-of-bounds 
heap write reachable from the `to_hex` Gandiva functions over untrusted input.
    
    * GitHub Issue: #50075
    
    Authored-by: metsw24-max <[email protected]>
    Signed-off-by: Sutou Kouhei <[email protected]>
---
 cpp/src/gandiva/precompiled/string_ops.cc | 8 +++++---
 1 file changed, 5 insertions(+), 3 deletions(-)

diff --git a/cpp/src/gandiva/precompiled/string_ops.cc 
b/cpp/src/gandiva/precompiled/string_ops.cc
index 8dc941e28c..0dd02cb1d8 100644
--- a/cpp/src/gandiva/precompiled/string_ops.cc
+++ b/cpp/src/gandiva/precompiled/string_ops.cc
@@ -2895,8 +2895,9 @@ const char* to_hex_binary(int64_t context, const char* 
text, int32_t text_len,
 FORCE_INLINE
 const char* to_hex_int64(int64_t context, int64_t data, int32_t* out_len) {
   const int64_t hex_long_max_size = 2 * sizeof(int64_t);
-  auto ret =
-      reinterpret_cast<char*>(gdv_fn_context_arena_malloc(context, 
hex_long_max_size));
+  // Allocate one extra byte for the null terminator written by snprintf.
+  auto ret = reinterpret_cast<char*>(
+      gdv_fn_context_arena_malloc(context, hex_long_max_size + 1));
 
   if (ret == nullptr) {
     gdv_fn_context_set_error_msg(context, "Could not allocate memory for 
output string");
@@ -2912,7 +2913,8 @@ const char* to_hex_int64(int64_t context, int64_t data, 
int32_t* out_len) {
 FORCE_INLINE
 const char* to_hex_int32(int64_t context, int32_t data, int32_t* out_len) {
   const int32_t max_size = 2 * sizeof(int32_t);
-  auto ret = reinterpret_cast<char*>(gdv_fn_context_arena_malloc(context, 
max_size));
+  // Allocate one extra byte for the null terminator written by snprintf.
+  auto ret = reinterpret_cast<char*>(gdv_fn_context_arena_malloc(context, 
max_size + 1));
 
   if (ret == nullptr) {
     gdv_fn_context_set_error_msg(context, "Could not allocate memory for 
output string");

Reply via email to