ref: 47daa4df3387c1529536243db80b81f3878cbf76
parent: 54f92068caa25ccf75af52067786caf0415a17e0
author: Ronald S. Bultje <rsbultje@gmail.com>
date: Mon Jun 22 17:10:55 EDT 2020
Accumulate leb128 value using uint64_t as intermediate type The shift-amount can be up to 56, and left-shifting 32-bit integers by values >=32 is undefined behaviour. Therefore, use 64-bit integers instead. Also slightly rewrite so we only call dav1d_get_bits() once for the combined more|bits value, and mask the relevant portions out instead of reading twice. Lastly, move the overflow check out of the loop (as suggested by @wtc) Fixes #341.
--- a/src/getbits.c
+++ b/src/getbits.c
@@ -81,25 +81,23 @@
return res >> shift;
}
-unsigned dav1d_get_uleb128(GetBits *c) {
- unsigned val = 0, more, i = 0, max = UINT_MAX;
+unsigned dav1d_get_uleb128(GetBits *const c) {
+ uint64_t val = 0;
+ unsigned i = 0, more;
do {
- more = dav1d_get_bits(c, 1);
- unsigned bits = dav1d_get_bits(c, 7);
- if (bits > max) {
- c->error = 1;
- return 0;
- }
- val |= bits << (i * 7);
- max >>= 7;
- if (more && ++i == 8) {
- c->error = 1;
- return 0;
- }
- } while (more);
+ const int v = dav1d_get_bits(c, 8);
+ more = v & 0x80;
+ val |= ((uint64_t) (v & 0x7F)) << i;
+ i += 7;
+ } while (more && i < 56);
- return val;
+ if (val > UINT_MAX || more) {
+ c->error = 1;
+ return 0;
+ }
+
+ return (unsigned) val;
}
unsigned dav1d_get_uniform(GetBits *const c, const unsigned max) {
--- a/tools/input/parse.h
+++ b/tools/input/parse.h
@@ -34,19 +34,19 @@
#include "dav1d/headers.h"
static int leb128(FILE *const f, size_t *const len) {
- unsigned i = 0, more, max = UINT_MAX;
- *len = 0;
+ uint64_t val = 0;
+ unsigned i = 0, more;
do {
- uint8_t byte;
- if (fread(&byte, 1, 1, f) < 1)
+ uint8_t v;
+ if (fread(&v, 1, 1, f) < 1)
return -1;
- more = byte & 0x80;
- const unsigned bits = byte & 0x7f;
- if (bits > max) return -1;
- *len |= bits << (i * 7);
- max >>= 7;
- if (++i == 8 && more) return -1;
- } while (more);
+ more = v & 0x80;
+ val |= ((uint64_t) (v & 0x7F)) << (i * 7);
+ i++;
+ } while (more && i < 8);
+ if (val > UINT_MAX || more)
+ return -1;
+ *len = (size_t) val;
return i;
}
@@ -54,18 +54,18 @@
// with author's permission
static int leb(const uint8_t *ptr, int sz, size_t *const len) {
- unsigned i = 0, more, max = UINT_MAX;
- *len = 0;
+ uint64_t val = 0;
+ unsigned i = 0, more;
do {
if (!sz--) return -1;
- const int byte = *ptr++;
- more = byte & 0x80;
- const unsigned bits = byte & 0x7f;
- if (bits > max) return -1;
- *len |= bits << (i * 7);
- max >>= 7;
- if (++i == 8 && more) return -1;
- } while (more);
+ const int v = *ptr++;
+ more = v & 0x80;
+ val |= ((uint64_t) (v & 0x7F)) << (i * 7);
+ i++;
+ } while (more && i < 8);
+ if (val > UINT_MAX || more)
+ return -1;
+ *len = (size_t) val;
return i;
}