Repository navigation
Commit e831b3e
authored
Bounds-check the FlatTensor root table offset before reading it (pytorch#22118)
### Summary
`FlatTensorDataMap::load()` reads the flatbuffer root table without
first bounds-checking the root offset:
```cpp
const flat_tensor_flatbuffer::FlatTensor* flat_tensor =
flat_tensor_flatbuffer::GetFlatTensor(flat_tensor_data->data());
// then immediately:
flat_tensor->named_data(); // walks the root vtable
flat_tensor->segments();
```
`GetFlatTensor()` interprets the `uoffset_t` at the start of the buffer
as the root-table offset and returns `buf + offset`. The first field
access then walks that table's vtable. Nothing on this path runs full
flatbuffer verification, so a corrupt or truncated PTD file with a bad
root offset makes these accessors dereference memory **outside the
buffer** (an OOB read, flagged by ASan).
The program loader already guards against exactly this in
`runtime/executor/program.cpp`. This change mirrors that guard for PTD
files.
### What changed
After the existing identifier and alignment checks, before
`GetFlatTensor()`:
- Confirm the buffer is at least a flatbuffer header long (`uoffset_t` +
file identifier).
- Confirm the root offset is `>= kMinBufferSize` and leaves room for a
vtable `soffset_t` within the buffer.
- Return `InvalidExternalData` otherwise (the same error the surrounding
checks use).
FlatTensor is **not** size-prefixed — both writers finish the buffer
plain (`builder.Finish` in C++, default `flatc` in Python) and the
reader uses `GetFlatTensor` (not the size-prefixed variant) — so the
root offset is at byte 0, exactly as in the program case.
### Scope
This is a pre-existing hardening, independent of the schema-version work
in pytorch#22114 (the version gate this protects is additive; the OOB path
exists today via `named_data()`/`segments()`).
### Test plan
New `FlatTensorDataMapTest.RejectsOutOfBoundsRootOffset`: copies a valid
PTD into a max-aligned buffer, overwrites only the root offset with a
value past the end (leaving identifier + alignment intact), and asserts
`load()` returns `InvalidExternalData`. Without the check, that same
input is an out-of-bounds vtable read under ASan.
> Note: I was unable to build/run the C++ suite in my local environment,
so I'm relying on this PR's CI (which builds the runtime and runs
`extension/flat_tensor` tests, including under ASan) as the
authoritative check. The change mirrors an existing, tested guard in
`program.cpp`.1 parent 6a315a4 commit e831b3e
2 files changed
Lines changed: 69 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
289 | 289 | | |
290 | 290 | | |
291 | 291 | | |
| 292 | + | |
| 293 | + | |
| 294 | + | |
| 295 | + | |
| 296 | + | |
| 297 | + | |
| 298 | + | |
| 299 | + | |
| 300 | + | |
| 301 | + | |
| 302 | + | |
| 303 | + | |
| 304 | + | |
| 305 | + | |
| 306 | + | |
| 307 | + | |
| 308 | + | |
| 309 | + | |
| 310 | + | |
| 311 | + | |
| 312 | + | |
| 313 | + | |
| 314 | + | |
| 315 | + | |
| 316 | + | |
| 317 | + | |
| 318 | + | |
| 319 | + | |
| 320 | + | |
| 321 | + | |
| 322 | + | |
| 323 | + | |
292 | 324 | | |
293 | 325 | | |
294 | 326 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
266 | 266 | | |
267 | 267 | | |
268 | 268 | | |
| 269 | + | |
| 270 | + | |
| 271 | + | |
| 272 | + | |
| 273 | + | |
| 274 | + | |
| 275 | + | |
| 276 | + | |
| 277 | + | |
| 278 | + | |
| 279 | + | |
| 280 | + | |
| 281 | + | |
| 282 | + | |
| 283 | + | |
| 284 | + | |
| 285 | + | |
| 286 | + | |
| 287 | + | |
| 288 | + | |
| 289 | + | |
| 290 | + | |
| 291 | + | |
| 292 | + | |
| 293 | + | |
| 294 | + | |
| 295 | + | |
| 296 | + | |
| 297 | + | |
| 298 | + | |
| 299 | + | |
| 300 | + | |
| 301 | + | |
| 302 | + | |
| 303 | + | |
| 304 | + | |
| 305 | + | |
0 commit comments