[FFmpeg-devel] [PATCH 1/7] avformat/avc: Fix undefined shift and assert when reading exp-golomb num
James Almer
jamrial at gmail.com
Thu Jul 9 22:21:15 EEST 2020
On 7/9/2020 7:35 AM, Andreas Rheinhardt wrote:
> 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;
> }
I think it's best if we use the lavc golomb code instead. When i
suggested to re implement it here i wasn't aware it was shared with lavf
within the golomb_tab.c source file.
More information about the ffmpeg-devel
mailing list