shithub: dav1d

Download patch

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;
 }