Prepare decoder and demuxer for -fbounds-safety adoption

Change memcpy|memset|memchr to unsafe variants

Add WEBP_ASSUME_UNSAFE_INDEXABLE_ABI to relevant files. I've also added
it to lossless.h, yuv.h, and decode.h as they're all imported by code in
dec, which will have -fbounds-safety annotations.

Bug: 432511225
Change-Id: I3011a0a56633b8437ead31607c7ac5f6311fa846
This commit is contained in:
mxms
2025-10-24 04:00:01 +00:00
committed by Max Shavrick
parent 9f14c2605b
commit ed05414168
20 changed files with 82 additions and 36 deletions

View File

@@ -26,6 +26,8 @@
#include "src/webp/format_constants.h"
#include "src/webp/types.h"
WEBP_ASSUME_UNSAFE_INDEXABLE_ABI
//------------------------------------------------------------------------------
// ALPHDecoder object.

View File

@@ -20,6 +20,8 @@
#include "src/utils/filters_utils.h"
#include "src/webp/types.h"
WEBP_ASSUME_UNSAFE_INDEXABLE_ABI
#ifdef __cplusplus
extern "C" {
#endif

View File

@@ -22,6 +22,8 @@
#include "src/webp/decode.h"
#include "src/webp/types.h"
WEBP_ASSUME_UNSAFE_INDEXABLE_ABI
//------------------------------------------------------------------------------
// WebPDecBuffer

View File

@@ -26,6 +26,8 @@
#include "src/webp/decode.h"
#include "src/webp/types.h"
WEBP_ASSUME_UNSAFE_INDEXABLE_ABI
//------------------------------------------------------------------------------
// Main reconstruction function.
@@ -47,7 +49,7 @@ static int CheckMode(int mb_x, int mb_y, int mode) {
}
static void Copy32b(uint8_t* const dst, const uint8_t* const src) {
memcpy(dst, src, 4);
WEBP_UNSAFE_MEMCPY(dst, src, 4);
}
static WEBP_INLINE void DoTransform(uint32_t bits, const int16_t* const src,
@@ -131,9 +133,9 @@ static void ReconstructRow(const VP8Decoder* const dec,
int n;
if (mb_y > 0) {
memcpy(y_dst - BPS, top_yuv[0].y, 16);
memcpy(u_dst - BPS, top_yuv[0].u, 8);
memcpy(v_dst - BPS, top_yuv[0].v, 8);
WEBP_UNSAFE_MEMCPY(y_dst - BPS, top_yuv[0].y, 16);
WEBP_UNSAFE_MEMCPY(u_dst - BPS, top_yuv[0].u, 8);
WEBP_UNSAFE_MEMCPY(v_dst - BPS, top_yuv[0].v, 8);
}
// predict and add residuals
@@ -144,7 +146,7 @@ static void ReconstructRow(const VP8Decoder* const dec,
if (mb_x >= dec->mb_w - 1) { // on rightmost border
memset(top_right, top_yuv[0].y[15], sizeof(*top_right));
} else {
memcpy(top_right, top_yuv[1].y, sizeof(*top_right));
WEBP_UNSAFE_MEMCPY(top_right, top_yuv[1].y, sizeof(*top_right));
}
}
// replicate the top-right pixels below
@@ -177,9 +179,9 @@ static void ReconstructRow(const VP8Decoder* const dec,
// stash away top samples for next block
if (mb_y < dec->mb_h - 1) {
memcpy(top_yuv[0].y, y_dst + 15 * BPS, 16);
memcpy(top_yuv[0].u, u_dst + 7 * BPS, 8);
memcpy(top_yuv[0].v, v_dst + 7 * BPS, 8);
WEBP_UNSAFE_MEMCPY(top_yuv[0].y, y_dst + 15 * BPS, 16);
WEBP_UNSAFE_MEMCPY(top_yuv[0].u, u_dst + 7 * BPS, 8);
WEBP_UNSAFE_MEMCPY(top_yuv[0].v, v_dst + 7 * BPS, 8);
}
}
// Transfer reconstructed samples from yuv_b cache to final destination.
@@ -190,11 +192,14 @@ static void ReconstructRow(const VP8Decoder* const dec,
uint8_t* const u_out = dec->cache_u + mb_x * 8 + uv_offset;
uint8_t* const v_out = dec->cache_v + mb_x * 8 + uv_offset;
for (j = 0; j < 16; ++j) {
memcpy(y_out + j * dec->cache_y_stride, y_dst + j * BPS, 16);
WEBP_UNSAFE_MEMCPY(y_out + j * dec->cache_y_stride, y_dst + j * BPS,
16);
}
for (j = 0; j < 8; ++j) {
memcpy(u_out + j * dec->cache_uv_stride, u_dst + j * BPS, 8);
memcpy(v_out + j * dec->cache_uv_stride, v_dst + j * BPS, 8);
WEBP_UNSAFE_MEMCPY(u_out + j * dec->cache_uv_stride, u_dst + j * BPS,
8);
WEBP_UNSAFE_MEMCPY(v_out + j * dec->cache_uv_stride, v_dst + j * BPS,
8);
}
}
}
@@ -494,9 +499,12 @@ static int FinishRow(void* arg1, void* arg2) {
// rotate top samples if needed
if (cache_id + 1 == dec->num_caches) {
if (!is_last_row) {
memcpy(dec->cache_y - ysize, ydst + 16 * dec->cache_y_stride, ysize);
memcpy(dec->cache_u - uvsize, udst + 8 * dec->cache_uv_stride, uvsize);
memcpy(dec->cache_v - uvsize, vdst + 8 * dec->cache_uv_stride, uvsize);
WEBP_UNSAFE_MEMCPY(dec->cache_y - ysize, ydst + 16 * dec->cache_y_stride,
ysize);
WEBP_UNSAFE_MEMCPY(dec->cache_u - uvsize, udst + 8 * dec->cache_uv_stride,
uvsize);
WEBP_UNSAFE_MEMCPY(dec->cache_v - uvsize, vdst + 8 * dec->cache_uv_stride,
uvsize);
}
}

View File

@@ -27,6 +27,8 @@
#include "src/webp/format_constants.h"
#include "src/webp/types.h"
WEBP_ASSUME_UNSAFE_INDEXABLE_ABI
// In append mode, buffer allocations increase as multiples of this value.
// Needs to be a power of 2.
#define CHUNK_SIZE 4096
@@ -196,7 +198,7 @@ WEBP_NODISCARD static int AppendToMemBuffer(WebPIDecoder* const idec,
uint8_t* const new_buf =
(uint8_t*)WebPSafeMalloc(extra_size, sizeof(*new_buf));
if (new_buf == NULL) return 0;
if (old_base != NULL) memcpy(new_buf, old_base, current_size);
if (old_base != NULL) WEBP_UNSAFE_MEMCPY(new_buf, old_base, current_size);
WebPSafeFree(mem->buf);
mem->buf = new_buf;
mem->buf_size = (size_t)extra_size;
@@ -205,7 +207,7 @@ WEBP_NODISCARD static int AppendToMemBuffer(WebPIDecoder* const idec,
}
assert(mem->buf != NULL);
memcpy(mem->buf + mem->end, data, data_size);
WEBP_UNSAFE_MEMCPY(mem->buf + mem->end, data, data_size);
mem->end += data_size;
assert(mem->end <= mem->buf_size);
@@ -401,7 +403,7 @@ static VP8StatusCode CopyParts0Data(WebPIDecoder* const idec) {
if (part0_buf == NULL) {
return VP8_STATUS_OUT_OF_MEMORY;
}
memcpy(part0_buf, br->buf, part_size);
WEBP_UNSAFE_MEMCPY(part0_buf, br->buf, part_size);
mem->part0_buf = part0_buf;
VP8BitReaderSetBuffer(br, part0_buf, part_size);
} else {

View File

@@ -27,6 +27,8 @@
#include "src/webp/decode.h"
#include "src/webp/types.h"
WEBP_ASSUME_UNSAFE_INDEXABLE_ABI
//------------------------------------------------------------------------------
// Main YUV<->RGB conversion functions
@@ -100,9 +102,9 @@ static int EmitFancyRGB(const VP8Io* const io, WebPDecParams* const p) {
cur_y += io->y_stride;
if (io->crop_top + y_end < io->crop_bottom) {
// Save the unfinished samples for next call (as we're not done yet).
memcpy(p->tmp_y, cur_y, mb_w * sizeof(*p->tmp_y));
memcpy(p->tmp_u, cur_u, uv_w * sizeof(*p->tmp_u));
memcpy(p->tmp_v, cur_v, uv_w * sizeof(*p->tmp_v));
WEBP_UNSAFE_MEMCPY(p->tmp_y, cur_y, mb_w * sizeof(*p->tmp_y));
WEBP_UNSAFE_MEMCPY(p->tmp_u, cur_u, uv_w * sizeof(*p->tmp_u));
WEBP_UNSAFE_MEMCPY(p->tmp_v, cur_v, uv_w * sizeof(*p->tmp_v));
// The fancy upsampler leaves a row unfinished behind
// (except for the very last row)
num_lines_out--;
@@ -140,7 +142,7 @@ static int EmitAlphaYUV(const VP8Io* const io, WebPDecParams* const p,
assert(expected_num_lines_out == mb_h);
if (alpha != NULL) {
for (j = 0; j < mb_h; ++j) {
memcpy(dst, alpha, mb_w * sizeof(*dst));
WEBP_UNSAFE_MEMCPY(dst, alpha, mb_w * sizeof(*dst));
alpha += io->width;
dst += buf->a_stride;
}

View File

@@ -17,6 +17,8 @@
#include "src/utils/bit_reader_utils.h"
#include "src/webp/types.h"
WEBP_ASSUME_UNSAFE_INDEXABLE_ABI
static WEBP_INLINE int clip(int v, int M) { return v < 0 ? 0 : v > M ? M : v; }
// Paragraph 14.1

View File

@@ -21,6 +21,8 @@
#include "src/utils/bit_reader_utils.h"
#include "src/webp/types.h"
WEBP_ASSUME_UNSAFE_INDEXABLE_ABI
#if !defined(USE_GENERIC_TREE)
#if !defined(__arm__) && !defined(_M_ARM) && !WEBP_AARCH64 && !defined(__wasm__)
// using a table is ~1-2% slower on ARM. Prefer the coded-tree approach then.
@@ -316,7 +318,7 @@ static void ParseIntraMode(VP8BitReader* const br, VP8Decoder* const dec,
#endif // USE_GENERIC_TREE
top[x] = ymode;
}
memcpy(modes, top, 4 * sizeof(*top));
WEBP_UNSAFE_MEMCPY(modes, top, 4 * sizeof(*top));
modes += 4;
left[y] = ymode;
}

View File

@@ -32,6 +32,8 @@
#include "src/webp/format_constants.h"
#include "src/webp/types.h"
WEBP_ASSUME_UNSAFE_INDEXABLE_ABI
//------------------------------------------------------------------------------
int WebPGetDecoderVersion(void) {

View File

@@ -19,6 +19,8 @@
#include "src/webp/decode.h"
#include "src/webp/types.h"
WEBP_ASSUME_UNSAFE_INDEXABLE_ABI
#ifdef __cplusplus
extern "C" {
#endif

View File

@@ -27,6 +27,8 @@
#include "src/webp/decode.h"
#include "src/webp/types.h"
WEBP_ASSUME_UNSAFE_INDEXABLE_ABI
#ifdef __cplusplus
extern "C" {
#endif

View File

@@ -34,6 +34,8 @@
#include "src/webp/format_constants.h"
#include "src/webp/types.h"
WEBP_ASSUME_UNSAFE_INDEXABLE_ABI
#define NUM_ARGB_CACHE_ROWS 16
static const int kCodeLengthLiterals = 16;
@@ -843,7 +845,7 @@ static void ApplyInverseTransforms(VP8LDecoder* const dec, int start_row,
}
if (rows_in != rows_out) {
// No transform called, hence just copy.
memcpy(rows_out, rows_in, cache_pixs * sizeof(*rows_out));
WEBP_UNSAFE_MEMCPY(rows_out, rows_in, cache_pixs * sizeof(*rows_out));
}
}
@@ -1022,7 +1024,7 @@ static WEBP_INLINE void CopyBlock8b(uint8_t* const dst, int dist, int length) {
break;
case 2:
#if !defined(WORDS_BIGENDIAN)
memcpy(&pattern, src, sizeof(uint16_t));
WEBP_UNSAFE_MEMCPY(&pattern, src, sizeof(uint16_t));
#else
pattern = ((uint32_t)src[0] << 8) | src[1];
#endif
@@ -1035,7 +1037,7 @@ static WEBP_INLINE void CopyBlock8b(uint8_t* const dst, int dist, int length) {
#endif
break;
case 4:
memcpy(&pattern, src, sizeof(uint32_t));
WEBP_UNSAFE_MEMCPY(&pattern, src, sizeof(uint32_t));
break;
default:
goto Copy;
@@ -1044,8 +1046,8 @@ static WEBP_INLINE void CopyBlock8b(uint8_t* const dst, int dist, int length) {
return;
}
Copy:
if (dist >= length) { // no overlap -> use memcpy()
memcpy(dst, src, length * sizeof(*dst));
if (dist >= length) { // no overlap -> use WEBP_UNSAFE_MEMCPY()
WEBP_UNSAFE_MEMCPY(dst, src, length * sizeof(*dst));
} else {
int i;
for (i = 0; i < length; ++i) dst[i] = src[i];
@@ -1079,11 +1081,11 @@ static WEBP_INLINE void CopyBlock32b(uint32_t* const dst, int dist,
pattern = (uint64_t)src[0];
pattern |= pattern << 32;
} else {
memcpy(&pattern, src, sizeof(pattern));
WEBP_UNSAFE_MEMCPY(&pattern, src, sizeof(pattern));
}
CopySmallPattern32b(src, dst, length, pattern);
} else if (dist >= length) { // no overlap
memcpy(dst, src, length * sizeof(*dst));
WEBP_UNSAFE_MEMCPY(dst, src, length * sizeof(*dst));
} else {
int i;
for (i = 0; i < length; ++i) dst[i] = src[i];

View File

@@ -27,6 +27,8 @@
#include "src/webp/format_constants.h"
#include "src/webp/types.h"
WEBP_ASSUME_UNSAFE_INDEXABLE_ABI
#ifdef __cplusplus
extern "C" {
#endif

View File

@@ -27,6 +27,8 @@
#include "src/webp/mux_types.h" // ALPHA_FLAG
#include "src/webp/types.h"
WEBP_ASSUME_UNSAFE_INDEXABLE_ABI
//------------------------------------------------------------------------------
// RIFF layout is:
// Offset tag

View File

@@ -25,6 +25,8 @@ extern "C" {
#include "src/webp/decode.h"
#include "src/webp/types.h"
WEBP_ASSUME_UNSAFE_INDEXABLE_ABI
//------------------------------------------------------------------------------
// WebPDecParams: Decoding output parameters. Transient internal object.

View File

@@ -24,6 +24,8 @@
#include "src/webp/mux_types.h"
#include "src/webp/types.h"
WEBP_ASSUME_UNSAFE_INDEXABLE_ABI
#define NUM_CHANNELS 4
// Channel extraction from a uint32_t representation of a uint8_t RGBA/BGRA
@@ -168,7 +170,7 @@ WEBP_NODISCARD static int ZeroFillCanvas(uint8_t* buf, uint32_t canvas_width,
const uint64_t size =
(uint64_t)canvas_width * canvas_height * NUM_CHANNELS * sizeof(*buf);
if (!CheckSizeOverflow(size)) return 0;
memset(buf, 0, (size_t)size);
WEBP_UNSAFE_MEMSET(buf, 0, (size_t)size);
return 1;
}
@@ -179,7 +181,7 @@ static void ZeroFillFrameRect(uint8_t* buf, int buf_stride, int x_offset,
assert(width * NUM_CHANNELS <= buf_stride);
buf += y_offset * buf_stride + x_offset * NUM_CHANNELS;
for (j = 0; j < height; ++j) {
memset(buf, 0, width * NUM_CHANNELS);
WEBP_UNSAFE_MEMSET(buf, 0, width * NUM_CHANNELS);
buf += buf_stride;
}
}
@@ -190,7 +192,7 @@ WEBP_NODISCARD static int CopyCanvas(const uint8_t* src, uint8_t* dst,
const uint64_t size = (uint64_t)width * height * NUM_CHANNELS;
if (!CheckSizeOverflow(size)) return 0;
assert(src != NULL && dst != NULL);
memcpy(dst, src, (size_t)size);
WEBP_UNSAFE_MEMCPY(dst, src, (size_t)size);
return 1;
}
@@ -456,7 +458,7 @@ void WebPAnimDecoderReset(WebPAnimDecoder* dec) {
if (dec != NULL) {
dec->prev_frame_timestamp = 0;
WebPDemuxReleaseIterator(&dec->prev_iter);
memset(&dec->prev_iter, 0, sizeof(dec->prev_iter));
WEBP_UNSAFE_MEMSET(&dec->prev_iter, 0, sizeof(dec->prev_iter));
dec->prev_frame_was_keyframe = 0;
dec->next_frame = 1;
}

View File

@@ -26,6 +26,8 @@
#include "src/webp/mux_types.h"
#include "src/webp/types.h"
WEBP_ASSUME_UNSAFE_INDEXABLE_ABI
#define DMUX_MAJ_VERSION 1
#define DMUX_MIN_VERSION 6
#define DMUX_REV_VERSION 0
@@ -116,7 +118,7 @@ static int RemapMemBuffer(MemBuffer* const mem, const uint8_t* data,
static int InitMemBuffer(MemBuffer* const mem, const uint8_t* data,
size_t size) {
memset(mem, 0, sizeof(*mem));
WEBP_UNSAFE_MEMSET(mem, 0, sizeof(*mem));
return RemapMemBuffer(mem, data, size);
}
@@ -874,7 +876,7 @@ static int SetFrame(int frame_num, WebPIterator* const iter) {
int WebPDemuxGetFrame(const WebPDemuxer* dmux, int frame, WebPIterator* iter) {
if (iter == NULL) return 0;
memset(iter, 0, sizeof(*iter));
WEBP_UNSAFE_MEMSET(iter, 0, sizeof(*iter));
iter->private_ = (void*)dmux;
return SetFrame(frame, iter);
}
@@ -945,7 +947,7 @@ int WebPDemuxGetChunk(const WebPDemuxer* dmux, const char fourcc[4],
int chunk_num, WebPChunkIterator* iter) {
if (iter == NULL) return 0;
memset(iter, 0, sizeof(*iter));
WEBP_UNSAFE_MEMSET(iter, 0, sizeof(*iter));
iter->private_ = (void*)dmux;
return SetChunk(fourcc, chunk_num, iter);
}

View File

@@ -19,6 +19,8 @@
#include "src/webp/decode.h"
#include "src/webp/types.h"
WEBP_ASSUME_UNSAFE_INDEXABLE_ABI
#ifdef __cplusplus
extern "C" {
#endif

View File

@@ -40,6 +40,8 @@
#include "src/dsp/dsp.h"
#include "src/webp/types.h"
WEBP_ASSUME_UNSAFE_INDEXABLE_ABI
// Macros to give the offset of each channel in a uint32_t containing ARGB.
#ifdef WORDS_BIGENDIAN
// uint32_t 0xff000000 is 0xff,00,00,00 in memory

View File

@@ -18,6 +18,8 @@
#include "./types.h"
WEBP_ASSUME_UNSAFE_INDEXABLE_ABI
#ifdef __cplusplus
extern "C" {
#endif