Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(123)

Side by Side Diff: source/libvpx/third_party/libwebm/mkvparser.cpp

Issue 1339513003: libvpx: Pull from upstream (Closed) Base URL: https://chromium.googlesource.com/chromium/deps/libvpx.git@master
Patch Set: Created 5 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright (c) 2012 The WebM project authors. All Rights Reserved. 1 // Copyright (c) 2012 The WebM project authors. All Rights Reserved.
2 // 2 //
3 // Use of this source code is governed by a BSD-style license 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 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 5 // tree. An additional intellectual property rights grant can be found
6 // in the file PATENTS. All contributing project authors may 6 // in the file PATENTS. All contributing project authors may
7 // be found in the AUTHORS file in the root of the source tree. 7 // be found in the AUTHORS file in the root of the source tree.
8 8
9 #include "mkvparser.hpp" 9 #include "mkvparser.hpp"
10
10 #include <cassert> 11 #include <cassert>
12 #include <climits>
13 #include <cmath>
11 #include <cstring> 14 #include <cstring>
12 #include <new> 15 #include <new>
13 #include <climits> 16
17 #include "webmids.hpp"
14 18
15 #ifdef _MSC_VER 19 #ifdef _MSC_VER
16 // Disable MSVC warnings that suggest making code non-portable. 20 // Disable MSVC warnings that suggest making code non-portable.
17 #pragma warning(disable : 4996) 21 #pragma warning(disable : 4996)
18 #endif 22 #endif
19 23
20 mkvparser::IMkvReader::~IMkvReader() {} 24 namespace mkvparser {
21 25
22 void mkvparser::GetVersion(int& major, int& minor, int& build, int& revision) { 26 IMkvReader::~IMkvReader() {}
27
28 template<typename Type> Type* SafeArrayAlloc(unsigned long long num_elements,
29 unsigned long long element_size) {
30 if (num_elements == 0 || element_size == 0)
31 return NULL;
32
33 const size_t kMaxAllocSize = 0x80000000; // 2GiB
34 const unsigned long long num_bytes = num_elements * element_size;
35 if (element_size > (kMaxAllocSize / num_elements))
36 return NULL;
37
38 return new (std::nothrow) Type[num_bytes];
39 }
40
41 void GetVersion(int& major, int& minor, int& build, int& revision) {
23 major = 1; 42 major = 1;
24 minor = 0; 43 minor = 0;
25 build = 0; 44 build = 0;
26 revision = 30; 45 revision = 30;
27 } 46 }
28 47
29 long long mkvparser::ReadUInt(IMkvReader* pReader, long long pos, long& len) { 48 long long ReadUInt(IMkvReader* pReader, long long pos, long& len) {
30 assert(pReader); 49 if (!pReader || pos < 0)
31 assert(pos >= 0); 50 return E_FILE_FORMAT_INVALID;
32
33 int status;
34
35 //#ifdef _DEBUG
36 // long long total, available;
37 // status = pReader->Length(&total, &available);
38 // assert(status >= 0);
39 // assert((total < 0) || (available <= total));
40 // assert(pos < available);
41 // assert((available - pos) >= 1); //assume here max u-int len is 8
42 //#endif
43 51
44 len = 1; 52 len = 1;
45
46 unsigned char b; 53 unsigned char b;
47 54 int status = pReader->Read(pos, 1, &b);
48 status = pReader->Read(pos, 1, &b);
49 55
50 if (status < 0) // error or underflow 56 if (status < 0) // error or underflow
51 return status; 57 return status;
52 58
53 if (status > 0) // interpreted as "underflow" 59 if (status > 0) // interpreted as "underflow"
54 return E_BUFFER_NOT_FULL; 60 return E_BUFFER_NOT_FULL;
55 61
56 if (b == 0) // we can't handle u-int values larger than 8 bytes 62 if (b == 0) // we can't handle u-int values larger than 8 bytes
57 return E_FILE_FORMAT_INVALID; 63 return E_FILE_FORMAT_INVALID;
58 64
59 unsigned char m = 0x80; 65 unsigned char m = 0x80;
60 66
61 while (!(b & m)) { 67 while (!(b & m)) {
62 m >>= 1; 68 m >>= 1;
63 ++len; 69 ++len;
64 } 70 }
65 71
66 //#ifdef _DEBUG
67 // assert((available - pos) >= len);
68 //#endif
69
70 long long result = b & (~m); 72 long long result = b & (~m);
71 ++pos; 73 ++pos;
72 74
73 for (int i = 1; i < len; ++i) { 75 for (int i = 1; i < len; ++i) {
74 status = pReader->Read(pos, 1, &b); 76 status = pReader->Read(pos, 1, &b);
75 77
76 if (status < 0) { 78 if (status < 0) {
77 len = 1; 79 len = 1;
78 return status; 80 return status;
79 } 81 }
80 82
81 if (status > 0) { 83 if (status > 0) {
82 len = 1; 84 len = 1;
83 return E_BUFFER_NOT_FULL; 85 return E_BUFFER_NOT_FULL;
84 } 86 }
85 87
86 result <<= 8; 88 result <<= 8;
87 result |= b; 89 result |= b;
88 90
89 ++pos; 91 ++pos;
90 } 92 }
91 93
92 return result; 94 return result;
93 } 95 }
94 96
95 long long mkvparser::GetUIntLength(IMkvReader* pReader, long long pos, 97 // Reads an EBML ID and returns it.
96 long& len) { 98 // An ID must at least 1 byte long, cannot exceed 4, and its value must be
97 assert(pReader); 99 // greater than 0.
98 assert(pos >= 0); 100 // See known EBML values and EBMLMaxIDLength:
101 // http://www.matroska.org/technical/specs/index.html
102 // Returns the ID, or a value less than 0 to report an error while reading the
103 // ID.
104 long long ReadID(IMkvReader* pReader, long long pos, long& len) {
105 if (pReader == NULL || pos < 0)
106 return E_FILE_FORMAT_INVALID;
107
108 // Read the first byte. The length in bytes of the ID is determined by
109 // finding the first set bit in the first byte of the ID.
110 unsigned char temp_byte = 0;
111 int read_status = pReader->Read(pos, 1, &temp_byte);
112
113 if (read_status < 0)
114 return E_FILE_FORMAT_INVALID;
115 else if (read_status > 0) // No data to read.
116 return E_BUFFER_NOT_FULL;
117
118 if (temp_byte == 0) // ID length > 8 bytes; invalid file.
119 return E_FILE_FORMAT_INVALID;
120
121 int bit_pos = 0;
122 const int kMaxIdLengthInBytes = 4;
123 const int kCheckByte = 0x80;
124
125 // Find the first bit that's set.
126 bool found_bit = false;
127 for (; bit_pos < kMaxIdLengthInBytes; ++bit_pos) {
128 if ((kCheckByte >> bit_pos) & temp_byte) {
129 found_bit = true;
130 break;
131 }
132 }
133
134 if (!found_bit) {
135 // The value is too large to be a valid ID.
136 return E_FILE_FORMAT_INVALID;
137 }
138
139 // Read the remaining bytes of the ID (if any).
140 const int id_length = bit_pos + 1;
141 long long ebml_id = temp_byte;
142 for (int i = 1; i < id_length; ++i) {
143 ebml_id <<= 8;
144 read_status = pReader->Read(pos + i, 1, &temp_byte);
145
146 if (read_status < 0)
147 return E_FILE_FORMAT_INVALID;
148 else if (read_status > 0)
149 return E_BUFFER_NOT_FULL;
150
151 ebml_id |= temp_byte;
152 }
153
154 len = id_length;
155 return ebml_id;
156 }
157
158 long long GetUIntLength(IMkvReader* pReader, long long pos, long& len) {
159 if (!pReader || pos < 0)
160 return E_FILE_FORMAT_INVALID;
99 161
100 long long total, available; 162 long long total, available;
101 163
102 int status = pReader->Length(&total, &available); 164 int status = pReader->Length(&total, &available);
103 assert(status >= 0); 165 if (status < 0 || (total >= 0 && available > total))
104 assert((total < 0) || (available <= total)); 166 return E_FILE_FORMAT_INVALID;
105 167
106 len = 1; 168 len = 1;
107 169
108 if (pos >= available) 170 if (pos >= available)
109 return pos; // too few bytes available 171 return pos; // too few bytes available
110 172
111 unsigned char b; 173 unsigned char b;
112 174
113 status = pReader->Read(pos, 1, &b); 175 status = pReader->Read(pos, 1, &b);
114 176
115 if (status < 0) 177 if (status != 0)
116 return status; 178 return status;
117 179
118 assert(status == 0);
119
120 if (b == 0) // we can't handle u-int values larger than 8 bytes 180 if (b == 0) // we can't handle u-int values larger than 8 bytes
121 return E_FILE_FORMAT_INVALID; 181 return E_FILE_FORMAT_INVALID;
122 182
123 unsigned char m = 0x80; 183 unsigned char m = 0x80;
124 184
125 while (!(b & m)) { 185 while (!(b & m)) {
126 m >>= 1; 186 m >>= 1;
127 ++len; 187 ++len;
128 } 188 }
129 189
130 return 0; // success 190 return 0; // success
131 } 191 }
132 192
133 // TODO(vigneshv): This function assumes that unsigned values never have their 193 // TODO(vigneshv): This function assumes that unsigned values never have their
134 // high bit set. 194 // high bit set.
135 long long mkvparser::UnserializeUInt(IMkvReader* pReader, long long pos, 195 long long UnserializeUInt(IMkvReader* pReader, long long pos, long long size) {
136 long long size) { 196 if (!pReader || pos < 0 || (size <= 0) || (size > 8))
137 assert(pReader);
138 assert(pos >= 0);
139
140 if ((size <= 0) || (size > 8))
141 return E_FILE_FORMAT_INVALID; 197 return E_FILE_FORMAT_INVALID;
142 198
143 long long result = 0; 199 long long result = 0;
144 200
145 for (long long i = 0; i < size; ++i) { 201 for (long long i = 0; i < size; ++i) {
146 unsigned char b; 202 unsigned char b;
147 203
148 const long status = pReader->Read(pos, 1, &b); 204 const long status = pReader->Read(pos, 1, &b);
149 205
150 if (status < 0) 206 if (status < 0)
151 return status; 207 return status;
152 208
153 result <<= 8; 209 result <<= 8;
154 result |= b; 210 result |= b;
155 211
156 ++pos; 212 ++pos;
157 } 213 }
158 214
159 return result; 215 return result;
160 } 216 }
161 217
162 long mkvparser::UnserializeFloat(IMkvReader* pReader, long long pos, 218 long UnserializeFloat(IMkvReader* pReader, long long pos, long long size_,
163 long long size_, double& result) { 219 double& result) {
164 assert(pReader); 220 if (!pReader || pos < 0 || ((size_ != 4) && (size_ != 8)))
165 assert(pos >= 0);
166
167 if ((size_ != 4) && (size_ != 8))
168 return E_FILE_FORMAT_INVALID; 221 return E_FILE_FORMAT_INVALID;
169 222
170 const long size = static_cast<long>(size_); 223 const long size = static_cast<long>(size_);
171 224
172 unsigned char buf[8]; 225 unsigned char buf[8];
173 226
174 const int status = pReader->Read(pos, size, buf); 227 const int status = pReader->Read(pos, size, buf);
175 228
176 if (status < 0) // error 229 if (status < 0) // error
177 return status; 230 return status;
(...skipping 10 matching lines...) Expand all
188 ff |= buf[i]; 241 ff |= buf[i];
189 242
190 if (++i >= 4) 243 if (++i >= 4)
191 break; 244 break;
192 245
193 ff <<= 8; 246 ff <<= 8;
194 } 247 }
195 248
196 result = f; 249 result = f;
197 } else { 250 } else {
198 assert(size == 8);
199
200 union { 251 union {
201 double d; 252 double d;
202 unsigned long long dd; 253 unsigned long long dd;
203 }; 254 };
204 255
205 dd = 0; 256 dd = 0;
206 257
207 for (int i = 0;;) { 258 for (int i = 0;;) {
208 dd |= buf[i]; 259 dd |= buf[i];
209 260
210 if (++i >= 8) 261 if (++i >= 8)
211 break; 262 break;
212 263
213 dd <<= 8; 264 dd <<= 8;
214 } 265 }
215 266
216 result = d; 267 result = d;
217 } 268 }
218 269
270 if (std::isinf(result) || std::isnan(result))
271 return E_FILE_FORMAT_INVALID;
272
219 return 0; 273 return 0;
220 } 274 }
221 275
222 long mkvparser::UnserializeInt(IMkvReader* pReader, long long pos, 276 long UnserializeInt(IMkvReader* pReader, long long pos, long long size,
223 long long size, long long& result) { 277 long long& result_ref) {
224 assert(pReader); 278 if (!pReader || pos < 0 || size < 1 || size > 8)
225 assert(pos >= 0); 279 return E_FILE_FORMAT_INVALID;
226 assert(size > 0);
227 assert(size <= 8);
228 280
229 { 281 signed char first_byte = 0;
230 signed char b; 282 const long status = pReader->Read(pos, 1, (unsigned char*)&first_byte);
231 283
232 const long status = pReader->Read(pos, 1, (unsigned char*)&b); 284 if (status < 0)
285 return status;
233 286
234 if (status < 0) 287 unsigned long long result = first_byte;
235 return status; 288 ++pos;
236
237 result = b;
238
239 ++pos;
240 }
241 289
242 for (long i = 1; i < size; ++i) { 290 for (long i = 1; i < size; ++i) {
243 unsigned char b; 291 unsigned char b;
244 292
245 const long status = pReader->Read(pos, 1, &b); 293 const long status = pReader->Read(pos, 1, &b);
246 294
247 if (status < 0) 295 if (status < 0)
248 return status; 296 return status;
249 297
250 result <<= 8; 298 result <<= 8;
251 result |= b; 299 result |= b;
252 300
253 ++pos; 301 ++pos;
254 } 302 }
255 303
256 return 0; // success 304 result_ref = static_cast<long long>(result);
305 return 0;
257 } 306 }
258 307
259 long mkvparser::UnserializeString(IMkvReader* pReader, long long pos, 308 long UnserializeString(IMkvReader* pReader, long long pos, long long size,
260 long long size_, char*& str) { 309 char*& str) {
261 delete[] str; 310 delete[] str;
262 str = NULL; 311 str = NULL;
263 312
264 if (size_ >= LONG_MAX) // we need (size+1) chars 313 if (size >= LONG_MAX || size < 0)
265 return E_FILE_FORMAT_INVALID; 314 return E_FILE_FORMAT_INVALID;
266 315
267 const long size = static_cast<long>(size_); 316 // +1 for '\0' terminator
317 const long required_size = static_cast<long>(size) + 1;
268 318
269 str = new (std::nothrow) char[size + 1]; 319 str = SafeArrayAlloc<char>(1, required_size);
270
271 if (str == NULL) 320 if (str == NULL)
272 return -1; 321 return E_FILE_FORMAT_INVALID;
273 322
274 unsigned char* const buf = reinterpret_cast<unsigned char*>(str); 323 unsigned char* const buf = reinterpret_cast<unsigned char*>(str);
275 324
276 const long status = pReader->Read(pos, size, buf); 325 const long status = pReader->Read(pos, size, buf);
277 326
278 if (status) { 327 if (status) {
279 delete[] str; 328 delete[] str;
280 str = NULL; 329 str = NULL;
281 330
282 return status; 331 return status;
283 } 332 }
284 333
285 str[size] = '\0'; 334 str[required_size - 1] = '\0';
286 335 return 0;
287 return 0; // success
288 } 336 }
289 337
290 long mkvparser::ParseElementHeader(IMkvReader* pReader, long long& pos, 338 long ParseElementHeader(IMkvReader* pReader, long long& pos,
291 long long stop, long long& id, 339 long long stop, long long& id,
292 long long& size) { 340 long long& size) {
293 if ((stop >= 0) && (pos >= stop)) 341 if (stop >= 0 && pos >= stop)
294 return E_FILE_FORMAT_INVALID; 342 return E_FILE_FORMAT_INVALID;
295 343
296 long len; 344 long len;
297 345
298 id = ReadUInt(pReader, pos, len); 346 id = ReadID(pReader, pos, len);
299 347
300 if (id < 0) 348 if (id < 0)
301 return E_FILE_FORMAT_INVALID; 349 return E_FILE_FORMAT_INVALID;
302 350
303 pos += len; // consume id 351 pos += len; // consume id
304 352
305 if ((stop >= 0) && (pos >= stop)) 353 if (stop >= 0 && pos >= stop)
306 return E_FILE_FORMAT_INVALID; 354 return E_FILE_FORMAT_INVALID;
307 355
308 size = ReadUInt(pReader, pos, len); 356 size = ReadUInt(pReader, pos, len);
309 357
310 if (size < 0) 358 if (size < 0 || len < 1 || len > 8) {
359 // Invalid: Negative payload size, negative or 0 length integer, or integer
360 // larger than 64 bits (libwebm cannot handle them).
361 return E_FILE_FORMAT_INVALID;
362 }
363
364 // Avoid rolling over pos when very close to LONG_LONG_MAX.
365 const unsigned long long rollover_check =
366 static_cast<unsigned long long>(pos) + len;
367 if (rollover_check > LONG_LONG_MAX)
311 return E_FILE_FORMAT_INVALID; 368 return E_FILE_FORMAT_INVALID;
312 369
313 pos += len; // consume length of size 370 pos += len; // consume length of size
314 371
315 // pos now designates payload 372 // pos now designates payload
316 373
317 if ((stop >= 0) && ((pos + size) > stop)) 374 if (stop >= 0 && pos >= stop)
318 return E_FILE_FORMAT_INVALID; 375 return E_FILE_FORMAT_INVALID;
319 376
320 return 0; // success 377 return 0; // success
321 } 378 }
322 379
323 bool mkvparser::Match(IMkvReader* pReader, long long& pos, unsigned long id_, 380 bool Match(IMkvReader* pReader, long long& pos, unsigned long expected_id,
324 long long& val) { 381 long long& val) {
325 assert(pReader); 382 if (!pReader || pos < 0)
326 assert(pos >= 0); 383 return false;
327 384
328 long long total, available; 385 long long total = 0;
386 long long available = 0;
329 387
330 const long status = pReader->Length(&total, &available); 388 const long status = pReader->Length(&total, &available);
331 assert(status >= 0); 389 if (status < 0 || (total >= 0 && available > total))
332 assert((total < 0) || (available <= total));
333 if (status < 0)
334 return false; 390 return false;
335 391
336 long len; 392 long len = 0;
337 393
338 const long long id = ReadUInt(pReader, pos, len); 394 const long long id = ReadID(pReader, pos, len);
339 assert(id >= 0); 395 if (id < 0 || (available - pos) > len)
340 assert(len > 0); 396 return false;
341 assert(len <= 8);
342 assert((pos + len) <= available);
343 397
344 if ((unsigned long)id != id_) 398 if (static_cast<unsigned long>(id) != expected_id)
345 return false; 399 return false;
346 400
347 pos += len; // consume id 401 pos += len; // consume id
348 402
349 const long long size = ReadUInt(pReader, pos, len); 403 const long long size = ReadUInt(pReader, pos, len);
350 assert(size >= 0); 404 if (size < 0 || size > 8 || len < 1 || len > 8 || (available - pos) > len)
351 assert(size <= 8); 405 return false;
352 assert(len > 0);
353 assert(len <= 8);
354 assert((pos + len) <= available);
355 406
356 pos += len; // consume length of size of payload 407 pos += len; // consume length of size of payload
357 408
358 val = UnserializeUInt(pReader, pos, size); 409 val = UnserializeUInt(pReader, pos, size);
359 assert(val >= 0); 410 if (val < 0)
411 return false;
360 412
361 pos += size; // consume size of payload 413 pos += size; // consume size of payload
362 414
363 return true; 415 return true;
364 } 416 }
365 417
366 bool mkvparser::Match(IMkvReader* pReader, long long& pos, unsigned long id_, 418 bool Match(IMkvReader* pReader, long long& pos, unsigned long expected_id,
367 unsigned char*& buf, size_t& buflen) { 419 unsigned char*& buf, size_t& buflen) {
368 assert(pReader); 420 if (!pReader || pos < 0)
369 assert(pos >= 0); 421 return false;
370 422
371 long long total, available; 423 long long total = 0;
424 long long available = 0;
372 425
373 long status = pReader->Length(&total, &available); 426 long status = pReader->Length(&total, &available);
374 assert(status >= 0); 427 if (status < 0 || (total >= 0 && available > total))
375 assert((total < 0) || (available <= total));
376 if (status < 0)
377 return false; 428 return false;
378 429
379 long len; 430 long len = 0;
380 const long long id = ReadUInt(pReader, pos, len); 431 const long long id = ReadID(pReader, pos, len);
381 assert(id >= 0); 432 if (id < 0 || (available - pos) > len)
382 assert(len > 0); 433 return false;
383 assert(len <= 8);
384 assert((pos + len) <= available);
385 434
386 if ((unsigned long)id != id_) 435 if (static_cast<unsigned long>(id) != expected_id)
387 return false; 436 return false;
388 437
389 pos += len; // consume id 438 pos += len; // consume id
390 439
391 const long long size_ = ReadUInt(pReader, pos, len); 440 const long long size = ReadUInt(pReader, pos, len);
392 assert(size_ >= 0); 441 if (size < 0 || len <= 0 || len > 8 || (available - pos) > len)
393 assert(len > 0); 442 return false;
394 assert(len <= 8); 443
395 assert((pos + len) <= available); 444 unsigned long long rollover_check =
445 static_cast<unsigned long long>(pos) + len;
446 if (rollover_check > LONG_LONG_MAX)
447 return false;
396 448
397 pos += len; // consume length of size of payload 449 pos += len; // consume length of size of payload
398 assert((pos + size_) <= available);
399 450
400 const long buflen_ = static_cast<long>(size_); 451 rollover_check = static_cast<unsigned long long>(pos) + size;
452 if (rollover_check > LONG_LONG_MAX)
453 return false;
401 454
402 buf = new (std::nothrow) unsigned char[buflen_]; 455 if ((pos + size) > available)
403 assert(buf); // TODO 456 return false;
457
458 if (size >= LONG_MAX)
459 return false;
460
461 const long buflen_ = static_cast<long>(size);
462
463 buf = SafeArrayAlloc<unsigned char>(1, buflen_);
464 if (!buf)
465 return false;
404 466
405 status = pReader->Read(pos, buflen_, buf); 467 status = pReader->Read(pos, buflen_, buf);
406 assert(status == 0); // TODO 468 if (status != 0)
469 return false;
407 470
408 buflen = buflen_; 471 buflen = buflen_;
409 472
410 pos += size_; // consume size of payload 473 pos += size; // consume size of payload
411 return true; 474 return true;
412 } 475 }
413 476
414 namespace mkvparser {
415
416 EBMLHeader::EBMLHeader() : m_docType(NULL) { Init(); } 477 EBMLHeader::EBMLHeader() : m_docType(NULL) { Init(); }
417 478
418 EBMLHeader::~EBMLHeader() { delete[] m_docType; } 479 EBMLHeader::~EBMLHeader() { delete[] m_docType; }
419 480
420 void EBMLHeader::Init() { 481 void EBMLHeader::Init() {
421 m_version = 1; 482 m_version = 1;
422 m_readVersion = 1; 483 m_readVersion = 1;
423 m_maxIdLength = 4; 484 m_maxIdLength = 4;
424 m_maxSizeLength = 8; 485 m_maxSizeLength = 8;
425 486
426 if (m_docType) { 487 if (m_docType) {
427 delete[] m_docType; 488 delete[] m_docType;
428 m_docType = NULL; 489 m_docType = NULL;
429 } 490 }
430 491
431 m_docTypeVersion = 1; 492 m_docTypeVersion = 1;
432 m_docTypeReadVersion = 1; 493 m_docTypeReadVersion = 1;
433 } 494 }
434 495
435 long long EBMLHeader::Parse(IMkvReader* pReader, long long& pos) { 496 long long EBMLHeader::Parse(IMkvReader* pReader, long long& pos) {
436 assert(pReader); 497 if (!pReader)
498 return E_FILE_FORMAT_INVALID;
437 499
438 long long total, available; 500 long long total, available;
439 501
440 long status = pReader->Length(&total, &available); 502 long status = pReader->Length(&total, &available);
441 503
442 if (status < 0) // error 504 if (status < 0) // error
443 return status; 505 return status;
444 506
445 pos = 0; 507 pos = 0;
446 long long end = (available >= 1024) ? 1024 : available; 508 long long end = (available >= 1024) ? 1024 : available;
447 509
448 for (;;) { 510 // Scan until we find what looks like the first byte of the EBML header.
449 unsigned char b = 0; 511 const int kMaxScanBytes = (available >= 1024) ? 1024 : available;
512 const unsigned char kEbmlByte0 = 0x1A;
513 unsigned char scan_byte = 0;
450 514
451 while (pos < end) { 515 while (pos < kMaxScanBytes) {
452 status = pReader->Read(pos, 1, &b); 516 status = pReader->Read(pos, 1, &scan_byte);
453 517
454 if (status < 0) // error 518 if (status < 0) // error
455 return status; 519 return status;
520 else if (status > 0)
521 return E_BUFFER_NOT_FULL;
456 522
457 if (b == 0x1A) 523 if (scan_byte == kEbmlByte0)
458 break; 524 break;
459 525
460 ++pos; 526 ++pos;
461 }
462
463 if (b != 0x1A) {
464 if (pos >= 1024)
465 return E_FILE_FORMAT_INVALID; // don't bother looking anymore
466
467 if ((total >= 0) && ((total - available) < 5))
468 return E_FILE_FORMAT_INVALID;
469
470 return available + 5; // 5 = 4-byte ID + 1st byte of size
471 }
472
473 if ((total >= 0) && ((total - pos) < 5))
474 return E_FILE_FORMAT_INVALID;
475
476 if ((available - pos) < 5)
477 return pos + 5; // try again later
478
479 long len;
480
481 const long long result = ReadUInt(pReader, pos, len);
482
483 if (result < 0) // error
484 return result;
485
486 if (result == 0x0A45DFA3) { // EBML Header ID
487 pos += len; // consume ID
488 break;
489 }
490
491 ++pos; // throw away just the 0x1A byte, and try again
492 } 527 }
493 528
494 // pos designates start of size field 529 long len = 0;
530 const long long ebml_id = ReadID(pReader, pos, len);
495 531
496 // get length of size field 532 // TODO(tomfinegan): Move Matroska ID constants into a common namespace.
533 if (len != 4 || ebml_id != mkvmuxer::kMkvEBML)
534 return E_FILE_FORMAT_INVALID;
497 535
498 long len; 536 // Move read pos forward to the EBML header size field.
537 pos += 4;
538
539 // Read length of size field.
499 long long result = GetUIntLength(pReader, pos, len); 540 long long result = GetUIntLength(pReader, pos, len);
500 541
501 if (result < 0) // error 542 if (result < 0) // error
502 return result; 543 return E_FILE_FORMAT_INVALID;
544 else if (result > 0) // need more data
545 return E_BUFFER_NOT_FULL;
503 546
504 if (result > 0) // need more data 547 if (len < 1 || len > 8)
505 return result; 548 return E_FILE_FORMAT_INVALID;
506
507 assert(len > 0);
508 assert(len <= 8);
509 549
510 if ((total >= 0) && ((total - pos) < len)) 550 if ((total >= 0) && ((total - pos) < len))
511 return E_FILE_FORMAT_INVALID; 551 return E_FILE_FORMAT_INVALID;
512 552
513 if ((available - pos) < len) 553 if ((available - pos) < len)
514 return pos + len; // try again later 554 return pos + len; // try again later
515 555
516 // get the EBML header size 556 // Read the EBML header size.
517
518 result = ReadUInt(pReader, pos, len); 557 result = ReadUInt(pReader, pos, len);
519 558
520 if (result < 0) // error 559 if (result < 0) // error
521 return result; 560 return result;
522 561
523 pos += len; // consume size field 562 pos += len; // consume size field
524 563
525 // pos now designates start of payload 564 // pos now designates start of payload
526 565
527 if ((total >= 0) && ((total - pos) < result)) 566 if ((total >= 0) && ((total - pos) < result))
528 return E_FILE_FORMAT_INVALID; 567 return E_FILE_FORMAT_INVALID;
529 568
530 if ((available - pos) < result) 569 if ((available - pos) < result)
531 return pos + result; 570 return pos + result;
532 571
533 end = pos + result; 572 end = pos + result;
534 573
535 Init(); 574 Init();
536 575
537 while (pos < end) { 576 while (pos < end) {
538 long long id, size; 577 long long id, size;
539 578
540 status = ParseElementHeader(pReader, pos, end, id, size); 579 status = ParseElementHeader(pReader, pos, end, id, size);
541 580
542 if (status < 0) // error 581 if (status < 0) // error
543 return status; 582 return status;
544 583
545 if (size == 0) // weird 584 if (size == 0)
546 return E_FILE_FORMAT_INVALID; 585 return E_FILE_FORMAT_INVALID;
547 586
548 if (id == 0x0286) { // version 587 if (id == mkvmuxer::kMkvEBMLVersion) {
549 m_version = UnserializeUInt(pReader, pos, size); 588 m_version = UnserializeUInt(pReader, pos, size);
550 589
551 if (m_version <= 0) 590 if (m_version <= 0)
552 return E_FILE_FORMAT_INVALID; 591 return E_FILE_FORMAT_INVALID;
553 } else if (id == 0x02F7) { // read version 592 } else if (id == mkvmuxer::kMkvEBMLReadVersion) {
554 m_readVersion = UnserializeUInt(pReader, pos, size); 593 m_readVersion = UnserializeUInt(pReader, pos, size);
555 594
556 if (m_readVersion <= 0) 595 if (m_readVersion <= 0)
557 return E_FILE_FORMAT_INVALID; 596 return E_FILE_FORMAT_INVALID;
558 } else if (id == 0x02F2) { // max id length 597 } else if (id == mkvmuxer::kMkvEBMLMaxIDLength) {
559 m_maxIdLength = UnserializeUInt(pReader, pos, size); 598 m_maxIdLength = UnserializeUInt(pReader, pos, size);
560 599
561 if (m_maxIdLength <= 0) 600 if (m_maxIdLength <= 0)
562 return E_FILE_FORMAT_INVALID; 601 return E_FILE_FORMAT_INVALID;
563 } else if (id == 0x02F3) { // max size length 602 } else if (id == mkvmuxer::kMkvEBMLMaxSizeLength) {
564 m_maxSizeLength = UnserializeUInt(pReader, pos, size); 603 m_maxSizeLength = UnserializeUInt(pReader, pos, size);
565 604
566 if (m_maxSizeLength <= 0) 605 if (m_maxSizeLength <= 0)
567 return E_FILE_FORMAT_INVALID; 606 return E_FILE_FORMAT_INVALID;
568 } else if (id == 0x0282) { // doctype 607 } else if (id == mkvmuxer::kMkvDocType) {
569 if (m_docType) 608 if (m_docType)
570 return E_FILE_FORMAT_INVALID; 609 return E_FILE_FORMAT_INVALID;
571 610
572 status = UnserializeString(pReader, pos, size, m_docType); 611 status = UnserializeString(pReader, pos, size, m_docType);
573 612
574 if (status) // error 613 if (status) // error
575 return status; 614 return status;
576 } else if (id == 0x0287) { // doctype version 615 } else if (id == mkvmuxer::kMkvDocTypeVersion) {
577 m_docTypeVersion = UnserializeUInt(pReader, pos, size); 616 m_docTypeVersion = UnserializeUInt(pReader, pos, size);
578 617
579 if (m_docTypeVersion <= 0) 618 if (m_docTypeVersion <= 0)
580 return E_FILE_FORMAT_INVALID; 619 return E_FILE_FORMAT_INVALID;
581 } else if (id == 0x0285) { // doctype read version 620 } else if (id == mkvmuxer::kMkvDocTypeReadVersion) {
582 m_docTypeReadVersion = UnserializeUInt(pReader, pos, size); 621 m_docTypeReadVersion = UnserializeUInt(pReader, pos, size);
583 622
584 if (m_docTypeReadVersion <= 0) 623 if (m_docTypeReadVersion <= 0)
585 return E_FILE_FORMAT_INVALID; 624 return E_FILE_FORMAT_INVALID;
586 } 625 }
587 626
588 pos += size; 627 pos += size;
589 } 628 }
590 629
591 assert(pos == end); 630 if (pos != end)
631 return E_FILE_FORMAT_INVALID;
632
633 // Make sure DocType, DocTypeReadVersion, and DocTypeVersion are valid.
634 if (m_docType == NULL || m_docTypeReadVersion <= 0 || m_docTypeVersion <= 0)
635 return E_FILE_FORMAT_INVALID;
636
637 // Make sure EBMLMaxIDLength and EBMLMaxSizeLength are valid.
638 if (m_maxIdLength <= 0 || m_maxIdLength > 4 ||
639 m_maxSizeLength <= 0 || m_maxSizeLength > 8)
640 return E_FILE_FORMAT_INVALID;
641
592 return 0; 642 return 0;
593 } 643 }
594 644
595 Segment::Segment(IMkvReader* pReader, long long elem_start, 645 Segment::Segment(IMkvReader* pReader, long long elem_start,
596 // long long elem_size, 646 // long long elem_size,
597 long long start, long long size) 647 long long start, long long size)
598 : m_pReader(pReader), 648 : m_pReader(pReader),
599 m_element_start(elem_start), 649 m_element_start(elem_start),
600 // m_element_size(elem_size), 650 // m_element_size(elem_size),
601 m_start(start), 651 m_start(start),
(...skipping 12 matching lines...) Expand all
614 m_clusterSize(0) {} 664 m_clusterSize(0) {}
615 665
616 Segment::~Segment() { 666 Segment::~Segment() {
617 const long count = m_clusterCount + m_clusterPreloadCount; 667 const long count = m_clusterCount + m_clusterPreloadCount;
618 668
619 Cluster** i = m_clusters; 669 Cluster** i = m_clusters;
620 Cluster** j = m_clusters + count; 670 Cluster** j = m_clusters + count;
621 671
622 while (i != j) { 672 while (i != j) {
623 Cluster* const p = *i++; 673 Cluster* const p = *i++;
624 assert(p);
625
626 delete p; 674 delete p;
627 } 675 }
628 676
629 delete[] m_clusters; 677 delete[] m_clusters;
630 678
631 delete m_pTracks; 679 delete m_pTracks;
632 delete m_pInfo; 680 delete m_pInfo;
633 delete m_pCues; 681 delete m_pCues;
634 delete m_pChapters; 682 delete m_pChapters;
635 delete m_pTags; 683 delete m_pTags;
636 delete m_pSeekHead; 684 delete m_pSeekHead;
637 } 685 }
638 686
639 long long Segment::CreateInstance(IMkvReader* pReader, long long pos, 687 long long Segment::CreateInstance(IMkvReader* pReader, long long pos,
640 Segment*& pSegment) { 688 Segment*& pSegment) {
641 assert(pReader); 689 if (pReader == NULL || pos < 0)
642 assert(pos >= 0); 690 return E_PARSE_FAILED;
643 691
644 pSegment = NULL; 692 pSegment = NULL;
645 693
646 long long total, available; 694 long long total, available;
647 695
648 const long status = pReader->Length(&total, &available); 696 const long status = pReader->Length(&total, &available);
649 697
650 if (status < 0) // error 698 if (status < 0) // error
651 return status; 699 return status;
652 700
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
684 if (result) // error, or too few available bytes 732 if (result) // error, or too few available bytes
685 return result; 733 return result;
686 734
687 if ((total >= 0) && ((pos + len) > total)) 735 if ((total >= 0) && ((pos + len) > total))
688 return E_FILE_FORMAT_INVALID; 736 return E_FILE_FORMAT_INVALID;
689 737
690 if ((pos + len) > available) 738 if ((pos + len) > available)
691 return pos + len; 739 return pos + len;
692 740
693 const long long idpos = pos; 741 const long long idpos = pos;
694 const long long id = ReadUInt(pReader, pos, len); 742 const long long id = ReadID(pReader, pos, len);
695 743
696 if (id < 0) // error 744 if (id < 0)
697 return id; 745 return E_FILE_FORMAT_INVALID;
698 746
699 pos += len; // consume ID 747 pos += len; // consume ID
700 748
701 // Read Size 749 // Read Size
702 750
703 result = GetUIntLength(pReader, pos, len); 751 result = GetUIntLength(pReader, pos, len);
704 752
705 if (result) // error, or too few available bytes 753 if (result) // error, or too few available bytes
706 return result; 754 return result;
707 755
708 if ((total >= 0) && ((pos + len) > total)) 756 if ((total >= 0) && ((pos + len) > total))
709 return E_FILE_FORMAT_INVALID; 757 return E_FILE_FORMAT_INVALID;
710 758
711 if ((pos + len) > available) 759 if ((pos + len) > available)
712 return pos + len; 760 return pos + len;
713 761
714 long long size = ReadUInt(pReader, pos, len); 762 long long size = ReadUInt(pReader, pos, len);
715 763
716 if (size < 0) // error 764 if (size < 0) // error
717 return size; 765 return size;
718 766
719 pos += len; // consume length of size of element 767 pos += len; // consume length of size of element
720 768
721 // Pos now points to start of payload 769 // Pos now points to start of payload
722 770
723 // Handle "unknown size" for live streaming of webm files. 771 // Handle "unknown size" for live streaming of webm files.
724 const long long unknown_size = (1LL << (7 * len)) - 1; 772 const long long unknown_size = (1LL << (7 * len)) - 1;
725 773
726 if (id == 0x08538067) { // Segment ID 774 if (id == mkvmuxer::kMkvSegment) {
727 if (size == unknown_size) 775 if (size == unknown_size)
728 size = -1; 776 size = -1;
729 777
730 else if (total < 0) 778 else if (total < 0)
731 size = -1; 779 size = -1;
732 780
733 else if ((pos + size) > total) 781 else if ((pos + size) > total)
734 size = -1; 782 size = -1;
735 783
736 pSegment = new (std::nothrow) Segment(pReader, idpos, 784 pSegment = new (std::nothrow) Segment(pReader, idpos, pos, size);
737 // elem_size 785 if (pSegment == NULL)
738 pos, size); 786 return E_PARSE_FAILED;
739
740 if (pSegment == 0)
741 return -1; // generic error
742 787
743 return 0; // success 788 return 0; // success
744 } 789 }
745 790
746 if (size == unknown_size) 791 if (size == unknown_size)
747 return E_FILE_FORMAT_INVALID; 792 return E_FILE_FORMAT_INVALID;
748 793
749 if ((total >= 0) && ((pos + size) > total)) 794 if ((total >= 0) && ((pos + size) > total))
750 return E_FILE_FORMAT_INVALID; 795 return E_FILE_FORMAT_INVALID;
751 796
752 if ((pos + size) > available) 797 if ((pos + size) > available)
753 return pos + size; 798 return pos + size;
754 799
755 pos += size; // consume payload 800 pos += size; // consume payload
756 } 801 }
757 } 802 }
758 803
759 long long Segment::ParseHeaders() { 804 long long Segment::ParseHeaders() {
760 // Outermost (level 0) segment object has been constructed, 805 // Outermost (level 0) segment object has been constructed,
761 // and pos designates start of payload. We need to find the 806 // and pos designates start of payload. We need to find the
762 // inner (level 1) elements. 807 // inner (level 1) elements.
763 long long total, available; 808 long long total, available;
764 809
765 const int status = m_pReader->Length(&total, &available); 810 const int status = m_pReader->Length(&total, &available);
766 811
767 if (status < 0) // error 812 if (status < 0) // error
768 return status; 813 return status;
769 814
770 assert((total < 0) || (available <= total)); 815 if (total > 0 && available > total)
816 return E_FILE_FORMAT_INVALID;
771 817
772 const long long segment_stop = (m_size < 0) ? -1 : m_start + m_size; 818 const long long segment_stop = (m_size < 0) ? -1 : m_start + m_size;
773 assert((segment_stop < 0) || (total < 0) || (segment_stop <= total)); 819
774 assert((segment_stop < 0) || (m_pos <= segment_stop)); 820 if ((segment_stop >= 0 && total >= 0 && segment_stop > total) ||
821 (segment_stop >= 0 && m_pos > segment_stop)) {
822 return E_FILE_FORMAT_INVALID;
823 }
775 824
776 for (;;) { 825 for (;;) {
777 if ((total >= 0) && (m_pos >= total)) 826 if ((total >= 0) && (m_pos >= total))
778 break; 827 break;
779 828
780 if ((segment_stop >= 0) && (m_pos >= segment_stop)) 829 if ((segment_stop >= 0) && (m_pos >= segment_stop))
781 break; 830 break;
782 831
783 long long pos = m_pos; 832 long long pos = m_pos;
784 const long long element_start = pos; 833 const long long element_start = pos;
785 834
835 // Avoid rolling over pos when very close to LONG_LONG_MAX.
836 unsigned long long rollover_check = pos + 1ULL;
837 if (rollover_check > LONG_LONG_MAX)
838 return E_FILE_FORMAT_INVALID;
839
786 if ((pos + 1) > available) 840 if ((pos + 1) > available)
787 return (pos + 1); 841 return (pos + 1);
788 842
789 long len; 843 long len;
790 long long result = GetUIntLength(m_pReader, pos, len); 844 long long result = GetUIntLength(m_pReader, pos, len);
791 845
792 if (result < 0) // error 846 if (result < 0) // error
793 return result; 847 return result;
794 848
795 if (result > 0) // underflow (weird) 849 if (result > 0) {
850 // MkvReader doesn't have enough data to satisfy this read attempt.
796 return (pos + 1); 851 return (pos + 1);
852 }
797 853
798 if ((segment_stop >= 0) && ((pos + len) > segment_stop)) 854 if ((segment_stop >= 0) && ((pos + len) > segment_stop))
799 return E_FILE_FORMAT_INVALID; 855 return E_FILE_FORMAT_INVALID;
800 856
801 if ((pos + len) > available) 857 if ((pos + len) > available)
802 return pos + len; 858 return pos + len;
803 859
804 const long long idpos = pos; 860 const long long idpos = pos;
805 const long long id = ReadUInt(m_pReader, idpos, len); 861 const long long id = ReadID(m_pReader, idpos, len);
806 862
807 if (id < 0) // error 863 if (id < 0)
808 return id; 864 return E_FILE_FORMAT_INVALID;
809 865
810 if (id == 0x0F43B675) // Cluster ID 866 if (id == mkvmuxer::kMkvCluster)
811 break; 867 break;
812 868
813 pos += len; // consume ID 869 pos += len; // consume ID
814 870
815 if ((pos + 1) > available) 871 if ((pos + 1) > available)
816 return (pos + 1); 872 return (pos + 1);
817 873
818 // Read Size 874 // Read Size
819 result = GetUIntLength(m_pReader, pos, len); 875 result = GetUIntLength(m_pReader, pos, len);
820 876
821 if (result < 0) // error 877 if (result < 0) // error
822 return result; 878 return result;
823 879
824 if (result > 0) // underflow (weird) 880 if (result > 0) {
881 // MkvReader doesn't have enough data to satisfy this read attempt.
825 return (pos + 1); 882 return (pos + 1);
883 }
826 884
827 if ((segment_stop >= 0) && ((pos + len) > segment_stop)) 885 if ((segment_stop >= 0) && ((pos + len) > segment_stop))
828 return E_FILE_FORMAT_INVALID; 886 return E_FILE_FORMAT_INVALID;
829 887
830 if ((pos + len) > available) 888 if ((pos + len) > available)
831 return pos + len; 889 return pos + len;
832 890
833 const long long size = ReadUInt(m_pReader, pos, len); 891 const long long size = ReadUInt(m_pReader, pos, len);
834 892
835 if (size < 0) // error 893 if (size < 0 || len < 1 || len > 8) {
894 // TODO(tomfinegan): ReadUInt should return an error when len is < 1 or
895 // len > 8 is true instead of checking this _everywhere_.
836 return size; 896 return size;
897 }
837 898
838 pos += len; // consume length of size of element 899 pos += len; // consume length of size of element
839 900
901 // Avoid rolling over pos when very close to LONG_LONG_MAX.
902 rollover_check = static_cast<unsigned long long>(pos) + size;
903 if (rollover_check > LONG_LONG_MAX)
904 return E_FILE_FORMAT_INVALID;
905
840 const long long element_size = size + pos - element_start; 906 const long long element_size = size + pos - element_start;
841 907
842 // Pos now points to start of payload 908 // Pos now points to start of payload
843 909
844 if ((segment_stop >= 0) && ((pos + size) > segment_stop)) 910 if ((segment_stop >= 0) && ((pos + size) > segment_stop))
845 return E_FILE_FORMAT_INVALID; 911 return E_FILE_FORMAT_INVALID;
846 912
847 // We read EBML elements either in total or nothing at all. 913 // We read EBML elements either in total or nothing at all.
848 914
849 if ((pos + size) > available) 915 if ((pos + size) > available)
850 return pos + size; 916 return pos + size;
851 917
852 if (id == 0x0549A966) { // Segment Info ID 918 if (id == mkvmuxer::kMkvInfo) {
853 if (m_pInfo) 919 if (m_pInfo)
854 return E_FILE_FORMAT_INVALID; 920 return E_FILE_FORMAT_INVALID;
855 921
856 m_pInfo = new (std::nothrow) 922 m_pInfo = new (std::nothrow)
857 SegmentInfo(this, pos, size, element_start, element_size); 923 SegmentInfo(this, pos, size, element_start, element_size);
858 924
859 if (m_pInfo == NULL) 925 if (m_pInfo == NULL)
860 return -1; 926 return -1;
861 927
862 const long status = m_pInfo->Parse(); 928 const long status = m_pInfo->Parse();
863 929
864 if (status) 930 if (status)
865 return status; 931 return status;
866 } else if (id == 0x0654AE6B) { // Tracks ID 932 } else if (id == mkvmuxer::kMkvTracks) {
867 if (m_pTracks) 933 if (m_pTracks)
868 return E_FILE_FORMAT_INVALID; 934 return E_FILE_FORMAT_INVALID;
869 935
870 m_pTracks = new (std::nothrow) 936 m_pTracks = new (std::nothrow)
871 Tracks(this, pos, size, element_start, element_size); 937 Tracks(this, pos, size, element_start, element_size);
872 938
873 if (m_pTracks == NULL) 939 if (m_pTracks == NULL)
874 return -1; 940 return -1;
875 941
876 const long status = m_pTracks->Parse(); 942 const long status = m_pTracks->Parse();
877 943
878 if (status) 944 if (status)
879 return status; 945 return status;
880 } else if (id == 0x0C53BB6B) { // Cues ID 946 } else if (id == mkvmuxer::kMkvCues) {
881 if (m_pCues == NULL) { 947 if (m_pCues == NULL) {
882 m_pCues = new (std::nothrow) 948 m_pCues = new (std::nothrow)
883 Cues(this, pos, size, element_start, element_size); 949 Cues(this, pos, size, element_start, element_size);
884 950
885 if (m_pCues == NULL) 951 if (m_pCues == NULL)
886 return -1; 952 return -1;
887 } 953 }
888 } else if (id == 0x014D9B74) { // SeekHead ID 954 } else if (id == mkvmuxer::kMkvSeekHead) {
889 if (m_pSeekHead == NULL) { 955 if (m_pSeekHead == NULL) {
890 m_pSeekHead = new (std::nothrow) 956 m_pSeekHead = new (std::nothrow)
891 SeekHead(this, pos, size, element_start, element_size); 957 SeekHead(this, pos, size, element_start, element_size);
892 958
893 if (m_pSeekHead == NULL) 959 if (m_pSeekHead == NULL)
894 return -1; 960 return -1;
895 961
896 const long status = m_pSeekHead->Parse(); 962 const long status = m_pSeekHead->Parse();
897 963
898 if (status) 964 if (status)
899 return status; 965 return status;
900 } 966 }
901 } else if (id == 0x0043A770) { // Chapters ID 967 } else if (id == mkvmuxer::kMkvChapters) {
902 if (m_pChapters == NULL) { 968 if (m_pChapters == NULL) {
903 m_pChapters = new (std::nothrow) 969 m_pChapters = new (std::nothrow)
904 Chapters(this, pos, size, element_start, element_size); 970 Chapters(this, pos, size, element_start, element_size);
905 971
906 if (m_pChapters == NULL) 972 if (m_pChapters == NULL)
907 return -1; 973 return -1;
908 974
909 const long status = m_pChapters->Parse(); 975 const long status = m_pChapters->Parse();
910 976
911 if (status) 977 if (status)
912 return status; 978 return status;
913 } 979 }
914 } else if (id == 0x0254C367) { // Tags ID 980 } else if (id == mkvmuxer::kMkvTags) {
915 if (m_pTags == NULL) { 981 if (m_pTags == NULL) {
916 m_pTags = new (std::nothrow) 982 m_pTags = new (std::nothrow)
917 Tags(this, pos, size, element_start, element_size); 983 Tags(this, pos, size, element_start, element_size);
918 984
919 if (m_pTags == NULL) 985 if (m_pTags == NULL)
920 return -1; 986 return -1;
921 987
922 const long status = m_pTags->Parse(); 988 const long status = m_pTags->Parse();
923 989
924 if (status) 990 if (status)
925 return status; 991 return status;
926 } 992 }
927 } 993 }
928 994
929 m_pos = pos + size; // consume payload 995 m_pos = pos + size; // consume payload
930 } 996 }
931 997
932 assert((segment_stop < 0) || (m_pos <= segment_stop)); 998 if (segment_stop >= 0 && m_pos > segment_stop)
999 return E_FILE_FORMAT_INVALID;
933 1000
934 if (m_pInfo == NULL) // TODO: liberalize this behavior 1001 if (m_pInfo == NULL) // TODO: liberalize this behavior
935 return E_FILE_FORMAT_INVALID; 1002 return E_FILE_FORMAT_INVALID;
936 1003
937 if (m_pTracks == NULL) 1004 if (m_pTracks == NULL)
938 return E_FILE_FORMAT_INVALID; 1005 return E_FILE_FORMAT_INVALID;
939 1006
940 return 0; // success 1007 return 0; // success
941 } 1008 }
942 1009
(...skipping 10 matching lines...) Expand all
953 if (m_pos < 0) 1020 if (m_pos < 0)
954 return DoLoadClusterUnknownSize(pos, len); 1021 return DoLoadClusterUnknownSize(pos, len);
955 1022
956 long long total, avail; 1023 long long total, avail;
957 1024
958 long status = m_pReader->Length(&total, &avail); 1025 long status = m_pReader->Length(&total, &avail);
959 1026
960 if (status < 0) // error 1027 if (status < 0) // error
961 return status; 1028 return status;
962 1029
963 assert((total < 0) || (avail <= total)); 1030 if (total >= 0 && avail > total)
1031 return E_FILE_FORMAT_INVALID;
964 1032
965 const long long segment_stop = (m_size < 0) ? -1 : m_start + m_size; 1033 const long long segment_stop = (m_size < 0) ? -1 : m_start + m_size;
966 1034
967 long long cluster_off = -1; // offset relative to start of segment 1035 long long cluster_off = -1; // offset relative to start of segment
968 long long cluster_size = -1; // size of cluster payload 1036 long long cluster_size = -1; // size of cluster payload
969 1037
970 for (;;) { 1038 for (;;) {
971 if ((total >= 0) && (m_pos >= total)) 1039 if ((total >= 0) && (m_pos >= total))
972 return 1; // no more clusters 1040 return 1; // no more clusters
973 1041
974 if ((segment_stop >= 0) && (m_pos >= segment_stop)) 1042 if ((segment_stop >= 0) && (m_pos >= segment_stop))
975 return 1; // no more clusters 1043 return 1; // no more clusters
976 1044
977 pos = m_pos; 1045 pos = m_pos;
978 1046
979 // Read ID 1047 // Read ID
980 1048
981 if ((pos + 1) > avail) { 1049 if ((pos + 1) > avail) {
982 len = 1; 1050 len = 1;
983 return E_BUFFER_NOT_FULL; 1051 return E_BUFFER_NOT_FULL;
984 } 1052 }
985 1053
986 long long result = GetUIntLength(m_pReader, pos, len); 1054 long long result = GetUIntLength(m_pReader, pos, len);
987 1055
988 if (result < 0) // error 1056 if (result < 0) // error
989 return static_cast<long>(result); 1057 return static_cast<long>(result);
990 1058
991 if (result > 0) // weird 1059 if (result > 0)
992 return E_BUFFER_NOT_FULL; 1060 return E_BUFFER_NOT_FULL;
993 1061
994 if ((segment_stop >= 0) && ((pos + len) > segment_stop)) 1062 if ((segment_stop >= 0) && ((pos + len) > segment_stop))
995 return E_FILE_FORMAT_INVALID; 1063 return E_FILE_FORMAT_INVALID;
996 1064
997 if ((pos + len) > avail) 1065 if ((pos + len) > avail)
998 return E_BUFFER_NOT_FULL; 1066 return E_BUFFER_NOT_FULL;
999 1067
1000 const long long idpos = pos; 1068 const long long idpos = pos;
1001 const long long id = ReadUInt(m_pReader, idpos, len); 1069 const long long id = ReadID(m_pReader, idpos, len);
1002 1070
1003 if (id < 0) // error (or underflow) 1071 if (id < 0)
1004 return static_cast<long>(id); 1072 return E_FILE_FORMAT_INVALID;
1005 1073
1006 pos += len; // consume ID 1074 pos += len; // consume ID
1007 1075
1008 // Read Size 1076 // Read Size
1009 1077
1010 if ((pos + 1) > avail) { 1078 if ((pos + 1) > avail) {
1011 len = 1; 1079 len = 1;
1012 return E_BUFFER_NOT_FULL; 1080 return E_BUFFER_NOT_FULL;
1013 } 1081 }
1014 1082
1015 result = GetUIntLength(m_pReader, pos, len); 1083 result = GetUIntLength(m_pReader, pos, len);
1016 1084
1017 if (result < 0) // error 1085 if (result < 0) // error
1018 return static_cast<long>(result); 1086 return static_cast<long>(result);
1019 1087
1020 if (result > 0) // weird 1088 if (result > 0)
1021 return E_BUFFER_NOT_FULL; 1089 return E_BUFFER_NOT_FULL;
1022 1090
1023 if ((segment_stop >= 0) && ((pos + len) > segment_stop)) 1091 if ((segment_stop >= 0) && ((pos + len) > segment_stop))
1024 return E_FILE_FORMAT_INVALID; 1092 return E_FILE_FORMAT_INVALID;
1025 1093
1026 if ((pos + len) > avail) 1094 if ((pos + len) > avail)
1027 return E_BUFFER_NOT_FULL; 1095 return E_BUFFER_NOT_FULL;
1028 1096
1029 const long long size = ReadUInt(m_pReader, pos, len); 1097 const long long size = ReadUInt(m_pReader, pos, len);
1030 1098
1031 if (size < 0) // error 1099 if (size < 0) // error
1032 return static_cast<long>(size); 1100 return static_cast<long>(size);
1033 1101
1034 pos += len; // consume length of size of element 1102 pos += len; // consume length of size of element
1035 1103
1036 // pos now points to start of payload 1104 // pos now points to start of payload
1037 1105
1038 if (size == 0) { // weird 1106 if (size == 0) {
1107 // Missing element payload: move on.
1039 m_pos = pos; 1108 m_pos = pos;
1040 continue; 1109 continue;
1041 } 1110 }
1042 1111
1043 const long long unknown_size = (1LL << (7 * len)) - 1; 1112 const long long unknown_size = (1LL << (7 * len)) - 1;
1044 1113
1045 if ((segment_stop >= 0) && (size != unknown_size) && 1114 if ((segment_stop >= 0) && (size != unknown_size) &&
1046 ((pos + size) > segment_stop)) { 1115 ((pos + size) > segment_stop)) {
1047 return E_FILE_FORMAT_INVALID; 1116 return E_FILE_FORMAT_INVALID;
1048 } 1117 }
1049 1118
1050 if (id == 0x0C53BB6B) { // Cues ID 1119 if (id == mkvmuxer::kMkvCues) {
1051 if (size == unknown_size) 1120 if (size == unknown_size) {
1052 return E_FILE_FORMAT_INVALID; // TODO: liberalize 1121 // Cues element of unknown size: Not supported.
1122 return E_FILE_FORMAT_INVALID;
1123 }
1053 1124
1054 if (m_pCues == NULL) { 1125 if (m_pCues == NULL) {
1055 const long long element_size = (pos - idpos) + size; 1126 const long long element_size = (pos - idpos) + size;
1056 1127
1057 m_pCues = new Cues(this, pos, size, idpos, element_size); 1128 m_pCues = new (std::nothrow) Cues(this, pos, size, idpos, element_size);
1058 assert(m_pCues); // TODO 1129 if (m_pCues == NULL)
1130 return -1;
1059 } 1131 }
1060 1132
1061 m_pos = pos + size; // consume payload 1133 m_pos = pos + size; // consume payload
1062 continue; 1134 continue;
1063 } 1135 }
1064 1136
1065 if (id != 0x0F43B675) { // Cluster ID 1137 if (id != mkvmuxer::kMkvCluster) {
1138 // Besides the Segment, Libwebm allows only cluster elements of unknown
1139 // size. Fail the parse upon encountering a non-cluster element reporting
1140 // unknown size.
1066 if (size == unknown_size) 1141 if (size == unknown_size)
1067 return E_FILE_FORMAT_INVALID; // TODO: liberalize 1142 return E_FILE_FORMAT_INVALID;
1068 1143
1069 m_pos = pos + size; // consume payload 1144 m_pos = pos + size; // consume payload
1070 continue; 1145 continue;
1071 } 1146 }
1072 1147
1073 // We have a cluster. 1148 // We have a cluster.
1074 1149
1075 cluster_off = idpos - m_start; // relative pos 1150 cluster_off = idpos - m_start; // relative pos
1076 1151
1077 if (size != unknown_size) 1152 if (size != unknown_size)
1078 cluster_size = size; 1153 cluster_size = size;
1079 1154
1080 break; 1155 break;
1081 } 1156 }
1082 1157
1083 assert(cluster_off >= 0); // have cluster 1158 if (cluster_off < 0) {
1159 // No cluster, die.
1160 return E_FILE_FORMAT_INVALID;
1161 }
1084 1162
1085 long long pos_; 1163 long long pos_;
1086 long len_; 1164 long len_;
1087 1165
1088 status = Cluster::HasBlockEntries(this, cluster_off, pos_, len_); 1166 status = Cluster::HasBlockEntries(this, cluster_off, pos_, len_);
1089 1167
1090 if (status < 0) { // error, or underflow 1168 if (status < 0) { // error, or underflow
1091 pos = pos_; 1169 pos = pos_;
1092 len = len_; 1170 len = len_;
1093 1171
(...skipping 25 matching lines...) Expand all
1119 // 1197 //
1120 // The problem is that we're asserting in asyncreadinit, 1198 // The problem is that we're asserting in asyncreadinit,
1121 // because we adjust the pos down to the curr seek pos, 1199 // because we adjust the pos down to the curr seek pos,
1122 // and the resulting adjusted len is > 2GB. I'm suspicious 1200 // and the resulting adjusted len is > 2GB. I'm suspicious
1123 // that this is even correct, but even if it is, we can't 1201 // that this is even correct, but even if it is, we can't
1124 // be loading that much data in the cache anyway. 1202 // be loading that much data in the cache anyway.
1125 1203
1126 const long idx = m_clusterCount; 1204 const long idx = m_clusterCount;
1127 1205
1128 if (m_clusterPreloadCount > 0) { 1206 if (m_clusterPreloadCount > 0) {
1129 assert(idx < m_clusterSize); 1207 if (idx >= m_clusterSize)
1208 return E_FILE_FORMAT_INVALID;
1130 1209
1131 Cluster* const pCluster = m_clusters[idx]; 1210 Cluster* const pCluster = m_clusters[idx];
1132 assert(pCluster); 1211 if (pCluster == NULL || pCluster->m_index >= 0)
1133 assert(pCluster->m_index < 0); 1212 return E_FILE_FORMAT_INVALID;
1134 1213
1135 const long long off = pCluster->GetPosition(); 1214 const long long off = pCluster->GetPosition();
1136 assert(off >= 0); 1215 if (off < 0)
1216 return E_FILE_FORMAT_INVALID;
1137 1217
1138 if (off == cluster_off) { // preloaded already 1218 if (off == cluster_off) { // preloaded already
1139 if (status == 0) // no entries found 1219 if (status == 0) // no entries found
1140 return E_FILE_FORMAT_INVALID; 1220 return E_FILE_FORMAT_INVALID;
1141 1221
1142 if (cluster_size >= 0) 1222 if (cluster_size >= 0)
1143 pos += cluster_size; 1223 pos += cluster_size;
1144 else { 1224 else {
1145 const long long element_size = pCluster->GetElementSize(); 1225 const long long element_size = pCluster->GetElementSize();
1146 1226
1147 if (element_size <= 0) 1227 if (element_size <= 0)
1148 return E_FILE_FORMAT_INVALID; // TODO: handle this case 1228 return E_FILE_FORMAT_INVALID; // TODO: handle this case
1149 1229
1150 pos = pCluster->m_element_start + element_size; 1230 pos = pCluster->m_element_start + element_size;
1151 } 1231 }
1152 1232
1153 pCluster->m_index = idx; // move from preloaded to loaded 1233 pCluster->m_index = idx; // move from preloaded to loaded
1154 ++m_clusterCount; 1234 ++m_clusterCount;
1155 --m_clusterPreloadCount; 1235 --m_clusterPreloadCount;
1156 1236
1157 m_pos = pos; // consume payload 1237 m_pos = pos; // consume payload
1158 assert((segment_stop < 0) || (m_pos <= segment_stop)); 1238 if (segment_stop >= 0 && m_pos > segment_stop)
1239 return E_FILE_FORMAT_INVALID;
1159 1240
1160 return 0; // success 1241 return 0; // success
1161 } 1242 }
1162 } 1243 }
1163 1244
1164 if (status == 0) { // no entries found 1245 if (status == 0) { // no entries found
1165 if (cluster_size >= 0) 1246 if (cluster_size >= 0)
1166 pos += cluster_size; 1247 pos += cluster_size;
1167 1248
1168 if ((total >= 0) && (pos >= total)) { 1249 if ((total >= 0) && (pos >= total)) {
1169 m_pos = total; 1250 m_pos = total;
1170 return 1; // no more clusters 1251 return 1; // no more clusters
1171 } 1252 }
1172 1253
1173 if ((segment_stop >= 0) && (pos >= segment_stop)) { 1254 if ((segment_stop >= 0) && (pos >= segment_stop)) {
1174 m_pos = segment_stop; 1255 m_pos = segment_stop;
1175 return 1; // no more clusters 1256 return 1; // no more clusters
1176 } 1257 }
1177 1258
1178 m_pos = pos; 1259 m_pos = pos;
1179 return 2; // try again 1260 return 2; // try again
1180 } 1261 }
1181 1262
1182 // status > 0 means we have an entry 1263 // status > 0 means we have an entry
1183 1264
1184 Cluster* const pCluster = Cluster::Create(this, idx, cluster_off); 1265 Cluster* const pCluster = Cluster::Create(this, idx, cluster_off);
1185 // element_size); 1266 if (pCluster == NULL)
1186 assert(pCluster); 1267 return -1;
1187 1268
1188 AppendCluster(pCluster); 1269 if (!AppendCluster(pCluster)) {
1189 assert(m_clusters); 1270 delete pCluster;
1190 assert(idx < m_clusterSize); 1271 return -1;
1191 assert(m_clusters[idx] == pCluster); 1272 }
1192 1273
1193 if (cluster_size >= 0) { 1274 if (cluster_size >= 0) {
1194 pos += cluster_size; 1275 pos += cluster_size;
1195 1276
1196 m_pos = pos; 1277 m_pos = pos;
1197 assert((segment_stop < 0) || (m_pos <= segment_stop)); 1278
1279 if (segment_stop > 0 && m_pos > segment_stop)
1280 return E_FILE_FORMAT_INVALID;
1198 1281
1199 return 0; 1282 return 0;
1200 } 1283 }
1201 1284
1202 m_pUnknownSize = pCluster; 1285 m_pUnknownSize = pCluster;
1203 m_pos = -pos; 1286 m_pos = -pos;
1204 1287
1205 return 0; // partial success, since we have a new cluster 1288 return 0; // partial success, since we have a new cluster
1206 1289
1207 // status == 0 means "no block entries found" 1290 // status == 0 means "no block entries found"
1208 // pos designates start of payload 1291 // pos designates start of payload
1209 // m_pos has NOT been adjusted yet (in case we need to come back here) 1292 // m_pos has NOT been adjusted yet (in case we need to come back here)
1210 } 1293 }
1211 1294
1212 long Segment::DoLoadClusterUnknownSize(long long& pos, long& len) { 1295 long Segment::DoLoadClusterUnknownSize(long long& pos, long& len) {
1213 assert(m_pos < 0); 1296 if (m_pos >= 0 || m_pUnknownSize == NULL)
1214 assert(m_pUnknownSize); 1297 return E_PARSE_FAILED;
1215 1298
1216 const long status = m_pUnknownSize->Parse(pos, len); 1299 const long status = m_pUnknownSize->Parse(pos, len);
1217 1300
1218 if (status < 0) // error or underflow 1301 if (status < 0) // error or underflow
1219 return status; 1302 return status;
1220 1303
1221 if (status == 0) // parsed a block 1304 if (status == 0) // parsed a block
1222 return 2; // continue parsing 1305 return 2; // continue parsing
1223 1306
1224 assert(status > 0); // nothing left to parse of this cluster 1307 const long long start = m_pUnknownSize->m_element_start;
1308 const long long size = m_pUnknownSize->GetElementSize();
1225 1309
1226 const long long start = m_pUnknownSize->m_element_start; 1310 if (size < 0)
1227 1311 return E_FILE_FORMAT_INVALID;
1228 const long long size = m_pUnknownSize->GetElementSize();
1229 assert(size >= 0);
1230 1312
1231 pos = start + size; 1313 pos = start + size;
1232 m_pos = pos; 1314 m_pos = pos;
1233 1315
1234 m_pUnknownSize = 0; 1316 m_pUnknownSize = 0;
1235 1317
1236 return 2; // continue parsing 1318 return 2; // continue parsing
1237 } 1319 }
1238 1320
1239 void Segment::AppendCluster(Cluster* pCluster) { 1321 bool Segment::AppendCluster(Cluster* pCluster) {
1240 assert(pCluster); 1322 if (pCluster == NULL || pCluster->m_index < 0)
1241 assert(pCluster->m_index >= 0); 1323 return false;
1242 1324
1243 const long count = m_clusterCount + m_clusterPreloadCount; 1325 const long count = m_clusterCount + m_clusterPreloadCount;
1244 1326
1245 long& size = m_clusterSize; 1327 long& size = m_clusterSize;
1246 assert(size >= count); 1328 const long idx = pCluster->m_index;
1247 1329
1248 const long idx = pCluster->m_index; 1330 if (size < count || idx != m_clusterCount)
1249 assert(idx == m_clusterCount); 1331 return false;
1250 1332
1251 if (count >= size) { 1333 if (count >= size) {
1252 const long n = (size <= 0) ? 2048 : 2 * size; 1334 const long n = (size <= 0) ? 2048 : 2 * size;
1253 1335
1254 Cluster** const qq = new Cluster*[n]; 1336 Cluster** const qq = new (std::nothrow) Cluster*[n];
1337 if (qq == NULL)
1338 return false;
1339
1255 Cluster** q = qq; 1340 Cluster** q = qq;
1256
1257 Cluster** p = m_clusters; 1341 Cluster** p = m_clusters;
1258 Cluster** const pp = p + count; 1342 Cluster** const pp = p + count;
1259 1343
1260 while (p != pp) 1344 while (p != pp)
1261 *q++ = *p++; 1345 *q++ = *p++;
1262 1346
1263 delete[] m_clusters; 1347 delete[] m_clusters;
1264 1348
1265 m_clusters = qq; 1349 m_clusters = qq;
1266 size = n; 1350 size = n;
1267 } 1351 }
1268 1352
1269 if (m_clusterPreloadCount > 0) { 1353 if (m_clusterPreloadCount > 0) {
1270 assert(m_clusters);
1271
1272 Cluster** const p = m_clusters + m_clusterCount; 1354 Cluster** const p = m_clusters + m_clusterCount;
1273 assert(*p); 1355 if (*p == NULL || (*p)->m_index >= 0)
1274 assert((*p)->m_index < 0); 1356 return false;
1275 1357
1276 Cluster** q = p + m_clusterPreloadCount; 1358 Cluster** q = p + m_clusterPreloadCount;
1277 assert(q < (m_clusters + size)); 1359 if (q >= (m_clusters + size))
1360 return false;
1278 1361
1279 for (;;) { 1362 for (;;) {
1280 Cluster** const qq = q - 1; 1363 Cluster** const qq = q - 1;
1281 assert((*qq)->m_index < 0); 1364 if ((*qq)->m_index >= 0)
1365 return false;
1282 1366
1283 *q = *qq; 1367 *q = *qq;
1284 q = qq; 1368 q = qq;
1285 1369
1286 if (q == p) 1370 if (q == p)
1287 break; 1371 break;
1288 } 1372 }
1289 } 1373 }
1290 1374
1291 m_clusters[idx] = pCluster; 1375 m_clusters[idx] = pCluster;
1292 ++m_clusterCount; 1376 ++m_clusterCount;
1377 return true;
1293 } 1378 }
1294 1379
1295 void Segment::PreloadCluster(Cluster* pCluster, ptrdiff_t idx) { 1380 bool Segment::PreloadCluster(Cluster* pCluster, ptrdiff_t idx) {
1296 assert(pCluster); 1381 if (pCluster == NULL || pCluster->m_index >= 0 || idx < m_clusterCount)
1297 assert(pCluster->m_index < 0); 1382 return false;
1298 assert(idx >= m_clusterCount);
1299 1383
1300 const long count = m_clusterCount + m_clusterPreloadCount; 1384 const long count = m_clusterCount + m_clusterPreloadCount;
1301 1385
1302 long& size = m_clusterSize; 1386 long& size = m_clusterSize;
1303 assert(size >= count); 1387 if (size < count)
1388 return false;
1304 1389
1305 if (count >= size) { 1390 if (count >= size) {
1306 const long n = (size <= 0) ? 2048 : 2 * size; 1391 const long n = (size <= 0) ? 2048 : 2 * size;
1307 1392
1308 Cluster** const qq = new Cluster*[n]; 1393 Cluster** const qq = new (std::nothrow) Cluster*[n];
1394 if (qq == NULL)
1395 return false;
1309 Cluster** q = qq; 1396 Cluster** q = qq;
1310 1397
1311 Cluster** p = m_clusters; 1398 Cluster** p = m_clusters;
1312 Cluster** const pp = p + count; 1399 Cluster** const pp = p + count;
1313 1400
1314 while (p != pp) 1401 while (p != pp)
1315 *q++ = *p++; 1402 *q++ = *p++;
1316 1403
1317 delete[] m_clusters; 1404 delete[] m_clusters;
1318 1405
1319 m_clusters = qq; 1406 m_clusters = qq;
1320 size = n; 1407 size = n;
1321 } 1408 }
1322 1409
1323 assert(m_clusters); 1410 if (m_clusters == NULL)
1411 return false;
1324 1412
1325 Cluster** const p = m_clusters + idx; 1413 Cluster** const p = m_clusters + idx;
1326 1414
1327 Cluster** q = m_clusters + count; 1415 Cluster** q = m_clusters + count;
1328 assert(q >= p); 1416 if (q < p || q >= (m_clusters + size))
1329 assert(q < (m_clusters + size)); 1417 return false;
1330 1418
1331 while (q > p) { 1419 while (q > p) {
1332 Cluster** const qq = q - 1; 1420 Cluster** const qq = q - 1;
1333 assert((*qq)->m_index < 0); 1421
1422 if ((*qq)->m_index >= 0)
1423 return false;
1334 1424
1335 *q = *qq; 1425 *q = *qq;
1336 q = qq; 1426 q = qq;
1337 } 1427 }
1338 1428
1339 m_clusters[idx] = pCluster; 1429 m_clusters[idx] = pCluster;
1340 ++m_clusterPreloadCount; 1430 ++m_clusterPreloadCount;
1431 return true;
1341 } 1432 }
1342 1433
1343 long Segment::Load() { 1434 long Segment::Load() {
1344 assert(m_clusters == NULL); 1435 if (m_clusters != NULL || m_clusterSize != 0 || m_clusterCount != 0)
1345 assert(m_clusterSize == 0); 1436 return E_PARSE_FAILED;
1346 assert(m_clusterCount == 0);
1347 // assert(m_size >= 0);
1348 1437
1349 // Outermost (level 0) segment object has been constructed, 1438 // Outermost (level 0) segment object has been constructed,
1350 // and pos designates start of payload. We need to find the 1439 // and pos designates start of payload. We need to find the
1351 // inner (level 1) elements. 1440 // inner (level 1) elements.
1352 1441
1353 const long long header_status = ParseHeaders(); 1442 const long long header_status = ParseHeaders();
1354 1443
1355 if (header_status < 0) // error 1444 if (header_status < 0) // error
1356 return static_cast<long>(header_status); 1445 return static_cast<long>(header_status);
1357 1446
1358 if (header_status > 0) // underflow 1447 if (header_status > 0) // underflow
1359 return E_BUFFER_NOT_FULL; 1448 return E_BUFFER_NOT_FULL;
1360 1449
1361 assert(m_pInfo); 1450 if (m_pInfo == NULL || m_pTracks == NULL)
1362 assert(m_pTracks); 1451 return E_FILE_FORMAT_INVALID;
1363 1452
1364 for (;;) { 1453 for (;;) {
1365 const int status = LoadCluster(); 1454 const int status = LoadCluster();
1366 1455
1367 if (status < 0) // error 1456 if (status < 0) // error
1368 return status; 1457 return status;
1369 1458
1370 if (status >= 1) // no more clusters 1459 if (status >= 1) // no more clusters
1371 return 0; 1460 return 0;
1372 } 1461 }
(...skipping 28 matching lines...) Expand all
1401 int void_element_count = 0; 1490 int void_element_count = 0;
1402 1491
1403 while (pos < stop) { 1492 while (pos < stop) {
1404 long long id, size; 1493 long long id, size;
1405 1494
1406 const long status = ParseElementHeader(pReader, pos, stop, id, size); 1495 const long status = ParseElementHeader(pReader, pos, stop, id, size);
1407 1496
1408 if (status < 0) // error 1497 if (status < 0) // error
1409 return status; 1498 return status;
1410 1499
1411 if (id == 0x0DBB) // SeekEntry ID 1500 if (id == mkvmuxer::kMkvSeek)
1412 ++entry_count; 1501 ++entry_count;
1413 else if (id == 0x6C) // Void ID 1502 else if (id == mkvmuxer::kMkvVoid)
1414 ++void_element_count; 1503 ++void_element_count;
1415 1504
1416 pos += size; // consume payload 1505 pos += size; // consume payload
1417 assert(pos <= stop); 1506
1507 if (pos > stop)
1508 return E_FILE_FORMAT_INVALID;
1418 } 1509 }
1419 1510
1420 assert(pos == stop); 1511 if (pos != stop)
1512 return E_FILE_FORMAT_INVALID;
1421 1513
1422 m_entries = new (std::nothrow) Entry[entry_count]; 1514 m_entries = new (std::nothrow) Entry[entry_count];
1423 1515
1424 if (m_entries == NULL) 1516 if (m_entries == NULL)
1425 return -1; 1517 return -1;
1426 1518
1427 m_void_elements = new (std::nothrow) VoidElement[void_element_count]; 1519 m_void_elements = new (std::nothrow) VoidElement[void_element_count];
1428 1520
1429 if (m_void_elements == NULL) 1521 if (m_void_elements == NULL)
1430 return -1; 1522 return -1;
1431 1523
1432 // now parse the entries and void elements 1524 // now parse the entries and void elements
1433 1525
1434 Entry* pEntry = m_entries; 1526 Entry* pEntry = m_entries;
1435 VoidElement* pVoidElement = m_void_elements; 1527 VoidElement* pVoidElement = m_void_elements;
1436 1528
1437 pos = m_start; 1529 pos = m_start;
1438 1530
1439 while (pos < stop) { 1531 while (pos < stop) {
1440 const long long idpos = pos; 1532 const long long idpos = pos;
1441 1533
1442 long long id, size; 1534 long long id, size;
1443 1535
1444 const long status = ParseElementHeader(pReader, pos, stop, id, size); 1536 const long status = ParseElementHeader(pReader, pos, stop, id, size);
1445 1537
1446 if (status < 0) // error 1538 if (status < 0) // error
1447 return status; 1539 return status;
1448 1540
1449 if (id == 0x0DBB) { // SeekEntry ID 1541 if (id == mkvmuxer::kMkvSeek) {
1450 if (ParseEntry(pReader, pos, size, pEntry)) { 1542 if (ParseEntry(pReader, pos, size, pEntry)) {
1451 Entry& e = *pEntry++; 1543 Entry& e = *pEntry++;
1452 1544
1453 e.element_start = idpos; 1545 e.element_start = idpos;
1454 e.element_size = (pos + size) - idpos; 1546 e.element_size = (pos + size) - idpos;
1455 } 1547 }
1456 } else if (id == 0x6C) { // Void ID 1548 } else if (id == mkvmuxer::kMkvVoid) {
1457 VoidElement& e = *pVoidElement++; 1549 VoidElement& e = *pVoidElement++;
1458 1550
1459 e.element_start = idpos; 1551 e.element_start = idpos;
1460 e.element_size = (pos + size) - idpos; 1552 e.element_size = (pos + size) - idpos;
1461 } 1553 }
1462 1554
1463 pos += size; // consume payload 1555 pos += size; // consume payload
1464 assert(pos <= stop); 1556 if (pos > stop)
1557 return E_FILE_FORMAT_INVALID;
1465 } 1558 }
1466 1559
1467 assert(pos == stop); 1560 if (pos != stop)
1561 return E_FILE_FORMAT_INVALID;
1468 1562
1469 ptrdiff_t count_ = ptrdiff_t(pEntry - m_entries); 1563 ptrdiff_t count_ = ptrdiff_t(pEntry - m_entries);
1470 assert(count_ >= 0); 1564 assert(count_ >= 0);
1471 assert(count_ <= entry_count); 1565 assert(count_ <= entry_count);
1472 1566
1473 m_entry_count = static_cast<int>(count_); 1567 m_entry_count = static_cast<int>(count_);
1474 1568
1475 count_ = ptrdiff_t(pVoidElement - m_void_elements); 1569 count_ = ptrdiff_t(pVoidElement - m_void_elements);
1476 assert(count_ >= 0); 1570 assert(count_ >= 0);
1477 assert(count_ <= void_element_count); 1571 assert(count_ <= void_element_count);
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after
1546 } 1640 }
1547 1641
1548 if ((segment_stop >= 0) && ((pos + len) > segment_stop)) 1642 if ((segment_stop >= 0) && ((pos + len) > segment_stop))
1549 return E_FILE_FORMAT_INVALID; 1643 return E_FILE_FORMAT_INVALID;
1550 1644
1551 if ((pos + len) > avail) 1645 if ((pos + len) > avail)
1552 return E_BUFFER_NOT_FULL; 1646 return E_BUFFER_NOT_FULL;
1553 1647
1554 const long long idpos = pos; 1648 const long long idpos = pos;
1555 1649
1556 const long long id = ReadUInt(m_pReader, idpos, len); 1650 const long long id = ReadID(m_pReader, idpos, len);
1557 1651
1558 if (id != 0x0C53BB6B) // Cues ID 1652 if (id != mkvmuxer::kMkvCues)
1559 return E_FILE_FORMAT_INVALID; 1653 return E_FILE_FORMAT_INVALID;
1560 1654
1561 pos += len; // consume ID 1655 pos += len; // consume ID
1562 assert((segment_stop < 0) || (pos <= segment_stop)); 1656 assert((segment_stop < 0) || (pos <= segment_stop));
1563 1657
1564 // Read Size 1658 // Read Size
1565 1659
1566 if ((pos + 1) > avail) { 1660 if ((pos + 1) > avail) {
1567 len = 1; 1661 len = 1;
1568 return E_BUFFER_NOT_FULL; 1662 return E_BUFFER_NOT_FULL;
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
1608 1702
1609 len = static_cast<long>(size); 1703 len = static_cast<long>(size);
1610 1704
1611 if (element_stop > avail) 1705 if (element_stop > avail)
1612 return E_BUFFER_NOT_FULL; 1706 return E_BUFFER_NOT_FULL;
1613 1707
1614 const long long element_size = element_stop - element_start; 1708 const long long element_size = element_stop - element_start;
1615 1709
1616 m_pCues = 1710 m_pCues =
1617 new (std::nothrow) Cues(this, pos, size, element_start, element_size); 1711 new (std::nothrow) Cues(this, pos, size, element_start, element_size);
1618 assert(m_pCues); // TODO 1712 if (m_pCues == NULL)
1713 return -1;
1619 1714
1620 return 0; // success 1715 return 0; // success
1621 } 1716 }
1622 1717
1623 bool SeekHead::ParseEntry(IMkvReader* pReader, long long start, long long size_, 1718 bool SeekHead::ParseEntry(IMkvReader* pReader, long long start, long long size_,
1624 Entry* pEntry) { 1719 Entry* pEntry) {
1625 if (size_ <= 0) 1720 if (size_ <= 0)
1626 return false; 1721 return false;
1627 1722
1628 long long pos = start; 1723 long long pos = start;
1629 const long long stop = start + size_; 1724 const long long stop = start + size_;
1630 1725
1631 long len; 1726 long len;
1632 1727
1633 // parse the container for the level-1 element ID 1728 // parse the container for the level-1 element ID
1634 1729
1635 const long long seekIdId = ReadUInt(pReader, pos, len); 1730 const long long seekIdId = ReadID(pReader, pos, len);
1636 // seekIdId; 1731 if (seekIdId < 0)
1732 return false;
1637 1733
1638 if (seekIdId != 0x13AB) // SeekID ID 1734 if (seekIdId != mkvmuxer::kMkvSeekID)
1639 return false; 1735 return false;
1640 1736
1641 if ((pos + len) > stop) 1737 if ((pos + len) > stop)
1642 return false; 1738 return false;
1643 1739
1644 pos += len; // consume SeekID id 1740 pos += len; // consume SeekID id
1645 1741
1646 const long long seekIdSize = ReadUInt(pReader, pos, len); 1742 const long long seekIdSize = ReadUInt(pReader, pos, len);
1647 1743
1648 if (seekIdSize <= 0) 1744 if (seekIdSize <= 0)
(...skipping 21 matching lines...) Expand all
1670 pEntry->id = ReadUInt(pReader, pos, len); // payload 1766 pEntry->id = ReadUInt(pReader, pos, len); // payload
1671 1767
1672 if (pEntry->id <= 0) 1768 if (pEntry->id <= 0)
1673 return false; 1769 return false;
1674 1770
1675 if (len != seekIdSize) 1771 if (len != seekIdSize)
1676 return false; 1772 return false;
1677 1773
1678 pos += seekIdSize; // consume SeekID payload 1774 pos += seekIdSize; // consume SeekID payload
1679 1775
1680 const long long seekPosId = ReadUInt(pReader, pos, len); 1776 const long long seekPosId = ReadID(pReader, pos, len);
1681 1777
1682 if (seekPosId != 0x13AC) // SeekPos ID 1778 if (seekPosId != mkvmuxer::kMkvSeekPosition)
1683 return false; 1779 return false;
1684 1780
1685 if ((pos + len) > stop) 1781 if ((pos + len) > stop)
1686 return false; 1782 return false;
1687 1783
1688 pos += len; // consume id 1784 pos += len; // consume id
1689 1785
1690 const long long seekPosSize = ReadUInt(pReader, pos, len); 1786 const long long seekPosSize = ReadUInt(pReader, pos, len);
1691 1787
1692 if (seekPosSize <= 0) 1788 if (seekPosSize <= 0)
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
1750 1846
1751 bool Cues::DoneParsing() const { 1847 bool Cues::DoneParsing() const {
1752 const long long stop = m_start + m_size; 1848 const long long stop = m_start + m_size;
1753 return (m_pos >= stop); 1849 return (m_pos >= stop);
1754 } 1850 }
1755 1851
1756 bool Cues::Init() const { 1852 bool Cues::Init() const {
1757 if (m_cue_points) 1853 if (m_cue_points)
1758 return true; 1854 return true;
1759 1855
1760 assert(m_count == 0); 1856 if (m_count != 0 || m_preload_count != 0)
1761 assert(m_preload_count == 0); 1857 return false;
1762 1858
1763 IMkvReader* const pReader = m_pSegment->m_pReader; 1859 IMkvReader* const pReader = m_pSegment->m_pReader;
1764 1860
1765 const long long stop = m_start + m_size; 1861 const long long stop = m_start + m_size;
1766 long long pos = m_start; 1862 long long pos = m_start;
1767 1863
1768 long cue_points_size = 0; 1864 long cue_points_size = 0;
1769 1865
1770 while (pos < stop) { 1866 while (pos < stop) {
1771 const long long idpos = pos; 1867 const long long idpos = pos;
1772 1868
1773 long len; 1869 long len;
1774 1870
1775 const long long id = ReadUInt(pReader, pos, len); 1871 const long long id = ReadID(pReader, pos, len);
1776 if (id < 0 || (pos + len) > stop) { 1872 if (id < 0 || (pos + len) > stop) {
1777 return false; 1873 return false;
1778 } 1874 }
1779 1875
1780 pos += len; // consume ID 1876 pos += len; // consume ID
1781 1877
1782 const long long size = ReadUInt(pReader, pos, len); 1878 const long long size = ReadUInt(pReader, pos, len);
1783 if (size < 0 || (pos + len > stop)) { 1879 if (size < 0 || (pos + len > stop)) {
1784 return false; 1880 return false;
1785 } 1881 }
1786 1882
1787 pos += len; // consume Size field 1883 pos += len; // consume Size field
1788 if (pos + size > stop) { 1884 if (pos + size > stop) {
1789 return false; 1885 return false;
1790 } 1886 }
1791 1887
1792 if (id == 0x3B) // CuePoint ID 1888 if (id == mkvmuxer::kMkvCuePoint) {
1793 PreloadCuePoint(cue_points_size, idpos); 1889 if (!PreloadCuePoint(cue_points_size, idpos))
1890 return false;
1891 }
1794 1892
1795 pos += size; // skip payload 1893 pos += size; // skip payload
1796 } 1894 }
1797 return true; 1895 return true;
1798 } 1896 }
1799 1897
1800 void Cues::PreloadCuePoint(long& cue_points_size, long long pos) const { 1898 bool Cues::PreloadCuePoint(long& cue_points_size, long long pos) const {
1801 assert(m_count == 0); 1899 if (m_count != 0)
1900 return false;
1802 1901
1803 if (m_preload_count >= cue_points_size) { 1902 if (m_preload_count >= cue_points_size) {
1804 const long n = (cue_points_size <= 0) ? 2048 : 2 * cue_points_size; 1903 const long n = (cue_points_size <= 0) ? 2048 : 2 * cue_points_size;
1805 1904
1806 CuePoint** const qq = new CuePoint*[n]; 1905 CuePoint** const qq = new (std::nothrow) CuePoint*[n];
1906 if (qq == NULL)
1907 return false;
1908
1807 CuePoint** q = qq; // beginning of target 1909 CuePoint** q = qq; // beginning of target
1808 1910
1809 CuePoint** p = m_cue_points; // beginning of source 1911 CuePoint** p = m_cue_points; // beginning of source
1810 CuePoint** const pp = p + m_preload_count; // end of source 1912 CuePoint** const pp = p + m_preload_count; // end of source
1811 1913
1812 while (p != pp) 1914 while (p != pp)
1813 *q++ = *p++; 1915 *q++ = *p++;
1814 1916
1815 delete[] m_cue_points; 1917 delete[] m_cue_points;
1816 1918
1817 m_cue_points = qq; 1919 m_cue_points = qq;
1818 cue_points_size = n; 1920 cue_points_size = n;
1819 } 1921 }
1820 1922
1821 CuePoint* const pCP = new CuePoint(m_preload_count, pos); 1923 CuePoint* const pCP = new (std::nothrow) CuePoint(m_preload_count, pos);
1924 if (pCP == NULL)
1925 return false;
1926
1822 m_cue_points[m_preload_count++] = pCP; 1927 m_cue_points[m_preload_count++] = pCP;
1928 return true;
1823 } 1929 }
1824 1930
1825 bool Cues::LoadCuePoint() const { 1931 bool Cues::LoadCuePoint() const {
1826 // odbgstream os;
1827 // os << "Cues::LoadCuePoint" << endl;
1828
1829 const long long stop = m_start + m_size; 1932 const long long stop = m_start + m_size;
1830 1933
1831 if (m_pos >= stop) 1934 if (m_pos >= stop)
1832 return false; // nothing else to do 1935 return false; // nothing else to do
1833 1936
1834 if (!Init()) { 1937 if (!Init()) {
1835 m_pos = stop; 1938 m_pos = stop;
1836 return false; 1939 return false;
1837 } 1940 }
1838 1941
1839 IMkvReader* const pReader = m_pSegment->m_pReader; 1942 IMkvReader* const pReader = m_pSegment->m_pReader;
1840 1943
1841 while (m_pos < stop) { 1944 while (m_pos < stop) {
1842 const long long idpos = m_pos; 1945 const long long idpos = m_pos;
1843 1946
1844 long len; 1947 long len;
1845 1948
1846 const long long id = ReadUInt(pReader, m_pos, len); 1949 const long long id = ReadID(pReader, m_pos, len);
1847 assert(id >= 0); // TODO 1950 if (id < 0 || (m_pos + len) > stop)
1848 assert((m_pos + len) <= stop); 1951 return false;
1849 1952
1850 m_pos += len; // consume ID 1953 m_pos += len; // consume ID
1851 1954
1852 const long long size = ReadUInt(pReader, m_pos, len); 1955 const long long size = ReadUInt(pReader, m_pos, len);
1853 assert(size >= 0); 1956 if (size < 0 || (m_pos + len) > stop)
1854 assert((m_pos + len) <= stop); 1957 return false;
1855 1958
1856 m_pos += len; // consume Size field 1959 m_pos += len; // consume Size field
1857 assert((m_pos + size) <= stop); 1960 if ((m_pos + size) > stop)
1961 return false;
1858 1962
1859 if (id != 0x3B) { // CuePoint ID 1963 if (id != mkvmuxer::kMkvCuePoint) {
1860 m_pos += size; // consume payload 1964 m_pos += size; // consume payload
1861 assert(m_pos <= stop); 1965 if (m_pos > stop)
1966 return false;
1862 1967
1863 continue; 1968 continue;
1864 } 1969 }
1865 1970
1866 assert(m_preload_count > 0); 1971 if (m_preload_count < 1)
1972 return false;
1867 1973
1868 CuePoint* const pCP = m_cue_points[m_count]; 1974 CuePoint* const pCP = m_cue_points[m_count];
1869 assert(pCP); 1975 if (!pCP || (pCP->GetTimeCode() < 0 && (-pCP->GetTimeCode() != idpos)))
1870 assert((pCP->GetTimeCode() >= 0) || (-pCP->GetTimeCode() == idpos));
1871 if (pCP->GetTimeCode() < 0 && (-pCP->GetTimeCode() != idpos))
1872 return false; 1976 return false;
1873 1977
1874 if (!pCP->Load(pReader)) { 1978 if (!pCP->Load(pReader)) {
1875 m_pos = stop; 1979 m_pos = stop;
1876 return false; 1980 return false;
1877 } 1981 }
1878 ++m_count; 1982 ++m_count;
1879 --m_preload_count; 1983 --m_preload_count;
1880 1984
1881 m_pos += size; // consume payload 1985 m_pos += size; // consume payload
1882 assert(m_pos <= stop); 1986 if (m_pos > stop)
1987 return false;
1883 1988
1884 return true; // yes, we loaded a cue point 1989 return true; // yes, we loaded a cue point
1885 } 1990 }
1886 1991
1887 // return (m_pos < stop);
1888 return false; // no, we did not load a cue point 1992 return false; // no, we did not load a cue point
1889 } 1993 }
1890 1994
1891 bool Cues::Find(long long time_ns, const Track* pTrack, const CuePoint*& pCP, 1995 bool Cues::Find(long long time_ns, const Track* pTrack, const CuePoint*& pCP,
1892 const CuePoint::TrackPosition*& pTP) const { 1996 const CuePoint::TrackPosition*& pTP) const {
1893 assert(time_ns >= 0); 1997 if (time_ns < 0 || pTrack == NULL || m_cue_points == NULL || m_count == 0)
1894 assert(pTrack);
1895
1896 if (m_cue_points == NULL)
1897 return false;
1898
1899 if (m_count == 0)
1900 return false; 1998 return false;
1901 1999
1902 CuePoint** const ii = m_cue_points; 2000 CuePoint** const ii = m_cue_points;
1903 CuePoint** i = ii; 2001 CuePoint** i = ii;
1904 2002
1905 CuePoint** const jj = ii + m_count; 2003 CuePoint** const jj = ii + m_count;
1906 CuePoint** j = jj; 2004 CuePoint** j = jj;
1907 2005
1908 pCP = *i; 2006 pCP = *i;
1909 assert(pCP); 2007 if (pCP == NULL)
2008 return false;
1910 2009
1911 if (time_ns <= pCP->GetTime(m_pSegment)) { 2010 if (time_ns <= pCP->GetTime(m_pSegment)) {
1912 pTP = pCP->Find(pTrack); 2011 pTP = pCP->Find(pTrack);
1913 return (pTP != NULL); 2012 return (pTP != NULL);
1914 } 2013 }
1915 2014
1916 while (i < j) { 2015 while (i < j) {
1917 // INVARIANT: 2016 // INVARIANT:
1918 //[ii, i) <= time_ns 2017 //[ii, i) <= time_ns
1919 //[i, j) ? 2018 //[i, j) ?
1920 //[j, jj) > time_ns 2019 //[j, jj) > time_ns
1921 2020
1922 CuePoint** const k = i + (j - i) / 2; 2021 CuePoint** const k = i + (j - i) / 2;
1923 assert(k < jj); 2022 if (k >= jj)
2023 return false;
1924 2024
1925 CuePoint* const pCP = *k; 2025 CuePoint* const pCP = *k;
1926 assert(pCP); 2026 if (pCP == NULL)
2027 return false;
1927 2028
1928 const long long t = pCP->GetTime(m_pSegment); 2029 const long long t = pCP->GetTime(m_pSegment);
1929 2030
1930 if (t <= time_ns) 2031 if (t <= time_ns)
1931 i = k + 1; 2032 i = k + 1;
1932 else 2033 else
1933 j = k; 2034 j = k;
1934 2035
1935 assert(i <= j); 2036 if (i > j)
2037 return false;
1936 } 2038 }
1937 2039
1938 assert(i == j); 2040 if (i != j || i > jj || i <= ii)
1939 assert(i <= jj); 2041 return false;
1940 assert(i > ii);
1941 2042
1942 pCP = *--i; 2043 pCP = *--i;
1943 assert(pCP); 2044
1944 assert(pCP->GetTime(m_pSegment) <= time_ns); 2045 if (pCP == NULL || pCP->GetTime(m_pSegment) > time_ns)
2046 return false;
1945 2047
1946 // TODO: here and elsewhere, it's probably not correct to search 2048 // TODO: here and elsewhere, it's probably not correct to search
1947 // for the cue point with this time, and then search for a matching 2049 // for the cue point with this time, and then search for a matching
1948 // track. In principle, the matching track could be on some earlier 2050 // track. In principle, the matching track could be on some earlier
1949 // cue point, and with our current algorithm, we'd miss it. To make 2051 // cue point, and with our current algorithm, we'd miss it. To make
1950 // this bullet-proof, we'd need to create a secondary structure, 2052 // this bullet-proof, we'd need to create a secondary structure,
1951 // with a list of cue points that apply to a track, and then search 2053 // with a list of cue points that apply to a track, and then search
1952 // that track-based structure for a matching cue point. 2054 // that track-based structure for a matching cue point.
1953 2055
1954 pTP = pCP->Find(pTrack); 2056 pTP = pCP->Find(pTrack);
1955 return (pTP != NULL); 2057 return (pTP != NULL);
1956 } 2058 }
1957 2059
1958 const CuePoint* Cues::GetFirst() const { 2060 const CuePoint* Cues::GetFirst() const {
1959 if (m_cue_points == NULL) 2061 if (m_cue_points == NULL || m_count == 0)
1960 return NULL;
1961
1962 if (m_count == 0)
1963 return NULL; 2062 return NULL;
1964 2063
1965 CuePoint* const* const pp = m_cue_points; 2064 CuePoint* const* const pp = m_cue_points;
1966 assert(pp); 2065 if (pp == NULL)
2066 return NULL;
1967 2067
1968 CuePoint* const pCP = pp[0]; 2068 CuePoint* const pCP = pp[0];
1969 assert(pCP); 2069 if (pCP == NULL || pCP->GetTimeCode() < 0)
1970 assert(pCP->GetTimeCode() >= 0); 2070 return NULL;
1971 2071
1972 return pCP; 2072 return pCP;
1973 } 2073 }
1974 2074
1975 const CuePoint* Cues::GetLast() const { 2075 const CuePoint* Cues::GetLast() const {
1976 if (m_cue_points == NULL) 2076 if (m_cue_points == NULL || m_count <= 0)
1977 return NULL;
1978
1979 if (m_count <= 0)
1980 return NULL; 2077 return NULL;
1981 2078
1982 const long index = m_count - 1; 2079 const long index = m_count - 1;
1983 2080
1984 CuePoint* const* const pp = m_cue_points; 2081 CuePoint* const* const pp = m_cue_points;
1985 assert(pp); 2082 if (pp == NULL)
2083 return NULL;
1986 2084
1987 CuePoint* const pCP = pp[index]; 2085 CuePoint* const pCP = pp[index];
1988 assert(pCP); 2086 if (pCP == NULL || pCP->GetTimeCode() < 0)
1989 assert(pCP->GetTimeCode() >= 0); 2087 return NULL;
1990 2088
1991 return pCP; 2089 return pCP;
1992 } 2090 }
1993 2091
1994 const CuePoint* Cues::GetNext(const CuePoint* pCurr) const { 2092 const CuePoint* Cues::GetNext(const CuePoint* pCurr) const {
1995 if (pCurr == NULL) 2093 if (pCurr == NULL || pCurr->GetTimeCode() < 0 ||
2094 m_cue_points == NULL || m_count < 1) {
2095 return NULL;
2096 }
2097
2098 long index = pCurr->m_index;
2099 if (index >= m_count)
1996 return NULL; 2100 return NULL;
1997 2101
1998 assert(pCurr->GetTimeCode() >= 0);
1999 assert(m_cue_points);
2000 assert(m_count >= 1);
2001
2002 long index = pCurr->m_index;
2003 assert(index < m_count);
2004
2005 CuePoint* const* const pp = m_cue_points; 2102 CuePoint* const* const pp = m_cue_points;
2006 assert(pp); 2103 if (pp == NULL || pp[index] != pCurr)
2007 assert(pp[index] == pCurr); 2104 return NULL;
2008 2105
2009 ++index; 2106 ++index;
2010 2107
2011 if (index >= m_count) 2108 if (index >= m_count)
2012 return NULL; 2109 return NULL;
2013 2110
2014 CuePoint* const pNext = pp[index]; 2111 CuePoint* const pNext = pp[index];
2015 assert(pNext); 2112
2016 assert(pNext->GetTimeCode() >= 0); 2113 if (pNext == NULL || pNext->GetTimeCode() < 0)
2114 return NULL;
2017 2115
2018 return pNext; 2116 return pNext;
2019 } 2117 }
2020 2118
2021 const BlockEntry* Cues::GetBlock(const CuePoint* pCP, 2119 const BlockEntry* Cues::GetBlock(const CuePoint* pCP,
2022 const CuePoint::TrackPosition* pTP) const { 2120 const CuePoint::TrackPosition* pTP) const {
2023 if (pCP == NULL) 2121 if (pCP == NULL || pTP == NULL)
2024 return NULL;
2025
2026 if (pTP == NULL)
2027 return NULL; 2122 return NULL;
2028 2123
2029 return m_pSegment->GetBlock(*pCP, *pTP); 2124 return m_pSegment->GetBlock(*pCP, *pTP);
2030 } 2125 }
2031 2126
2032 const BlockEntry* Segment::GetBlock(const CuePoint& cp, 2127 const BlockEntry* Segment::GetBlock(const CuePoint& cp,
2033 const CuePoint::TrackPosition& tp) { 2128 const CuePoint::TrackPosition& tp) {
2034 Cluster** const ii = m_clusters; 2129 Cluster** const ii = m_clusters;
2035 Cluster** i = ii; 2130 Cluster** i = ii;
2036 2131
(...skipping 26 matching lines...) Expand all
2063 else if (pos > tp.m_pos) 2158 else if (pos > tp.m_pos)
2064 j = k; 2159 j = k;
2065 else 2160 else
2066 return pCluster->GetEntry(cp, tp); 2161 return pCluster->GetEntry(cp, tp);
2067 } 2162 }
2068 2163
2069 assert(i == j); 2164 assert(i == j);
2070 // assert(Cluster::HasBlockEntries(this, tp.m_pos)); 2165 // assert(Cluster::HasBlockEntries(this, tp.m_pos));
2071 2166
2072 Cluster* const pCluster = Cluster::Create(this, -1, tp.m_pos); //, -1); 2167 Cluster* const pCluster = Cluster::Create(this, -1, tp.m_pos); //, -1);
2073 assert(pCluster); 2168 if (pCluster == NULL)
2169 return NULL;
2074 2170
2075 const ptrdiff_t idx = i - m_clusters; 2171 const ptrdiff_t idx = i - m_clusters;
2076 2172
2077 PreloadCluster(pCluster, idx); 2173 if (!PreloadCluster(pCluster, idx)) {
2174 delete pCluster;
2175 return NULL;
2176 }
2078 assert(m_clusters); 2177 assert(m_clusters);
2079 assert(m_clusterPreloadCount > 0); 2178 assert(m_clusterPreloadCount > 0);
2080 assert(m_clusters[idx] == pCluster); 2179 assert(m_clusters[idx] == pCluster);
2081 2180
2082 return pCluster->GetEntry(cp, tp); 2181 return pCluster->GetEntry(cp, tp);
2083 } 2182 }
2084 2183
2085 const Cluster* Segment::FindOrPreloadCluster(long long requested_pos) { 2184 const Cluster* Segment::FindOrPreloadCluster(long long requested_pos) {
2086 if (requested_pos < 0) 2185 if (requested_pos < 0)
2087 return 0; 2186 return 0;
(...skipping 30 matching lines...) Expand all
2118 else if (pos > requested_pos) 2217 else if (pos > requested_pos)
2119 j = k; 2218 j = k;
2120 else 2219 else
2121 return pCluster; 2220 return pCluster;
2122 } 2221 }
2123 2222
2124 assert(i == j); 2223 assert(i == j);
2125 // assert(Cluster::HasBlockEntries(this, tp.m_pos)); 2224 // assert(Cluster::HasBlockEntries(this, tp.m_pos));
2126 2225
2127 Cluster* const pCluster = Cluster::Create(this, -1, requested_pos); 2226 Cluster* const pCluster = Cluster::Create(this, -1, requested_pos);
2128 //-1); 2227 if (pCluster == NULL)
2129 assert(pCluster); 2228 return NULL;
2130 2229
2131 const ptrdiff_t idx = i - m_clusters; 2230 const ptrdiff_t idx = i - m_clusters;
2132 2231
2133 PreloadCluster(pCluster, idx); 2232 if (!PreloadCluster(pCluster, idx)) {
2233 delete pCluster;
2234 return NULL;
2235 }
2134 assert(m_clusters); 2236 assert(m_clusters);
2135 assert(m_clusterPreloadCount > 0); 2237 assert(m_clusterPreloadCount > 0);
2136 assert(m_clusters[idx] == pCluster); 2238 assert(m_clusters[idx] == pCluster);
2137 2239
2138 return pCluster; 2240 return pCluster;
2139 } 2241 }
2140 2242
2141 CuePoint::CuePoint(long idx, long long pos) 2243 CuePoint::CuePoint(long idx, long long pos)
2142 : m_element_start(0), 2244 : m_element_start(0),
2143 m_element_size(0), 2245 m_element_size(0),
(...skipping 17 matching lines...) Expand all
2161 assert(m_track_positions_count == 0); 2263 assert(m_track_positions_count == 0);
2162 2264
2163 long long pos_ = -m_timecode; 2265 long long pos_ = -m_timecode;
2164 const long long element_start = pos_; 2266 const long long element_start = pos_;
2165 2267
2166 long long stop; 2268 long long stop;
2167 2269
2168 { 2270 {
2169 long len; 2271 long len;
2170 2272
2171 const long long id = ReadUInt(pReader, pos_, len); 2273 const long long id = ReadID(pReader, pos_, len);
2172 assert(id == 0x3B); // CuePoint ID 2274 if (id != mkvmuxer::kMkvCuePoint)
2173 if (id != 0x3B)
2174 return false; 2275 return false;
2175 2276
2176 pos_ += len; // consume ID 2277 pos_ += len; // consume ID
2177 2278
2178 const long long size = ReadUInt(pReader, pos_, len); 2279 const long long size = ReadUInt(pReader, pos_, len);
2179 assert(size >= 0); 2280 assert(size >= 0);
2180 2281
2181 pos_ += len; // consume Size field 2282 pos_ += len; // consume Size field
2182 // pos_ now points to start of payload 2283 // pos_ now points to start of payload
2183 2284
2184 stop = pos_ + size; 2285 stop = pos_ + size;
2185 } 2286 }
2186 2287
2187 const long long element_size = stop - element_start; 2288 const long long element_size = stop - element_start;
2188 2289
2189 long long pos = pos_; 2290 long long pos = pos_;
2190 2291
2191 // First count number of track positions 2292 // First count number of track positions
2192 2293
2193 while (pos < stop) { 2294 while (pos < stop) {
2194 long len; 2295 long len;
2195 2296
2196 const long long id = ReadUInt(pReader, pos, len); 2297 const long long id = ReadID(pReader, pos, len);
2197 if ((id < 0) || (pos + len > stop)) { 2298 if ((id < 0) || (pos + len > stop)) {
2198 return false; 2299 return false;
2199 } 2300 }
2200 2301
2201 pos += len; // consume ID 2302 pos += len; // consume ID
2202 2303
2203 const long long size = ReadUInt(pReader, pos, len); 2304 const long long size = ReadUInt(pReader, pos, len);
2204 if ((size < 0) || (pos + len > stop)) { 2305 if ((size < 0) || (pos + len > stop)) {
2205 return false; 2306 return false;
2206 } 2307 }
2207 2308
2208 pos += len; // consume Size field 2309 pos += len; // consume Size field
2209 if ((pos + size) > stop) { 2310 if ((pos + size) > stop) {
2210 return false; 2311 return false;
2211 } 2312 }
2212 2313
2213 if (id == 0x33) // CueTime ID 2314 if (id == mkvmuxer::kMkvCueTime)
2214 m_timecode = UnserializeUInt(pReader, pos, size); 2315 m_timecode = UnserializeUInt(pReader, pos, size);
2215 2316
2216 else if (id == 0x37) // CueTrackPosition(s) ID 2317 else if (id == mkvmuxer::kMkvCueTrackPositions)
2217 ++m_track_positions_count; 2318 ++m_track_positions_count;
2218 2319
2219 pos += size; // consume payload 2320 pos += size; // consume payload
2220 } 2321 }
2221 2322
2222 if (m_timecode < 0 || m_track_positions_count <= 0) { 2323 if (m_timecode < 0 || m_track_positions_count <= 0) {
2223 return false; 2324 return false;
2224 } 2325 }
2225 2326
2226 // os << "CuePoint::Load(cont'd): idpos=" << idpos 2327 // os << "CuePoint::Load(cont'd): idpos=" << idpos
2227 // << " timecode=" << m_timecode 2328 // << " timecode=" << m_timecode
2228 // << endl; 2329 // << endl;
2229 2330
2230 m_track_positions = new TrackPosition[m_track_positions_count]; 2331 m_track_positions = new (std::nothrow) TrackPosition[m_track_positions_count];
2332 if (m_track_positions == NULL)
2333 return false;
2231 2334
2232 // Now parse track positions 2335 // Now parse track positions
2233 2336
2234 TrackPosition* p = m_track_positions; 2337 TrackPosition* p = m_track_positions;
2235 pos = pos_; 2338 pos = pos_;
2236 2339
2237 while (pos < stop) { 2340 while (pos < stop) {
2238 long len; 2341 long len;
2239 2342
2240 const long long id = ReadUInt(pReader, pos, len); 2343 const long long id = ReadID(pReader, pos, len);
2241 assert(id >= 0); 2344 if (id < 0 || (pos + len) > stop)
2242 assert((pos + len) <= stop); 2345 return false;
2243 2346
2244 pos += len; // consume ID 2347 pos += len; // consume ID
2245 2348
2246 const long long size = ReadUInt(pReader, pos, len); 2349 const long long size = ReadUInt(pReader, pos, len);
2247 assert(size >= 0); 2350 assert(size >= 0);
2248 assert((pos + len) <= stop); 2351 assert((pos + len) <= stop);
2249 2352
2250 pos += len; // consume Size field 2353 pos += len; // consume Size field
2251 assert((pos + size) <= stop); 2354 assert((pos + size) <= stop);
2252 2355
2253 if (id == 0x37) { // CueTrackPosition(s) ID 2356 if (id == mkvmuxer::kMkvCueTrackPositions) {
2254 TrackPosition& tp = *p++; 2357 TrackPosition& tp = *p++;
2255 if (!tp.Parse(pReader, pos, size)) { 2358 if (!tp.Parse(pReader, pos, size)) {
2256 return false; 2359 return false;
2257 } 2360 }
2258 } 2361 }
2259 2362
2260 pos += size; // consume payload 2363 pos += size; // consume payload
2261 assert(pos <= stop); 2364 if (pos > stop)
2365 return false;
2262 } 2366 }
2263 2367
2264 assert(size_t(p - m_track_positions) == m_track_positions_count); 2368 assert(size_t(p - m_track_positions) == m_track_positions_count);
2265 2369
2266 m_element_start = element_start; 2370 m_element_start = element_start;
2267 m_element_size = element_size; 2371 m_element_size = element_size;
2268 2372
2269 return true; 2373 return true;
2270 } 2374 }
2271 2375
2272 bool CuePoint::TrackPosition::Parse(IMkvReader* pReader, long long start_, 2376 bool CuePoint::TrackPosition::Parse(IMkvReader* pReader, long long start_,
2273 long long size_) { 2377 long long size_) {
2274 const long long stop = start_ + size_; 2378 const long long stop = start_ + size_;
2275 long long pos = start_; 2379 long long pos = start_;
2276 2380
2277 m_track = -1; 2381 m_track = -1;
2278 m_pos = -1; 2382 m_pos = -1;
2279 m_block = 1; // default 2383 m_block = 1; // default
2280 2384
2281 while (pos < stop) { 2385 while (pos < stop) {
2282 long len; 2386 long len;
2283 2387
2284 const long long id = ReadUInt(pReader, pos, len); 2388 const long long id = ReadID(pReader, pos, len);
2285 if ((id < 0) || ((pos + len) > stop)) { 2389 if ((id < 0) || ((pos + len) > stop)) {
2286 return false; 2390 return false;
2287 } 2391 }
2288 2392
2289 pos += len; // consume ID 2393 pos += len; // consume ID
2290 2394
2291 const long long size = ReadUInt(pReader, pos, len); 2395 const long long size = ReadUInt(pReader, pos, len);
2292 if ((size < 0) || ((pos + len) > stop)) { 2396 if ((size < 0) || ((pos + len) > stop)) {
2293 return false; 2397 return false;
2294 } 2398 }
2295 2399
2296 pos += len; // consume Size field 2400 pos += len; // consume Size field
2297 if ((pos + size) > stop) { 2401 if ((pos + size) > stop) {
2298 return false; 2402 return false;
2299 } 2403 }
2300 2404
2301 if (id == 0x77) // CueTrack ID 2405 if (id == mkvmuxer::kMkvCueTrack)
2302 m_track = UnserializeUInt(pReader, pos, size); 2406 m_track = UnserializeUInt(pReader, pos, size);
2303 2407 else if (id == mkvmuxer::kMkvCueClusterPosition)
2304 else if (id == 0x71) // CueClusterPos ID
2305 m_pos = UnserializeUInt(pReader, pos, size); 2408 m_pos = UnserializeUInt(pReader, pos, size);
2306 2409 else if (id == mkvmuxer::kMkvCueBlockNumber)
2307 else if (id == 0x1378) // CueBlockNumber
2308 m_block = UnserializeUInt(pReader, pos, size); 2410 m_block = UnserializeUInt(pReader, pos, size);
2309 2411
2310 pos += size; // consume payload 2412 pos += size; // consume payload
2311 } 2413 }
2312 2414
2313 if ((m_pos < 0) || (m_track <= 0)) { 2415 if ((m_pos < 0) || (m_track <= 0)) {
2314 return false; 2416 return false;
2315 } 2417 }
2316 2418
2317 return true; 2419 return true;
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after
2430 2532
2431 { 2533 {
2432 long len; 2534 long len;
2433 2535
2434 long long result = GetUIntLength(m_pReader, pos, len); 2536 long long result = GetUIntLength(m_pReader, pos, len);
2435 assert(result == 0); 2537 assert(result == 0);
2436 assert((pos + len) <= stop); // TODO 2538 assert((pos + len) <= stop); // TODO
2437 if (result != 0) 2539 if (result != 0)
2438 return NULL; 2540 return NULL;
2439 2541
2440 const long long id = ReadUInt(m_pReader, pos, len); 2542 const long long id = ReadID(m_pReader, pos, len);
2441 assert(id == 0x0F43B675); // Cluster ID 2543 if (id != mkvmuxer::kMkvCluster)
2442 if (id != 0x0F43B675)
2443 return NULL; 2544 return NULL;
2444 2545
2445 pos += len; // consume ID 2546 pos += len; // consume ID
2446 2547
2447 // Read Size 2548 // Read Size
2448 result = GetUIntLength(m_pReader, pos, len); 2549 result = GetUIntLength(m_pReader, pos, len);
2449 assert(result == 0); // TODO 2550 assert(result == 0); // TODO
2450 assert((pos + len) <= stop); // TODO 2551 assert((pos + len) <= stop); // TODO
2451 2552
2452 const long long size = ReadUInt(m_pReader, pos, len); 2553 const long long size = ReadUInt(m_pReader, pos, len);
(...skipping 14 matching lines...) Expand all
2467 long len; 2568 long len;
2468 2569
2469 long long result = GetUIntLength(m_pReader, pos, len); 2570 long long result = GetUIntLength(m_pReader, pos, len);
2470 assert(result == 0); 2571 assert(result == 0);
2471 assert((pos + len) <= stop); // TODO 2572 assert((pos + len) <= stop); // TODO
2472 if (result != 0) 2573 if (result != 0)
2473 return NULL; 2574 return NULL;
2474 2575
2475 const long long idpos = pos; // pos of next (potential) cluster 2576 const long long idpos = pos; // pos of next (potential) cluster
2476 2577
2477 const long long id = ReadUInt(m_pReader, idpos, len); 2578 const long long id = ReadID(m_pReader, idpos, len);
2478 assert(id > 0); // TODO 2579 if (id < 0)
2580 return NULL;
2479 2581
2480 pos += len; // consume ID 2582 pos += len; // consume ID
2481 2583
2482 // Read Size 2584 // Read Size
2483 result = GetUIntLength(m_pReader, pos, len); 2585 result = GetUIntLength(m_pReader, pos, len);
2484 assert(result == 0); // TODO 2586 assert(result == 0); // TODO
2485 assert((pos + len) <= stop); // TODO 2587 assert((pos + len) <= stop); // TODO
2486 2588
2487 const long long size = ReadUInt(m_pReader, pos, len); 2589 const long long size = ReadUInt(m_pReader, pos, len);
2488 assert(size >= 0); // TODO 2590 assert(size >= 0); // TODO
2489 2591
2490 pos += len; // consume length of size of element 2592 pos += len; // consume length of size of element
2491 assert((pos + size) <= stop); // TODO 2593 assert((pos + size) <= stop); // TODO
2492 2594
2493 // Pos now points to start of payload 2595 // Pos now points to start of payload
2494 2596
2495 if (size == 0) // weird 2597 if (size == 0) // weird
2496 continue; 2598 continue;
2497 2599
2498 if (id == 0x0F43B675) { // Cluster ID 2600 if (id == mkvmuxer::kMkvCluster) {
2499 const long long off_next_ = idpos - m_start; 2601 const long long off_next_ = idpos - m_start;
2500 2602
2501 long long pos_; 2603 long long pos_;
2502 long len_; 2604 long len_;
2503 2605
2504 const long status = Cluster::HasBlockEntries(this, off_next_, pos_, len_); 2606 const long status = Cluster::HasBlockEntries(this, off_next_, pos_, len_);
2505 2607
2506 assert(status >= 0); 2608 assert(status >= 0);
2507 2609
2508 if (status > 0) { 2610 if (status > 0) {
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
2546 i = k + 1; 2648 i = k + 1;
2547 else if (pos > off_next) 2649 else if (pos > off_next)
2548 j = k; 2650 j = k;
2549 else 2651 else
2550 return pNext; 2652 return pNext;
2551 } 2653 }
2552 2654
2553 assert(i == j); 2655 assert(i == j);
2554 2656
2555 Cluster* const pNext = Cluster::Create(this, -1, off_next); 2657 Cluster* const pNext = Cluster::Create(this, -1, off_next);
2556 assert(pNext); 2658 if (pNext == NULL)
2659 return NULL;
2557 2660
2558 const ptrdiff_t idx_next = i - m_clusters; // insertion position 2661 const ptrdiff_t idx_next = i - m_clusters; // insertion position
2559 2662
2560 PreloadCluster(pNext, idx_next); 2663 if (!PreloadCluster(pNext, idx_next)) {
2664 delete pNext;
2665 return NULL;
2666 }
2561 assert(m_clusters); 2667 assert(m_clusters);
2562 assert(idx_next < m_clusterSize); 2668 assert(idx_next < m_clusterSize);
2563 assert(m_clusters[idx_next] == pNext); 2669 assert(m_clusters[idx_next] == pNext);
2564 2670
2565 return pNext; 2671 return pNext;
2566 } 2672 }
2567 2673
2568 long Segment::ParseNext(const Cluster* pCurr, const Cluster*& pResult, 2674 long Segment::ParseNext(const Cluster* pCurr, const Cluster*& pResult,
2569 long long& pos, long& len) { 2675 long long& pos, long& len) {
2570 assert(pCurr); 2676 assert(pCurr);
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
2634 return E_BUFFER_NOT_FULL; 2740 return E_BUFFER_NOT_FULL;
2635 2741
2636 if ((segment_stop >= 0) && ((pos + len) > segment_stop)) 2742 if ((segment_stop >= 0) && ((pos + len) > segment_stop))
2637 return E_FILE_FORMAT_INVALID; 2743 return E_FILE_FORMAT_INVALID;
2638 2744
2639 if ((pos + len) > avail) 2745 if ((pos + len) > avail)
2640 return E_BUFFER_NOT_FULL; 2746 return E_BUFFER_NOT_FULL;
2641 2747
2642 const long long id = ReadUInt(m_pReader, pos, len); 2748 const long long id = ReadUInt(m_pReader, pos, len);
2643 2749
2644 if (id != 0x0F43B675) // weird: not Cluster ID 2750 if (id != mkvmuxer::kMkvCluster)
2645 return -1; 2751 return -1;
2646 2752
2647 pos += len; // consume ID 2753 pos += len; // consume ID
2648 2754
2649 // Read Size 2755 // Read Size
2650 2756
2651 if ((pos + 1) > avail) { 2757 if ((pos + 1) > avail) {
2652 len = 1; 2758 len = 1;
2653 return E_BUFFER_NOT_FULL; 2759 return E_BUFFER_NOT_FULL;
2654 } 2760 }
(...skipping 25 matching lines...) Expand all
2680 return E_FILE_FORMAT_INVALID; // TODO: resolve this 2786 return E_FILE_FORMAT_INVALID; // TODO: resolve this
2681 2787
2682 // assert((pCurr->m_size <= 0) || (pCurr->m_size == size)); 2788 // assert((pCurr->m_size <= 0) || (pCurr->m_size == size));
2683 2789
2684 if ((segment_stop >= 0) && ((pos + size) > segment_stop)) 2790 if ((segment_stop >= 0) && ((pos + size) > segment_stop))
2685 return E_FILE_FORMAT_INVALID; 2791 return E_FILE_FORMAT_INVALID;
2686 2792
2687 // Pos now points to start of payload 2793 // Pos now points to start of payload
2688 2794
2689 pos += size; // consume payload (that is, the current cluster) 2795 pos += size; // consume payload (that is, the current cluster)
2690 assert((segment_stop < 0) || (pos <= segment_stop)); 2796 if (segment_stop >= 0 && pos > segment_stop)
2797 return E_FILE_FORMAT_INVALID;
2691 2798
2692 // By consuming the payload, we are assuming that the curr 2799 // By consuming the payload, we are assuming that the curr
2693 // cluster isn't interesting. That is, we don't bother checking 2800 // cluster isn't interesting. That is, we don't bother checking
2694 // whether the payload of the curr cluster is less than what 2801 // whether the payload of the curr cluster is less than what
2695 // happens to be available (obtained via IMkvReader::Length). 2802 // happens to be available (obtained via IMkvReader::Length).
2696 // Presumably the caller has already dispensed with the current 2803 // Presumably the caller has already dispensed with the current
2697 // cluster, and really does want the next cluster. 2804 // cluster, and really does want the next cluster.
2698 } 2805 }
2699 2806
2700 // pos now points to just beyond the last fully-loaded cluster 2807 // pos now points to just beyond the last fully-loaded cluster
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
2748 2855
2749 if ((segment_stop >= 0) && ((pos + len) > segment_stop)) 2856 if ((segment_stop >= 0) && ((pos + len) > segment_stop))
2750 return E_FILE_FORMAT_INVALID; 2857 return E_FILE_FORMAT_INVALID;
2751 2858
2752 if ((pos + len) > avail) 2859 if ((pos + len) > avail)
2753 return E_BUFFER_NOT_FULL; 2860 return E_BUFFER_NOT_FULL;
2754 2861
2755 const long long idpos = pos; // absolute 2862 const long long idpos = pos; // absolute
2756 const long long idoff = pos - m_start; // relative 2863 const long long idoff = pos - m_start; // relative
2757 2864
2758 const long long id = ReadUInt(m_pReader, idpos, len); // absolute 2865 const long long id = ReadID(m_pReader, idpos, len); // absolute
2759 2866
2760 if (id < 0) // error 2867 if (id < 0) // error
2761 return static_cast<long>(id); 2868 return static_cast<long>(id);
2762 2869
2763 if (id == 0) // weird 2870 if (id == 0) // weird
2764 return -1; // generic error 2871 return -1; // generic error
2765 2872
2766 pos += len; // consume ID 2873 pos += len; // consume ID
2767 2874
2768 // Read Size 2875 // Read Size
(...skipping 29 matching lines...) Expand all
2798 if (size == 0) // weird 2905 if (size == 0) // weird
2799 continue; 2906 continue;
2800 2907
2801 const long long unknown_size = (1LL << (7 * len)) - 1; 2908 const long long unknown_size = (1LL << (7 * len)) - 1;
2802 2909
2803 if ((segment_stop >= 0) && (size != unknown_size) && 2910 if ((segment_stop >= 0) && (size != unknown_size) &&
2804 ((pos + size) > segment_stop)) { 2911 ((pos + size) > segment_stop)) {
2805 return E_FILE_FORMAT_INVALID; 2912 return E_FILE_FORMAT_INVALID;
2806 } 2913 }
2807 2914
2808 if (id == 0x0C53BB6B) { // Cues ID 2915 if (id == mkvmuxer::kMkvCues) {
2809 if (size == unknown_size) 2916 if (size == unknown_size)
2810 return E_FILE_FORMAT_INVALID; 2917 return E_FILE_FORMAT_INVALID;
2811 2918
2812 const long long element_stop = pos + size; 2919 const long long element_stop = pos + size;
2813 2920
2814 if ((segment_stop >= 0) && (element_stop > segment_stop)) 2921 if ((segment_stop >= 0) && (element_stop > segment_stop))
2815 return E_FILE_FORMAT_INVALID; 2922 return E_FILE_FORMAT_INVALID;
2816 2923
2817 const long long element_start = idpos; 2924 const long long element_start = idpos;
2818 const long long element_size = element_stop - element_start; 2925 const long long element_size = element_stop - element_start;
2819 2926
2820 if (m_pCues == NULL) { 2927 if (m_pCues == NULL) {
2821 m_pCues = new Cues(this, pos, size, element_start, element_size); 2928 m_pCues = new (std::nothrow)
2822 assert(m_pCues); // TODO 2929 Cues(this, pos, size, element_start, element_size);
2930 if (m_pCues == NULL)
2931 return false;
2823 } 2932 }
2824 2933
2825 pos += size; // consume payload 2934 pos += size; // consume payload
2826 assert((segment_stop < 0) || (pos <= segment_stop)); 2935 if (segment_stop >= 0 && pos > segment_stop)
2936 return E_FILE_FORMAT_INVALID;
2827 2937
2828 continue; 2938 continue;
2829 } 2939 }
2830 2940
2831 if (id != 0x0F43B675) { // not a Cluster ID 2941 if (id != mkvmuxer::kMkvCluster) { // not a Cluster ID
2832 if (size == unknown_size) 2942 if (size == unknown_size)
2833 return E_FILE_FORMAT_INVALID; 2943 return E_FILE_FORMAT_INVALID;
2834 2944
2835 pos += size; // consume payload 2945 pos += size; // consume payload
2836 assert((segment_stop < 0) || (pos <= segment_stop)); 2946 if (segment_stop >= 0 && pos > segment_stop)
2947 return E_FILE_FORMAT_INVALID;
2837 2948
2838 continue; 2949 continue;
2839 } 2950 }
2840 2951
2841 // We have a cluster. 2952 // We have a cluster.
2842 off_next = idoff; 2953 off_next = idoff;
2843 2954
2844 if (size != unknown_size) 2955 if (size != unknown_size)
2845 cluster_size = size; 2956 cluster_size = size;
2846 2957
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
2898 pos = pos_; 3009 pos = pos_;
2899 len = len_; 3010 len = len_;
2900 3011
2901 return status; 3012 return status;
2902 } 3013 }
2903 3014
2904 if (status > 0) { // means "found at least one block entry" 3015 if (status > 0) { // means "found at least one block entry"
2905 Cluster* const pNext = Cluster::Create(this, 3016 Cluster* const pNext = Cluster::Create(this,
2906 -1, // preloaded 3017 -1, // preloaded
2907 off_next); 3018 off_next);
2908 // element_size); 3019 if (pNext == NULL)
2909 assert(pNext); 3020 return -1;
2910 3021
2911 const ptrdiff_t idx_next = i - m_clusters; // insertion position 3022 const ptrdiff_t idx_next = i - m_clusters; // insertion position
2912 3023
2913 PreloadCluster(pNext, idx_next); 3024 if (!PreloadCluster(pNext, idx_next)) {
3025 delete pNext;
3026 return -1;
3027 }
2914 assert(m_clusters); 3028 assert(m_clusters);
2915 assert(idx_next < m_clusterSize); 3029 assert(idx_next < m_clusterSize);
2916 assert(m_clusters[idx_next] == pNext); 3030 assert(m_clusters[idx_next] == pNext);
2917 3031
2918 pResult = pNext; 3032 pResult = pNext;
2919 return 0; // success 3033 return 0; // success
2920 } 3034 }
2921 3035
2922 // status == 0 means "no block entries found" 3036 // status == 0 means "no block entries found"
2923 3037
(...skipping 22 matching lines...) Expand all
2946 if (result > 0) // weird 3060 if (result > 0) // weird
2947 return E_BUFFER_NOT_FULL; 3061 return E_BUFFER_NOT_FULL;
2948 3062
2949 if ((segment_stop >= 0) && ((pos + len) > segment_stop)) 3063 if ((segment_stop >= 0) && ((pos + len) > segment_stop))
2950 return E_FILE_FORMAT_INVALID; 3064 return E_FILE_FORMAT_INVALID;
2951 3065
2952 if ((pos + len) > avail) 3066 if ((pos + len) > avail)
2953 return E_BUFFER_NOT_FULL; 3067 return E_BUFFER_NOT_FULL;
2954 3068
2955 const long long idpos = pos; 3069 const long long idpos = pos;
2956 const long long id = ReadUInt(m_pReader, idpos, len); 3070 const long long id = ReadID(m_pReader, idpos, len);
2957 3071
2958 if (id < 0) // error (or underflow) 3072 if (id < 0) // error (or underflow)
2959 return static_cast<long>(id); 3073 return static_cast<long>(id);
2960 3074
2961 // This is the distinguished set of ID's we use to determine 3075 // This is the distinguished set of ID's we use to determine
2962 // that we have exhausted the sub-element's inside the cluster 3076 // that we have exhausted the sub-element's inside the cluster
2963 // whose ID we parsed earlier. 3077 // whose ID we parsed earlier.
2964 3078
2965 if (id == 0x0F43B675) // Cluster ID 3079 if (id == mkvmuxer::kMkvCluster || id == mkvmuxer::kMkvCues)
2966 break;
2967
2968 if (id == 0x0C53BB6B) // Cues ID
2969 break; 3080 break;
2970 3081
2971 pos += len; // consume ID (of sub-element) 3082 pos += len; // consume ID (of sub-element)
2972 3083
2973 // Read Size 3084 // Read Size
2974 3085
2975 if ((pos + 1) > avail) { 3086 if ((pos + 1) > avail) {
2976 len = 1; 3087 len = 1;
2977 return E_BUFFER_NOT_FULL; 3088 return E_BUFFER_NOT_FULL;
2978 } 3089 }
(...skipping 26 matching lines...) Expand all
3005 3116
3006 const long long unknown_size = (1LL << (7 * len)) - 1; 3117 const long long unknown_size = (1LL << (7 * len)) - 1;
3007 3118
3008 if (size == unknown_size) 3119 if (size == unknown_size)
3009 return E_FILE_FORMAT_INVALID; // not allowed for sub-elements 3120 return E_FILE_FORMAT_INVALID; // not allowed for sub-elements
3010 3121
3011 if ((segment_stop >= 0) && ((pos + size) > segment_stop)) // weird 3122 if ((segment_stop >= 0) && ((pos + size) > segment_stop)) // weird
3012 return E_FILE_FORMAT_INVALID; 3123 return E_FILE_FORMAT_INVALID;
3013 3124
3014 pos += size; // consume payload of sub-element 3125 pos += size; // consume payload of sub-element
3015 assert((segment_stop < 0) || (pos <= segment_stop)); 3126 if (segment_stop >= 0 && pos > segment_stop)
3127 return E_FILE_FORMAT_INVALID;
3016 } // determine cluster size 3128 } // determine cluster size
3017 3129
3018 cluster_size = pos - payload_pos; 3130 cluster_size = pos - payload_pos;
3019 assert(cluster_size >= 0); // TODO: handle cluster_size = 0 3131 assert(cluster_size >= 0); // TODO: handle cluster_size = 0
3020 3132
3021 pos = payload_pos; // reset and re-parse original cluster 3133 pos = payload_pos; // reset and re-parse original cluster
3022 } 3134 }
3023 3135
3024 pos += cluster_size; // consume payload 3136 pos += cluster_size; // consume payload
3025 assert((segment_stop < 0) || (pos <= segment_stop)); 3137 if (segment_stop >= 0 && pos > segment_stop)
3138 return E_FILE_FORMAT_INVALID;
3026 3139
3027 return 2; // try to find a cluster that follows next 3140 return 2; // try to find a cluster that follows next
3028 } 3141 }
3029 3142
3030 const Cluster* Segment::FindCluster(long long time_ns) const { 3143 const Cluster* Segment::FindCluster(long long time_ns) const {
3031 if ((m_clusters == NULL) || (m_clusterCount <= 0)) 3144 if ((m_clusters == NULL) || (m_clusterCount <= 0))
3032 return &m_eos; 3145 return &m_eos;
3033 3146
3034 { 3147 {
3035 Cluster* const pCluster = m_clusters[0]; 3148 Cluster* const pCluster = m_clusters[0];
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after
3124 long long id, size; 3237 long long id, size;
3125 3238
3126 long status = ParseElementHeader(pReader, pos, stop, id, size); 3239 long status = ParseElementHeader(pReader, pos, stop, id, size);
3127 3240
3128 if (status < 0) // error 3241 if (status < 0) // error
3129 return status; 3242 return status;
3130 3243
3131 if (size == 0) // weird 3244 if (size == 0) // weird
3132 continue; 3245 continue;
3133 3246
3134 if (id == 0x05B9) { // EditionEntry ID 3247 if (id == mkvmuxer::kMkvEditionEntry) {
3135 status = ParseEdition(pos, size); 3248 status = ParseEdition(pos, size);
3136 3249
3137 if (status < 0) // error 3250 if (status < 0) // error
3138 return status; 3251 return status;
3139 } 3252 }
3140 3253
3141 pos += size; 3254 pos += size;
3142 assert(pos <= stop); 3255 if (pos > stop)
3256 return E_FILE_FORMAT_INVALID;
3143 } 3257 }
3144 3258
3145 assert(pos == stop); 3259 if (pos != stop)
3260 return E_FILE_FORMAT_INVALID;
3146 return 0; 3261 return 0;
3147 } 3262 }
3148 3263
3149 int Chapters::GetEditionCount() const { return m_editions_count; } 3264 int Chapters::GetEditionCount() const { return m_editions_count; }
3150 3265
3151 const Chapters::Edition* Chapters::GetEdition(int idx) const { 3266 const Chapters::Edition* Chapters::GetEdition(int idx) const {
3152 if (idx < 0) 3267 if (idx < 0)
3153 return NULL; 3268 return NULL;
3154 3269
3155 if (idx >= m_editions_count) 3270 if (idx >= m_editions_count)
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after
3235 const long long stop = pos + size; 3350 const long long stop = pos + size;
3236 3351
3237 while (pos < stop) { 3352 while (pos < stop) {
3238 long long id, size; 3353 long long id, size;
3239 3354
3240 long status = ParseElementHeader(pReader, pos, stop, id, size); 3355 long status = ParseElementHeader(pReader, pos, stop, id, size);
3241 3356
3242 if (status < 0) // error 3357 if (status < 0) // error
3243 return status; 3358 return status;
3244 3359
3245 if (size == 0) // weird 3360 if (size == 0)
3246 continue; 3361 continue;
3247 3362
3248 if (id == 0x36) { // Atom ID 3363 if (id == mkvmuxer::kMkvChapterAtom) {
3249 status = ParseAtom(pReader, pos, size); 3364 status = ParseAtom(pReader, pos, size);
3250 3365
3251 if (status < 0) // error 3366 if (status < 0) // error
3252 return status; 3367 return status;
3253 } 3368 }
3254 3369
3255 pos += size; 3370 pos += size;
3256 assert(pos <= stop); 3371 if (pos > stop)
3372 return E_FILE_FORMAT_INVALID;
3257 } 3373 }
3258 3374
3259 assert(pos == stop); 3375 if (pos != stop)
3376 return E_FILE_FORMAT_INVALID;
3260 return 0; 3377 return 0;
3261 } 3378 }
3262 3379
3263 long Chapters::Edition::ParseAtom(IMkvReader* pReader, long long pos, 3380 long Chapters::Edition::ParseAtom(IMkvReader* pReader, long long pos,
3264 long long size) { 3381 long long size) {
3265 if (!ExpandAtomsArray()) 3382 if (!ExpandAtomsArray())
3266 return -1; 3383 return -1;
3267 3384
3268 Atom& a = m_atoms[m_atoms_count++]; 3385 Atom& a = m_atoms[m_atoms_count++];
3269 a.Init(); 3386 a.Init();
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after
3366 const long long stop = pos + size; 3483 const long long stop = pos + size;
3367 3484
3368 while (pos < stop) { 3485 while (pos < stop) {
3369 long long id, size; 3486 long long id, size;
3370 3487
3371 long status = ParseElementHeader(pReader, pos, stop, id, size); 3488 long status = ParseElementHeader(pReader, pos, stop, id, size);
3372 3489
3373 if (status < 0) // error 3490 if (status < 0) // error
3374 return status; 3491 return status;
3375 3492
3376 if (size == 0) // weird 3493 if (size == 0) // 0 length payload, skip.
3377 continue; 3494 continue;
3378 3495
3379 if (id == 0x00) { // Display ID 3496 if (id == mkvmuxer::kMkvChapterDisplay) {
3380 status = ParseDisplay(pReader, pos, size); 3497 status = ParseDisplay(pReader, pos, size);
3381 3498
3382 if (status < 0) // error 3499 if (status < 0) // error
3383 return status; 3500 return status;
3384 } else if (id == 0x1654) { // StringUID ID 3501 } else if (id == mkvmuxer::kMkvChapterStringUID) {
3385 status = UnserializeString(pReader, pos, size, m_string_uid); 3502 status = UnserializeString(pReader, pos, size, m_string_uid);
3386 3503
3387 if (status < 0) // error 3504 if (status < 0) // error
3388 return status; 3505 return status;
3389 } else if (id == 0x33C4) { // UID ID 3506 } else if (id == mkvmuxer::kMkvChapterUID) {
3390 long long val; 3507 long long val;
3391 status = UnserializeInt(pReader, pos, size, val); 3508 status = UnserializeInt(pReader, pos, size, val);
3392 3509
3393 if (status < 0) // error 3510 if (status < 0) // error
3394 return status; 3511 return status;
3395 3512
3396 m_uid = static_cast<unsigned long long>(val); 3513 m_uid = static_cast<unsigned long long>(val);
3397 } else if (id == 0x11) { // TimeStart ID 3514 } else if (id == mkvmuxer::kMkvChapterTimeStart) {
3398 const long long val = UnserializeUInt(pReader, pos, size); 3515 const long long val = UnserializeUInt(pReader, pos, size);
3399 3516
3400 if (val < 0) // error 3517 if (val < 0) // error
3401 return static_cast<long>(val); 3518 return static_cast<long>(val);
3402 3519
3403 m_start_timecode = val; 3520 m_start_timecode = val;
3404 } else if (id == 0x12) { // TimeEnd ID 3521 } else if (id == mkvmuxer::kMkvChapterTimeEnd) {
3405 const long long val = UnserializeUInt(pReader, pos, size); 3522 const long long val = UnserializeUInt(pReader, pos, size);
3406 3523
3407 if (val < 0) // error 3524 if (val < 0) // error
3408 return static_cast<long>(val); 3525 return static_cast<long>(val);
3409 3526
3410 m_stop_timecode = val; 3527 m_stop_timecode = val;
3411 } 3528 }
3412 3529
3413 pos += size; 3530 pos += size;
3414 assert(pos <= stop); 3531 if (pos > stop)
3532 return E_FILE_FORMAT_INVALID;
3415 } 3533 }
3416 3534
3417 assert(pos == stop); 3535 if (pos != stop)
3536 return E_FILE_FORMAT_INVALID;
3418 return 0; 3537 return 0;
3419 } 3538 }
3420 3539
3421 long long Chapters::Atom::GetTime(const Chapters* pChapters, 3540 long long Chapters::Atom::GetTime(const Chapters* pChapters,
3422 long long timecode) { 3541 long long timecode) {
3423 if (pChapters == NULL) 3542 if (pChapters == NULL)
3424 return -1; 3543 return -1;
3425 3544
3426 Segment* const pSegment = pChapters->m_pSegment; 3545 Segment* const pSegment = pChapters->m_pSegment;
3427 3546
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after
3517 const long long stop = pos + size; 3636 const long long stop = pos + size;
3518 3637
3519 while (pos < stop) { 3638 while (pos < stop) {
3520 long long id, size; 3639 long long id, size;
3521 3640
3522 long status = ParseElementHeader(pReader, pos, stop, id, size); 3641 long status = ParseElementHeader(pReader, pos, stop, id, size);
3523 3642
3524 if (status < 0) // error 3643 if (status < 0) // error
3525 return status; 3644 return status;
3526 3645
3527 if (size == 0) // weird 3646 if (size == 0) // No payload.
3528 continue; 3647 continue;
3529 3648
3530 if (id == 0x05) { // ChapterString ID 3649 if (id == mkvmuxer::kMkvChapString) {
3531 status = UnserializeString(pReader, pos, size, m_string); 3650 status = UnserializeString(pReader, pos, size, m_string);
3532 3651
3533 if (status) 3652 if (status)
3534 return status; 3653 return status;
3535 } else if (id == 0x037C) { // ChapterLanguage ID 3654 } else if (id == mkvmuxer::kMkvChapLanguage) {
3536 status = UnserializeString(pReader, pos, size, m_language); 3655 status = UnserializeString(pReader, pos, size, m_language);
3537 3656
3538 if (status) 3657 if (status)
3539 return status; 3658 return status;
3540 } else if (id == 0x037E) { // ChapterCountry ID 3659 } else if (id == mkvmuxer::kMkvChapCountry) {
3541 status = UnserializeString(pReader, pos, size, m_country); 3660 status = UnserializeString(pReader, pos, size, m_country);
3542 3661
3543 if (status) 3662 if (status)
3544 return status; 3663 return status;
3545 } 3664 }
3546 3665
3547 pos += size; 3666 pos += size;
3548 assert(pos <= stop); 3667 if (pos > stop)
3668 return E_FILE_FORMAT_INVALID;
3549 } 3669 }
3550 3670
3551 assert(pos == stop); 3671 if (pos != stop)
3672 return E_FILE_FORMAT_INVALID;
3552 return 0; 3673 return 0;
3553 } 3674 }
3554 3675
3555 Tags::Tags(Segment* pSegment, long long payload_start, long long payload_size, 3676 Tags::Tags(Segment* pSegment, long long payload_start, long long payload_size,
3556 long long element_start, long long element_size) 3677 long long element_start, long long element_size)
3557 : m_pSegment(pSegment), 3678 : m_pSegment(pSegment),
3558 m_start(payload_start), 3679 m_start(payload_start),
3559 m_size(payload_size), 3680 m_size(payload_size),
3560 m_element_start(element_start), 3681 m_element_start(element_start),
3561 m_element_size(element_size), 3682 m_element_size(element_size),
(...skipping 19 matching lines...) Expand all
3581 long long id, size; 3702 long long id, size;
3582 3703
3583 long status = ParseElementHeader(pReader, pos, stop, id, size); 3704 long status = ParseElementHeader(pReader, pos, stop, id, size);
3584 3705
3585 if (status < 0) 3706 if (status < 0)
3586 return status; 3707 return status;
3587 3708
3588 if (size == 0) // 0 length tag, read another 3709 if (size == 0) // 0 length tag, read another
3589 continue; 3710 continue;
3590 3711
3591 if (id == 0x3373) { // Tag ID 3712 if (id == mkvmuxer::kMkvTag) {
3592 status = ParseTag(pos, size); 3713 status = ParseTag(pos, size);
3593 3714
3594 if (status < 0) 3715 if (status < 0)
3595 return status; 3716 return status;
3596 } 3717 }
3597 3718
3598 pos += size; 3719 pos += size;
3599 assert(pos <= stop);
3600 if (pos > stop) 3720 if (pos > stop)
3601 return -1; 3721 return E_FILE_FORMAT_INVALID;
3602 } 3722 }
3603 3723
3604 assert(pos == stop);
3605 if (pos != stop) 3724 if (pos != stop)
3606 return -1; 3725 return E_FILE_FORMAT_INVALID;
3607 3726
3608 return 0; 3727 return 0;
3609 } 3728 }
3610 3729
3611 int Tags::GetTagCount() const { return m_tags_count; } 3730 int Tags::GetTagCount() const { return m_tags_count; }
3612 3731
3613 const Tags::Tag* Tags::GetTag(int idx) const { 3732 const Tags::Tag* Tags::GetTag(int idx) const {
3614 if (idx < 0) 3733 if (idx < 0)
3615 return NULL; 3734 return NULL;
3616 3735
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after
3699 long long id, size; 3818 long long id, size;
3700 3819
3701 long status = ParseElementHeader(pReader, pos, stop, id, size); 3820 long status = ParseElementHeader(pReader, pos, stop, id, size);
3702 3821
3703 if (status < 0) 3822 if (status < 0)
3704 return status; 3823 return status;
3705 3824
3706 if (size == 0) // 0 length tag, read another 3825 if (size == 0) // 0 length tag, read another
3707 continue; 3826 continue;
3708 3827
3709 if (id == 0x27C8) { // SimpleTag ID 3828 if (id == mkvmuxer::kMkvSimpleTag) {
3710 status = ParseSimpleTag(pReader, pos, size); 3829 status = ParseSimpleTag(pReader, pos, size);
3711 3830
3712 if (status < 0) 3831 if (status < 0)
3713 return status; 3832 return status;
3714 } 3833 }
3715 3834
3716 pos += size; 3835 pos += size;
3717 assert(pos <= stop);
3718 if (pos > stop) 3836 if (pos > stop)
3719 return -1; 3837 return E_FILE_FORMAT_INVALID;
3720 } 3838 }
3721 3839
3722 assert(pos == stop);
3723 if (pos != stop) 3840 if (pos != stop)
3724 return -1; 3841 return E_FILE_FORMAT_INVALID;
3725 return 0; 3842 return 0;
3726 } 3843 }
3727 3844
3728 long Tags::Tag::ParseSimpleTag(IMkvReader* pReader, long long pos, 3845 long Tags::Tag::ParseSimpleTag(IMkvReader* pReader, long long pos,
3729 long long size) { 3846 long long size) {
3730 if (!ExpandSimpleTagsArray()) 3847 if (!ExpandSimpleTagsArray())
3731 return -1; 3848 return -1;
3732 3849
3733 SimpleTag& st = m_simple_tags[m_simple_tags_count++]; 3850 SimpleTag& st = m_simple_tags[m_simple_tags_count++];
3734 st.Init(); 3851 st.Init();
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
3792 long long id, size; 3909 long long id, size;
3793 3910
3794 long status = ParseElementHeader(pReader, pos, stop, id, size); 3911 long status = ParseElementHeader(pReader, pos, stop, id, size);
3795 3912
3796 if (status < 0) // error 3913 if (status < 0) // error
3797 return status; 3914 return status;
3798 3915
3799 if (size == 0) // weird 3916 if (size == 0) // weird
3800 continue; 3917 continue;
3801 3918
3802 if (id == 0x5A3) { // TagName ID 3919 if (id == mkvmuxer::kMkvTagName) {
3803 status = UnserializeString(pReader, pos, size, m_tag_name); 3920 status = UnserializeString(pReader, pos, size, m_tag_name);
3804 3921
3805 if (status) 3922 if (status)
3806 return status; 3923 return status;
3807 } else if (id == 0x487) { // TagString ID 3924 } else if (id == mkvmuxer::kMkvTagString) {
3808 status = UnserializeString(pReader, pos, size, m_tag_string); 3925 status = UnserializeString(pReader, pos, size, m_tag_string);
3809 3926
3810 if (status) 3927 if (status)
3811 return status; 3928 return status;
3812 } 3929 }
3813 3930
3814 pos += size; 3931 pos += size;
3815 assert(pos <= stop);
3816 if (pos > stop) 3932 if (pos > stop)
3817 return -1; 3933 return E_FILE_FORMAT_INVALID;
3818 } 3934 }
3819 3935
3820 assert(pos == stop);
3821 if (pos != stop) 3936 if (pos != stop)
3822 return -1; 3937 return E_FILE_FORMAT_INVALID;
3823 return 0; 3938 return 0;
3824 } 3939 }
3825 3940
3826 SegmentInfo::SegmentInfo(Segment* pSegment, long long start, long long size_, 3941 SegmentInfo::SegmentInfo(Segment* pSegment, long long start, long long size_,
3827 long long element_start, long long element_size) 3942 long long element_start, long long element_size)
3828 : m_pSegment(pSegment), 3943 : m_pSegment(pSegment),
3829 m_start(start), 3944 m_start(start),
3830 m_size(size_), 3945 m_size(size_),
3831 m_element_start(element_start), 3946 m_element_start(element_start),
3832 m_element_size(element_size), 3947 m_element_size(element_size),
(...skipping 26 matching lines...) Expand all
3859 m_duration = -1; 3974 m_duration = -1;
3860 3975
3861 while (pos < stop) { 3976 while (pos < stop) {
3862 long long id, size; 3977 long long id, size;
3863 3978
3864 const long status = ParseElementHeader(pReader, pos, stop, id, size); 3979 const long status = ParseElementHeader(pReader, pos, stop, id, size);
3865 3980
3866 if (status < 0) // error 3981 if (status < 0) // error
3867 return status; 3982 return status;
3868 3983
3869 if (id == 0x0AD7B1) { // Timecode Scale 3984 if (id == mkvmuxer::kMkvTimecodeScale) {
3870 m_timecodeScale = UnserializeUInt(pReader, pos, size); 3985 m_timecodeScale = UnserializeUInt(pReader, pos, size);
3871 3986
3872 if (m_timecodeScale <= 0) 3987 if (m_timecodeScale <= 0)
3873 return E_FILE_FORMAT_INVALID; 3988 return E_FILE_FORMAT_INVALID;
3874 } else if (id == 0x0489) { // Segment duration 3989 } else if (id == mkvmuxer::kMkvDuration) {
3875 const long status = UnserializeFloat(pReader, pos, size, m_duration); 3990 const long status = UnserializeFloat(pReader, pos, size, m_duration);
3876 3991
3877 if (status < 0) 3992 if (status < 0)
3878 return status; 3993 return status;
3879 3994
3880 if (m_duration < 0) 3995 if (m_duration < 0)
3881 return E_FILE_FORMAT_INVALID; 3996 return E_FILE_FORMAT_INVALID;
3882 } else if (id == 0x0D80) { // MuxingApp 3997 } else if (id == mkvmuxer::kMkvMuxingApp) {
3883 const long status = 3998 const long status =
3884 UnserializeString(pReader, pos, size, m_pMuxingAppAsUTF8); 3999 UnserializeString(pReader, pos, size, m_pMuxingAppAsUTF8);
3885 4000
3886 if (status) 4001 if (status)
3887 return status; 4002 return status;
3888 } else if (id == 0x1741) { // WritingApp 4003 } else if (id == mkvmuxer::kMkvWritingApp) {
3889 const long status = 4004 const long status =
3890 UnserializeString(pReader, pos, size, m_pWritingAppAsUTF8); 4005 UnserializeString(pReader, pos, size, m_pWritingAppAsUTF8);
3891 4006
3892 if (status) 4007 if (status)
3893 return status; 4008 return status;
3894 } else if (id == 0x3BA9) { // Title 4009 } else if (id == mkvmuxer::kMkvTitle) {
3895 const long status = UnserializeString(pReader, pos, size, m_pTitleAsUTF8); 4010 const long status = UnserializeString(pReader, pos, size, m_pTitleAsUTF8);
3896 4011
3897 if (status) 4012 if (status)
3898 return status; 4013 return status;
3899 } 4014 }
3900 4015
3901 pos += size; 4016 pos += size;
3902 assert(pos <= stop); 4017
4018 if (pos > stop)
4019 return E_FILE_FORMAT_INVALID;
3903 } 4020 }
3904 4021
3905 assert(pos == stop); 4022 const double rollover_check = m_duration * m_timecodeScale;
4023 if (rollover_check > LONG_LONG_MAX)
4024 return E_FILE_FORMAT_INVALID;
4025
4026 if (pos != stop)
4027 return E_FILE_FORMAT_INVALID;
3906 4028
3907 return 0; 4029 return 0;
3908 } 4030 }
3909 4031
3910 long long SegmentInfo::GetTimeCodeScale() const { return m_timecodeScale; } 4032 long long SegmentInfo::GetTimeCodeScale() const { return m_timecodeScale; }
3911 4033
3912 long long SegmentInfo::GetDuration() const { 4034 long long SegmentInfo::GetDuration() const {
3913 if (m_duration < 0) 4035 if (m_duration < 0)
3914 return -1; 4036 return -1;
3915 4037
(...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after
4032 4154
4033 long long pos = start; 4155 long long pos = start;
4034 const long long stop = start + size; 4156 const long long stop = start + size;
4035 4157
4036 while (pos < stop) { 4158 while (pos < stop) {
4037 long long id, size; 4159 long long id, size;
4038 const long status = ParseElementHeader(pReader, pos, stop, id, size); 4160 const long status = ParseElementHeader(pReader, pos, stop, id, size);
4039 if (status < 0) // error 4161 if (status < 0) // error
4040 return status; 4162 return status;
4041 4163
4042 if (id == 0x7E8) { 4164 if (id == mkvmuxer::kMkvAESSettingsCipherMode) {
4043 // AESSettingsCipherMode
4044 aes->cipher_mode = UnserializeUInt(pReader, pos, size); 4165 aes->cipher_mode = UnserializeUInt(pReader, pos, size);
4045 if (aes->cipher_mode != 1) 4166 if (aes->cipher_mode != 1)
4046 return E_FILE_FORMAT_INVALID; 4167 return E_FILE_FORMAT_INVALID;
4047 } 4168 }
4048 4169
4049 pos += size; // consume payload 4170 pos += size; // consume payload
4050 assert(pos <= stop); 4171 if (pos > stop)
4172 return E_FILE_FORMAT_INVALID;
4051 } 4173 }
4052 4174
4053 return 0; 4175 return 0;
4054 } 4176 }
4055 4177
4056 long ContentEncoding::ParseContentEncodingEntry(long long start, long long size, 4178 long ContentEncoding::ParseContentEncodingEntry(long long start, long long size,
4057 IMkvReader* pReader) { 4179 IMkvReader* pReader) {
4058 assert(pReader); 4180 assert(pReader);
4059 4181
4060 long long pos = start; 4182 long long pos = start;
4061 const long long stop = start + size; 4183 const long long stop = start + size;
4062 4184
4063 // Count ContentCompression and ContentEncryption elements. 4185 // Count ContentCompression and ContentEncryption elements.
4064 int compression_count = 0; 4186 int compression_count = 0;
4065 int encryption_count = 0; 4187 int encryption_count = 0;
4066 4188
4067 while (pos < stop) { 4189 while (pos < stop) {
4068 long long id, size; 4190 long long id, size;
4069 const long status = ParseElementHeader(pReader, pos, stop, id, size); 4191 const long status = ParseElementHeader(pReader, pos, stop, id, size);
4070 if (status < 0) // error 4192 if (status < 0) // error
4071 return status; 4193 return status;
4072 4194
4073 if (id == 0x1034) // ContentCompression ID 4195 if (id == mkvmuxer::kMkvContentCompression)
4074 ++compression_count; 4196 ++compression_count;
4075 4197
4076 if (id == 0x1035) // ContentEncryption ID 4198 if (id == mkvmuxer::kMkvContentEncryption)
4077 ++encryption_count; 4199 ++encryption_count;
4078 4200
4079 pos += size; // consume payload 4201 pos += size; // consume payload
4080 assert(pos <= stop); 4202 if (pos > stop)
4203 return E_FILE_FORMAT_INVALID;
4081 } 4204 }
4082 4205
4083 if (compression_count <= 0 && encryption_count <= 0) 4206 if (compression_count <= 0 && encryption_count <= 0)
4084 return -1; 4207 return -1;
4085 4208
4086 if (compression_count > 0) { 4209 if (compression_count > 0) {
4087 compression_entries_ = 4210 compression_entries_ =
4088 new (std::nothrow) ContentCompression*[compression_count]; 4211 new (std::nothrow) ContentCompression*[compression_count];
4089 if (!compression_entries_) 4212 if (!compression_entries_)
4090 return -1; 4213 return -1;
(...skipping 10 matching lines...) Expand all
4101 encryption_entries_end_ = encryption_entries_; 4224 encryption_entries_end_ = encryption_entries_;
4102 } 4225 }
4103 4226
4104 pos = start; 4227 pos = start;
4105 while (pos < stop) { 4228 while (pos < stop) {
4106 long long id, size; 4229 long long id, size;
4107 long status = ParseElementHeader(pReader, pos, stop, id, size); 4230 long status = ParseElementHeader(pReader, pos, stop, id, size);
4108 if (status < 0) // error 4231 if (status < 0) // error
4109 return status; 4232 return status;
4110 4233
4111 if (id == 0x1031) { 4234 if (id == mkvmuxer::kMkvContentEncodingOrder) {
4112 // ContentEncodingOrder
4113 encoding_order_ = UnserializeUInt(pReader, pos, size); 4235 encoding_order_ = UnserializeUInt(pReader, pos, size);
4114 } else if (id == 0x1032) { 4236 } else if (id == mkvmuxer::kMkvContentEncodingScope) {
4115 // ContentEncodingScope
4116 encoding_scope_ = UnserializeUInt(pReader, pos, size); 4237 encoding_scope_ = UnserializeUInt(pReader, pos, size);
4117 if (encoding_scope_ < 1) 4238 if (encoding_scope_ < 1)
4118 return -1; 4239 return -1;
4119 } else if (id == 0x1033) { 4240 } else if (id == mkvmuxer::kMkvContentEncodingType) {
4120 // ContentEncodingType
4121 encoding_type_ = UnserializeUInt(pReader, pos, size); 4241 encoding_type_ = UnserializeUInt(pReader, pos, size);
4122 } else if (id == 0x1034) { 4242 } else if (id == mkvmuxer::kMkvContentCompression) {
4123 // ContentCompression ID
4124 ContentCompression* const compression = 4243 ContentCompression* const compression =
4125 new (std::nothrow) ContentCompression(); 4244 new (std::nothrow) ContentCompression();
4126 if (!compression) 4245 if (!compression)
4127 return -1; 4246 return -1;
4128 4247
4129 status = ParseCompressionEntry(pos, size, pReader, compression); 4248 status = ParseCompressionEntry(pos, size, pReader, compression);
4130 if (status) { 4249 if (status) {
4131 delete compression; 4250 delete compression;
4132 return status; 4251 return status;
4133 } 4252 }
4134 *compression_entries_end_++ = compression; 4253 *compression_entries_end_++ = compression;
4135 } else if (id == 0x1035) { 4254 } else if (id == mkvmuxer::kMkvContentEncryption) {
4136 // ContentEncryption ID
4137 ContentEncryption* const encryption = 4255 ContentEncryption* const encryption =
4138 new (std::nothrow) ContentEncryption(); 4256 new (std::nothrow) ContentEncryption();
4139 if (!encryption) 4257 if (!encryption)
4140 return -1; 4258 return -1;
4141 4259
4142 status = ParseEncryptionEntry(pos, size, pReader, encryption); 4260 status = ParseEncryptionEntry(pos, size, pReader, encryption);
4143 if (status) { 4261 if (status) {
4144 delete encryption; 4262 delete encryption;
4145 return status; 4263 return status;
4146 } 4264 }
4147 *encryption_entries_end_++ = encryption; 4265 *encryption_entries_end_++ = encryption;
4148 } 4266 }
4149 4267
4150 pos += size; // consume payload 4268 pos += size; // consume payload
4151 assert(pos <= stop); 4269 if (pos > stop)
4270 return E_FILE_FORMAT_INVALID;
4152 } 4271 }
4153 4272
4154 assert(pos == stop); 4273 if (pos != stop)
4274 return E_FILE_FORMAT_INVALID;
4155 return 0; 4275 return 0;
4156 } 4276 }
4157 4277
4158 long ContentEncoding::ParseCompressionEntry(long long start, long long size, 4278 long ContentEncoding::ParseCompressionEntry(long long start, long long size,
4159 IMkvReader* pReader, 4279 IMkvReader* pReader,
4160 ContentCompression* compression) { 4280 ContentCompression* compression) {
4161 assert(pReader); 4281 assert(pReader);
4162 assert(compression); 4282 assert(compression);
4163 4283
4164 long long pos = start; 4284 long long pos = start;
4165 const long long stop = start + size; 4285 const long long stop = start + size;
4166 4286
4167 bool valid = false; 4287 bool valid = false;
4168 4288
4169 while (pos < stop) { 4289 while (pos < stop) {
4170 long long id, size; 4290 long long id, size;
4171 const long status = ParseElementHeader(pReader, pos, stop, id, size); 4291 const long status = ParseElementHeader(pReader, pos, stop, id, size);
4172 if (status < 0) // error 4292 if (status < 0) // error
4173 return status; 4293 return status;
4174 4294
4175 if (id == 0x254) { 4295 if (id == mkvmuxer::kMkvContentCompAlgo) {
4176 // ContentCompAlgo
4177 long long algo = UnserializeUInt(pReader, pos, size); 4296 long long algo = UnserializeUInt(pReader, pos, size);
4178 if (algo < 0) 4297 if (algo < 0)
4179 return E_FILE_FORMAT_INVALID; 4298 return E_FILE_FORMAT_INVALID;
4180 compression->algo = algo; 4299 compression->algo = algo;
4181 valid = true; 4300 valid = true;
4182 } else if (id == 0x255) { 4301 } else if (id == mkvmuxer::kMkvContentCompSettings) {
4183 // ContentCompSettings
4184 if (size <= 0) 4302 if (size <= 0)
4185 return E_FILE_FORMAT_INVALID; 4303 return E_FILE_FORMAT_INVALID;
4186 4304
4187 const size_t buflen = static_cast<size_t>(size); 4305 const size_t buflen = static_cast<size_t>(size);
4188 typedef unsigned char* buf_t; 4306 unsigned char* buf = SafeArrayAlloc<unsigned char>(1, buflen);
4189 const buf_t buf = new (std::nothrow) unsigned char[buflen];
4190 if (buf == NULL) 4307 if (buf == NULL)
4191 return -1; 4308 return -1;
4192 4309
4193 const int read_status = 4310 const int read_status =
4194 pReader->Read(pos, static_cast<long>(buflen), buf); 4311 pReader->Read(pos, static_cast<long>(buflen), buf);
4195 if (read_status) { 4312 if (read_status) {
4196 delete[] buf; 4313 delete[] buf;
4197 return status; 4314 return status;
4198 } 4315 }
4199 4316
4200 compression->settings = buf; 4317 compression->settings = buf;
4201 compression->settings_len = buflen; 4318 compression->settings_len = buflen;
4202 } 4319 }
4203 4320
4204 pos += size; // consume payload 4321 pos += size; // consume payload
4205 assert(pos <= stop); 4322 if (pos > stop)
4323 return E_FILE_FORMAT_INVALID;
4206 } 4324 }
4207 4325
4208 // ContentCompAlgo is mandatory 4326 // ContentCompAlgo is mandatory
4209 if (!valid) 4327 if (!valid)
4210 return E_FILE_FORMAT_INVALID; 4328 return E_FILE_FORMAT_INVALID;
4211 4329
4212 return 0; 4330 return 0;
4213 } 4331 }
4214 4332
4215 long ContentEncoding::ParseEncryptionEntry(long long start, long long size, 4333 long ContentEncoding::ParseEncryptionEntry(long long start, long long size,
4216 IMkvReader* pReader, 4334 IMkvReader* pReader,
4217 ContentEncryption* encryption) { 4335 ContentEncryption* encryption) {
4218 assert(pReader); 4336 assert(pReader);
4219 assert(encryption); 4337 assert(encryption);
4220 4338
4221 long long pos = start; 4339 long long pos = start;
4222 const long long stop = start + size; 4340 const long long stop = start + size;
4223 4341
4224 while (pos < stop) { 4342 while (pos < stop) {
4225 long long id, size; 4343 long long id, size;
4226 const long status = ParseElementHeader(pReader, pos, stop, id, size); 4344 const long status = ParseElementHeader(pReader, pos, stop, id, size);
4227 if (status < 0) // error 4345 if (status < 0) // error
4228 return status; 4346 return status;
4229 4347
4230 if (id == 0x7E1) { 4348 if (id == mkvmuxer::kMkvContentEncAlgo) {
4231 // ContentEncAlgo
4232 encryption->algo = UnserializeUInt(pReader, pos, size); 4349 encryption->algo = UnserializeUInt(pReader, pos, size);
4233 if (encryption->algo != 5) 4350 if (encryption->algo != 5)
4234 return E_FILE_FORMAT_INVALID; 4351 return E_FILE_FORMAT_INVALID;
4235 } else if (id == 0x7E2) { 4352 } else if (id == mkvmuxer::kMkvContentEncKeyID) {
4236 // ContentEncKeyID
4237 delete[] encryption->key_id; 4353 delete[] encryption->key_id;
4238 encryption->key_id = NULL; 4354 encryption->key_id = NULL;
4239 encryption->key_id_len = 0; 4355 encryption->key_id_len = 0;
4240 4356
4241 if (size <= 0) 4357 if (size <= 0)
4242 return E_FILE_FORMAT_INVALID; 4358 return E_FILE_FORMAT_INVALID;
4243 4359
4244 const size_t buflen = static_cast<size_t>(size); 4360 const size_t buflen = static_cast<size_t>(size);
4245 typedef unsigned char* buf_t; 4361 unsigned char* buf = SafeArrayAlloc<unsigned char>(1, buflen);
4246 const buf_t buf = new (std::nothrow) unsigned char[buflen];
4247 if (buf == NULL) 4362 if (buf == NULL)
4248 return -1; 4363 return -1;
4249 4364
4250 const int read_status = 4365 const int read_status =
4251 pReader->Read(pos, static_cast<long>(buflen), buf); 4366 pReader->Read(pos, static_cast<long>(buflen), buf);
4252 if (read_status) { 4367 if (read_status) {
4253 delete[] buf; 4368 delete[] buf;
4254 return status; 4369 return status;
4255 } 4370 }
4256 4371
4257 encryption->key_id = buf; 4372 encryption->key_id = buf;
4258 encryption->key_id_len = buflen; 4373 encryption->key_id_len = buflen;
4259 } else if (id == 0x7E3) { 4374 } else if (id == mkvmuxer::kMkvContentSignature) {
4260 // ContentSignature
4261 delete[] encryption->signature; 4375 delete[] encryption->signature;
4262 encryption->signature = NULL; 4376 encryption->signature = NULL;
4263 encryption->signature_len = 0; 4377 encryption->signature_len = 0;
4264 4378
4265 if (size <= 0) 4379 if (size <= 0)
4266 return E_FILE_FORMAT_INVALID; 4380 return E_FILE_FORMAT_INVALID;
4267 4381
4268 const size_t buflen = static_cast<size_t>(size); 4382 const size_t buflen = static_cast<size_t>(size);
4269 typedef unsigned char* buf_t; 4383 unsigned char* buf = SafeArrayAlloc<unsigned char>(1, buflen);
4270 const buf_t buf = new (std::nothrow) unsigned char[buflen];
4271 if (buf == NULL) 4384 if (buf == NULL)
4272 return -1; 4385 return -1;
4273 4386
4274 const int read_status = 4387 const int read_status =
4275 pReader->Read(pos, static_cast<long>(buflen), buf); 4388 pReader->Read(pos, static_cast<long>(buflen), buf);
4276 if (read_status) { 4389 if (read_status) {
4277 delete[] buf; 4390 delete[] buf;
4278 return status; 4391 return status;
4279 } 4392 }
4280 4393
4281 encryption->signature = buf; 4394 encryption->signature = buf;
4282 encryption->signature_len = buflen; 4395 encryption->signature_len = buflen;
4283 } else if (id == 0x7E4) { 4396 } else if (id == mkvmuxer::kMkvContentSigKeyID) {
4284 // ContentSigKeyID
4285 delete[] encryption->sig_key_id; 4397 delete[] encryption->sig_key_id;
4286 encryption->sig_key_id = NULL; 4398 encryption->sig_key_id = NULL;
4287 encryption->sig_key_id_len = 0; 4399 encryption->sig_key_id_len = 0;
4288 4400
4289 if (size <= 0) 4401 if (size <= 0)
4290 return E_FILE_FORMAT_INVALID; 4402 return E_FILE_FORMAT_INVALID;
4291 4403
4292 const size_t buflen = static_cast<size_t>(size); 4404 const size_t buflen = static_cast<size_t>(size);
4293 typedef unsigned char* buf_t; 4405 unsigned char* buf = SafeArrayAlloc<unsigned char>(1, buflen);
4294 const buf_t buf = new (std::nothrow) unsigned char[buflen];
4295 if (buf == NULL) 4406 if (buf == NULL)
4296 return -1; 4407 return -1;
4297 4408
4298 const int read_status = 4409 const int read_status =
4299 pReader->Read(pos, static_cast<long>(buflen), buf); 4410 pReader->Read(pos, static_cast<long>(buflen), buf);
4300 if (read_status) { 4411 if (read_status) {
4301 delete[] buf; 4412 delete[] buf;
4302 return status; 4413 return status;
4303 } 4414 }
4304 4415
4305 encryption->sig_key_id = buf; 4416 encryption->sig_key_id = buf;
4306 encryption->sig_key_id_len = buflen; 4417 encryption->sig_key_id_len = buflen;
4307 } else if (id == 0x7E5) { 4418 } else if (id == mkvmuxer::kMkvContentSigAlgo) {
4308 // ContentSigAlgo
4309 encryption->sig_algo = UnserializeUInt(pReader, pos, size); 4419 encryption->sig_algo = UnserializeUInt(pReader, pos, size);
4310 } else if (id == 0x7E6) { 4420 } else if (id == mkvmuxer::kMkvContentSigHashAlgo) {
4311 // ContentSigHashAlgo
4312 encryption->sig_hash_algo = UnserializeUInt(pReader, pos, size); 4421 encryption->sig_hash_algo = UnserializeUInt(pReader, pos, size);
4313 } else if (id == 0x7E7) { 4422 } else if (id == mkvmuxer::kMkvContentEncAESSettings) {
4314 // ContentEncAESSettings
4315 const long status = ParseContentEncAESSettingsEntry( 4423 const long status = ParseContentEncAESSettingsEntry(
4316 pos, size, pReader, &encryption->aes_settings); 4424 pos, size, pReader, &encryption->aes_settings);
4317 if (status) 4425 if (status)
4318 return status; 4426 return status;
4319 } 4427 }
4320 4428
4321 pos += size; // consume payload 4429 pos += size; // consume payload
4322 assert(pos <= stop); 4430 if (pos > stop)
4431 return E_FILE_FORMAT_INVALID;
4323 } 4432 }
4324 4433
4325 return 0; 4434 return 0;
4326 } 4435 }
4327 4436
4328 Track::Track(Segment* pSegment, long long element_start, long long element_size) 4437 Track::Track(Segment* pSegment, long long element_start, long long element_size)
4329 : m_pSegment(pSegment), 4438 : m_pSegment(pSegment),
4330 m_element_start(element_start), 4439 m_element_start(element_start),
4331 m_element_size(element_size), 4440 m_element_size(element_size),
4332 content_encoding_entries_(NULL), 4441 content_encoding_entries_(NULL),
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after
4411 if (dst) // should be NULL already 4520 if (dst) // should be NULL already
4412 return -1; 4521 return -1;
4413 4522
4414 const char* const src = this->*str; 4523 const char* const src = this->*str;
4415 4524
4416 if (src == NULL) 4525 if (src == NULL)
4417 return 0; 4526 return 0;
4418 4527
4419 const size_t len = strlen(src); 4528 const size_t len = strlen(src);
4420 4529
4421 dst = new (std::nothrow) char[len + 1]; 4530 dst = SafeArrayAlloc<char>(1, len + 1);
4422 4531
4423 if (dst == NULL) 4532 if (dst == NULL)
4424 return -1; 4533 return -1;
4425 4534
4426 strcpy(dst, src); 4535 strcpy(dst, src);
4427 4536
4428 return 0; 4537 return 0;
4429 } 4538 }
4430 4539
4431 int Track::Info::Copy(Info& dst) const { 4540 int Track::Info::Copy(Info& dst) const {
(...skipping 30 matching lines...) Expand all
4462 if (codecPrivateSize > 0) { 4571 if (codecPrivateSize > 0) {
4463 if (codecPrivate == NULL) 4572 if (codecPrivate == NULL)
4464 return -1; 4573 return -1;
4465 4574
4466 if (dst.codecPrivate) 4575 if (dst.codecPrivate)
4467 return -1; 4576 return -1;
4468 4577
4469 if (dst.codecPrivateSize != 0) 4578 if (dst.codecPrivateSize != 0)
4470 return -1; 4579 return -1;
4471 4580
4472 dst.codecPrivate = new (std::nothrow) unsigned char[codecPrivateSize]; 4581 dst.codecPrivate = SafeArrayAlloc<unsigned char>(1, codecPrivateSize);
4473 4582
4474 if (dst.codecPrivate == NULL) 4583 if (dst.codecPrivate == NULL)
4475 return -1; 4584 return -1;
4476 4585
4477 memcpy(dst.codecPrivate, codecPrivate, codecPrivateSize); 4586 memcpy(dst.codecPrivate, codecPrivate, codecPrivateSize);
4478 dst.codecPrivateSize = codecPrivateSize; 4587 dst.codecPrivateSize = codecPrivateSize;
4479 } 4588 }
4480 4589
4481 return 0; 4590 return 0;
4482 } 4591 }
(...skipping 307 matching lines...) Expand 10 before | Expand all | Expand 10 after
4790 4899
4791 // Count ContentEncoding elements. 4900 // Count ContentEncoding elements.
4792 int count = 0; 4901 int count = 0;
4793 while (pos < stop) { 4902 while (pos < stop) {
4794 long long id, size; 4903 long long id, size;
4795 const long status = ParseElementHeader(pReader, pos, stop, id, size); 4904 const long status = ParseElementHeader(pReader, pos, stop, id, size);
4796 if (status < 0) // error 4905 if (status < 0) // error
4797 return status; 4906 return status;
4798 4907
4799 // pos now designates start of element 4908 // pos now designates start of element
4800 if (id == 0x2240) // ContentEncoding ID 4909 if (id == mkvmuxer::kMkvContentEncoding)
4801 ++count; 4910 ++count;
4802 4911
4803 pos += size; // consume payload 4912 pos += size; // consume payload
4804 assert(pos <= stop); 4913 if (pos > stop)
4914 return E_FILE_FORMAT_INVALID;
4805 } 4915 }
4806 4916
4807 if (count <= 0) 4917 if (count <= 0)
4808 return -1; 4918 return -1;
4809 4919
4810 content_encoding_entries_ = new (std::nothrow) ContentEncoding*[count]; 4920 content_encoding_entries_ = new (std::nothrow) ContentEncoding*[count];
4811 if (!content_encoding_entries_) 4921 if (!content_encoding_entries_)
4812 return -1; 4922 return -1;
4813 4923
4814 content_encoding_entries_end_ = content_encoding_entries_; 4924 content_encoding_entries_end_ = content_encoding_entries_;
4815 4925
4816 pos = start; 4926 pos = start;
4817 while (pos < stop) { 4927 while (pos < stop) {
4818 long long id, size; 4928 long long id, size;
4819 long status = ParseElementHeader(pReader, pos, stop, id, size); 4929 long status = ParseElementHeader(pReader, pos, stop, id, size);
4820 if (status < 0) // error 4930 if (status < 0) // error
4821 return status; 4931 return status;
4822 4932
4823 // pos now designates start of element 4933 // pos now designates start of element
4824 if (id == 0x2240) { // ContentEncoding ID 4934 if (id == mkvmuxer::kMkvContentEncoding) {
4825 ContentEncoding* const content_encoding = 4935 ContentEncoding* const content_encoding =
4826 new (std::nothrow) ContentEncoding(); 4936 new (std::nothrow) ContentEncoding();
4827 if (!content_encoding) 4937 if (!content_encoding)
4828 return -1; 4938 return -1;
4829 4939
4830 status = content_encoding->ParseContentEncodingEntry(pos, size, pReader); 4940 status = content_encoding->ParseContentEncodingEntry(pos, size, pReader);
4831 if (status) { 4941 if (status) {
4832 delete content_encoding; 4942 delete content_encoding;
4833 return status; 4943 return status;
4834 } 4944 }
4835 4945
4836 *content_encoding_entries_end_++ = content_encoding; 4946 *content_encoding_entries_end_++ = content_encoding;
4837 } 4947 }
4838 4948
4839 pos += size; // consume payload 4949 pos += size; // consume payload
4840 assert(pos <= stop); 4950 if (pos > stop)
4951 return E_FILE_FORMAT_INVALID;
4841 } 4952 }
4842 4953
4843 assert(pos == stop); 4954 if (pos != stop)
4955 return E_FILE_FORMAT_INVALID;
4844 4956
4845 return 0; 4957 return 0;
4846 } 4958 }
4847 4959
4848 Track::EOSBlock::EOSBlock() : BlockEntry(NULL, LONG_MIN) {} 4960 Track::EOSBlock::EOSBlock() : BlockEntry(NULL, LONG_MIN) {}
4849 4961
4850 BlockEntry::Kind Track::EOSBlock::GetKind() const { return kBlockEOS; } 4962 BlockEntry::Kind Track::EOSBlock::GetKind() const { return kBlockEOS; }
4851 4963
4852 const Block* Track::EOSBlock::GetBlock() const { return NULL; } 4964 const Block* Track::EOSBlock::GetBlock() const { return NULL; }
4853 4965
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
4885 const long long stop = pos + s.size; 4997 const long long stop = pos + s.size;
4886 4998
4887 while (pos < stop) { 4999 while (pos < stop) {
4888 long long id, size; 5000 long long id, size;
4889 5001
4890 const long status = ParseElementHeader(pReader, pos, stop, id, size); 5002 const long status = ParseElementHeader(pReader, pos, stop, id, size);
4891 5003
4892 if (status < 0) // error 5004 if (status < 0) // error
4893 return status; 5005 return status;
4894 5006
4895 if (id == 0x30) { // pixel width 5007 if (id == mkvmuxer::kMkvPixelWidth) {
4896 width = UnserializeUInt(pReader, pos, size); 5008 width = UnserializeUInt(pReader, pos, size);
4897 5009
4898 if (width <= 0) 5010 if (width <= 0)
4899 return E_FILE_FORMAT_INVALID; 5011 return E_FILE_FORMAT_INVALID;
4900 } else if (id == 0x3A) { // pixel height 5012 } else if (id == mkvmuxer::kMkvPixelHeight) {
4901 height = UnserializeUInt(pReader, pos, size); 5013 height = UnserializeUInt(pReader, pos, size);
4902 5014
4903 if (height <= 0) 5015 if (height <= 0)
4904 return E_FILE_FORMAT_INVALID; 5016 return E_FILE_FORMAT_INVALID;
4905 } else if (id == 0x14B0) { // display width 5017 } else if (id == mkvmuxer::kMkvDisplayWidth) {
4906 display_width = UnserializeUInt(pReader, pos, size); 5018 display_width = UnserializeUInt(pReader, pos, size);
4907 5019
4908 if (display_width <= 0) 5020 if (display_width <= 0)
4909 return E_FILE_FORMAT_INVALID; 5021 return E_FILE_FORMAT_INVALID;
4910 } else if (id == 0x14BA) { // display height 5022 } else if (id == mkvmuxer::kMkvDisplayHeight) {
4911 display_height = UnserializeUInt(pReader, pos, size); 5023 display_height = UnserializeUInt(pReader, pos, size);
4912 5024
4913 if (display_height <= 0) 5025 if (display_height <= 0)
4914 return E_FILE_FORMAT_INVALID; 5026 return E_FILE_FORMAT_INVALID;
4915 } else if (id == 0x14B2) { // display unit 5027 } else if (id == mkvmuxer::kMkvDisplayUnit) {
4916 display_unit = UnserializeUInt(pReader, pos, size); 5028 display_unit = UnserializeUInt(pReader, pos, size);
4917 5029
4918 if (display_unit < 0) 5030 if (display_unit < 0)
4919 return E_FILE_FORMAT_INVALID; 5031 return E_FILE_FORMAT_INVALID;
4920 } else if (id == 0x13B8) { // stereo mode 5032 } else if (id == mkvmuxer::kMkvStereoMode) {
4921 stereo_mode = UnserializeUInt(pReader, pos, size); 5033 stereo_mode = UnserializeUInt(pReader, pos, size);
4922 5034
4923 if (stereo_mode < 0) 5035 if (stereo_mode < 0)
4924 return E_FILE_FORMAT_INVALID; 5036 return E_FILE_FORMAT_INVALID;
4925 } else if (id == 0x0383E3) { // frame rate 5037 } else if (id == mkvmuxer::kMkvFrameRate) {
4926 const long status = UnserializeFloat(pReader, pos, size, rate); 5038 const long status = UnserializeFloat(pReader, pos, size, rate);
4927 5039
4928 if (status < 0) 5040 if (status < 0)
4929 return status; 5041 return status;
4930 5042
4931 if (rate <= 0) 5043 if (rate <= 0)
4932 return E_FILE_FORMAT_INVALID; 5044 return E_FILE_FORMAT_INVALID;
4933 } 5045 }
4934 5046
4935 pos += size; // consume payload 5047 pos += size; // consume payload
4936 assert(pos <= stop); 5048 if (pos > stop)
5049 return E_FILE_FORMAT_INVALID;
4937 } 5050 }
4938 5051
4939 assert(pos == stop); 5052 if (pos != stop)
5053 return E_FILE_FORMAT_INVALID;
4940 5054
4941 VideoTrack* const pTrack = 5055 VideoTrack* const pTrack =
4942 new (std::nothrow) VideoTrack(pSegment, element_start, element_size); 5056 new (std::nothrow) VideoTrack(pSegment, element_start, element_size);
4943 5057
4944 if (pTrack == NULL) 5058 if (pTrack == NULL)
4945 return -1; // generic error 5059 return -1; // generic error
4946 5060
4947 const int status = info.Copy(pTrack->m_info); 5061 const int status = info.Copy(pTrack->m_info);
4948 5062
4949 if (status) { // error 5063 if (status) { // error
(...skipping 153 matching lines...) Expand 10 before | Expand all | Expand 10 after
5103 long long bit_depth = 0; 5217 long long bit_depth = 0;
5104 5218
5105 while (pos < stop) { 5219 while (pos < stop) {
5106 long long id, size; 5220 long long id, size;
5107 5221
5108 long status = ParseElementHeader(pReader, pos, stop, id, size); 5222 long status = ParseElementHeader(pReader, pos, stop, id, size);
5109 5223
5110 if (status < 0) // error 5224 if (status < 0) // error
5111 return status; 5225 return status;
5112 5226
5113 if (id == 0x35) { // Sample Rate 5227 if (id == mkvmuxer::kMkvSamplingFrequency) {
5114 status = UnserializeFloat(pReader, pos, size, rate); 5228 status = UnserializeFloat(pReader, pos, size, rate);
5115 5229
5116 if (status < 0) 5230 if (status < 0)
5117 return status; 5231 return status;
5118 5232
5119 if (rate <= 0) 5233 if (rate <= 0)
5120 return E_FILE_FORMAT_INVALID; 5234 return E_FILE_FORMAT_INVALID;
5121 } else if (id == 0x1F) { // Channel Count 5235 } else if (id == mkvmuxer::kMkvChannels) {
5122 channels = UnserializeUInt(pReader, pos, size); 5236 channels = UnserializeUInt(pReader, pos, size);
5123 5237
5124 if (channels <= 0) 5238 if (channels <= 0)
5125 return E_FILE_FORMAT_INVALID; 5239 return E_FILE_FORMAT_INVALID;
5126 } else if (id == 0x2264) { // Bit Depth 5240 } else if (id == mkvmuxer::kMkvBitDepth) {
5127 bit_depth = UnserializeUInt(pReader, pos, size); 5241 bit_depth = UnserializeUInt(pReader, pos, size);
5128 5242
5129 if (bit_depth <= 0) 5243 if (bit_depth <= 0)
5130 return E_FILE_FORMAT_INVALID; 5244 return E_FILE_FORMAT_INVALID;
5131 } 5245 }
5132 5246
5133 pos += size; // consume payload 5247 pos += size; // consume payload
5134 assert(pos <= stop); 5248 if (pos > stop)
5249 return E_FILE_FORMAT_INVALID;
5135 } 5250 }
5136 5251
5137 assert(pos == stop); 5252 if (pos != stop)
5253 return E_FILE_FORMAT_INVALID;
5138 5254
5139 AudioTrack* const pTrack = 5255 AudioTrack* const pTrack =
5140 new (std::nothrow) AudioTrack(pSegment, element_start, element_size); 5256 new (std::nothrow) AudioTrack(pSegment, element_start, element_size);
5141 5257
5142 if (pTrack == NULL) 5258 if (pTrack == NULL)
5143 return -1; // generic error 5259 return -1; // generic error
5144 5260
5145 const int status = info.Copy(pTrack->m_info); 5261 const int status = info.Copy(pTrack->m_info);
5146 5262
5147 if (status) { 5263 if (status) {
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
5187 long long id, size; 5303 long long id, size;
5188 5304
5189 const long status = ParseElementHeader(pReader, pos, stop, id, size); 5305 const long status = ParseElementHeader(pReader, pos, stop, id, size);
5190 5306
5191 if (status < 0) // error 5307 if (status < 0) // error
5192 return status; 5308 return status;
5193 5309
5194 if (size == 0) // weird 5310 if (size == 0) // weird
5195 continue; 5311 continue;
5196 5312
5197 if (id == 0x2E) // TrackEntry ID 5313 if (id == mkvmuxer::kMkvTrackEntry)
5198 ++count; 5314 ++count;
5199 5315
5200 pos += size; // consume payload 5316 pos += size; // consume payload
5201 assert(pos <= stop); 5317 if (pos > stop)
5318 return E_FILE_FORMAT_INVALID;
5202 } 5319 }
5203 5320
5204 assert(pos == stop); 5321 if (pos != stop)
5322 return E_FILE_FORMAT_INVALID;
5205 5323
5206 if (count <= 0) 5324 if (count <= 0)
5207 return 0; // success 5325 return 0; // success
5208 5326
5209 m_trackEntries = new (std::nothrow) Track*[count]; 5327 m_trackEntries = new (std::nothrow) Track*[count];
5210 5328
5211 if (m_trackEntries == NULL) 5329 if (m_trackEntries == NULL)
5212 return -1; 5330 return -1;
5213 5331
5214 m_trackEntriesEnd = m_trackEntries; 5332 m_trackEntriesEnd = m_trackEntries;
(...skipping 12 matching lines...) Expand all
5227 return status; 5345 return status;
5228 5346
5229 if (payload_size == 0) // weird 5347 if (payload_size == 0) // weird
5230 continue; 5348 continue;
5231 5349
5232 const long long payload_stop = pos + payload_size; 5350 const long long payload_stop = pos + payload_size;
5233 assert(payload_stop <= stop); // checked in ParseElement 5351 assert(payload_stop <= stop); // checked in ParseElement
5234 5352
5235 const long long element_size = payload_stop - element_start; 5353 const long long element_size = payload_stop - element_start;
5236 5354
5237 if (id == 0x2E) { // TrackEntry ID 5355 if (id == mkvmuxer::kMkvTrackEntry) {
5238 Track*& pTrack = *m_trackEntriesEnd; 5356 Track*& pTrack = *m_trackEntriesEnd;
5239 pTrack = NULL; 5357 pTrack = NULL;
5240 5358
5241 const long status = ParseTrackEntry(pos, payload_size, element_start, 5359 const long status = ParseTrackEntry(pos, payload_size, element_start,
5242 element_size, pTrack); 5360 element_size, pTrack);
5243
5244 if (status) 5361 if (status)
5245 return status; 5362 return status;
5246 5363
5247 if (pTrack) 5364 if (pTrack)
5248 ++m_trackEntriesEnd; 5365 ++m_trackEntriesEnd;
5249 } 5366 }
5250 5367
5251 pos = payload_stop; 5368 pos = payload_stop;
5252 assert(pos <= stop); 5369 if (pos > stop)
5370 return E_FILE_FORMAT_INVALID;
5253 } 5371 }
5254 5372
5255 assert(pos == stop); 5373 if (pos != stop)
5374 return E_FILE_FORMAT_INVALID;
5256 5375
5257 return 0; // success 5376 return 0; // success
5258 } 5377 }
5259 5378
5260 unsigned long Tracks::GetTracksCount() const { 5379 unsigned long Tracks::GetTracksCount() const {
5261 const ptrdiff_t result = m_trackEntriesEnd - m_trackEntries; 5380 const ptrdiff_t result = m_trackEntriesEnd - m_trackEntries;
5262 assert(result >= 0); 5381 assert(result >= 0);
5263 5382
5264 return static_cast<unsigned long>(result); 5383 return static_cast<unsigned long>(result);
5265 } 5384 }
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
5302 const long status = ParseElementHeader(pReader, pos, track_stop, id, size); 5421 const long status = ParseElementHeader(pReader, pos, track_stop, id, size);
5303 5422
5304 if (status < 0) // error 5423 if (status < 0) // error
5305 return status; 5424 return status;
5306 5425
5307 if (size < 0) 5426 if (size < 0)
5308 return E_FILE_FORMAT_INVALID; 5427 return E_FILE_FORMAT_INVALID;
5309 5428
5310 const long long start = pos; 5429 const long long start = pos;
5311 5430
5312 if (id == 0x60) { // VideoSettings ID 5431 if (id == mkvmuxer::kMkvVideo) {
5313 v.start = start; 5432 v.start = start;
5314 v.size = size; 5433 v.size = size;
5315 } else if (id == 0x61) { // AudioSettings ID 5434 } else if (id == mkvmuxer::kMkvAudio) {
5316 a.start = start; 5435 a.start = start;
5317 a.size = size; 5436 a.size = size;
5318 } else if (id == 0x2D80) { // ContentEncodings ID 5437 } else if (id == mkvmuxer::kMkvContentEncodings) {
5319 e.start = start; 5438 e.start = start;
5320 e.size = size; 5439 e.size = size;
5321 } else if (id == 0x33C5) { // Track UID 5440 } else if (id == mkvmuxer::kMkvTrackUID) {
5322 if (size > 8) 5441 if (size > 8)
5323 return E_FILE_FORMAT_INVALID; 5442 return E_FILE_FORMAT_INVALID;
5324 5443
5325 info.uid = 0; 5444 info.uid = 0;
5326 5445
5327 long long pos_ = start; 5446 long long pos_ = start;
5328 const long long pos_end = start + size; 5447 const long long pos_end = start + size;
5329 5448
5330 while (pos_ != pos_end) { 5449 while (pos_ != pos_end) {
5331 unsigned char b; 5450 unsigned char b;
5332 5451
5333 const int status = pReader->Read(pos_, 1, &b); 5452 const int status = pReader->Read(pos_, 1, &b);
5334 5453
5335 if (status) 5454 if (status)
5336 return status; 5455 return status;
5337 5456
5338 info.uid <<= 8; 5457 info.uid <<= 8;
5339 info.uid |= b; 5458 info.uid |= b;
5340 5459
5341 ++pos_; 5460 ++pos_;
5342 } 5461 }
5343 } else if (id == 0x57) { // Track Number 5462 } else if (id == mkvmuxer::kMkvTrackNumber) {
5344 const long long num = UnserializeUInt(pReader, pos, size); 5463 const long long num = UnserializeUInt(pReader, pos, size);
5345 5464
5346 if ((num <= 0) || (num > 127)) 5465 if ((num <= 0) || (num > 127))
5347 return E_FILE_FORMAT_INVALID; 5466 return E_FILE_FORMAT_INVALID;
5348 5467
5349 info.number = static_cast<long>(num); 5468 info.number = static_cast<long>(num);
5350 } else if (id == 0x03) { // Track Type 5469 } else if (id == mkvmuxer::kMkvTrackType) {
5351 const long long type = UnserializeUInt(pReader, pos, size); 5470 const long long type = UnserializeUInt(pReader, pos, size);
5352 5471
5353 if ((type <= 0) || (type > 254)) 5472 if ((type <= 0) || (type > 254))
5354 return E_FILE_FORMAT_INVALID; 5473 return E_FILE_FORMAT_INVALID;
5355 5474
5356 info.type = static_cast<long>(type); 5475 info.type = static_cast<long>(type);
5357 } else if (id == 0x136E) { // Track Name 5476 } else if (id == mkvmuxer::kMkvName) {
5358 const long status = 5477 const long status =
5359 UnserializeString(pReader, pos, size, info.nameAsUTF8); 5478 UnserializeString(pReader, pos, size, info.nameAsUTF8);
5360 5479
5361 if (status) 5480 if (status)
5362 return status; 5481 return status;
5363 } else if (id == 0x02B59C) { // Track Language 5482 } else if (id == mkvmuxer::kMkvLanguage) {
5364 const long status = UnserializeString(pReader, pos, size, info.language); 5483 const long status = UnserializeString(pReader, pos, size, info.language);
5365 5484
5366 if (status) 5485 if (status)
5367 return status; 5486 return status;
5368 } else if (id == 0x03E383) { // Default Duration 5487 } else if (id == mkvmuxer::kMkvDefaultDuration) {
5369 const long long duration = UnserializeUInt(pReader, pos, size); 5488 const long long duration = UnserializeUInt(pReader, pos, size);
5370 5489
5371 if (duration < 0) 5490 if (duration < 0)
5372 return E_FILE_FORMAT_INVALID; 5491 return E_FILE_FORMAT_INVALID;
5373 5492
5374 info.defaultDuration = static_cast<unsigned long long>(duration); 5493 info.defaultDuration = static_cast<unsigned long long>(duration);
5375 } else if (id == 0x06) { // CodecID 5494 } else if (id == mkvmuxer::kMkvCodecID) {
5376 const long status = UnserializeString(pReader, pos, size, info.codecId); 5495 const long status = UnserializeString(pReader, pos, size, info.codecId);
5377 5496
5378 if (status) 5497 if (status)
5379 return status; 5498 return status;
5380 } else if (id == 0x1C) { // lacing 5499 } else if (id == mkvmuxer::kMkvFlagLacing) {
5381 lacing = UnserializeUInt(pReader, pos, size); 5500 lacing = UnserializeUInt(pReader, pos, size);
5382 5501
5383 if ((lacing < 0) || (lacing > 1)) 5502 if ((lacing < 0) || (lacing > 1))
5384 return E_FILE_FORMAT_INVALID; 5503 return E_FILE_FORMAT_INVALID;
5385 } else if (id == 0x23A2) { // Codec Private 5504 } else if (id == mkvmuxer::kMkvCodecPrivate) {
5386 delete[] info.codecPrivate; 5505 delete[] info.codecPrivate;
5387 info.codecPrivate = NULL; 5506 info.codecPrivate = NULL;
5388 info.codecPrivateSize = 0; 5507 info.codecPrivateSize = 0;
5389 5508
5390 const size_t buflen = static_cast<size_t>(size); 5509 const size_t buflen = static_cast<size_t>(size);
5391 5510
5392 if (buflen) { 5511 if (buflen) {
5393 typedef unsigned char* buf_t; 5512 unsigned char* buf = SafeArrayAlloc<unsigned char>(1, buflen);
5394
5395 const buf_t buf = new (std::nothrow) unsigned char[buflen];
5396 5513
5397 if (buf == NULL) 5514 if (buf == NULL)
5398 return -1; 5515 return -1;
5399 5516
5400 const int status = pReader->Read(pos, static_cast<long>(buflen), buf); 5517 const int status = pReader->Read(pos, static_cast<long>(buflen), buf);
5401 5518
5402 if (status) { 5519 if (status) {
5403 delete[] buf; 5520 delete[] buf;
5404 return status; 5521 return status;
5405 } 5522 }
5406 5523
5407 info.codecPrivate = buf; 5524 info.codecPrivate = buf;
5408 info.codecPrivateSize = buflen; 5525 info.codecPrivateSize = buflen;
5409 } 5526 }
5410 } else if (id == 0x058688) { // Codec Name 5527 } else if (id == mkvmuxer::kMkvCodecName) {
5411 const long status = 5528 const long status =
5412 UnserializeString(pReader, pos, size, info.codecNameAsUTF8); 5529 UnserializeString(pReader, pos, size, info.codecNameAsUTF8);
5413 5530
5414 if (status) 5531 if (status)
5415 return status; 5532 return status;
5416 } else if (id == 0x16AA) { // Codec Delay 5533 } else if (id == mkvmuxer::kMkvCodecDelay) {
5417 info.codecDelay = UnserializeUInt(pReader, pos, size); 5534 info.codecDelay = UnserializeUInt(pReader, pos, size);
5418 } else if (id == 0x16BB) { // Seek Pre Roll 5535 } else if (id == mkvmuxer::kMkvSeekPreRoll) {
5419 info.seekPreRoll = UnserializeUInt(pReader, pos, size); 5536 info.seekPreRoll = UnserializeUInt(pReader, pos, size);
5420 } 5537 }
5421 5538
5422 pos += size; // consume payload 5539 pos += size; // consume payload
5423 assert(pos <= track_stop); 5540 if (pos > track_stop)
5541 return E_FILE_FORMAT_INVALID;
5424 } 5542 }
5425 5543
5426 assert(pos == track_stop); 5544 if (pos != track_stop)
5545 return E_FILE_FORMAT_INVALID;
5427 5546
5428 if (info.number <= 0) // not specified 5547 if (info.number <= 0) // not specified
5429 return E_FILE_FORMAT_INVALID; 5548 return E_FILE_FORMAT_INVALID;
5430 5549
5431 if (GetTrackByNumber(info.number)) 5550 if (GetTrackByNumber(info.number))
5432 return E_FILE_FORMAT_INVALID; 5551 return E_FILE_FORMAT_INVALID;
5433 5552
5434 if (info.type <= 0) // not specified 5553 if (info.type <= 0) // not specified
5435 return E_FILE_FORMAT_INVALID; 5554 return E_FILE_FORMAT_INVALID;
5436 5555
(...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after
5545 const Track* Tracks::GetTrackByIndex(unsigned long idx) const { 5664 const Track* Tracks::GetTrackByIndex(unsigned long idx) const {
5546 const ptrdiff_t count = m_trackEntriesEnd - m_trackEntries; 5665 const ptrdiff_t count = m_trackEntriesEnd - m_trackEntries;
5547 5666
5548 if (idx >= static_cast<unsigned long>(count)) 5667 if (idx >= static_cast<unsigned long>(count))
5549 return NULL; 5668 return NULL;
5550 5669
5551 return m_trackEntries[idx]; 5670 return m_trackEntries[idx];
5552 } 5671 }
5553 5672
5554 long Cluster::Load(long long& pos, long& len) const { 5673 long Cluster::Load(long long& pos, long& len) const {
5555 assert(m_pSegment); 5674 if (m_pSegment == NULL)
5556 assert(m_pos >= m_element_start); 5675 return E_PARSE_FAILED;
5557 5676
5558 if (m_timecode >= 0) // at least partially loaded 5677 if (m_timecode >= 0) // at least partially loaded
5559 return 0; 5678 return 0;
5560 5679
5561 assert(m_pos == m_element_start); 5680 if (m_pos != m_element_start || m_element_size >= 0)
5562 assert(m_element_size < 0); 5681 return E_PARSE_FAILED;
5563 5682
5564 IMkvReader* const pReader = m_pSegment->m_pReader; 5683 IMkvReader* const pReader = m_pSegment->m_pReader;
5565
5566 long long total, avail; 5684 long long total, avail;
5567
5568 const int status = pReader->Length(&total, &avail); 5685 const int status = pReader->Length(&total, &avail);
5569 5686
5570 if (status < 0) // error 5687 if (status < 0) // error
5571 return status; 5688 return status;
5572 5689
5573 assert((total < 0) || (avail <= total)); 5690 if (total >= 0 && (avail > total || m_pos > total))
5574 assert((total < 0) || (m_pos <= total)); // TODO: verify this 5691 return E_FILE_FORMAT_INVALID;
5575 5692
5576 pos = m_pos; 5693 pos = m_pos;
5577 5694
5578 long long cluster_size = -1; 5695 long long cluster_size = -1;
5579 5696
5580 { 5697 if ((pos + 1) > avail) {
5581 if ((pos + 1) > avail) { 5698 len = 1;
5582 len = 1; 5699 return E_BUFFER_NOT_FULL;
5583 return E_BUFFER_NOT_FULL; 5700 }
5584 }
5585 5701
5586 long long result = GetUIntLength(pReader, pos, len); 5702 long long result = GetUIntLength(pReader, pos, len);
5587 5703
5588 if (result < 0) // error or underflow 5704 if (result < 0) // error or underflow
5589 return static_cast<long>(result); 5705 return static_cast<long>(result);
5590 5706
5591 if (result > 0) // underflow (weird) 5707 if (result > 0)
5592 return E_BUFFER_NOT_FULL; 5708 return E_BUFFER_NOT_FULL;
5593 5709
5594 // if ((pos + len) > segment_stop) 5710 if ((pos + len) > avail)
5595 // return E_FILE_FORMAT_INVALID; 5711 return E_BUFFER_NOT_FULL;
5596 5712
5597 if ((pos + len) > avail) 5713 const long long id_ = ReadID(pReader, pos, len);
5598 return E_BUFFER_NOT_FULL;
5599 5714
5600 const long long id_ = ReadUInt(pReader, pos, len); 5715 if (id_ < 0) // error
5716 return static_cast<long>(id_);
5601 5717
5602 if (id_ < 0) // error 5718 if (id_ != mkvmuxer::kMkvCluster)
5603 return static_cast<long>(id_); 5719 return E_FILE_FORMAT_INVALID;
5604 5720
5605 if (id_ != 0x0F43B675) // Cluster ID 5721 pos += len; // consume id
5606 return E_FILE_FORMAT_INVALID;
5607 5722
5608 pos += len; // consume id 5723 // read cluster size
5609 5724
5610 // read cluster size 5725 if ((pos + 1) > avail) {
5726 len = 1;
5727 return E_BUFFER_NOT_FULL;
5728 }
5611 5729
5612 if ((pos + 1) > avail) { 5730 result = GetUIntLength(pReader, pos, len);
5613 len = 1;
5614 return E_BUFFER_NOT_FULL;
5615 }
5616 5731
5617 result = GetUIntLength(pReader, pos, len); 5732 if (result < 0) // error
5733 return static_cast<long>(result);
5618 5734
5619 if (result < 0) // error 5735 if (result > 0)
5620 return static_cast<long>(result); 5736 return E_BUFFER_NOT_FULL;
5621 5737
5622 if (result > 0) // weird 5738 if ((pos + len) > avail)
5623 return E_BUFFER_NOT_FULL; 5739 return E_BUFFER_NOT_FULL;
5624 5740
5625 // if ((pos + len) > segment_stop) 5741 const long long size = ReadUInt(pReader, pos, len);
5626 // return E_FILE_FORMAT_INVALID;
5627 5742
5628 if ((pos + len) > avail) 5743 if (size < 0) // error
5629 return E_BUFFER_NOT_FULL; 5744 return static_cast<long>(cluster_size);
5630 5745
5631 const long long size = ReadUInt(pReader, pos, len); 5746 if (size == 0)
5747 return E_FILE_FORMAT_INVALID;
5632 5748
5633 if (size < 0) // error 5749 pos += len; // consume length of size of element
5634 return static_cast<long>(cluster_size);
5635 5750
5636 if (size == 0) 5751 const long long unknown_size = (1LL << (7 * len)) - 1;
5637 return E_FILE_FORMAT_INVALID; // TODO: verify this
5638 5752
5639 pos += len; // consume length of size of element 5753 if (size != unknown_size)
5640 5754 cluster_size = size;
5641 const long long unknown_size = (1LL << (7 * len)) - 1;
5642
5643 if (size != unknown_size)
5644 cluster_size = size;
5645 }
5646 5755
5647 // pos points to start of payload 5756 // pos points to start of payload
5648 long long timecode = -1; 5757 long long timecode = -1;
5649 long long new_pos = -1; 5758 long long new_pos = -1;
5650 bool bBlock = false; 5759 bool bBlock = false;
5651 5760
5652 long long cluster_stop = (cluster_size < 0) ? -1 : pos + cluster_size; 5761 long long cluster_stop = (cluster_size < 0) ? -1 : pos + cluster_size;
5653 5762
5654 for (;;) { 5763 for (;;) {
5655 if ((cluster_stop >= 0) && (pos >= cluster_stop)) 5764 if ((cluster_stop >= 0) && (pos >= cluster_stop))
5656 break; 5765 break;
5657 5766
5658 // Parse ID 5767 // Parse ID
5659 5768
5660 if ((pos + 1) > avail) { 5769 if ((pos + 1) > avail) {
5661 len = 1; 5770 len = 1;
5662 return E_BUFFER_NOT_FULL; 5771 return E_BUFFER_NOT_FULL;
5663 } 5772 }
5664 5773
5665 long long result = GetUIntLength(pReader, pos, len); 5774 long long result = GetUIntLength(pReader, pos, len);
5666 5775
5667 if (result < 0) // error 5776 if (result < 0) // error
5668 return static_cast<long>(result); 5777 return static_cast<long>(result);
5669 5778
5670 if (result > 0) // weird 5779 if (result > 0)
5671 return E_BUFFER_NOT_FULL; 5780 return E_BUFFER_NOT_FULL;
5672 5781
5673 if ((cluster_stop >= 0) && ((pos + len) > cluster_stop)) 5782 if ((cluster_stop >= 0) && ((pos + len) > cluster_stop))
5674 return E_FILE_FORMAT_INVALID; 5783 return E_FILE_FORMAT_INVALID;
5675 5784
5676 if ((pos + len) > avail) 5785 if ((pos + len) > avail)
5677 return E_BUFFER_NOT_FULL; 5786 return E_BUFFER_NOT_FULL;
5678 5787
5679 const long long id = ReadUInt(pReader, pos, len); 5788 const long long id = ReadID(pReader, pos, len);
5680 5789
5681 if (id < 0) // error 5790 if (id < 0) // error
5682 return static_cast<long>(id); 5791 return static_cast<long>(id);
5683 5792
5684 if (id == 0) 5793 if (id == 0)
5685 return E_FILE_FORMAT_INVALID; 5794 return E_FILE_FORMAT_INVALID;
5686 5795
5687 // This is the distinguished set of ID's we use to determine 5796 // This is the distinguished set of ID's we use to determine
5688 // that we have exhausted the sub-element's inside the cluster 5797 // that we have exhausted the sub-element's inside the cluster
5689 // whose ID we parsed earlier. 5798 // whose ID we parsed earlier.
5690 5799
5691 if (id == 0x0F43B675) // Cluster ID 5800 if (id == mkvmuxer::kMkvCluster)
5692 break; 5801 break;
5693 5802
5694 if (id == 0x0C53BB6B) // Cues ID 5803 if (id == mkvmuxer::kMkvCues)
5695 break; 5804 break;
5696 5805
5697 pos += len; // consume ID field 5806 pos += len; // consume ID field
5698 5807
5699 // Parse Size 5808 // Parse Size
5700 5809
5701 if ((pos + 1) > avail) { 5810 if ((pos + 1) > avail) {
5702 len = 1; 5811 len = 1;
5703 return E_BUFFER_NOT_FULL; 5812 return E_BUFFER_NOT_FULL;
5704 } 5813 }
5705 5814
5706 result = GetUIntLength(pReader, pos, len); 5815 result = GetUIntLength(pReader, pos, len);
5707 5816
5708 if (result < 0) // error 5817 if (result < 0) // error
5709 return static_cast<long>(result); 5818 return static_cast<long>(result);
5710 5819
5711 if (result > 0) // weird 5820 if (result > 0)
5712 return E_BUFFER_NOT_FULL; 5821 return E_BUFFER_NOT_FULL;
5713 5822
5714 if ((cluster_stop >= 0) && ((pos + len) > cluster_stop)) 5823 if ((cluster_stop >= 0) && ((pos + len) > cluster_stop))
5715 return E_FILE_FORMAT_INVALID; 5824 return E_FILE_FORMAT_INVALID;
5716 5825
5717 if ((pos + len) > avail) 5826 if ((pos + len) > avail)
5718 return E_BUFFER_NOT_FULL; 5827 return E_BUFFER_NOT_FULL;
5719 5828
5720 const long long size = ReadUInt(pReader, pos, len); 5829 const long long size = ReadUInt(pReader, pos, len);
5721 5830
5722 if (size < 0) // error 5831 if (size < 0) // error
5723 return static_cast<long>(size); 5832 return static_cast<long>(size);
5724 5833
5725 const long long unknown_size = (1LL << (7 * len)) - 1; 5834 const long long unknown_size = (1LL << (7 * len)) - 1;
5726 5835
5727 if (size == unknown_size) 5836 if (size == unknown_size)
5728 return E_FILE_FORMAT_INVALID; 5837 return E_FILE_FORMAT_INVALID;
5729 5838
5730 pos += len; // consume size field 5839 pos += len; // consume size field
5731 5840
5732 if ((cluster_stop >= 0) && (pos > cluster_stop)) 5841 if ((cluster_stop >= 0) && (pos > cluster_stop))
5733 return E_FILE_FORMAT_INVALID; 5842 return E_FILE_FORMAT_INVALID;
5734 5843
5735 // pos now points to start of payload 5844 // pos now points to start of payload
5736 5845
5737 if (size == 0) // weird 5846 if (size == 0)
5738 continue; 5847 continue;
5739 5848
5740 if ((cluster_stop >= 0) && ((pos + size) > cluster_stop)) 5849 if ((cluster_stop >= 0) && ((pos + size) > cluster_stop))
5741 return E_FILE_FORMAT_INVALID; 5850 return E_FILE_FORMAT_INVALID;
5742 5851
5743 if (id == 0x67) { // TimeCode ID 5852 if (id == mkvmuxer::kMkvTimecode) {
5744 len = static_cast<long>(size); 5853 len = static_cast<long>(size);
5745 5854
5746 if ((pos + size) > avail) 5855 if ((pos + size) > avail)
5747 return E_BUFFER_NOT_FULL; 5856 return E_BUFFER_NOT_FULL;
5748 5857
5749 timecode = UnserializeUInt(pReader, pos, size); 5858 timecode = UnserializeUInt(pReader, pos, size);
5750 5859
5751 if (timecode < 0) // error (or underflow) 5860 if (timecode < 0) // error (or underflow)
5752 return static_cast<long>(timecode); 5861 return static_cast<long>(timecode);
5753 5862
5754 new_pos = pos + size; 5863 new_pos = pos + size;
5755 5864
5756 if (bBlock) 5865 if (bBlock)
5757 break; 5866 break;
5758 } else if (id == 0x20) { // BlockGroup ID 5867 } else if (id == mkvmuxer::kMkvBlockGroup) {
5759 bBlock = true; 5868 bBlock = true;
5760 break; 5869 break;
5761 } else if (id == 0x23) { // SimpleBlock ID 5870 } else if (id == mkvmuxer::kMkvSimpleBlock) {
5762 bBlock = true; 5871 bBlock = true;
5763 break; 5872 break;
5764 } 5873 }
5765 5874
5766 pos += size; // consume payload 5875 pos += size; // consume payload
5767 assert((cluster_stop < 0) || (pos <= cluster_stop)); 5876 if (cluster_stop >= 0 && pos > cluster_stop)
5877 return E_FILE_FORMAT_INVALID;
5768 } 5878 }
5769 5879
5770 assert((cluster_stop < 0) || (pos <= cluster_stop)); 5880 if (cluster_stop >= 0 && pos > cluster_stop)
5881 return E_FILE_FORMAT_INVALID;
5771 5882
5772 if (timecode < 0) // no timecode found 5883 if (timecode < 0) // no timecode found
5773 return E_FILE_FORMAT_INVALID; 5884 return E_FILE_FORMAT_INVALID;
5774 5885
5775 if (!bBlock) 5886 if (!bBlock)
5776 return E_FILE_FORMAT_INVALID; 5887 return E_FILE_FORMAT_INVALID;
5777 5888
5778 m_pos = new_pos; // designates position just beyond timecode payload 5889 m_pos = new_pos; // designates position just beyond timecode payload
5779 m_timecode = timecode; // m_timecode >= 0 means we're partially loaded 5890 m_timecode = timecode; // m_timecode >= 0 means we're partially loaded
5780 5891
5781 if (cluster_size >= 0) 5892 if (cluster_size >= 0)
5782 m_element_size = cluster_stop - m_element_start; 5893 m_element_size = cluster_stop - m_element_start;
5783 5894
5784 return 0; 5895 return 0;
5785 } 5896 }
5786 5897
5787 long Cluster::Parse(long long& pos, long& len) const { 5898 long Cluster::Parse(long long& pos, long& len) const {
5788 long status = Load(pos, len); 5899 long status = Load(pos, len);
5789 5900
5790 if (status < 0) 5901 if (status < 0)
5791 return status; 5902 return status;
5792 5903
5793 assert(m_pos >= m_element_start); 5904 if (m_pos < m_element_start || m_timecode < 0)
5794 assert(m_timecode >= 0); 5905 return E_PARSE_FAILED;
5795 // assert(m_size > 0);
5796 // assert(m_element_size > m_size);
5797 5906
5798 const long long cluster_stop = 5907 const long long cluster_stop =
5799 (m_element_size < 0) ? -1 : m_element_start + m_element_size; 5908 (m_element_size < 0) ? -1 : m_element_start + m_element_size;
5800 5909
5801 if ((cluster_stop >= 0) && (m_pos >= cluster_stop)) 5910 if ((cluster_stop >= 0) && (m_pos >= cluster_stop))
5802 return 1; // nothing else to do 5911 return 1; // nothing else to do
5803 5912
5804 IMkvReader* const pReader = m_pSegment->m_pReader; 5913 IMkvReader* const pReader = m_pSegment->m_pReader;
5805 5914
5806 long long total, avail; 5915 long long total, avail;
5807 5916
5808 status = pReader->Length(&total, &avail); 5917 status = pReader->Length(&total, &avail);
5809 5918
5810 if (status < 0) // error 5919 if (status < 0) // error
5811 return status; 5920 return status;
5812 5921
5813 assert((total < 0) || (avail <= total)); 5922 if (total >= 0 && avail > total)
5923 return E_FILE_FORMAT_INVALID;
5814 5924
5815 pos = m_pos; 5925 pos = m_pos;
5816 5926
5817 for (;;) { 5927 for (;;) {
5818 if ((cluster_stop >= 0) && (pos >= cluster_stop)) 5928 if ((cluster_stop >= 0) && (pos >= cluster_stop))
5819 break; 5929 break;
5820 5930
5821 if ((total >= 0) && (pos >= total)) { 5931 if ((total >= 0) && (pos >= total)) {
5822 if (m_element_size < 0) 5932 if (m_element_size < 0)
5823 m_element_size = pos - m_element_start; 5933 m_element_size = pos - m_element_start;
5824 5934
5825 break; 5935 break;
5826 } 5936 }
5827 5937
5828 // Parse ID 5938 // Parse ID
5829 5939
5830 if ((pos + 1) > avail) { 5940 if ((pos + 1) > avail) {
5831 len = 1; 5941 len = 1;
5832 return E_BUFFER_NOT_FULL; 5942 return E_BUFFER_NOT_FULL;
5833 } 5943 }
5834 5944
5835 long long result = GetUIntLength(pReader, pos, len); 5945 long long result = GetUIntLength(pReader, pos, len);
5836 5946
5837 if (result < 0) // error 5947 if (result < 0) // error
5838 return static_cast<long>(result); 5948 return static_cast<long>(result);
5839 5949
5840 if (result > 0) // weird 5950 if (result > 0)
5841 return E_BUFFER_NOT_FULL; 5951 return E_BUFFER_NOT_FULL;
5842 5952
5843 if ((cluster_stop >= 0) && ((pos + len) > cluster_stop)) 5953 if ((cluster_stop >= 0) && ((pos + len) > cluster_stop))
5844 return E_FILE_FORMAT_INVALID; 5954 return E_FILE_FORMAT_INVALID;
5845 5955
5846 if ((pos + len) > avail) 5956 if ((pos + len) > avail)
5847 return E_BUFFER_NOT_FULL; 5957 return E_BUFFER_NOT_FULL;
5848 5958
5849 const long long id = ReadUInt(pReader, pos, len); 5959 const long long id = ReadID(pReader, pos, len);
5850 5960
5851 if (id < 0) // error 5961 if (id < 0)
5852 return static_cast<long>(id);
5853
5854 if (id == 0) // weird
5855 return E_FILE_FORMAT_INVALID; 5962 return E_FILE_FORMAT_INVALID;
5856 5963
5857 // This is the distinguished set of ID's we use to determine 5964 // This is the distinguished set of ID's we use to determine
5858 // that we have exhausted the sub-element's inside the cluster 5965 // that we have exhausted the sub-element's inside the cluster
5859 // whose ID we parsed earlier. 5966 // whose ID we parsed earlier.
5860 5967
5861 if ((id == 0x0F43B675) || (id == 0x0C53BB6B)) { // Cluster or Cues ID 5968 if ((id == mkvmuxer::kMkvCluster) || (id == mkvmuxer::kMkvCues)) {
5862 if (m_element_size < 0) 5969 if (m_element_size < 0)
5863 m_element_size = pos - m_element_start; 5970 m_element_size = pos - m_element_start;
5864 5971
5865 break; 5972 break;
5866 } 5973 }
5867 5974
5868 pos += len; // consume ID field 5975 pos += len; // consume ID field
5869 5976
5870 // Parse Size 5977 // Parse Size
5871 5978
5872 if ((pos + 1) > avail) { 5979 if ((pos + 1) > avail) {
5873 len = 1; 5980 len = 1;
5874 return E_BUFFER_NOT_FULL; 5981 return E_BUFFER_NOT_FULL;
5875 } 5982 }
5876 5983
5877 result = GetUIntLength(pReader, pos, len); 5984 result = GetUIntLength(pReader, pos, len);
5878 5985
5879 if (result < 0) // error 5986 if (result < 0) // error
5880 return static_cast<long>(result); 5987 return static_cast<long>(result);
5881 5988
5882 if (result > 0) // weird 5989 if (result > 0)
5883 return E_BUFFER_NOT_FULL; 5990 return E_BUFFER_NOT_FULL;
5884 5991
5885 if ((cluster_stop >= 0) && ((pos + len) > cluster_stop)) 5992 if ((cluster_stop >= 0) && ((pos + len) > cluster_stop))
5886 return E_FILE_FORMAT_INVALID; 5993 return E_FILE_FORMAT_INVALID;
5887 5994
5888 if ((pos + len) > avail) 5995 if ((pos + len) > avail)
5889 return E_BUFFER_NOT_FULL; 5996 return E_BUFFER_NOT_FULL;
5890 5997
5891 const long long size = ReadUInt(pReader, pos, len); 5998 const long long size = ReadUInt(pReader, pos, len);
5892 5999
5893 if (size < 0) // error 6000 if (size < 0) // error
5894 return static_cast<long>(size); 6001 return static_cast<long>(size);
5895 6002
5896 const long long unknown_size = (1LL << (7 * len)) - 1; 6003 const long long unknown_size = (1LL << (7 * len)) - 1;
5897 6004
5898 if (size == unknown_size) 6005 if (size == unknown_size)
5899 return E_FILE_FORMAT_INVALID; 6006 return E_FILE_FORMAT_INVALID;
5900 6007
5901 pos += len; // consume size field 6008 pos += len; // consume size field
5902 6009
5903 if ((cluster_stop >= 0) && (pos > cluster_stop)) 6010 if ((cluster_stop >= 0) && (pos > cluster_stop))
5904 return E_FILE_FORMAT_INVALID; 6011 return E_FILE_FORMAT_INVALID;
5905 6012
5906 // pos now points to start of payload 6013 // pos now points to start of payload
5907 6014
5908 if (size == 0) // weird 6015 if (size == 0)
5909 continue; 6016 continue;
5910 6017
5911 // const long long block_start = pos; 6018 // const long long block_start = pos;
5912 const long long block_stop = pos + size; 6019 const long long block_stop = pos + size;
5913 6020
5914 if (cluster_stop >= 0) { 6021 if (cluster_stop >= 0) {
5915 if (block_stop > cluster_stop) { 6022 if (block_stop > cluster_stop) {
5916 if ((id == 0x20) || (id == 0x23)) 6023 if (id == mkvmuxer::kMkvBlockGroup ||
6024 id == mkvmuxer::kMkvSimpleBlock) {
5917 return E_FILE_FORMAT_INVALID; 6025 return E_FILE_FORMAT_INVALID;
6026 }
5918 6027
5919 pos = cluster_stop; 6028 pos = cluster_stop;
5920 break; 6029 break;
5921 } 6030 }
5922 } else if ((total >= 0) && (block_stop > total)) { 6031 } else if ((total >= 0) && (block_stop > total)) {
5923 m_element_size = total - m_element_start; 6032 m_element_size = total - m_element_start;
5924 pos = total; 6033 pos = total;
5925 break; 6034 break;
5926 } else if (block_stop > avail) { 6035 } else if (block_stop > avail) {
5927 len = static_cast<long>(size); 6036 len = static_cast<long>(size);
5928 return E_BUFFER_NOT_FULL; 6037 return E_BUFFER_NOT_FULL;
5929 } 6038 }
5930 6039
5931 Cluster* const this_ = const_cast<Cluster*>(this); 6040 Cluster* const this_ = const_cast<Cluster*>(this);
5932 6041
5933 if (id == 0x20) // BlockGroup 6042 if (id == mkvmuxer::kMkvBlockGroup)
5934 return this_->ParseBlockGroup(size, pos, len); 6043 return this_->ParseBlockGroup(size, pos, len);
5935 6044
5936 if (id == 0x23) // SimpleBlock 6045 if (id == mkvmuxer::kMkvSimpleBlock)
5937 return this_->ParseSimpleBlock(size, pos, len); 6046 return this_->ParseSimpleBlock(size, pos, len);
5938 6047
5939 pos += size; // consume payload 6048 pos += size; // consume payload
5940 assert((cluster_stop < 0) || (pos <= cluster_stop)); 6049 if (cluster_stop >= 0 && pos > cluster_stop)
6050 return E_FILE_FORMAT_INVALID;
5941 } 6051 }
5942 6052
5943 assert(m_element_size > 0); 6053 if (m_element_size < 1)
6054 return E_FILE_FORMAT_INVALID;
5944 6055
5945 m_pos = pos; 6056 m_pos = pos;
5946 assert((cluster_stop < 0) || (m_pos <= cluster_stop)); 6057 if (cluster_stop >= 0 && m_pos > cluster_stop)
6058 return E_FILE_FORMAT_INVALID;
5947 6059
5948 if (m_entries_count > 0) { 6060 if (m_entries_count > 0) {
5949 const long idx = m_entries_count - 1; 6061 const long idx = m_entries_count - 1;
5950 6062
5951 const BlockEntry* const pLast = m_entries[idx]; 6063 const BlockEntry* const pLast = m_entries[idx];
5952 assert(pLast); 6064 if (pLast == NULL)
6065 return E_PARSE_FAILED;
5953 6066
5954 const Block* const pBlock = pLast->GetBlock(); 6067 const Block* const pBlock = pLast->GetBlock();
5955 assert(pBlock); 6068 if (pBlock == NULL)
6069 return E_PARSE_FAILED;
5956 6070
5957 const long long start = pBlock->m_start; 6071 const long long start = pBlock->m_start;
5958 6072
5959 if ((total >= 0) && (start > total)) 6073 if ((total >= 0) && (start > total))
5960 return -1; // defend against trucated stream 6074 return E_PARSE_FAILED; // defend against trucated stream
5961 6075
5962 const long long size = pBlock->m_size; 6076 const long long size = pBlock->m_size;
5963 6077
5964 const long long stop = start + size; 6078 const long long stop = start + size;
5965 assert((cluster_stop < 0) || (stop <= cluster_stop)); 6079 if (cluster_stop >= 0 && stop > cluster_stop)
6080 return E_FILE_FORMAT_INVALID;
5966 6081
5967 if ((total >= 0) && (stop > total)) 6082 if ((total >= 0) && (stop > total))
5968 return -1; // defend against trucated stream 6083 return E_PARSE_FAILED; // defend against trucated stream
5969 } 6084 }
5970 6085
5971 return 1; // no more entries 6086 return 1; // no more entries
5972 } 6087 }
5973 6088
5974 long Cluster::ParseSimpleBlock(long long block_size, long long& pos, 6089 long Cluster::ParseSimpleBlock(long long block_size, long long& pos,
5975 long& len) { 6090 long& len) {
5976 const long long block_start = pos; 6091 const long long block_start = pos;
5977 const long long block_stop = pos + block_size; 6092 const long long block_stop = pos + block_size;
5978 6093
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after
6051 if (pos >= block_stop) 6166 if (pos >= block_stop)
6052 return E_FILE_FORMAT_INVALID; 6167 return E_FILE_FORMAT_INVALID;
6053 6168
6054 const int lacing = int(flags & 0x06) >> 1; 6169 const int lacing = int(flags & 0x06) >> 1;
6055 6170
6056 if ((lacing != 0) && (block_stop > avail)) { 6171 if ((lacing != 0) && (block_stop > avail)) {
6057 len = static_cast<long>(block_stop - pos); 6172 len = static_cast<long>(block_stop - pos);
6058 return E_BUFFER_NOT_FULL; 6173 return E_BUFFER_NOT_FULL;
6059 } 6174 }
6060 6175
6061 status = CreateBlock(0x23, // simple block id 6176 status = CreateBlock(mkvmuxer::kMkvSimpleBlock,
6062 block_start, block_size, 6177 block_start, block_size,
6063 0); // DiscardPadding 6178 0); // DiscardPadding
6064 6179
6065 if (status != 0) 6180 if (status != 0)
6066 return status; 6181 return status;
6067 6182
6068 m_pos = block_stop; 6183 m_pos = block_stop;
6069 6184
6070 return 0; // success 6185 return 0; // success
6071 } 6186 }
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
6111 6226
6112 if (result > 0) // weird 6227 if (result > 0) // weird
6113 return E_BUFFER_NOT_FULL; 6228 return E_BUFFER_NOT_FULL;
6114 6229
6115 if ((pos + len) > payload_stop) 6230 if ((pos + len) > payload_stop)
6116 return E_FILE_FORMAT_INVALID; 6231 return E_FILE_FORMAT_INVALID;
6117 6232
6118 if ((pos + len) > avail) 6233 if ((pos + len) > avail)
6119 return E_BUFFER_NOT_FULL; 6234 return E_BUFFER_NOT_FULL;
6120 6235
6121 const long long id = ReadUInt(pReader, pos, len); 6236 const long long id = ReadID(pReader, pos, len);
6122 6237
6123 if (id < 0) // error 6238 if (id < 0) // error
6124 return static_cast<long>(id); 6239 return static_cast<long>(id);
6125 6240
6126 if (id == 0) // not a value ID 6241 if (id == 0) // not a valid ID
6127 return E_FILE_FORMAT_INVALID; 6242 return E_FILE_FORMAT_INVALID;
6128 6243
6129 pos += len; // consume ID field 6244 pos += len; // consume ID field
6130 6245
6131 // Parse Size 6246 // Parse Size
6132 6247
6133 if ((pos + 1) > avail) { 6248 if ((pos + 1) > avail) {
6134 len = 1; 6249 len = 1;
6135 return E_BUFFER_NOT_FULL; 6250 return E_BUFFER_NOT_FULL;
6136 } 6251 }
(...skipping 25 matching lines...) Expand all
6162 return E_FILE_FORMAT_INVALID; 6277 return E_FILE_FORMAT_INVALID;
6163 6278
6164 if (size == 0) // weird 6279 if (size == 0) // weird
6165 continue; 6280 continue;
6166 6281
6167 const long long unknown_size = (1LL << (7 * len)) - 1; 6282 const long long unknown_size = (1LL << (7 * len)) - 1;
6168 6283
6169 if (size == unknown_size) 6284 if (size == unknown_size)
6170 return E_FILE_FORMAT_INVALID; 6285 return E_FILE_FORMAT_INVALID;
6171 6286
6172 if (id == 0x35A2) { // DiscardPadding 6287 if (id == mkvmuxer::kMkvDiscardPadding) {
6173 status = UnserializeInt(pReader, pos, size, discard_padding); 6288 status = UnserializeInt(pReader, pos, size, discard_padding);
6174 6289
6175 if (status < 0) // error 6290 if (status < 0) // error
6176 return status; 6291 return status;
6177 } 6292 }
6178 6293
6179 if (id != 0x21) { // sub-part of BlockGroup is not a Block 6294 if (id != mkvmuxer::kMkvBlock) {
6180 pos += size; // consume sub-part of block group 6295 pos += size; // consume sub-part of block group
6181 6296
6182 if (pos > payload_stop) 6297 if (pos > payload_stop)
6183 return E_FILE_FORMAT_INVALID; 6298 return E_FILE_FORMAT_INVALID;
6184 6299
6185 continue; 6300 continue;
6186 } 6301 }
6187 6302
6188 const long long block_stop = pos + size; 6303 const long long block_stop = pos + size;
6189 6304
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after
6255 return E_FILE_FORMAT_INVALID; 6370 return E_FILE_FORMAT_INVALID;
6256 6371
6257 const int lacing = int(flags & 0x06) >> 1; 6372 const int lacing = int(flags & 0x06) >> 1;
6258 6373
6259 if ((lacing != 0) && (block_stop > avail)) { 6374 if ((lacing != 0) && (block_stop > avail)) {
6260 len = static_cast<long>(block_stop - pos); 6375 len = static_cast<long>(block_stop - pos);
6261 return E_BUFFER_NOT_FULL; 6376 return E_BUFFER_NOT_FULL;
6262 } 6377 }
6263 6378
6264 pos = block_stop; // consume block-part of block group 6379 pos = block_stop; // consume block-part of block group
6265 assert(pos <= payload_stop); 6380 if (pos > payload_stop)
6381 return E_FILE_FORMAT_INVALID;
6266 } 6382 }
6267 6383
6268 assert(pos == payload_stop); 6384 if (pos != payload_stop)
6385 return E_FILE_FORMAT_INVALID;
6269 6386
6270 status = CreateBlock(0x20, // BlockGroup ID 6387 status = CreateBlock(mkvmuxer::kMkvBlockGroup,
6271 payload_start, payload_size, discard_padding); 6388 payload_start, payload_size, discard_padding);
6272 if (status != 0) 6389 if (status != 0)
6273 return status; 6390 return status;
6274 6391
6275 m_pos = payload_stop; 6392 m_pos = payload_stop;
6276 6393
6277 return 0; // success 6394 return 0; // success
6278 } 6395 }
6279 6396
6280 long Cluster::GetEntry(long index, const mkvparser::BlockEntry*& pEntry) const { 6397 long Cluster::GetEntry(long index, const mkvparser::BlockEntry*& pEntry) const {
(...skipping 22 matching lines...) Expand all
6303 return E_BUFFER_NOT_FULL; // underflow 6420 return E_BUFFER_NOT_FULL; // underflow
6304 6421
6305 const long long element_stop = m_element_start + m_element_size; 6422 const long long element_stop = m_element_start + m_element_size;
6306 6423
6307 if (m_pos >= element_stop) 6424 if (m_pos >= element_stop)
6308 return 0; // nothing left to parse 6425 return 0; // nothing left to parse
6309 6426
6310 return E_BUFFER_NOT_FULL; // underflow, since more remains to be parsed 6427 return E_BUFFER_NOT_FULL; // underflow, since more remains to be parsed
6311 } 6428 }
6312 6429
6313 Cluster* Cluster::Create(Segment* pSegment, long idx, long long off) 6430 Cluster* Cluster::Create(Segment* pSegment, long idx, long long off) {
6314 // long long element_size) 6431 if (!pSegment || off < 0)
6315 { 6432 return NULL;
6316 assert(pSegment);
6317 assert(off >= 0);
6318 6433
6319 const long long element_start = pSegment->m_start + off; 6434 const long long element_start = pSegment->m_start + off;
6320 6435
6321 Cluster* const pCluster = new Cluster(pSegment, idx, element_start); 6436 Cluster* const pCluster =
6322 // element_size); 6437 new (std::nothrow) Cluster(pSegment, idx, element_start);
6323 assert(pCluster);
6324 6438
6325 return pCluster; 6439 return pCluster;
6326 } 6440 }
6327 6441
6328 Cluster::Cluster() 6442 Cluster::Cluster()
6329 : m_pSegment(NULL), 6443 : m_pSegment(NULL),
6330 m_element_start(0), 6444 m_element_start(0),
6331 m_index(0), 6445 m_index(0),
6332 m_pos(0), 6446 m_pos(0),
6333 m_element_size(0), 6447 m_element_size(0),
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after
6424 6538
6425 if ((segment_stop >= 0) && ((pos + len) > segment_stop)) 6539 if ((segment_stop >= 0) && ((pos + len) > segment_stop))
6426 return E_FILE_FORMAT_INVALID; 6540 return E_FILE_FORMAT_INVALID;
6427 6541
6428 if ((total >= 0) && ((pos + len) > total)) 6542 if ((total >= 0) && ((pos + len) > total))
6429 return 0; 6543 return 0;
6430 6544
6431 if ((pos + len) > avail) 6545 if ((pos + len) > avail)
6432 return E_BUFFER_NOT_FULL; 6546 return E_BUFFER_NOT_FULL;
6433 6547
6434 const long long id = ReadUInt(pReader, pos, len); 6548 const long long id = ReadID(pReader, pos, len);
6435 6549
6436 if (id < 0) // error 6550 if (id < 0) // error
6437 return static_cast<long>(id); 6551 return static_cast<long>(id);
6438 6552
6439 if (id != 0x0F43B675) // weird: not cluster ID 6553 if (id != mkvmuxer::kMkvCluster)
6440 return -1; // generic error 6554 return E_PARSE_FAILED;
6441 6555
6442 pos += len; // consume Cluster ID field 6556 pos += len; // consume Cluster ID field
6443 6557
6444 // read size field 6558 // read size field
6445 6559
6446 if ((pos + 1) > avail) { 6560 if ((pos + 1) > avail) {
6447 len = 1; 6561 len = 1;
6448 return E_BUFFER_NOT_FULL; 6562 return E_BUFFER_NOT_FULL;
6449 } 6563 }
6450 6564
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
6508 6622
6509 if (result > 0) // need more data 6623 if (result > 0) // need more data
6510 return E_BUFFER_NOT_FULL; 6624 return E_BUFFER_NOT_FULL;
6511 6625
6512 if ((cluster_stop >= 0) && ((pos + len) > cluster_stop)) 6626 if ((cluster_stop >= 0) && ((pos + len) > cluster_stop))
6513 return E_FILE_FORMAT_INVALID; 6627 return E_FILE_FORMAT_INVALID;
6514 6628
6515 if ((pos + len) > avail) 6629 if ((pos + len) > avail)
6516 return E_BUFFER_NOT_FULL; 6630 return E_BUFFER_NOT_FULL;
6517 6631
6518 const long long id = ReadUInt(pReader, pos, len); 6632 const long long id = ReadID(pReader, pos, len);
6519 6633
6520 if (id < 0) // error 6634 if (id < 0) // error
6521 return static_cast<long>(id); 6635 return static_cast<long>(id);
6522 6636
6523 // This is the distinguished set of ID's we use to determine 6637 // This is the distinguished set of ID's we use to determine
6524 // that we have exhausted the sub-element's inside the cluster 6638 // that we have exhausted the sub-element's inside the cluster
6525 // whose ID we parsed earlier. 6639 // whose ID we parsed earlier.
6526 6640
6527 if (id == 0x0F43B675) // Cluster ID 6641 if (id == mkvmuxer::kMkvCluster)
6528 return 0; // no entries found 6642 return 0; // no entries found
6529 6643
6530 if (id == 0x0C53BB6B) // Cues ID 6644 if (id == mkvmuxer::kMkvCues)
6531 return 0; // no entries found 6645 return 0; // no entries found
6532 6646
6533 pos += len; // consume id field 6647 pos += len; // consume id field
6534 6648
6535 if ((cluster_stop >= 0) && (pos >= cluster_stop)) 6649 if ((cluster_stop >= 0) && (pos >= cluster_stop))
6536 return E_FILE_FORMAT_INVALID; 6650 return E_FILE_FORMAT_INVALID;
6537 6651
6538 // read size field 6652 // read size field
6539 6653
6540 if ((pos + 1) > avail) { 6654 if ((pos + 1) > avail) {
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
6572 continue; 6686 continue;
6573 6687
6574 const long long unknown_size = (1LL << (7 * len)) - 1; 6688 const long long unknown_size = (1LL << (7 * len)) - 1;
6575 6689
6576 if (size == unknown_size) 6690 if (size == unknown_size)
6577 return E_FILE_FORMAT_INVALID; // not supported inside cluster 6691 return E_FILE_FORMAT_INVALID; // not supported inside cluster
6578 6692
6579 if ((cluster_stop >= 0) && ((pos + size) > cluster_stop)) 6693 if ((cluster_stop >= 0) && ((pos + size) > cluster_stop))
6580 return E_FILE_FORMAT_INVALID; 6694 return E_FILE_FORMAT_INVALID;
6581 6695
6582 if (id == 0x20) // BlockGroup ID 6696 if (id == mkvmuxer::kMkvBlockGroup)
6583 return 1; // have at least one entry 6697 return 1; // have at least one entry
6584 6698
6585 if (id == 0x23) // SimpleBlock ID 6699 if (id == mkvmuxer::kMkvSimpleBlock)
6586 return 1; // have at least one entry 6700 return 1; // have at least one entry
6587 6701
6588 pos += size; // consume payload 6702 pos += size; // consume payload
6589 assert((cluster_stop < 0) || (pos <= cluster_stop)); 6703 if (cluster_stop >= 0 && pos > cluster_stop)
6704 return E_FILE_FORMAT_INVALID;
6590 } 6705 }
6591 } 6706 }
6592 6707
6593 long long Cluster::GetTimeCode() const { 6708 long long Cluster::GetTimeCode() const {
6594 long long pos; 6709 long long pos;
6595 long len; 6710 long len;
6596 6711
6597 const long status = Load(pos, len); 6712 const long status = Load(pos, len);
6598 6713
6599 if (status < 0) // error 6714 if (status < 0) // error
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
6649 6764
6650 const Block* const pBlock = pEntry->GetBlock(); 6765 const Block* const pBlock = pEntry->GetBlock();
6651 assert(pBlock); 6766 assert(pBlock);
6652 6767
6653 return pBlock->GetTime(this); 6768 return pBlock->GetTime(this);
6654 } 6769 }
6655 6770
6656 long Cluster::CreateBlock(long long id, 6771 long Cluster::CreateBlock(long long id,
6657 long long pos, // absolute pos of payload 6772 long long pos, // absolute pos of payload
6658 long long size, long long discard_padding) { 6773 long long size, long long discard_padding) {
6659 assert((id == 0x20) || (id == 0x23)); // BlockGroup or SimpleBlock 6774 if (id != mkvmuxer::kMkvBlockGroup && id != mkvmuxer::kMkvSimpleBlock)
6775 return E_PARSE_FAILED;
6660 6776
6661 if (m_entries_count < 0) { // haven't parsed anything yet 6777 if (m_entries_count < 0) { // haven't parsed anything yet
6662 assert(m_entries == NULL); 6778 assert(m_entries == NULL);
6663 assert(m_entries_size == 0); 6779 assert(m_entries_size == 0);
6664 6780
6665 m_entries_size = 1024; 6781 m_entries_size = 1024;
6666 m_entries = new BlockEntry*[m_entries_size]; 6782 m_entries = new (std::nothrow) BlockEntry*[m_entries_size];
6783 if (m_entries == NULL)
6784 return -1;
6667 6785
6668 m_entries_count = 0; 6786 m_entries_count = 0;
6669 } else { 6787 } else {
6670 assert(m_entries); 6788 assert(m_entries);
6671 assert(m_entries_size > 0); 6789 assert(m_entries_size > 0);
6672 assert(m_entries_count <= m_entries_size); 6790 assert(m_entries_count <= m_entries_size);
6673 6791
6674 if (m_entries_count >= m_entries_size) { 6792 if (m_entries_count >= m_entries_size) {
6675 const long entries_size = 2 * m_entries_size; 6793 const long entries_size = 2 * m_entries_size;
6676 6794
6677 BlockEntry** const entries = new BlockEntry*[entries_size]; 6795 BlockEntry** const entries = new (std::nothrow) BlockEntry*[entries_size];
6678 assert(entries); 6796 if (entries == NULL)
6797 return -1;
6679 6798
6680 BlockEntry** src = m_entries; 6799 BlockEntry** src = m_entries;
6681 BlockEntry** const src_end = src + m_entries_count; 6800 BlockEntry** const src_end = src + m_entries_count;
6682 6801
6683 BlockEntry** dst = entries; 6802 BlockEntry** dst = entries;
6684 6803
6685 while (src != src_end) 6804 while (src != src_end)
6686 *dst++ = *src++; 6805 *dst++ = *src++;
6687 6806
6688 delete[] m_entries; 6807 delete[] m_entries;
6689 6808
6690 m_entries = entries; 6809 m_entries = entries;
6691 m_entries_size = entries_size; 6810 m_entries_size = entries_size;
6692 } 6811 }
6693 } 6812 }
6694 6813
6695 if (id == 0x20) // BlockGroup ID 6814 if (id == mkvmuxer::kMkvBlockGroup)
6696 return CreateBlockGroup(pos, size, discard_padding); 6815 return CreateBlockGroup(pos, size, discard_padding);
6697 else // SimpleBlock ID 6816 else
6698 return CreateSimpleBlock(pos, size); 6817 return CreateSimpleBlock(pos, size);
6699 } 6818 }
6700 6819
6701 long Cluster::CreateBlockGroup(long long start_offset, long long size, 6820 long Cluster::CreateBlockGroup(long long start_offset, long long size,
6702 long long discard_padding) { 6821 long long discard_padding) {
6703 assert(m_entries); 6822 assert(m_entries);
6704 assert(m_entries_size > 0); 6823 assert(m_entries_size > 0);
6705 assert(m_entries_count >= 0); 6824 assert(m_entries_count >= 0);
6706 assert(m_entries_count < m_entries_size); 6825 assert(m_entries_count < m_entries_size);
6707 6826
(...skipping 10 matching lines...) Expand all
6718 6837
6719 long long prev = 1; // nonce 6838 long long prev = 1; // nonce
6720 long long next = 0; // nonce 6839 long long next = 0; // nonce
6721 long long duration = -1; // really, this is unsigned 6840 long long duration = -1; // really, this is unsigned
6722 6841
6723 long long bpos = -1; 6842 long long bpos = -1;
6724 long long bsize = -1; 6843 long long bsize = -1;
6725 6844
6726 while (pos < stop) { 6845 while (pos < stop) {
6727 long len; 6846 long len;
6728 const long long id = ReadUInt(pReader, pos, len); 6847 const long long id = ReadID(pReader, pos, len);
6729 assert(id >= 0); // TODO 6848 if (id < 0 || (pos + len) > stop)
6730 assert((pos + len) <= stop); 6849 return E_FILE_FORMAT_INVALID;
6731 6850
6732 pos += len; // consume ID 6851 pos += len; // consume ID
6733 6852
6734 const long long size = ReadUInt(pReader, pos, len); 6853 const long long size = ReadUInt(pReader, pos, len);
6735 assert(size >= 0); // TODO 6854 assert(size >= 0); // TODO
6736 assert((pos + len) <= stop); 6855 assert((pos + len) <= stop);
6737 6856
6738 pos += len; // consume size 6857 pos += len; // consume size
6739 6858
6740 if (id == 0x21) { // Block ID 6859 if (id == mkvmuxer::kMkvBlock) {
6741 if (bpos < 0) { // Block ID 6860 if (bpos < 0) { // Block ID
6742 bpos = pos; 6861 bpos = pos;
6743 bsize = size; 6862 bsize = size;
6744 } 6863 }
6745 } else if (id == 0x1B) { // Duration ID 6864 } else if (id == mkvmuxer::kMkvBlockDuration) {
6746 if (size > 8) 6865 if (size > 8)
6747 return E_FILE_FORMAT_INVALID; 6866 return E_FILE_FORMAT_INVALID;
6748 6867
6749 duration = UnserializeUInt(pReader, pos, size); 6868 duration = UnserializeUInt(pReader, pos, size);
6750 6869
6751 if (duration < 0) 6870 if (duration < 0)
6752 return E_FILE_FORMAT_INVALID; 6871 return E_FILE_FORMAT_INVALID;
6753 } else if (id == 0x7B) { // ReferenceBlock 6872 } else if (id == mkvmuxer::kMkvReferenceBlock) {
6754 if (size > 8 || size <= 0) 6873 if (size > 8 || size <= 0)
6755 return E_FILE_FORMAT_INVALID; 6874 return E_FILE_FORMAT_INVALID;
6756 const long size_ = static_cast<long>(size); 6875 const long size_ = static_cast<long>(size);
6757 6876
6758 long long time; 6877 long long time;
6759 6878
6760 long status = UnserializeInt(pReader, pos, size_, time); 6879 long status = UnserializeInt(pReader, pos, size_, time);
6761 assert(status == 0); 6880 assert(status == 0);
6762 if (status != 0) 6881 if (status != 0)
6763 return -1; 6882 return -1;
6764 6883
6765 if (time <= 0) // see note above 6884 if (time <= 0) // see note above
6766 prev = time; 6885 prev = time;
6767 else // weird 6886 else
6768 next = time; 6887 next = time;
6769 } 6888 }
6770 6889
6771 pos += size; // consume payload 6890 pos += size; // consume payload
6772 assert(pos <= stop); 6891 if (pos > stop)
6892 return E_FILE_FORMAT_INVALID;
6773 } 6893 }
6774 if (bpos < 0) 6894 if (bpos < 0)
6775 return E_FILE_FORMAT_INVALID; 6895 return E_FILE_FORMAT_INVALID;
6776 6896
6777 assert(pos == stop); 6897 if (pos != stop)
6898 return E_FILE_FORMAT_INVALID;
6778 assert(bsize >= 0); 6899 assert(bsize >= 0);
6779 6900
6780 const long idx = m_entries_count; 6901 const long idx = m_entries_count;
6781 6902
6782 BlockEntry** const ppEntry = m_entries + idx; 6903 BlockEntry** const ppEntry = m_entries + idx;
6783 BlockEntry*& pEntry = *ppEntry; 6904 BlockEntry*& pEntry = *ppEntry;
6784 6905
6785 pEntry = new (std::nothrow) 6906 pEntry = new (std::nothrow)
6786 BlockGroup(this, idx, bpos, bsize, prev, next, duration, discard_padding); 6907 BlockGroup(this, idx, bpos, bsize, prev, next, duration, discard_padding);
6787 6908
(...skipping 418 matching lines...) Expand 10 before | Expand all | Expand 10 after
7206 7327
7207 const int lacing = int(m_flags & 0x06) >> 1; 7328 const int lacing = int(m_flags & 0x06) >> 1;
7208 7329
7209 ++pos; // consume flags byte 7330 ++pos; // consume flags byte
7210 7331
7211 if (lacing == 0) { // no lacing 7332 if (lacing == 0) { // no lacing
7212 if (pos > stop) 7333 if (pos > stop)
7213 return E_FILE_FORMAT_INVALID; 7334 return E_FILE_FORMAT_INVALID;
7214 7335
7215 m_frame_count = 1; 7336 m_frame_count = 1;
7216 m_frames = new Frame[m_frame_count]; 7337 m_frames = new (std::nothrow) Frame[m_frame_count];
7338 if (m_frames == NULL)
7339 return -1;
7217 7340
7218 Frame& f = m_frames[0]; 7341 Frame& f = m_frames[0];
7219 f.pos = pos; 7342 f.pos = pos;
7220 7343
7221 const long long frame_size = stop - pos; 7344 const long long frame_size = stop - pos;
7222 7345
7223 if (frame_size > LONG_MAX || frame_size <= 0) 7346 if (frame_size > LONG_MAX || frame_size <= 0)
7224 return E_FILE_FORMAT_INVALID; 7347 return E_FILE_FORMAT_INVALID;
7225 7348
7226 f.len = static_cast<long>(frame_size); 7349 f.len = static_cast<long>(frame_size);
7227 7350
7228 return 0; // success 7351 return 0; // success
7229 } 7352 }
7230 7353
7231 if (pos >= stop) 7354 if (pos >= stop)
7232 return E_FILE_FORMAT_INVALID; 7355 return E_FILE_FORMAT_INVALID;
7233 7356
7234 unsigned char biased_count; 7357 unsigned char biased_count;
7235 7358
7236 status = pReader->Read(pos, 1, &biased_count); 7359 status = pReader->Read(pos, 1, &biased_count);
7237 7360
7238 if (status) 7361 if (status)
7239 return E_FILE_FORMAT_INVALID; 7362 return E_FILE_FORMAT_INVALID;
7240 7363
7241 ++pos; // consume frame count 7364 ++pos; // consume frame count
7242 assert(pos <= stop); 7365 if (pos > stop)
7366 return E_FILE_FORMAT_INVALID;
7243 7367
7244 m_frame_count = int(biased_count) + 1; 7368 m_frame_count = int(biased_count) + 1;
7245 7369
7246 m_frames = new Frame[m_frame_count]; 7370 m_frames = new (std::nothrow) Frame[m_frame_count];
7247 assert(m_frames); 7371 if (m_frames == NULL)
7372 return -1;
7373
7374 if (!m_frames)
7375 return E_FILE_FORMAT_INVALID;
7248 7376
7249 if (lacing == 1) { // Xiph 7377 if (lacing == 1) { // Xiph
7250 Frame* pf = m_frames; 7378 Frame* pf = m_frames;
7251 Frame* const pf_end = pf + m_frame_count; 7379 Frame* const pf_end = pf + m_frame_count;
7252 7380
7253 long size = 0; 7381 long long size = 0;
7254 int frame_count = m_frame_count; 7382 int frame_count = m_frame_count;
7255 7383
7256 while (frame_count > 1) { 7384 while (frame_count > 1) {
7257 long frame_size = 0; 7385 long frame_size = 0;
7258 7386
7259 for (;;) { 7387 for (;;) {
7260 unsigned char val; 7388 unsigned char val;
7261 7389
7262 if (pos >= stop) 7390 if (pos >= stop)
7263 return E_FILE_FORMAT_INVALID; 7391 return E_FILE_FORMAT_INVALID;
7264 7392
7265 status = pReader->Read(pos, 1, &val); 7393 status = pReader->Read(pos, 1, &val);
7266 7394
7267 if (status) 7395 if (status)
7268 return E_FILE_FORMAT_INVALID; 7396 return E_FILE_FORMAT_INVALID;
7269 7397
7270 ++pos; // consume xiph size byte 7398 ++pos; // consume xiph size byte
7271 7399
7272 frame_size += val; 7400 frame_size += val;
7273 7401
7274 if (val < 255) 7402 if (val < 255)
7275 break; 7403 break;
7276 } 7404 }
7277 7405
7278 Frame& f = *pf++; 7406 Frame& f = *pf++;
7279 assert(pf < pf_end); 7407 assert(pf < pf_end);
7408 if (pf >= pf_end)
7409 return E_FILE_FORMAT_INVALID;
7280 7410
7281 f.pos = 0; // patch later 7411 f.pos = 0; // patch later
7282 7412
7283 if (frame_size <= 0) 7413 if (frame_size <= 0)
7284 return E_FILE_FORMAT_INVALID; 7414 return E_FILE_FORMAT_INVALID;
7285 7415
7286 f.len = frame_size; 7416 f.len = frame_size;
7287 size += frame_size; // contribution of this frame 7417 size += frame_size; // contribution of this frame
7288 7418
7289 --frame_count; 7419 --frame_count;
7290 } 7420 }
7291 7421
7292 assert(pf < pf_end); 7422 if (pf >= pf_end || pos > stop)
7293 assert(pos <= stop); 7423 return E_FILE_FORMAT_INVALID;
7294 7424
7295 { 7425 {
7296 Frame& f = *pf++; 7426 Frame& f = *pf++;
7297 7427
7298 if (pf != pf_end) 7428 if (pf != pf_end)
7299 return E_FILE_FORMAT_INVALID; 7429 return E_FILE_FORMAT_INVALID;
7300 7430
7301 f.pos = 0; // patch later 7431 f.pos = 0; // patch later
7302 7432
7303 const long long total_size = stop - pos; 7433 const long long total_size = stop - pos;
7304 7434
7305 if (total_size < size) 7435 if (total_size < size)
7306 return E_FILE_FORMAT_INVALID; 7436 return E_FILE_FORMAT_INVALID;
7307 7437
7308 const long long frame_size = total_size - size; 7438 const long long frame_size = total_size - size;
7309 7439
7310 if (frame_size > LONG_MAX || frame_size <= 0) 7440 if (frame_size > LONG_MAX || frame_size <= 0)
7311 return E_FILE_FORMAT_INVALID; 7441 return E_FILE_FORMAT_INVALID;
7312 7442
7313 f.len = static_cast<long>(frame_size); 7443 f.len = static_cast<long>(frame_size);
7314 } 7444 }
7315 7445
7316 pf = m_frames; 7446 pf = m_frames;
7317 while (pf != pf_end) { 7447 while (pf != pf_end) {
7318 Frame& f = *pf++; 7448 Frame& f = *pf++;
7319 assert((pos + f.len) <= stop); 7449 assert((pos + f.len) <= stop);
7320 7450
7451 if ((pos + f.len) > stop)
7452 return E_FILE_FORMAT_INVALID;
7453
7321 f.pos = pos; 7454 f.pos = pos;
7322 pos += f.len; 7455 pos += f.len;
7323 } 7456 }
7324 7457
7325 assert(pos == stop); 7458 assert(pos == stop);
7459 if (pos != stop)
7460 return E_FILE_FORMAT_INVALID;
7461
7326 } else if (lacing == 2) { // fixed-size lacing 7462 } else if (lacing == 2) { // fixed-size lacing
7327 if (pos >= stop) 7463 if (pos >= stop)
7328 return E_FILE_FORMAT_INVALID; 7464 return E_FILE_FORMAT_INVALID;
7329 7465
7330 const long long total_size = stop - pos; 7466 const long long total_size = stop - pos;
7331 7467
7332 if ((total_size % m_frame_count) != 0) 7468 if ((total_size % m_frame_count) != 0)
7333 return E_FILE_FORMAT_INVALID; 7469 return E_FILE_FORMAT_INVALID;
7334 7470
7335 const long long frame_size = total_size / m_frame_count; 7471 const long long frame_size = total_size / m_frame_count;
7336 7472
7337 if (frame_size > LONG_MAX || frame_size <= 0) 7473 if (frame_size > LONG_MAX || frame_size <= 0)
7338 return E_FILE_FORMAT_INVALID; 7474 return E_FILE_FORMAT_INVALID;
7339 7475
7340 Frame* pf = m_frames; 7476 Frame* pf = m_frames;
7341 Frame* const pf_end = pf + m_frame_count; 7477 Frame* const pf_end = pf + m_frame_count;
7342 7478
7343 while (pf != pf_end) { 7479 while (pf != pf_end) {
7344 assert((pos + frame_size) <= stop); 7480 assert((pos + frame_size) <= stop);
7481 if ((pos + frame_size) > stop)
7482 return E_FILE_FORMAT_INVALID;
7345 7483
7346 Frame& f = *pf++; 7484 Frame& f = *pf++;
7347 7485
7348 f.pos = pos; 7486 f.pos = pos;
7349 f.len = static_cast<long>(frame_size); 7487 f.len = static_cast<long>(frame_size);
7350 7488
7351 pos += frame_size; 7489 pos += frame_size;
7352 } 7490 }
7353 7491
7354 assert(pos == stop); 7492 assert(pos == stop);
7493 if (pos != stop)
7494 return E_FILE_FORMAT_INVALID;
7495
7355 } else { 7496 } else {
7356 assert(lacing == 3); // EBML lacing 7497 assert(lacing == 3); // EBML lacing
7357 7498
7358 if (pos >= stop) 7499 if (pos >= stop)
7359 return E_FILE_FORMAT_INVALID; 7500 return E_FILE_FORMAT_INVALID;
7360 7501
7361 long size = 0; 7502 long long size = 0;
7362 int frame_count = m_frame_count; 7503 int frame_count = m_frame_count;
7363 7504
7364 long long frame_size = ReadUInt(pReader, pos, len); 7505 long long frame_size = ReadUInt(pReader, pos, len);
7365 7506
7366 if (frame_size <= 0) 7507 if (frame_size <= 0)
7367 return E_FILE_FORMAT_INVALID; 7508 return E_FILE_FORMAT_INVALID;
7368 7509
7369 if (frame_size > LONG_MAX) 7510 if (frame_size > LONG_MAX)
7370 return E_FILE_FORMAT_INVALID; 7511 return E_FILE_FORMAT_INVALID;
7371 7512
(...skipping 17 matching lines...) Expand all
7389 size += curr.len; // contribution of this frame 7530 size += curr.len; // contribution of this frame
7390 } 7531 }
7391 7532
7392 --frame_count; 7533 --frame_count;
7393 7534
7394 while (frame_count > 1) { 7535 while (frame_count > 1) {
7395 if (pos >= stop) 7536 if (pos >= stop)
7396 return E_FILE_FORMAT_INVALID; 7537 return E_FILE_FORMAT_INVALID;
7397 7538
7398 assert(pf < pf_end); 7539 assert(pf < pf_end);
7540 if (pf >= pf_end)
7541 return E_FILE_FORMAT_INVALID;
7542
7399 7543
7400 const Frame& prev = *pf++; 7544 const Frame& prev = *pf++;
7401 assert(prev.len == frame_size); 7545 assert(prev.len == frame_size);
7402 if (prev.len != frame_size) 7546 if (prev.len != frame_size)
7403 return E_FILE_FORMAT_INVALID; 7547 return E_FILE_FORMAT_INVALID;
7404 7548
7405 assert(pf < pf_end); 7549 assert(pf < pf_end);
7550 if (pf >= pf_end)
7551 return E_FILE_FORMAT_INVALID;
7406 7552
7407 Frame& curr = *pf; 7553 Frame& curr = *pf;
7408 7554
7409 curr.pos = 0; // patch later 7555 curr.pos = 0; // patch later
7410 7556
7411 const long long delta_size_ = ReadUInt(pReader, pos, len); 7557 const long long delta_size_ = ReadUInt(pReader, pos, len);
7412 7558
7413 if (delta_size_ < 0) 7559 if (delta_size_ < 0)
7414 return E_FILE_FORMAT_INVALID; 7560 return E_FILE_FORMAT_INVALID;
7415 7561
7416 if ((pos + len) > stop) 7562 if ((pos + len) > stop)
7417 return E_FILE_FORMAT_INVALID; 7563 return E_FILE_FORMAT_INVALID;
7418 7564
7419 pos += len; // consume length of (delta) size 7565 pos += len; // consume length of (delta) size
7420 assert(pos <= stop); 7566 if (pos > stop)
7567 return E_FILE_FORMAT_INVALID;
7421 7568
7422 const int exp = 7 * len - 1; 7569 const int exp = 7 * len - 1;
7423 const long long bias = (1LL << exp) - 1LL; 7570 const long long bias = (1LL << exp) - 1LL;
7424 const long long delta_size = delta_size_ - bias; 7571 const long long delta_size = delta_size_ - bias;
7425 7572
7426 frame_size += delta_size; 7573 frame_size += delta_size;
7427 7574
7428 if (frame_size <= 0) 7575 if (frame_size <= 0)
7429 return E_FILE_FORMAT_INVALID; 7576 return E_FILE_FORMAT_INVALID;
7430 7577
7431 if (frame_size > LONG_MAX) 7578 if (frame_size > LONG_MAX)
7432 return E_FILE_FORMAT_INVALID; 7579 return E_FILE_FORMAT_INVALID;
7433 7580
7434 curr.len = static_cast<long>(frame_size); 7581 curr.len = static_cast<long>(frame_size);
7435 size += curr.len; // contribution of this frame 7582 size += curr.len; // contribution of this frame
7436 7583
7437 --frame_count; 7584 --frame_count;
7438 } 7585 }
7439 7586
7440 // parse last frame 7587 // parse last frame
7441 if (frame_count > 0) { 7588 if (frame_count > 0) {
7442 assert(pos <= stop); 7589 if (pos > stop || pf >= pf_end)
7443 assert(pf < pf_end); 7590 return E_FILE_FORMAT_INVALID;
7444 7591
7445 const Frame& prev = *pf++; 7592 const Frame& prev = *pf++;
7446 assert(prev.len == frame_size); 7593 assert(prev.len == frame_size);
7447 if (prev.len != frame_size) 7594 if (prev.len != frame_size)
7448 return E_FILE_FORMAT_INVALID; 7595 return E_FILE_FORMAT_INVALID;
7449 7596
7450 assert(pf < pf_end); 7597 if (pf >= pf_end)
7598 return E_FILE_FORMAT_INVALID;
7451 7599
7452 Frame& curr = *pf++; 7600 Frame& curr = *pf++;
7453 assert(pf == pf_end); 7601 if (pf != pf_end)
7602 return E_FILE_FORMAT_INVALID;
7454 7603
7455 curr.pos = 0; // patch later 7604 curr.pos = 0; // patch later
7456 7605
7457 const long long total_size = stop - pos; 7606 const long long total_size = stop - pos;
7458 7607
7459 if (total_size < size) 7608 if (total_size < size)
7460 return E_FILE_FORMAT_INVALID; 7609 return E_FILE_FORMAT_INVALID;
7461 7610
7462 frame_size = total_size - size; 7611 frame_size = total_size - size;
7463 7612
7464 if (frame_size > LONG_MAX || frame_size <= 0) 7613 if (frame_size > LONG_MAX || frame_size <= 0)
7465 return E_FILE_FORMAT_INVALID; 7614 return E_FILE_FORMAT_INVALID;
7466 7615
7467 curr.len = static_cast<long>(frame_size); 7616 curr.len = static_cast<long>(frame_size);
7468 } 7617 }
7469 7618
7470 pf = m_frames; 7619 pf = m_frames;
7471 while (pf != pf_end) { 7620 while (pf != pf_end) {
7472 Frame& f = *pf++; 7621 Frame& f = *pf++;
7473 assert((pos + f.len) <= stop); 7622 assert((pos + f.len) <= stop);
7623 if ((pos + f.len) > stop)
7624 return E_FILE_FORMAT_INVALID;
7474 7625
7475 f.pos = pos; 7626 f.pos = pos;
7476 pos += f.len; 7627 pos += f.len;
7477 } 7628 }
7478 7629
7479 if (pos != stop) 7630 if (pos != stop)
7480 return E_FILE_FORMAT_INVALID; 7631 return E_FILE_FORMAT_INVALID;
7481 } 7632 }
7482 7633
7483 return 0; // success 7634 return 0; // success
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after
7549 assert(pReader); 7700 assert(pReader);
7550 assert(buf); 7701 assert(buf);
7551 7702
7552 const long status = pReader->Read(pos, len, buf); 7703 const long status = pReader->Read(pos, len, buf);
7553 return status; 7704 return status;
7554 } 7705 }
7555 7706
7556 long long Block::GetDiscardPadding() const { return m_discard_padding; } 7707 long long Block::GetDiscardPadding() const { return m_discard_padding; }
7557 7708
7558 } // end namespace mkvparser 7709 } // end namespace mkvparser
OLDNEW
« no previous file with comments | « source/libvpx/third_party/libwebm/mkvparser.hpp ('k') | source/libvpx/third_party/libwebm/webmids.hpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698