Commit c213343c8d for aom
commit c213343c8d32bcae729fe09fcba16e1f371cb23b
Author: Wan-Teh Chang <wtc@google.com>
Date: Fri May 22 16:34:28 2026 -0700
Check bitstream buffer size in av1_pack_tile_info
Add the `size` field to struct aom_writer for the buffer size. Add a new
version of aom_start_encode() called aom_start_encode_with_size() that
sets the `size` field. The current aom_start_encode() function sets the
`size` field to 0, which means the buffer size is unknown.
Call the new aom_start_encode_with_size() function in
av1_pack_tile_info() so that the aom_stop_encode() call can check the
tile bitstream buffer size before writing to the tile bitstream buffer.
Clarify two comments about tile size in av1_pack_tile_info().
In write_tile_obu(), set pack_bs_params.tile_buf_size because this field
will be used in av1_pack_tile_info().
Bug: 42302568
Bug: oss-fuzz:514006304
Change-Id: I4e4660255cb9d3d53f96084197ed71d82830266b
diff --git a/aom_dsp/bitwriter.c b/aom_dsp/bitwriter.c
index 36f43da3b6..7fb660dea8 100644
--- a/aom_dsp/bitwriter.c
+++ b/aom_dsp/bitwriter.c
@@ -13,7 +13,14 @@
#include "aom_dsp/bitwriter.h"
void aom_start_encode(aom_writer *w, uint8_t *source) {
+ // TODO: bug 42302568 - During the transition period, size=0 means the
+ // buffer size is unknown.
+ aom_start_encode_with_size(w, source, /*size=*/0);
+}
+
+void aom_start_encode_with_size(aom_writer *w, uint8_t *source, size_t size) {
w->buffer = source;
+ w->size = size;
w->pos = 0;
od_ec_enc_init(&w->ec, 62025);
}
@@ -23,7 +30,9 @@ int aom_stop_encode(aom_writer *w) {
uint32_t bytes;
unsigned char *data;
data = od_ec_enc_done(&w->ec, &bytes);
- if (!data) {
+ // TODO: bug 42302568 - Remove "w->size != 0 &&" after all aom_start_encode()
+ // calls have been converted to aom_start_encode_with_size().
+ if (!data || (w->size != 0 && bytes > w->size)) {
od_ec_enc_clear(&w->ec);
return -1;
}
diff --git a/aom_dsp/bitwriter.h b/aom_dsp/bitwriter.h
index 5cb26169e9..46da728432 100644
--- a/aom_dsp/bitwriter.h
+++ b/aom_dsp/bitwriter.h
@@ -35,6 +35,7 @@ extern "C" {
struct aom_writer {
unsigned int pos;
uint8_t *buffer;
+ size_t size;
od_ec_enc ec;
uint8_t allow_update_cdf;
};
@@ -60,7 +61,12 @@ static inline void init_token_stats(TOKEN_STATS *token_stats) {
token_stats->cost = 0;
}
+// TODO: bug 42302568 - Gradually replace aom_start_encode() calls with
+// aom_start_encode_with_size(). When there are no more aom_start_encode()
+// calls, remove aom_start_encode() and rename aom_start_encode_with_size()
+// back to aom_start_encode().
void aom_start_encode(aom_writer *w, uint8_t *buffer);
+void aom_start_encode_with_size(aom_writer *w, uint8_t *buffer, size_t size);
// Returns a negative number on error. Caller must check the return value and
// handle error.
diff --git a/av1/encoder/bitstream.c b/av1/encoder/bitstream.c
index 2d6890a678..7cb21bdc65 100644
--- a/av1/encoder/bitstream.c
+++ b/av1/encoder/bitstream.c
@@ -3854,11 +3854,16 @@ void av1_pack_tile_info(AV1_COMP *const cpi, ThreadData *const td,
pack_bs_params->buf.data = pack_bs_params->dst + *total_size;
- // The last tile of the tile group does not have a header.
+ // The last tile of the tile group does not have a tile_size_minus_1 header.
if (!pack_bs_params->is_last_tile_in_tg) *total_size += 4;
// Pack tile data
- aom_start_encode(&mode_bc, pack_bs_params->dst + *total_size);
+ if (pack_bs_params->tile_buf_size <= *total_size) {
+ aom_internal_error(td->mb.e_mbd.error_info, AOM_CODEC_ERROR,
+ "Error writing modes");
+ }
+ aom_start_encode_with_size(&mode_bc, pack_bs_params->dst + *total_size,
+ pack_bs_params->tile_buf_size - *total_size);
write_modes(cpi, td, &tile_info, &mode_bc, tile_row, tile_col);
if (aom_stop_encode(&mode_bc) < 0) {
aom_internal_error(td->mb.e_mbd.error_info, AOM_CODEC_ERROR,
@@ -3871,7 +3876,7 @@ void av1_pack_tile_info(AV1_COMP *const cpi, ThreadData *const td,
// Write tile size
if (!pack_bs_params->is_last_tile_in_tg) {
- // size of this tile
+ // size of this tile minus 1
mem_put_le32(pack_bs_params->buf.data, tile_size - AV1_MIN_TILE_SIZE_BYTES);
}
}
@@ -3953,11 +3958,11 @@ void av1_accumulate_pack_bs_thread_data(AV1_COMP *const cpi,
// Store information related to each default tile in the OBU header.
static void write_tile_obu(
- AV1_COMP *const cpi, uint8_t *const dst, uint32_t *total_size,
- struct aom_write_bit_buffer *saved_wb, uint8_t obu_extn_header,
- const FrameHeaderInfo *fh_info, int *const largest_tile_id,
- unsigned int *max_tile_size, uint32_t *const obu_header_size,
- uint8_t **tile_data_start) {
+ AV1_COMP *const cpi, uint8_t *const dst, size_t dst_size,
+ uint32_t *total_size, struct aom_write_bit_buffer *saved_wb,
+ uint8_t obu_extn_header, const FrameHeaderInfo *fh_info,
+ int *const largest_tile_id, unsigned int *max_tile_size,
+ uint32_t *const obu_header_size, uint8_t **tile_data_start) {
AV1_COMMON *const cm = &cpi->common;
MACROBLOCKD *const xd = &cpi->td.mb.e_mbd;
const CommonTileParams *const tiles = &cm->tiles;
@@ -3994,6 +3999,7 @@ static void write_tile_obu(
// info.
PackBSParams pack_bs_params;
pack_bs_params.dst = dst;
+ pack_bs_params.tile_buf_size = dst_size;
pack_bs_params.curr_tg_hdr_size = 0;
pack_bs_params.is_last_tile_in_tg = is_last_tile_in_tg;
pack_bs_params.new_tg = new_tg;
@@ -4149,9 +4155,9 @@ static inline uint32_t pack_tiles_in_tg_obus(
&max_tile_size, &obu_header_size, &tile_data_start,
num_workers);
} else {
- write_tile_obu(cpi, dst, &total_size, saved_wb, obu_extension_header,
- fh_info, largest_tile_id, &max_tile_size, &obu_header_size,
- &tile_data_start);
+ write_tile_obu(cpi, dst, dst_size, &total_size, saved_wb,
+ obu_extension_header, fh_info, largest_tile_id,
+ &max_tile_size, &obu_header_size, &tile_data_start);
}
if (num_tiles > 1)