Skip to content

Validate STACKER init parameters against overflow and tensor sizes#3604

Open
adilburaksen wants to merge 1 commit into
tensorflow:mainfrom
adilburaksen:fix-stacker-param-validation
Open

Validate STACKER init parameters against overflow and tensor sizes#3604
adilburaksen wants to merge 1 commit into
tensorflow:mainfrom
adilburaksen:fix-stacker-param-validation

Conversation

@adilburaksen

Copy link
Copy Markdown

BUG=out-of-bounds access in STACKER kernel from unvalidated init parameters

What

StackerInit reads num_channels, stacker_left_context, stacker_right_context
and stacker_step from the init flexbuffer and computes:

buffer_size = num_channels * (stacker_left_context + stacker_right_context + 1);
step_size   = num_channels * stacker_step;

StackerPrepare validated only tensor ranks/types — never these parameters. A
crafted model (e.g. stacker_right_context = -1, making buffer_size = 0, or
values whose product overflows) produces a zero/undersized circular buffer.
StackerEval then calls CircularBufferWrite / CircularBufferExtend, copying
num_channels values per frame and reading buffer_size values into the output,
out of bounds.

In release builds the ASSERT(...) in CircularBufferWrite (#define ASSERT assert) is compiled out under -DNDEBUG, so this is an out-of-bounds
read/write. Confirmed with AddressSanitizer (built with -DNDEBUG):

ERROR: AddressSanitizer: global-buffer-overflow in __asan_memcpy
  #1 CircularBufferWrite   signal/src/circular_buffer.cc:97
  #2 CircularBufferExtend  signal/src/circular_buffer.cc:178
  #3 StackerEval           signal/micro/kernels/stacker.cc:139

Change

  • stacker.cc: StackerPrepare validates num_channels > 0, contexts >= 0,
    stacker_step > 0, num_channels <= input size, that the buffer_size product
    does not overflow, and that the output is large enough.
  • stacker_test.cc: regression test that the malformed parameters are rejected.

No change for valid models.

StackerInit reads num_channels, stacker_left_context, stacker_right_context and
stacker_step from the init flexbuffer and computes buffer_size = num_channels *
(left + right + 1) and step_size = num_channels * stacker_step. StackerPrepare
validated only tensor ranks and types, never these parameters. Negative or
overflowing values yield a zero/undersized circular buffer that StackerEval then
writes and reads out of bounds via CircularBufferWrite/CircularBufferExtend
(num_channels values are copied per frame and buffer_size values are read into the
output). In release builds the bounds assert in CircularBufferWrite is compiled
out, so this is an out-of-bounds access; confirmed with AddressSanitizer.

Validate num_channels > 0, the contexts >= 0, stacker_step > 0, num_channels <=
input size, that the buffer_size product does not overflow, and that the output is
large enough, plus a regression test.
@adilburaksen adilburaksen requested a review from a team as a code owner June 19, 2026 00:04
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant