Skip to content

Add bounds check in AddSingleValueAndAdvance to prevent OOB read from empty repeated fields - #4147

Open
shaggyinsomniac wants to merge 1 commit into
tensorflow:masterfrom
shaggyinsomniac:fix/json-tensor-oob-read
Open

Add bounds check in AddSingleValueAndAdvance to prevent OOB read from empty repeated fields#4147
shaggyinsomniac wants to merge 1 commit into
tensorflow:masterfrom
shaggyinsomniac:fix/json-tensor-oob-read

Conversation

@shaggyinsomniac

Copy link
Copy Markdown

Problem

When --enable_serialization_as_tensor_content is set (a documented performance flag, model_servers/main.cc:312), output tensors are serialized via AsProtoTensorContent (predict_util.cc:185), placing data in TensorProto.tensor_content and leaving the typed repeated fields (float_val, int_val, etc.) empty.

The REST handler then serializes via MakeJsonFromTensors (http_rest_api_handler.cc:176) whose AddSingleValueAndAdvance (json_tensor.cc:888+) calls tensor.float_val(*offset) etc. unconditionally.

Protobuf's RepeatedField::Get(index) uses DCHECK — compiled out in release builds. On an empty repeated field:

  • Get(0) reads uninitialized heap memory → written into the JSON response body (heap disclosure)
  • Or dereferences null → SIGSEGV kills the server

Fix

Add a bounds check before the switch statement: compute the repeated field's size() for the tensor's dtype and verify *offset < size. If out of bounds, return InvalidArgument with a descriptive message instead of indexing OOB.

Verification

Reproduced in a C++ release build (protobuf 36, -O2 -DNDEBUG): a TensorProto with tensor_content set and float_val empty; calling float_val(0) (the exact indexing the REST writer performs) returns garbage from uninitialized memory. With this fix, the call returns an InvalidArgument error.

Reported via Google Bug Hunters (issue 553430318).

When --enable_serialization_as_tensor_content is set, output tensors are
serialized via AsProtoTensorContent, placing data in tensor_content and
leaving the typed repeated fields (float_val, int_val, etc.) empty. The
REST handler's AddSingleValueAndAdvance then calls
tensor.float_val(*offset) etc. unconditionally. Protobuf's
RepeatedField::Get uses DCHECK, compiled out in release builds, causing
an OOB read (uninitialized heap value written into the JSON response) or
nullptr dereference (SIGSEGV killing the server).

Fix: check that *offset is within the repeated field's size() before
calling Get(), returning an InvalidArgument error instead.
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