diff --git a/src/s2/s2cell.cc b/src/s2/s2cell.cc index 44b1f589..baba5edb 100644 --- a/src/s2/s2cell.cc +++ b/src/s2/s2cell.cc @@ -325,7 +325,7 @@ void S2Cell::Encode(Encoder* const encoder) const { bool S2Cell::Decode(Decoder* const decoder) { S2CellId id; - if (!id.Decode(decoder)) return false; + if (!id.Decode(decoder) || !id.is_valid()) return false; this->~S2Cell(); new (this) S2Cell(id); return true; diff --git a/src/s2/s2cell_test.cc b/src/s2/s2cell_test.cc index dd63eee0..388a06b1 100644 --- a/src/s2/s2cell_test.cc +++ b/src/s2/s2cell_test.cc @@ -1011,6 +1011,17 @@ TEST(S2Cell, EncodeDecode) { EXPECT_EQ(orig_cell.GetBoundUV(), decoded_cell.GetBoundUV()); } +TEST(S2Cell, DecodeRejectsInvalidCellId) { + // Face 7 is out of range and 0 has no level marker bit. + for (S2CellId id : {S2CellId(~uint64_t{0}), S2CellId::None()}) { + Encoder encoder; + id.Encode(&encoder); + S2Cell cell; + Decoder decoder(encoder.base(), encoder.length()); + EXPECT_FALSE(cell.Decode(&decoder)); + } +} + TEST(S2Cell, GetUVCoordOfEdge) { // Four cells on face 0 with two boundaries each on 0/0. S2Cell kCell0[4] = { diff --git a/src/s2/s2cell_union.cc b/src/s2/s2cell_union.cc index a3df7ba3..6b912d3e 100644 --- a/src/s2/s2cell_union.cc +++ b/src/s2/s2cell_union.cc @@ -555,7 +555,9 @@ bool S2CellUnion::Decode(Decoder* const decoder) { vector temp_cell_ids(num_cells); for (size_t i = 0; i < num_cells; ++i) { - if (!temp_cell_ids[i].Decode(decoder)) return false; + if (!temp_cell_ids[i].Decode(decoder) || !temp_cell_ids[i].is_valid()) { + return false; + } } cell_ids_.swap(temp_cell_ids); return true; diff --git a/src/s2/s2cell_union_test.cc b/src/s2/s2cell_union_test.cc index 2270a80d..cc73d822 100644 --- a/src/s2/s2cell_union_test.cc +++ b/src/s2/s2cell_union_test.cc @@ -787,6 +787,19 @@ TEST(S2CellUnion, RefuseToDecode) { EXPECT_FALSE(decoded_cell_union.Decode(&decoder)); } +TEST(S2CellUnion, DecodeRejectsInvalidCellId) { + // Same layout as S2CellUnion::Encode(), with an id on face 7. + Encoder encoder; + encoder.Ensure(sizeof(uint8_t) + 3 * sizeof(uint64_t)); + encoder.put8(1); + encoder.put64(2); + encoder.put64(S2CellId::FromFace(1).id()); + encoder.put64(~uint64_t{0}); + Decoder decoder(encoder.base(), encoder.length()); + S2CellUnion decoded_cell_union; + EXPECT_FALSE(decoded_cell_union.Decode(&decoder)); +} + TEST(S2CellUnion, Release) { S2CellId face1_id = S2CellId::FromFace(1); S2CellUnion face1_union({face1_id});