When JSON_STREAM_INPUT_SENSITIVE is set before the first read,
input_buffer is NULL, input_buffer_size is 0, and input_buffer_index
is 0. The old condition '!INPUT_SENSITIVE && index == 0' would route
this case into the else branch which calls memcpy() with a NULL source
pointer, which is undefined behavior even when the length is zero, and
is caught by UBSan.
Fix by checking input_buffer_index == 0 first, then allowing the
GREEDY_REALLOC fast path also when input_buffer_size == 0, since
there is no sensitive data to protect from realloc() copying in that
case. The else branch is now only entered when there is actual data
to copy (input_buffer_size > 0), guaranteeing input_buffer is
non-NULL.
Follow-up for
6b1a59d59426cdda56648b00394addde2d454418
add = MIN(s->buffer_max - s->input_buffer_size, s->read_chunk);
add = MIN(s->buffer_max - s->input_buffer_size, s->read_chunk);
- if (!FLAGS_SET(s->flags, JSON_STREAM_INPUT_SENSITIVE) && s->input_buffer_index == 0) {
+ if (s->input_buffer_index == 0 &&
+ (!FLAGS_SET(s->flags, JSON_STREAM_INPUT_SENSITIVE) || s->input_buffer_size == 0)) {
if (!GREEDY_REALLOC(s->input_buffer, s->input_buffer_size + add))
return -ENOMEM;
} else {
if (!GREEDY_REALLOC(s->input_buffer, s->input_buffer_size + add))
return -ENOMEM;
} else {