Chromium Code Reviews| Index: media/formats/mp4/box_reader_unittest.cc |
| diff --git a/media/formats/mp4/box_reader_unittest.cc b/media/formats/mp4/box_reader_unittest.cc |
| index 09df3d7f3d36c3f88a5b6da421ff559512435442..b416ab55eebb46b906afff216b2bcb596783d531 100644 |
| --- a/media/formats/mp4/box_reader_unittest.cc |
| +++ b/media/formats/mp4/box_reader_unittest.cc |
| @@ -301,21 +301,11 @@ TEST_F(BoxReaderTest, ScanChildrenWithInvalidChild) { |
| EXPECT_FALSE(reader->ReadChild(&child)); |
| } |
| -TEST_F(BoxReaderTest, ReadAllChildrenWithInvalidChild) { |
|
chcunningham
2017/01/18 21:13:31
This test was busted. On 32-bit, we overflow when
|
| - // This data is not a valid 'emsg' box. It is just used as a top-level box |
| - // as ReadTopLevelBox() has a restricted set of boxes it allows. |
| - // The nested 'trun' box is used as it includes a count of the number |
| - // of samples. The data specifies a large number of samples, but only 1 |
| - // is actually included in the box. Verifying that the large count does not |
| - // cause an int32_t overflow which would allow parsing of TrackFragmentRun |
| - // to read past the end of the buffer. |
| +TEST_F(BoxReaderTest, ReadAllChildrenWithChildLargerThanParent) { |
| static const uint8_t kData[] = { |
| - 0x00, 0x00, 0x00, 0x28, 'e', 'm', 's', 'g', // outer box |
| - 0x00, 0x00, 0x00, 0x20, 't', 'r', 'u', 'n', // nested box |
| - 0x00, 0x00, 0x0f, 0x00, // version = 0, flags = samples present |
| - 0xff, 0xff, 0xff, 0xff, // count = max, but only 1 actually included |
| - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
| - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; |
| + 0x00, 0x00, 0x00, 0x10, 's', 'k', 'i', 'p', // outer box |
| + 0x00, 0x00, 0x00, 0x10, 'p', 's', 's', 'h', // nested box |
| + }; |
| bool err; |
| std::unique_ptr<BoxReader> reader( |
| @@ -323,19 +313,32 @@ TEST_F(BoxReaderTest, ReadAllChildrenWithInvalidChild) { |
| EXPECT_FALSE(err); |
| EXPECT_TRUE(reader); |
| - EXPECT_EQ(FOURCC_EMSG, reader->type()); |
| + EXPECT_EQ(FOURCC_SKIP, reader->type()); |
| - // Reading the child should fail since the number of samples specified |
| - // doesn't match what is in the box. |
| - std::vector<TrackFragmentRun> children; |
| - EXPECT_FALSE(reader->ReadAllChildrenAndCheckFourCC(&children)); |
| + std::vector<PsshBox> tmp; |
| + EXPECT_FALSE(reader->ReadAllChildren(&tmp)); |
| } |
| -TEST_F(BoxReaderTest, ReadAllChildrenWithChildLargerThanParent) { |
| +TEST_F(BoxReaderTest, TrunSampleCount32bitOverflow) { |
| + // This data is not a valid 'emsg' box. It is just used as a top-level box |
| + // as ReadTopLevelBox() has a restricted set of boxes it allows. |
| + // The nested 'trun' box specifies an unusually high number of samples, though |
| + // only one sample is actually included in the box. The values for "sample |
| + // count" and "flags" are chosen such that their 32-bit product will overflow |
| + // to a very small number (4), leading to incorrect assumptions about bytes |
| + // available and ultimately OOB reads. http://crbug.com/679640 |
| static const uint8_t kData[] = { |
| - 0x00, 0x00, 0x00, 0x10, 's', 'k', 'i', 'p', // outer box |
| - 0x00, 0x00, 0x00, 0x10, 'p', 's', 's', 'h', // nested box |
| - }; |
| + 0x00, 0x00, 0x00, 0x28, |
| + 'e', 'm', 's', 'g', // outer box |
| + 0x00, 0x00, 0x00, 0x20, |
| + 't', 'r', 'u', 'n', // nested box |
| + 0x00, 0x00, // version = 0 |
| + 0x03, 0x00, // flags = 2 fields present (sample duration and sample size) |
| + 0x80, 0x00, 0x00, 0x02, // sample count = 2147483650 |
| + 0x00, 0x00, 0x00, 0x00, |
| + 0x00, 0x00, 0x00, 0x00, // only one sample present |
| + 0x00, 0x00, 0x00, 0x00, |
| + 0x00, 0x00, 0x00, 0x00}; |
| bool err; |
| std::unique_ptr<BoxReader> reader( |
| @@ -343,10 +346,25 @@ TEST_F(BoxReaderTest, ReadAllChildrenWithChildLargerThanParent) { |
| EXPECT_FALSE(err); |
| EXPECT_TRUE(reader); |
| - EXPECT_EQ(FOURCC_SKIP, reader->type()); |
| + EXPECT_EQ(FOURCC_EMSG, reader->type()); |
| - std::vector<PsshBox> tmp; |
| - EXPECT_FALSE(reader->ReadAllChildren(&tmp)); |
| +// Overflow is only triggered/caught on 32-bit systems. 64-bit systems will |
| +// instead fail parsing because kData does not have enough bytes to describe |
| +// the large number of samples. |
| +#if defined(ARCH_CPU_32_BITS) |
| + const int kOverflowLogCount = 1; |
| +#else |
| + const int kOverflowLogCount = 0; |
| +#endif |
| + |
| + EXPECT_MEDIA_LOG( |
| + HasSubstr("Extreme TRUN sample count exceeds system address space")) |
| + .Times(kOverflowLogCount); |
| + |
| + // Reading the child should fail since the number of samples specified |
| + // doesn't match what is in the box. |
| + std::vector<TrackFragmentRun> children; |
| + EXPECT_FALSE(reader->ReadAllChildrenAndCheckFourCC(&children)); |
| } |
| } // namespace mp4 |