Views
No views yet
VariablesIndex entry-length out-of-bounds readvariables/variables.index SSTable in native code. In
VariablesIndex::read_variables_index_pair(), it decodes the shared key
prefix, non-shared key suffix, and value length from model-controlled bytes,
then uses those lengths without checking how many bytes remain:1shared = smUnpack<uint32_t>(ptr, ptr_end);
2nonShared = smUnpack<uint32_t>(ptr, ptr_end);
3val_length = smUnpack<uint32_t>(ptr, ptr_end);
4key.resize(shared);
5key.append(ptr, nonShared);
6value = ptr + nonShared;
7ptr = value + val_length;nonShared or val_length exceed the remaining
block bytes. The included trigger changes one byte in an otherwise identical
SavedModel and deterministically crashes OpenVINO in std::string::append().2026.2.1-21919-ede283a88e3-releases/2026/22970df68018e1fb7d7d0c4a834c34687a843a3681python3 -m venv .venv
2./.venv/bin/pip install openvino==2026.2.0
3
4./.venv/bin/python generate_fixtures.py
5./.venv/bin/python load_model.py models/control
6# InputModel
7./.venv/bin/python load_model.py models/trigger
8# Segmentation fault (exit 139)| Fixture | Run 1 | Run 2 | Run 3 |
|---|---|---|---|
| control | 0 | 0 | 0 |
| trigger | 139 | 139 | 139 |
| Model | variables.index size | SHA-256 | Result |
|---|---|---|---|
control | 97 bytes | 17fc9111ff827ba8f6ccf06a91351da68fc101e774584e14515bc457fff33727 | loads successfully |
trigger | 97 bytes | 0a1f779a14abd5cbff419afd37bcaaaa9fdb7d3318f1d910344177ef486a7d6d | process exit 139 |
saved_model.pb files and the two variable-data shards are
byte-identical. The 97-byte index files differ at exactly one byte: offset 31
is 0x00 in the control and 0x01 in the trigger. That changes the decoded
non-shared key length from 1 to 268435457 while the block contains one key
byte.crash-stack.txt. The fault is an
invalid read in _platform_memmove, reached from:1std::string::__grow_by_and_replace
2std::string::append
3ov::frontend::tensorflow::VariablesIndex::read_variables_index_pair
4ov::frontend::tensorflow::VariablesIndex::read_variables_index
5ov::frontend::tensorflow::VariablesIndex::read_variables
6ov::frontend::tensorflow::GraphIteratorSavedModel::read_saved_model
7ov::frontend::tensorflow::FrontEnd::load_implshared <= key.size() and
nonShared + val_length <= ptr_end - ptr without overflowing the addition.
Advance pointers only after those checks. OpenVINO already uses the appropriate
remaining-buffer validation pattern in TensorFlow frontend
checkpoint_utils.cpp::decode_entry().generate_fixtures.py - builds the differential SavedModel pair.load_model.py - loads the model through the OpenVINO TensorFlow frontend.models/control - valid minimal SavedModel.models/trigger - one-byte-different crashing SavedModel.crash-stack.txt - sanitized native crash evidence.