History

lavc/bitstream: avoid UB in bits_{read,peek}_signed(0)

bits_*_signed(0) will currently invoke an undefined shift by 8 * sizeof(int). Add bits_*_signed_nz() that only works for n>0, analogous to bits_read_nz(). Add an explicit check for n=0 in bits_*_signed().

Anton Khirnov committed 3 years ago

Commit 0b333101 parent bf23d533 files · +39 −3Browse files

Unified · Split

3 files
  1. libavcodec/bitstream.h +4 −0
  2. libavcodec/bitstream_template.h +34 −2
  3. libavcodec/get_bits.h +1 −1
libavcodec/bitstream.h+4−0
@@ -89,9 +89,11 @@ · 88 unmodified lines
8989 # define bits_read_63 bits_read_63_le
9090 # define bits_read_64 bits_read_64_le
9191 # define bits_read_signed bits_read_signed_le
92+# define bits_read_signed_nz bits_read_signed_nz_le
9293 # define bits_peek_nz bits_peek_nz_le
9394 # define bits_peek bits_peek_le
9495 # define bits_peek_signed bits_peek_signed_le
96+# define bits_peek_signed_nz bits_peek_signed_nz_le
9597 # define bits_skip bits_skip_le
9698 # define bits_seek bits_seek_le
9799 # define bits_align bits_align_le
@@ -115,9 +117,11 @@ · 17 unmodified lines
115117 # define bits_read_63 bits_read_63_be
116118 # define bits_read_64 bits_read_64_be
117119 # define bits_read_signed bits_read_signed_be
120+# define bits_read_signed_nz bits_read_signed_nz_be
118121 # define bits_peek_nz bits_peek_nz_be
119122 # define bits_peek bits_peek_be
120123 # define bits_peek_signed bits_peek_signed_be
124+# define bits_peek_signed_nz bits_peek_signed_nz_be
121125 # define bits_skip bits_skip_be
122126 # define bits_seek bits_seek_be
123127 # define bits_align bits_align_be
libavcodec/bitstream_template.h+34−2
@@ -290,13 +290,29 @@ static inline uint64_t BS_FUNC(read_64)(BSCTX *bc, unsigned int n) · 289 unmodified lines
290290 return BS_FUNC(read_63)(bc, n);
291291 }
292292
293+/**
294+ * Return n bits from the buffer as a signed integer, n has to be in the 1-32
295+ * range. May be faster than bits_read_signed() when n is not a compile-time
296+ * constant and is known to be non-zero;
297+ */
298+static inline int32_t BS_FUNC(read_signed_nz)(BSCTX *bc, unsigned int n)
299+{
300+ av_assert2(n > 0 && n <= 32);
301+ return sign_extend(BS_FUNC(read_nz)(bc, n), n);
302+}
303+
293304 /**
294305 * Return n bits from the buffer as a signed integer.
295306 * n has to be in the 0-32 range.
296307 */
297308 static inline int32_t BS_FUNC(read_signed)(BSCTX *bc, unsigned int n)
298309 {
299− return sign_extend(BS_FUNC(read)(bc, n), n);
310+ av_assert2(n <= 32);
311+
312+ if (!n)
313+ return 0;
314+
315+ return BS_FUNC(read_signed_nz)(bc, n);
300316 }
301317
302318 /**
@@ -327,6 +343,17 @@ static inline uint32_t BS_FUNC(peek)(BSCTX *bc, unsigned int n) · 24 unmodified lines
327343 return BS_FUNC(peek_nz)(bc, n);
328344 }
329345
346+/**
347+ * Return n bits from the buffer as a signed integer, do not change the buffer
348+ * state. n has to be in the 1-32 range. May be faster than bits_peek_signed()
349+ * when n is not a compile-time constant and is known to be non-zero;
350+ */
351+static inline int BS_FUNC(peek_signed_nz)(BSCTX *bc, unsigned int n)
352+{
353+ av_assert2(n > 0 && n <= 32);
354+ return sign_extend(BS_FUNC(peek_nz)(bc, n), n);
355+}
356+
330357 /**
331358 * Return n bits from the buffer as a signed integer,
332359 * do not change the buffer state.
@@ -334,7 +361,12 @@ static inline uint32_t BS_FUNC(peek)(BSCTX *bc, unsigned int n) · 1 unmodified line
334361 */
335362 static inline int BS_FUNC(peek_signed)(BSCTX *bc, unsigned int n)
336363 {
337− return sign_extend(BS_FUNC(peek)(bc, n), n);
364+ av_assert2(n <= 32);
365+
366+ if (!n)
367+ return 0;
368+
369+ return BS_FUNC(peek_signed_nz)(bc, n);
338370 }
339371
340372 /**
libavcodec/get_bits.h+1−1
@@ -85,7 +85,7 @@ typedef BitstreamContext GetBitContext; · 84 unmodified lines
8585 #define get_bits1 bits_read_bit
8686 #define get_bits64 bits_read_64
8787 #define get_xbits bits_read_xbits
88−#define get_sbits bits_read_signed
88+#define get_sbits bits_read_signed_nz
8989 #define get_sbits_long bits_read_signed
9090 #define show_bits bits_peek
9191 #define show_bits_long bits_peek

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t