cbs_av1: Reject thirty-two zero bits in uvlc code

The spec allows at least thirty-two zero bits followed by a one to mean
2^32-1, with no constraint on the number of zeroes.  The libaom
reference decoder does not match this, instead reading thirty-two zeroes
but not the following one to mean 2^32-1.  These two interpretations are
incompatible and other implementations may follow one or the other.
Therefore reject thirty-two zeroes because the intended behaviour is not
clear.

Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
This commit is contained in:
Mark Thompson 2023-10-22 19:35:52 +01:00 committed by Michael Niedermayer
parent 3faadbe2a2
commit 7110a36ba0
No known key found for this signature in database
GPG Key ID: B18E8928B3948D64
1 changed files with 13 additions and 5 deletions

View File

@ -36,7 +36,7 @@ static int cbs_av1_read_uvlc(CodedBitstreamContext *ctx, GetBitContext *gbc,
CBS_TRACE_READ_START(); CBS_TRACE_READ_START();
zeroes = 0; zeroes = 0;
while (1) { while (zeroes < 32) {
if (get_bits_left(gbc) < 1) { if (get_bits_left(gbc) < 1) {
av_log(ctx->log_ctx, AV_LOG_ERROR, "Invalid uvlc code at " av_log(ctx->log_ctx, AV_LOG_ERROR, "Invalid uvlc code at "
"%s: bitstream ended.\n", name); "%s: bitstream ended.\n", name);
@ -49,10 +49,18 @@ static int cbs_av1_read_uvlc(CodedBitstreamContext *ctx, GetBitContext *gbc,
} }
if (zeroes >= 32) { if (zeroes >= 32) {
// Note that the spec allows an arbitrarily large number of // The spec allows at least thirty-two zero bits followed by a
// zero bits followed by a one bit in this case, but the // one to mean 2^32-1, with no constraint on the number of
// libaom implementation does not support it. // zeroes. The libaom reference decoder does not match this,
value = MAX_UINT_BITS(32); // instead reading thirty-two zeroes but not the following one
// to mean 2^32-1. These two interpretations are incompatible
// and other implementations may follow one or the other.
// Therefore we reject thirty-two zeroes because the intended
// behaviour is not clear.
av_log(ctx->log_ctx, AV_LOG_ERROR, "Thirty-two zero bits in "
"%s uvlc code: considered invalid due to conflicting "
"standard and reference decoder behaviour.\n", name);
return AVERROR_INVALIDDATA;
} else { } else {
if (get_bits_left(gbc) < zeroes) { if (get_bits_left(gbc) < zeroes) {
av_log(ctx->log_ctx, AV_LOG_ERROR, "Invalid uvlc code at " av_log(ctx->log_ctx, AV_LOG_ERROR, "Invalid uvlc code at "