apache / apache/arrow

[C++][Gandiva] Integer overflow in mask output buffer size causes heap overflow

Open
#50,472 0 comments 0 reactions 1 assignee Claimed by @Arawoof06 View on GitHub
Component: C++ Component: Gandiva
Dominant language
C++
Stars
17.1k
Forks
4.3k
Avg merge
3d 13h
Merged PRs (30d)
88

Description

### Describe the bug, including details regarding any error messages, version, and platform.

`mask_utf8_utf8_utf8_utf8` in `cpp/src/gandiva/gdv_function_stubs.cc` computes the size of its output buffer as:

```cpp
int32_t max_length =
std::max(upper_length, std::max(lower_length, num_length)) * data_len;
```

Both the replacement length and `data_len` come from the SQL `mask(str, upper, lower, num)` arguments. The multiplication is done in `int32_t`, so a large replacement string combined with a large input wraps around and produces a small (or negative) `max_length`. The arena allocation is then far smaller than the masking loop needs, and the subsequent `memcpy` of each replacement writes past the buffer.

Example: `data_len = 65536` with a 65537-byte replacement gives a true size of 4,295,032,832 which truncates to 65536, so the very first masked character already writes 65537 bytes into a 65536-byte allocation. Running the masking function on such inputs crashes with SIGSEGV (heap buffer overflow).

Sibling functions (`repeat_utf8_int32`, `to_hex_binary`, the multibyte `translate` path) already guard these size multiplications with `arrow::internal::MultiplyWithOverflow`; `mask` is missing that guard.

### Component(s)

C++, Gandiva

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.