Repository navigation
Conversation
S2ShapeIndexCell::Decode only guarded decoded shape ids against INT32_MAX, not against num_shape_ids. A crafted encoded index whose cell names a shape id past the end of the index decodes fine, and the usual shape(clipped.shape_id()) lookup then reads out of bounds.
There was a problem hiding this comment.
Code Review
This pull request introduces validation to reject out-of-range shape IDs during decoding in S2ShapeIndexCell::Decode, preventing potential out-of-bounds reads, and adds a corresponding unit test. The reviewer recommends validating the shape_id immediately after it is updated in each branch of the conditional block, rather than at the end of the loop, to prevent implicit narrowing conversions of unvalidated values when calling clipped->Init.
| // Shape ids come from the encoded data, so reject any that are out of | ||
| // range. Otherwise a caller that indexes S2ShapeIndex::shape() with a | ||
| // decoded shape id reads out of bounds. | ||
| if (shape_id >= num_shape_ids) return false; |
There was a problem hiding this comment.
While this check successfully prevents out-of-bounds access during queries, clipped->Init(shape_id, ...) is called earlier in the loop body before this validation occurs. Since shape_id is an int64_t and clipped->Init expects an int32_t, an extremely large shape_id from malformed encoded data could trigger an implicit narrowing conversion of an unvalidated value before the check is reached.\n\nTo improve robustness and adhere to defensive programming practices, consider validating shape_id immediately after it is updated in each of the three branches of the if-else statement (i.e., right before clipped->Init is called), rather than waiting until the end of the loop.
S2ShapeIndexCell::Decodeguards decoded shape ids againstINT32_MAXbut not againstnum_shape_ids, so an encoded index whose cell references a shape id past the end of the index decodes without error. Theindex.shape(clipped.shape_id())lookup that essentially every query performs while walking the index then indexesshapes_out of bounds:Reproduced by hand-encoding a one-cell index whose clipped shape carries shape id 5000, decoding it with a 2-shape
ShapeFactory, and reading the referenced shape. The added regression test decodes the same blob and expectsInitto reject it.The fix rejects out-of-range shape ids inside the decode loop, next to the existing
INT32_MAXguard.