93 lines
3.4 KiB
Diff
93 lines
3.4 KiB
Diff
From a216f6ea8264726a593908562ecbd509bf6a69ee Mon Sep 17 00:00:00 2001
|
|
From: Wan-Teh Chang <wtc@google.com>
|
|
Date: Wed, 21 Jan 2026 18:03:55 -0800
|
|
Subject: [PATCH] write_superframe_index: return 0 if buffer is full
|
|
|
|
write_superframe_index() should return the number of bytes written to
|
|
ctx->pending_cx_data. If ctx->pending_cx_data is full,
|
|
write_superframe_index() doesn't write the optional superframe index, so
|
|
it should return 0 in this case. Add an assertion that would have
|
|
detected this bug. Add and clarify comments for code related to this
|
|
bug.
|
|
|
|
Also fix the buffer full check. The check should not assume that
|
|
ctx->pending_cx_data is equal to ctx->cx_data, and the check had an
|
|
off-by-one error.
|
|
|
|
The bug was introduced when write_superframe_index() was added in the
|
|
following CLs:
|
|
https://chromium-review.googlesource.com/c/webm/libvpx/+/44659
|
|
https://chromium-review.googlesource.com/c/webm/libvpx/+/45268
|
|
|
|
Bug: oss-fuzz:476466137
|
|
Change-Id: Ie113568cf25acc73f8af640a3c51cfdb5b900613
|
|
---
|
|
vp9/vp9_cx_iface.c | 22 ++++++++++++++++++----
|
|
1 file changed, 18 insertions(+), 4 deletions(-)
|
|
|
|
diff --git a/vp9/vp9_cx_iface.c b/vp9/vp9_cx_iface.c
|
|
index 9074e1b4e..5e7c1d6f6 100644
|
|
--- a/vp9/vp9_cx_iface.c
|
|
+++ b/vp9/vp9_cx_iface.c
|
|
@@ -8,6 +8,10 @@
|
|
* be found in the AUTHORS file in the root of the source tree.
|
|
*/
|
|
|
|
+#include <assert.h>
|
|
+#include <limits.h>
|
|
+#include <stddef.h>
|
|
+#include <stdint.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
@@ -110,6 +114,7 @@ struct vpx_codec_alg_priv {
|
|
VP9_COMP *cpi;
|
|
unsigned char *cx_data;
|
|
size_t cx_data_sz;
|
|
+ // pending_cx_data either is a null pointer or points into the cx_data buffer.
|
|
unsigned char *pending_cx_data;
|
|
size_t pending_cx_data_sz;
|
|
int pending_frame_count;
|
|
@@ -1020,8 +1025,12 @@ static int write_superframe_index(vpx_codec_alg_priv_t *ctx) {
|
|
|
|
// Write the index
|
|
index_sz = 2 + (mag + 1) * ctx->pending_frame_count;
|
|
- if (ctx->pending_cx_data_sz + index_sz < ctx->cx_data_sz) {
|
|
- uint8_t *x = ctx->pending_cx_data + ctx->pending_cx_data_sz;
|
|
+ unsigned char *cx_data_end = ctx->cx_data + ctx->cx_data_sz;
|
|
+ unsigned char *pending_cx_data_end =
|
|
+ ctx->pending_cx_data + ctx->pending_cx_data_sz;
|
|
+ ptrdiff_t space_remaining = cx_data_end - pending_cx_data_end;
|
|
+ if (index_sz <= space_remaining) {
|
|
+ uint8_t *x = pending_cx_data_end;
|
|
int i, j;
|
|
#ifdef TEST_SUPPLEMENTAL_SUPERFRAME_DATA
|
|
uint8_t marker_test = 0xc0;
|
|
@@ -1052,6 +1061,8 @@ static int write_superframe_index(vpx_codec_alg_priv_t *ctx) {
|
|
#ifdef TEST_SUPPLEMENTAL_SUPERFRAME_DATA
|
|
index_sz += index_sz_test;
|
|
#endif
|
|
+ } else {
|
|
+ index_sz = 0;
|
|
}
|
|
return index_sz;
|
|
}
|
|
@@ -1315,9 +1326,12 @@ static vpx_codec_err_t encoder_encode(vpx_codec_alg_priv_t *ctx,
|
|
ctx->pending_frame_sizes[ctx->pending_frame_count++] = size;
|
|
ctx->pending_frame_magnitude |= size;
|
|
ctx->pending_cx_data_sz += size;
|
|
- // write the superframe only for the case when
|
|
- if (!ctx->output_cx_pkt_cb.output_cx_pkt)
|
|
+ // write the superframe only for the case when the callback function
|
|
+ // for getting per-layer packets is not registered.
|
|
+ if (!ctx->output_cx_pkt_cb.output_cx_pkt) {
|
|
size += write_superframe_index(ctx);
|
|
+ assert(size <= cx_data_sz);
|
|
+ }
|
|
pkt.data.frame.buf = ctx->pending_cx_data;
|
|
pkt.data.frame.sz = ctx->pending_cx_data_sz;
|
|
ctx->pending_cx_data = NULL;
|
|
--
|
|
2.53.0
|
|
|