1 // Copyright (c) 2016 The WebM project authors. All Rights Reserved.
2 //
3 // Use of this source code is governed by a BSD-style license
4 // that can be found in the LICENSE file in the root of the source
5 // tree. An additional intellectual property rights grant can be found
6 // in the file PATENTS.  All contributing project authors may
7 // be found in the AUTHORS file in the root of the source tree.
8 #include "src/master_parser.h"
9 
10 #include <cstdint>
11 #include <memory>
12 #include <vector>
13 
14 #include "gmock/gmock.h"
15 #include "gtest/gtest.h"
16 
17 #include "src/byte_parser.h"
18 #include "test_utils/element_parser_test.h"
19 #include "webm/element.h"
20 #include "webm/id.h"
21 #include "webm/status.h"
22 
23 using testing::_;
24 using testing::DoAll;
25 using testing::InSequence;
26 using testing::NotNull;
27 using testing::Return;
28 using testing::SetArgPointee;
29 
30 using webm::Action;
31 using webm::BinaryParser;
32 using webm::ElementMetadata;
33 using webm::ElementParser;
34 using webm::ElementParserTest;
35 using webm::Id;
36 using webm::kUnknownElementSize;
37 using webm::LimitedReader;
38 using webm::MasterParser;
39 using webm::Status;
40 
41 namespace {
42 
43 // Simple helper method that just takes an Id and ElementParser* and returns
44 // them in a std::pair<Id, std::unique_ptr<ElementParser>>. Provided just for
45 // simplifying some statements.
ParserForId(Id id,ElementParser * parser)46 std::pair<Id, std::unique_ptr<ElementParser>> ParserForId(
47     Id id, ElementParser* parser) {
48   return {id, std::unique_ptr<ElementParser>(parser)};
49 }
50 
51 class MasterParserTest : public ElementParserTest<MasterParser> {};
52 
53 // Errors parsing an ID should be returned to the caller.
TEST_F(MasterParserTest,BadId)54 TEST_F(MasterParserTest, BadId) {
55   SetReaderData({
56       0x00,  // Invalid ID.
57       0x80,  // ID = 0x80 (unknown).
58       0x80,  // Size = 0.
59   });
60 
61   EXPECT_CALL(callback_, OnElementBegin(_, _)).Times(0);
62 
63   ParseAndExpectResult(Status::kInvalidElementId);
64 }
65 
66 // Errors from a child parser's Init should be returned to the caller.
TEST_F(MasterParserTest,ChildInitFails)67 TEST_F(MasterParserTest, ChildInitFails) {
68   SetReaderData({
69       0xEC,  // ID = 0xEC (Void).
70       0xFF,  // Size = unknown.
71   });
72 
73   const ElementMetadata metadata = {Id::kVoid, 2, kUnknownElementSize, 0};
74   EXPECT_CALL(callback_, OnElementBegin(metadata, NotNull())).Times(1);
75 
76   ParseAndExpectResult(Status::kInvalidElementSize);
77 }
78 
79 // Indefinite unknown children should result in an error.
TEST_F(MasterParserTest,IndefiniteUnknownChild)80 TEST_F(MasterParserTest, IndefiniteUnknownChild) {
81   SetReaderData({
82       0x80,  // ID = 0x80 (unknown).
83       0xFF,  // Size = unknown.
84       0x00, 0x00,  // Body.
85   });
86 
87   EXPECT_CALL(callback_, OnElementBegin(_, _)).Times(0);
88 
89   ParseAndExpectResult(Status::kIndefiniteUnknownElement);
90 }
91 
92 // Child elements that overflow the master element's size should be detected.
TEST_F(MasterParserTest,ChildOverflow)93 TEST_F(MasterParserTest, ChildOverflow) {
94   SetReaderData({
95       0xEC,  // ID = 0xEC (Void).
96       0x82,  // Size = 2.
97       0x00, 0x00,  // Body.
98   });
99 
100   EXPECT_CALL(callback_, OnElementBegin(_, _)).Times(0);
101   EXPECT_CALL(callback_, OnVoid(_, _, _)).Times(0);
102 
103   ParseAndExpectResult(Status::kElementOverflow, reader_.size() - 1);
104 }
105 
106 // Child elements with an unknown size can't be naively checked to see if they
107 // overflow the master element's size. Make sure the overflow is still detected.
TEST_F(MasterParserTest,ChildOverflowWithUnknownSize)108 TEST_F(MasterParserTest, ChildOverflowWithUnknownSize) {
109   SetReaderData({
110       0xA1,  // ID = 0xA1 (Block) (master).
111       0xFF,  // Size = unknown.
112 
113       0xEC,  //   ID = 0xEC (Void) (child).
114       0x81,  //   Size = 1.
115       0x12,  //   Body.
116   });
117 
118   {
119     InSequence dummy;
120 
121     ElementMetadata metadata = {Id::kBlock, 2, kUnknownElementSize, 0};
122     EXPECT_CALL(callback_, OnElementBegin(metadata, NotNull())).Times(1);
123   }
124 
125   ResetParser(ParserForId(Id::kBlock, new MasterParser));
126 
127   ParseAndExpectResult(Status::kElementOverflow, 4);
128 }
129 
130 // An element with an unknown size should be terminated by its parents bounds.
TEST_F(MasterParserTest,ChildWithUnknownSizeBoundedByParentSize)131 TEST_F(MasterParserTest, ChildWithUnknownSizeBoundedByParentSize) {
132   SetReaderData({
133       0xA1,  // ID = 0xA1 (Block) (master).
134       0xFF,  // Size = unknown.
135 
136       0xEC,  //   ID = 0xEC (Void) (child).
137       0x81,  //   Size = 1.
138       0x12,  //   Body.
139 
140       0x00,  // Invalid ID. This should not be read.
141   });
142 
143   {
144     InSequence dummy;
145 
146     ElementMetadata metadata = {Id::kBlock, 2, kUnknownElementSize, 0};
147     EXPECT_CALL(callback_, OnElementBegin(metadata, NotNull())).Times(1);
148 
149     metadata = {Id::kVoid, 2, 1, 2};
150     EXPECT_CALL(callback_, OnElementBegin(metadata, NotNull())).Times(1);
151     EXPECT_CALL(callback_, OnVoid(metadata, NotNull(), NotNull())).Times(1);
152   }
153 
154   ResetParser(ParserForId(Id::kBlock, new MasterParser));
155 
156   ParseAndVerify(reader_.size() - 1);
157 }
158 
159 // An empty master element is okay.
TEST_F(MasterParserTest,Empty)160 TEST_F(MasterParserTest, Empty) {
161   EXPECT_CALL(callback_, OnElementBegin(_, _)).Times(0);
162 
163   ParseAndVerify();
164 }
165 
TEST_F(MasterParserTest,DefaultActionIsRead)166 TEST_F(MasterParserTest, DefaultActionIsRead) {
167   SetReaderData({
168       0xEC,  // ID = 0xEC (Void).
169       0x80,  // Size = 0.
170   });
171 
172   {
173     InSequence dummy;
174 
175     const ElementMetadata metadata = {Id::kVoid, 2, 0, 0};
176 
177     // This intentionally does not set the action and relies on the parser using
178     // a default action value of kRead.
179     EXPECT_CALL(callback_, OnElementBegin(metadata, NotNull()))
180         .WillOnce(Return(Status(Status::kOkCompleted)));
181     EXPECT_CALL(callback_, OnVoid(metadata, NotNull(), NotNull())).Times(1);
182   }
183 
184   ParseAndVerify();
185 }
186 
187 // Unrecognized children should be skipped over.
TEST_F(MasterParserTest,UnknownChildren)188 TEST_F(MasterParserTest, UnknownChildren) {
189   SetReaderData({
190       0x40, 0x00,  // ID = 0x4000 (unknown).
191       0x80,  // Size = 0.
192 
193       0x80,  // ID = 0x80 (unknown).
194       0x40, 0x00,  // Size = 0.
195   });
196 
197   EXPECT_CALL(callback_, OnVoid(_, _, _)).Times(0);
198   {
199     InSequence dummy;
200 
201     ElementMetadata metadata = {static_cast<Id>(0x4000), 3, 0, 0};
202     EXPECT_CALL(callback_, OnElementBegin(metadata, NotNull())).Times(1);
203 
204     metadata = {static_cast<Id>(0x80), 3, 0, 3};
205     EXPECT_CALL(callback_, OnElementBegin(metadata, NotNull())).Times(1);
206   }
207 
208   ParseAndVerify();
209 }
210 
211 // A master element with unknown size is terminated by the first element that is
212 // not a valid child.
TEST_F(MasterParserTest,UnknownSize)213 TEST_F(MasterParserTest, UnknownSize) {
214   SetReaderData({
215       // Void elements may appear anywhere in a master element and should not
216       // terminate the parse for a master element with an unknown size. In other
217       // words, they're always valid children.
218       0xEC,  // ID = 0xEC (Void).
219       0x81,  // Size = 1.
220       0x00,  // Body.
221 
222       // This element marks the end for the parser since this is the first
223       // unrecognized element. The ID and size should be read (which the parser
224       // uses to determine the end has been reached), but nothing more.
225       0x80,  // ID = 0x80 (unknown).
226       0x81,  // Size = 1.
227       0x12,  // Body.
228   });
229 
230   {
231     InSequence dummy;
232 
233     const ElementMetadata metadata = {Id::kVoid, 2, 1, 0};
234     EXPECT_CALL(callback_, OnElementBegin(metadata, NotNull())).Times(1);
235     EXPECT_CALL(callback_, OnVoid(metadata, NotNull(), NotNull())).Times(1);
236   }
237 
238   ParseAndVerify(kUnknownElementSize);
239 
240   EXPECT_EQ(static_cast<std::uint64_t>(5), reader_.Position());
241 }
242 
243 // Consecutive elements with unknown size should parse without issues, despite
244 // the internal parsers having to read ahead into the next (non-child) element.
TEST_F(MasterParserTest,MultipleUnknownChildSize)245 TEST_F(MasterParserTest, MultipleUnknownChildSize) {
246   SetReaderData({
247       0xA1,  // ID = 0xA1 (Block) (master).
248       0xFF,  // Size = unknown.
249 
250       0xEC,  //   ID = 0xEC (Void) (child).
251       0x81,  //   Size = 1.
252       0x12,  //   Body.
253 
254       0xA1,  // ID = 0xA1 (Block) (master).
255       0xFF,  // Size = unknown.
256 
257       0xEC,  //   ID = 0xEC (Void) (child).
258       0x81,  //   Size = 1.
259       0x13,  //   Body.
260   });
261 
262   {
263     InSequence dummy;
264 
265     ElementMetadata metadata = {Id::kBlock, 2, kUnknownElementSize, 0};
266     EXPECT_CALL(callback_, OnElementBegin(metadata, NotNull())).Times(1);
267 
268     metadata = {Id::kVoid, 2, 1, 2};
269     EXPECT_CALL(callback_, OnElementBegin(metadata, NotNull())).Times(1);
270     EXPECT_CALL(callback_, OnVoid(metadata, NotNull(), NotNull())).Times(1);
271 
272     metadata = {Id::kBlock, 2, kUnknownElementSize, 5};
273     EXPECT_CALL(callback_, OnElementBegin(metadata, NotNull())).Times(1);
274 
275     metadata = {Id::kVoid, 2, 1, 7};
276     EXPECT_CALL(callback_, OnElementBegin(metadata, NotNull())).Times(1);
277     EXPECT_CALL(callback_, OnVoid(metadata, NotNull(), NotNull())).Times(1);
278   }
279 
280   ResetParser(ParserForId(Id::kBlock, new MasterParser));
281 
282   ParseAndVerify();
283 }
284 
285 // Reaching the end of the file while reading an element with unknown size
286 // should return Status::kOkCompleted instead of Status::kEndOfFile.
TEST_F(MasterParserTest,UnknownSizeToFileEnd)287 TEST_F(MasterParserTest, UnknownSizeToFileEnd) {
288   SetReaderData({
289       0xEC,  // ID = 0xEC (Void).
290       0x81,  // Size = 1.
291       0x00,  // Body.
292   });
293 
294   {
295     InSequence dummy;
296 
297     const ElementMetadata metadata = {Id::kVoid, 2, 1, 0};
298     EXPECT_CALL(callback_, OnElementBegin(metadata, NotNull())).Times(1);
299     EXPECT_CALL(callback_, OnVoid(metadata, NotNull(), NotNull())).Times(1);
300   }
301 
302   ParseAndVerify();
303 }
304 
305 // Parsing one byte at a time is okay.
TEST_F(MasterParserTest,IncrementalParse)306 TEST_F(MasterParserTest, IncrementalParse) {
307   SetReaderData({
308       0x1A, 0x45, 0xDF, 0xA3,  // ID = 0x1A45DFA3 (EBML).
309       0x08, 0x00, 0x00, 0x00, 0x06,  // Size = 6.
310       0x01, 0x02, 0x03, 0x04, 0x05, 0x06,  // Body.
311   });
312 
313   const ElementMetadata metadata = {Id::kEbml, 9, 6, 0};
314   EXPECT_CALL(callback_, OnElementBegin(metadata, NotNull())).Times(1);
315 
316   BinaryParser* binary_parser = new BinaryParser;
317   ResetParser(ParserForId(Id::kEbml, binary_parser));
318 
319   IncrementalParseAndVerify();
320 
321   std::vector<std::uint8_t> expected = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06};
322   EXPECT_EQ(expected, binary_parser->value());
323 }
324 
325 // Alternating actions between skip and read is okay. The parser should remember
326 // the requested action between repeated calls to Feed.
TEST_F(MasterParserTest,IncrementalSkipThenReadThenSkip)327 TEST_F(MasterParserTest, IncrementalSkipThenReadThenSkip) {
328   SetReaderData({
329       0xA1,  // ID = 0xA1 (Block) (master).
330       0x83,  // Size = 3.
331 
332       0xEC,  //   ID = 0xEC (Void) (child).
333       0x81,  //   Size = 1.
334       0x12,  //   Body.
335 
336       0xA1,  // ID = 0xA1 (Block) (master).
337       0x83,  // Size = 3.
338 
339       0xEC,  //   ID = 0xEC (Void) (child).
340       0x81,  //   Size = 1.
341       0x13,  //   Body.
342 
343       0xA1,  // ID = 0xA1 (Block) (master).
344       0xFF,  // Size = unknown.
345 
346       0xEC,  //   ID = 0xEC (Void) (child).
347       0x81,  //   Size = 1.
348       0x14,  //   Body.
349   });
350 
351   {
352     InSequence dummy;
353 
354     ElementMetadata metadata = {Id::kBlock, 2, 3, 0};
355     EXPECT_CALL(callback_, OnElementBegin(metadata, NotNull()))
356         .WillOnce(Return(Status(Status::kOkPartial)))
357         .WillOnce(DoAll(SetArgPointee<1>(Action::kSkip),
358                         Return(Status(Status::kOkCompleted))));
359 
360     metadata = {Id::kBlock, 2, 3, 5};
361     EXPECT_CALL(callback_, OnElementBegin(metadata, NotNull())).Times(1);
362 
363     metadata = {Id::kVoid, 2, 1, 7};
364     EXPECT_CALL(callback_, OnElementBegin(metadata, NotNull())).Times(1);
365 
366     // Expect to get called twice because we'll cap the LimitedReader to 1-byte
367     // reads. The first attempt to read will fail because we'll have already
368     // reached the 1-byte max.
369     EXPECT_CALL(callback_, OnVoid(metadata, NotNull(), NotNull())).Times(2);
370 
371     metadata = {Id::kBlock, 2, kUnknownElementSize, 10};
372     EXPECT_CALL(callback_, OnElementBegin(metadata, NotNull()))
373         .WillOnce(DoAll(SetArgPointee<1>(Action::kSkip),
374                         Return(Status(Status::kOkCompleted))));
375   }
376 
377   ResetParser(ParserForId(Id::kBlock, new MasterParser));
378 
379   IncrementalParseAndVerify();
380 }
381 
382 }  // namespace
383