[FFmpeg-devel] [PATCH 1/7] avformat/avc: Fix undefined shift and assert when reading exp-golomb num
Andreas Rheinhardt
andreas.rheinhardt at gmail.com
Thu Jul 9 13:35:36 EEST 2020
The current code for parsing unsigned exponential-golomb codes is not
suitable for long codes: If there are enough leading zeroes, it
left-shifts 1 by 32 places and uses get_bitsz to read 32 bits, although
it is only suitable to read 0-25 bits. There is an av_assert2 to
ensure this when using the uncached bitstream reader; with valid input
one can still run into the assert and left-shift 1 by 31 which is
undefined.
This commit changes this. All valid data is parsed correctly; invalid
data does no longer lead to undefined behaviour or to asserts. Parsing
all valid data correctly also necessitated changing the return value to
unsigned; also an intermediate variable used for parsing signed
exponential-golomb codes needed to be made unsigned, too, in order to
parse long signed codes correctly.
Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt at gmail.com>
---
Moving the function to the beginning is done in preparation for another
commit that I'll send soon.
libavformat/avc.c | 24 ++++++++++++++++--------
1 file changed, 16 insertions(+), 8 deletions(-)
diff --git a/libavformat/avc.c b/libavformat/avc.c
index b5e2921388..55494eb08a 100644
--- a/libavformat/avc.c
+++ b/libavformat/avc.c
@@ -27,6 +27,21 @@
#include "avc.h"
#include "avio_internal.h"
+static inline unsigned get_ue_golomb(GetBitContext *gb)
+{
+ int i;
+ for (i = 1; i <= 32; i++) {
+ if (get_bits_left(gb) < i)
+ return 0;
+ if (show_bits1(gb))
+ break;
+ skip_bits1(gb);
+ }
+ if (i > 32)
+ return 0;
+ return get_bits_long(gb, i) - 1;
+}
+
static const uint8_t *avc_find_startcode_internal(const uint8_t *p, const uint8_t *end)
{
const uint8_t *a = p + 4 - ((intptr_t)p & 3);
@@ -318,15 +333,8 @@ static const AVRational avc_sample_aspect_ratio[17] = {
{ 2, 1 },
};
-static inline int get_ue_golomb(GetBitContext *gb) {
- int i;
- for (i = 0; i < 32 && !get_bits1(gb); i++)
- ;
- return get_bitsz(gb, i) + (1 << i) - 1;
-}
-
static inline int get_se_golomb(GetBitContext *gb) {
- int v = get_ue_golomb(gb) + 1;
+ unsigned v = get_ue_golomb(gb) + 1;
int sign = -(v & 1);
return ((v >> 1) ^ sign) - sign;
}
--
2.20.1
More information about the ffmpeg-devel
mailing list