Describe the bug, including details regarding any error messages, version, and platform.
translate_utf8_utf8_utf8 (cpp/src/gandiva/gdv_string_function_stubs.cc) has a multi-byte code path that runs whenever any of the input, FROM, or TO strings contains a byte > 127. That path reads gdv_fn_utf8_char_length on a lead byte and then builds a std::string of that many bytes without checking how many bytes are left in the buffer.
Three reads can go past the end:
- a truncated trailing multi-byte glyph in the input (e.g. a lone
0xF0) reads up to 3 bytes past the input;
- a multi-byte input character that is not present in FROM reads one byte past FROM at the end-of-list sentinel (the
from_for == from_len check happens after the read);
- a truncated glyph in TO reads past TO.
All three are reachable from the SQL translate(in, from, to) function on adversarial or simply truncated column data.
Minimal ASAN reproduction of the input over-read (faithful extraction of the multi-byte branch):
char* in = new char[1];
in[0] = (char)0xF0; // claims a 4-byte glyph, only 1 byte present
translate_utf8_utf8_utf8(ctx, in, 1, "a", 1, "b", 1, &out_len);
// AddressSanitizer: heap-buffer-overflow READ of size 4, 0 bytes after 1-byte region
Component(s)
C++ - Gandiva
Describe the bug, including details regarding any error messages, version, and platform.
translate_utf8_utf8_utf8(cpp/src/gandiva/gdv_string_function_stubs.cc) has a multi-byte code path that runs whenever any of the input, FROM, or TO strings contains a byte > 127. That path readsgdv_fn_utf8_char_lengthon a lead byte and then builds astd::stringof that many bytes without checking how many bytes are left in the buffer.Three reads can go past the end:
0xF0) reads up to 3 bytes past the input;from_for == from_lencheck happens after the read);All three are reachable from the SQL
translate(in, from, to)function on adversarial or simply truncated column data.Minimal ASAN reproduction of the input over-read (faithful extraction of the multi-byte branch):
Component(s)
C++ - Gandiva