Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,16 @@ bool MeshPredictionSchemeTexCoordsPortableDecoder<
if (!buffer->Decode(&num_orientations) || num_orientations < 0) {
return false;
}
// Each predicted entry uses at most one orientation, so the count cannot be
// larger than the number of entries. The loop below cannot stop early,
// because DecodeNextBit() returns false both for a zero bit and at the end
// of the buffer.
const std::vector<CornerIndex> *const data_to_corner_map =
this->mesh_data().data_to_corner_map();
if (data_to_corner_map == nullptr ||
static_cast<size_t>(num_orientations) > data_to_corner_map->size()) {
return false;
}
predictor_.ResizeOrientations(num_orientations);
bool last_orientation = true;
RAnsBitDecoder decoder;
Expand Down
31 changes: 31 additions & 0 deletions src/draco/compression/decode_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -242,4 +242,35 @@ TEST_F(DecodeTest, TestSkipAttributeTransformUniqueId) {
<< std::endl;
}

TEST_F(DecodeTest, TestTexCoordOrientationCountIsBounded) {
// A 224-byte EdgeBreaker mesh whose portable texture coordinate prediction
// declares about two billion orientations. The decoder rejects the count
// because there are far fewer entries to use them.
const uint8_t data[] = {
0x44, 0x52, 0x41, 0x43, 0x4f, 0x02, 0x02, 0x01, 0x01, 0x00, 0x00, 0x00,
0x08, 0x0c, 0x02, 0x0b, 0x00, 0x00, 0x03, 0x5f, 0x4b, 0x15, 0x01, 0x01,
0x10, 0x55, 0x04, 0x8a, 0xac, 0xa4, 0x46, 0x55, 0x04, 0x8a, 0xac, 0xa4,
0x46, 0x03, 0xff, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01,
0x00, 0x09, 0x03, 0x00, 0x00, 0x02, 0x01, 0x03, 0x09, 0x02, 0x00, 0x01,
0x02, 0x01, 0x01, 0x09, 0x03, 0x00, 0x02, 0x03, 0x01, 0x01, 0x01, 0x00,
0x03, 0x03, 0x01, 0x30, 0x01, 0x10, 0x03, 0x00, 0x28, 0x96, 0x8e, 0x08,
0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x0f, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x80, 0x3f, 0x14, 0x05, 0x01, 0x01, 0x00, 0x0d, 0x03, 0x55, 0x0d, 0xad,
0x12, 0x07, 0x01, 0x08, 0x17, 0x01, 0x18, 0x08, 0x8d, 0x82, 0x72, 0xc3,
0xb7, 0x3c, 0x83, 0x8d, 0x06, 0xbc, 0xfc, 0xbf, 0xbf, 0xe5, 0xfb, 0xbf,
0xbf, 0xfc, 0xcb, 0xbf, 0xba, 0x81, 0xfc, 0xcb, 0x3f, 0x9a, 0xfc, 0xcb,
0xff, 0xfb, 0xbf, 0x7f, 0x02, 0xf6, 0xfb, 0xcb, 0x3e, 0x2e, 0xff, 0xef,
0xff, 0xfe, 0xf2, 0x0f, 0x0c, 0x00, 0x00, 0x3e, 0x01, 0x02, 0xc0, 0x40,
0x00, 0x00, 0x00, 0x00, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x3f, 0x0c, 0x06, 0x03, 0x01,
0x01, 0x03, 0x01, 0x01, 0x40, 0x01, 0x00, 0xff, 0x0f, 0x00, 0x00, 0xff,
0x07, 0x00, 0x00, 0xff, 0x02, 0xa1, 0x41, 0x0c,
};
draco::DecoderBuffer buffer;
buffer.Init(reinterpret_cast<const char *>(data), sizeof(data));
draco::Decoder decoder;
ASSERT_FALSE(decoder.DecodeMeshFromBuffer(&buffer).ok());
}

} // namespace
Loading