From 44cde38c8acbef7d5250e6d1b52b1020871e093b Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Tue, 12 Sep 2017 22:11:41 +0100 Subject: cbs: Always check for bitstream end before reading --- libavcodec/cbs.c | 6 +++ libavcodec/cbs_h2645.c | 118 ++++++++++++++++++++++++------------------------- libavcodec/cbs_mpeg2.c | 5 ++- 3 files changed, 67 insertions(+), 62 deletions(-) (limited to 'libavcodec') diff --git a/libavcodec/cbs.c b/libavcodec/cbs.c index 10943164da..7440914939 100644 --- a/libavcodec/cbs.c +++ b/libavcodec/cbs.c @@ -313,6 +313,12 @@ int ff_cbs_read_unsigned(CodedBitstreamContext *ctx, BitstreamContext *bc, av_assert0(width <= 32); + if (bitstream_bits_left(bc) < width) { + av_log(ctx->log_ctx, AV_LOG_ERROR, "Invalid value at " + "%s: bitstream ended.\n", name); + return AVERROR_INVALIDDATA; + } + if (ctx->trace_enable) position = bitstream_tell(bc); diff --git a/libavcodec/cbs_h2645.c b/libavcodec/cbs_h2645.c index 4d8ba99b35..c8a13f1679 100644 --- a/libavcodec/cbs_h2645.c +++ b/libavcodec/cbs_h2645.c @@ -36,40 +36,39 @@ static int cbs_read_ue_golomb(CodedBitstreamContext *ctx, BitstreamContext *bc, uint32_t range_min, uint32_t range_max) { uint32_t value; - int position; + int position, i, j; + unsigned int k; + char bits[65]; - if (ctx->trace_enable) { - char bits[65]; - unsigned int k; - int i, j; + position = bitstream_tell(bc); - position = bitstream_tell(bc); - - for (i = 0; i < 32; i++) { - k = bitstream_read_bit(bc); - bits[i] = k ? '1' : '0'; - if (k) - break; - } - if (i >= 32) { - av_log(ctx->log_ctx, AV_LOG_ERROR, "Invalid ue-golomb " - "code found while reading %s: " - "more than 31 zeroes.\n", name); + for (i = 0; i < 32; i++) { + if (bitstream_bits_left(bc) < i + 1) { + av_log(ctx->log_ctx, AV_LOG_ERROR, "Invalid ue-golomb code at " + "%s: bitstream ended.\n", name); return AVERROR_INVALIDDATA; } - value = 1; - for (j = 0; j < i; j++) { - k = bitstream_read_bit(bc); - bits[i + j + 1] = k ? '1' : '0'; - value = value << 1 | k; - } - bits[i + j + 1] = 0; - --value; + k = bitstream_read_bit(bc); + bits[i] = k ? '1' : '0'; + if (k) + break; + } + if (i >= 32) { + av_log(ctx->log_ctx, AV_LOG_ERROR, "Invalid ue-golomb code at " + "%s: more than 31 zeroes.\n", name); + return AVERROR_INVALIDDATA; + } + value = 1; + for (j = 0; j < i; j++) { + k = bitstream_read_bit(bc); + bits[i + j + 1] = k ? '1' : '0'; + value = value << 1 | k; + } + bits[i + j + 1] = 0; + --value; + if (ctx->trace_enable) ff_cbs_trace_syntax_element(ctx, position, name, bits, value); - } else { - value = get_ue_golomb_long(bc); - } if (value < range_min || value > range_max) { av_log(ctx->log_ctx, AV_LOG_ERROR, "%s out of range: " @@ -87,44 +86,43 @@ static int cbs_read_se_golomb(CodedBitstreamContext *ctx, BitstreamContext *bc, int32_t range_min, int32_t range_max) { int32_t value; - int position; + int position, i, j; + unsigned int k; + uint32_t v; + char bits[65]; - if (ctx->trace_enable) { - char bits[65]; - uint32_t v; - unsigned int k; - int i, j; - - position = bitstream_tell(bc); + position = bitstream_tell(bc); - for (i = 0; i < 32; i++) { - k = bitstream_read_bit(bc); - bits[i] = k ? '1' : '0'; - if (k) - break; - } - if (i >= 32) { - av_log(ctx->log_ctx, AV_LOG_ERROR, "Invalid se-golomb " - "code found while reading %s: " - "more than 31 zeroes.\n", name); + for (i = 0; i < 32; i++) { + if (bitstream_bits_left(bc) < i + 1) { + av_log(ctx->log_ctx, AV_LOG_ERROR, "Invalid se-golomb code at " + "%s: bitstream ended.\n", name); return AVERROR_INVALIDDATA; } - v = 1; - for (j = 0; j < i; j++) { - k = bitstream_read_bit(bc); - bits[i + j + 1] = k ? '1' : '0'; - v = v << 1 | k; - } - bits[i + j + 1] = 0; - if (v & 1) - value = -(int32_t)(v / 2); - else - value = v / 2; + k = bitstream_read_bit(bc); + bits[i] = k ? '1' : '0'; + if (k) + break; + } + if (i >= 32) { + av_log(ctx->log_ctx, AV_LOG_ERROR, "Invalid se-golomb code at " + "%s: more than 31 zeroes.\n", name); + return AVERROR_INVALIDDATA; + } + v = 1; + for (j = 0; j < i; j++) { + k = bitstream_read_bit(bc); + bits[i + j + 1] = k ? '1' : '0'; + v = v << 1 | k; + } + bits[i + j + 1] = 0; + if (v & 1) + value = -(int32_t)(v / 2); + else + value = v / 2; + if (ctx->trace_enable) ff_cbs_trace_syntax_element(ctx, position, name, bits, value); - } else { - value = get_se_golomb_long(bc); - } if (value < range_min || value > range_max) { av_log(ctx->log_ctx, AV_LOG_ERROR, "%s out of range: " diff --git a/libavcodec/cbs_mpeg2.c b/libavcodec/cbs_mpeg2.c index fede3ff471..cbee42e905 100644 --- a/libavcodec/cbs_mpeg2.c +++ b/libavcodec/cbs_mpeg2.c @@ -58,8 +58,9 @@ CHECK(ff_cbs_read_unsigned(ctx, rw, 1, "marker_bit", &one, 1, 1)); \ } while (0) -#define nextbits(width, compare, var) (var = bitstream_peek(rw, width), \ - var == (compare)) +#define nextbits(width, compare, var) \ + (bitstream_bits_left(rw) >= width && \ + (var = bitstream_peek(rw, width)) == (compare)) #include "cbs_mpeg2_syntax_template.c" -- cgit v1.2.3