[C++][Gandiva] Integer overflow in mask output buffer size causes heap overflow
- 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
Assessment
This issue has not been assessed yet.