tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

commit e0de88fc96a55e4bb53c80b7970205d738aeef7a
parent dba4fc7e5995f501da0ff329806fc9a8031ee4f9
Author: Updatebot <updatebot@mozilla.com>
Date:   Mon, 15 Dec 2025 20:47:07 +0000

Bug 2004760 - Update libvpx to 98a119c2c67d41f6354281f2cb719c8229c30601 r=chunmin

Differential Revision: https://phabricator.services.mozilla.com/D275496

Diffstat:
Amedia/libvpx/libvpx/examples/vpx_enc_fuzzer.cc | 235+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mmedia/libvpx/libvpx/vp8/vp8_cx_iface.c | 17++++-------------
Mmedia/libvpx/libvpx/vp9/vp9_cx_iface.c | 19+++++--------------
Mmedia/libvpx/libvpx/vpx_dsp/arm/highbd_vpx_convolve8_sve2.c | 100++++++++++++-------------------------------------------------------------------
Mmedia/libvpx/libvpx/vpx_ports/aarch64_cpudetect.c | 4++--
Mmedia/libvpx/moz.yaml | 4++--
6 files changed, 263 insertions(+), 116 deletions(-)

diff --git a/media/libvpx/libvpx/examples/vpx_enc_fuzzer.cc b/media/libvpx/libvpx/examples/vpx_enc_fuzzer.cc @@ -0,0 +1,235 @@ +/* + * Copyright (c) 2025 The WebM project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +/* + * Fuzzer for libvpx encoders + * ========================== + * Requirements + * -------------- + * Requires Clang 6.0 or above as -fsanitize=fuzzer is used as a linker + * option. + + * Steps to build + * -------------- + * Clone libvpx repository + $git clone https://chromium.googlesource.com/webm/libvpx + + * Create a directory in parallel to libvpx and change directory + $mkdir vpx_enc_fuzzer + $cd vpx_enc_fuzzer/ + + * Enable sanitizers (Supported: address integer memory thread undefined) + $source ../libvpx/tools/set_analyzer_env.sh address + + * Configure libvpx. + * Note --size-limit and VPX_MAX_ALLOCABLE_MEMORY are defined to avoid + * Out of memory errors when running generated fuzzer binary + $../libvpx/configure --disable-unit-tests --size-limit=12288x12288 \ + --extra-cflags="-fsanitize=fuzzer-no-link \ + -DVPX_MAX_ALLOCABLE_MEMORY=1073741824" \ + --disable-webm-io --enable-debug --enable-vp8-encoder \ + --enable-vp9-encoder --disable-examples + + * Build libvpx + $make -j32 + + * Build vp9 fuzzer + $ $CXX $CXXFLAGS -std=gnu++17 -DENCODER=vp9 \ + -fsanitize=fuzzer -I../libvpx -I. -Wl,--start-group \ + ../libvpx/examples/vpx_enc_fuzzer.cc -o ./vpx_enc_fuzzer_vp9 \ + ./libvpx.a -Wl,--end-group + + * ENCODER should be defined as vp9 or vp8 to enable vp9/vp8 + * + * create a corpus directory and copy some ivf files there. + * Based on which codec (vp8/vp9) is being tested, it is recommended to + * have corresponding ivf files in corpus directory + * Empty corpus directory also is acceptable, though not recommended + $mkdir CORPUS && cp some-files CORPUS + + * Run fuzzing: + $./vpx_enc_fuzzer_vp9 CORPUS + + * References: + * http://llvm.org/docs/LibFuzzer.html + * https://github.com/google/oss-fuzz + */ + +#include <assert.h> +#include <stddef.h> +#include <stdint.h> +#include <stdio.h> +#include <stdlib.h> + +#include "vpx/vp8cx.h" +#include "vpx/vpx_encoder.h" +#include "vpx_ports/mem_ops.h" +#include "third_party/nalloc/nalloc.h" + +// fuzz header to have config options, before raw image data +#define FUZZ_HDR_SZ 32 + +#define VPXC_INTERFACE(name) VPXC_INTERFACE_(name) +#define VPXC_INTERFACE_(name) vpx_codec_##name##_cx() + +extern "C" void usage_exit(void) { exit(EXIT_FAILURE); } + +static int vpx_img_plane_width(const vpx_image_t *img, int plane) { + if (plane > 0 && img->x_chroma_shift > 0) + return (img->d_w + 1) >> img->x_chroma_shift; + else + return img->d_w; +} + +static int vpx_img_plane_height(const vpx_image_t *img, int plane) { + if (plane > 0 && img->y_chroma_shift > 0) + return (img->d_h + 1) >> img->y_chroma_shift; + else + return img->d_h; +} + +static int fuzz_vpx_img_read(vpx_image_t *img, const uint8_t *data, + size_t size) { + int plane; + // TODO: wtc - Need to clamp the sample values so that they are in range + // For example, if the bit depth is 10, the sample values must be <= 1023. + assert(img->bit_depth == 8); + const size_t bytespp = (img->fmt & VPX_IMG_FMT_HIGHBITDEPTH) ? 2 : 1; + + if (size == 0) return 0; + size_t used = 0; + for (plane = 0; plane < 3; ++plane) { + unsigned char *buf = img->planes[plane]; + const int stride = img->stride[plane]; + int w = vpx_img_plane_width(img, plane); + const int h = vpx_img_plane_height(img, plane); + int y; + + // Assuming that for nv12 we read all chroma data at once + if (img->fmt == VPX_IMG_FMT_NV12 && plane > 1) break; + // Fixing NV12 chroma width if it is odd + if (img->fmt == VPX_IMG_FMT_NV12 && plane == 1) w = (w + 1) & ~1; + + for (y = 0; y < h; ++y) { + size_t nb = bytespp * w; + if (nb > size - used) { + nb = size - used; + } + memcpy(buf, data, nb); + memset(buf + nb, 0, bytespp * w - nb); + buf += stride; + data += nb; + used += nb; + } + } + + return used; +} + +static int encode_frame(vpx_codec_ctx_t *codec, vpx_image_t *img, + int frame_index, int flags, FILE *out, + vpx_enc_deadline_t quality) { + int got_pkts = 0; + vpx_codec_iter_t iter = NULL; + const vpx_codec_cx_pkt_t *pkt = NULL; + const vpx_codec_err_t res = + vpx_codec_encode(codec, img, frame_index, 1, flags, quality); + if (res != VPX_CODEC_OK) return 0; + + while ((pkt = vpx_codec_get_cx_data(codec, &iter)) != NULL) { + got_pkts = 1; + + if (pkt->kind == VPX_CODEC_CX_FRAME_PKT) { + if (fwrite(pkt->data.frame.buf, 1, pkt->data.frame.sz, out) != + pkt->data.frame.sz) + return 0; + } + } + + return got_pkts; +} + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { + if (size <= FUZZ_HDR_SZ) { + return 0; + } + nalloc_init(nullptr); + + int keyframe_interval = 0; + int frame_count = 0; + vpx_codec_ctx_t codec; + vpx_image_t raw; + vpx_codec_enc_cfg_t cfg; + vpx_enc_deadline_t quality = VPX_DL_GOOD_QUALITY; + + if ((data[0] & 0x80) != 0) { + keyframe_interval = 8; + } + if ((data[0] & 0x40) != 0) { + quality = VPX_DL_REALTIME; + } else if ((data[0] & 0x20) != 0) { + quality = VPX_DL_BEST_QUALITY; + } + + if (vpx_codec_enc_config_default(VPXC_INTERFACE(ENCODER), &cfg, 0)) abort(); + FILE *out = fopen("/dev/null", "wb"); + + switch (data[0] & 0x1F) { + case 0: cfg.g_w = 64; cfg.g_h = 1; + case 1: cfg.g_w = 1; cfg.g_h = 48; + case 2: cfg.g_w = 1; cfg.g_h = 1; + case 3: cfg.g_w = 4; cfg.g_h = 4; + case 4: cfg.g_w = 16; cfg.g_h = 16; + default: cfg.g_w = 64; cfg.g_h = 48; + } + cfg.g_timebase.num = 1; + cfg.g_timebase.den = 30; // fps + cfg.rc_target_bitrate = 200; + cfg.g_error_resilient = 1; + + if (vpx_codec_enc_init(&codec, VPXC_INTERFACE(ENCODER), &cfg, 0)) { + return 0; + } + + if (!vpx_img_alloc(&raw, VPX_IMG_FMT_I420, cfg.g_w, cfg.g_h, 1)) { + goto fail; + } + + nalloc_start(data, size); + // We may want to add more config options (for more complex encoders as seen + // in the examples) in the future while still maintaining the same format (so + // that generated corpus is still valid). So we reserve FUZZ_HDR_SZ=32 bytes + // for this even if we just use one byte so far. + data += FUZZ_HDR_SZ; + size -= FUZZ_HDR_SZ; + + // Encode frames. + while (1) { + int flags = 0; + size_t size_read = fuzz_vpx_img_read(&raw, data, size); + if (size_read == 0) break; + data += size_read; + size -= size_read; + if (keyframe_interval > 0 && frame_count % keyframe_interval == 0) + flags |= VPX_EFLAG_FORCE_KF; + encode_frame(&codec, &raw, frame_count++, flags, out, quality); + } + + // Flush encoder. + while (encode_frame(&codec, NULL, -1, 0, out, quality)) { + } + +fail: + nalloc_end(); + vpx_img_free(&raw); + vpx_codec_destroy(&codec); + fclose(out); + return 0; +} diff --git a/media/libvpx/libvpx/vp8/vp8_cx_iface.c b/media/libvpx/libvpx/vp8/vp8_cx_iface.c @@ -1022,19 +1022,10 @@ static vpx_codec_err_t vp8e_encode(vpx_codec_alg_priv_t *ctx, res = image2yuvconfig(img, &sd); - if (sd.y_width != ctx->cfg.g_w || sd.y_height != ctx->cfg.g_h) { - /* from vpx_encoder.h for g_w/g_h: - "Note that the frames passed as input to the encoder must have this - resolution" - */ - ctx->base.err_detail = "Invalid input frame resolution"; - res = VPX_CODEC_INVALID_PARAM; - } else { - if (vp8_receive_raw_frame(ctx->cpi, ctx->next_frame_flag | lib_flags, - &sd, dst_time_stamp, dst_end_time_stamp)) { - VP8_COMP *cpi = (VP8_COMP *)ctx->cpi; - res = update_error_state(ctx, &cpi->common.error); - } + if (vp8_receive_raw_frame(ctx->cpi, ctx->next_frame_flag | lib_flags, &sd, + dst_time_stamp, dst_end_time_stamp)) { + VP8_COMP *cpi = (VP8_COMP *)ctx->cpi; + res = update_error_state(ctx, &cpi->common.error); } /* reset for next frame */ diff --git a/media/libvpx/libvpx/vp9/vp9_cx_iface.c b/media/libvpx/libvpx/vp9/vp9_cx_iface.c @@ -1478,22 +1478,13 @@ static vpx_codec_err_t encoder_encode(vpx_codec_alg_priv_t *ctx, timebase_units_to_ticks(timebase_in_ts, pts_end); res = image2yuvconfig(img, &sd); - if (sd.y_width != ctx->cfg.g_w || sd.y_height != ctx->cfg.g_h) { - /* from vpx_encoder.h for g_w/g_h: - "Note that the frames passed as input to the encoder must have this - resolution" - */ - ctx->base.err_detail = "Invalid input frame resolution"; - res = VPX_CODEC_INVALID_PARAM; - } else { - // Store the original flags in to the frame buffer. Will extract the - // key frame flag when we actually encode this frame. - if (vp9_receive_raw_frame(cpi, flags | ctx->next_frame_flags, &sd, + // Store the original flags in to the frame buffer. Will extract the + // key frame flag when we actually encode this frame. + if (vp9_receive_raw_frame(cpi, flags | ctx->next_frame_flags, &sd, dst_time_stamp, dst_end_time_stamp)) { - res = update_error_state(ctx, &cpi->common.error); - } - ctx->next_frame_flags = 0; + res = update_error_state(ctx, &cpi->common.error); } + ctx->next_frame_flags = 0; } cx_data = ctx->cx_data; diff --git a/media/libvpx/libvpx/vpx_dsp/arm/highbd_vpx_convolve8_sve2.c b/media/libvpx/libvpx/vpx_dsp/arm/highbd_vpx_convolve8_sve2.c @@ -80,23 +80,12 @@ static INLINE void highbd_convolve8_8tap_vert_sve2( const uint16_t *src, ptrdiff_t src_stride, uint16_t *dst, ptrdiff_t dst_stride, int w, int h, const int16x8_t filter, int bd) { assert(w >= 4 && h >= 4); - uint16x8x3_t merge_tbl_idx = vld1q_u16_x3(kDotProdMergeBlockTbl); - // Correct indices by the size of vector length. - merge_tbl_idx.val[0] = vaddq_u16( - merge_tbl_idx.val[0], - vreinterpretq_u16_u64(vdupq_n_u64(svcnth() * 0x0001000000000000ULL))); - merge_tbl_idx.val[1] = vaddq_u16( - merge_tbl_idx.val[1], - vreinterpretq_u16_u64(vdupq_n_u64(svcnth() * 0x0001000100000000ULL))); - merge_tbl_idx.val[2] = vaddq_u16( - merge_tbl_idx.val[2], - vreinterpretq_u16_u64(vdupq_n_u64(svcnth() * 0x0001000100010000ULL))); - - if (w == 4) { + do { const uint16x4_t max = vdup_n_u16((1 << bd) - 1); const int16_t *s = (const int16_t *)src; uint16_t *d = dst; + int height = h; int16x4_t s0, s1, s2, s3, s4, s5, s6; load_s16_4x7(s, src_stride, &s0, &s1, &s2, &s3, &s4, &s5, &s6); @@ -114,12 +103,11 @@ static INLINE void highbd_convolve8_8tap_vert_sve2( load_s16_4x4(s, src_stride, &s7, &s8, &s9, &sA); int16x8_t s4567[2], s5678[2], s6789[2], s789A[2]; + transpose_concat_s16_4x4(s4, s5, s6, s7, &s4567[0], &s4567[1]); + transpose_concat_s16_4x4(s5, s6, s7, s8, &s5678[0], &s5678[1]); + transpose_concat_s16_4x4(s6, s7, s8, s9, &s6789[0], &s6789[1]); transpose_concat_s16_4x4(s7, s8, s9, sA, &s789A[0], &s789A[1]); - vpx_tbl2x2_s16(s3456, s789A, s4567, merge_tbl_idx.val[0]); - vpx_tbl2x2_s16(s3456, s789A, s5678, merge_tbl_idx.val[1]); - vpx_tbl2x2_s16(s3456, s789A, s6789, merge_tbl_idx.val[2]); - uint16x4_t d0 = highbd_convolve8_4_v(s0123, s4567, filter, max); uint16x4_t d1 = highbd_convolve8_4_v(s1234, s5678, filter, max); uint16x4_t d2 = highbd_convolve8_4_v(s2345, s6789, filter, max); @@ -136,77 +124,19 @@ static INLINE void highbd_convolve8_8tap_vert_sve2( s3456[0] = s789A[0]; s3456[1] = s789A[1]; + s4 = s8; + s5 = s9; + s6 = sA; + s += 4 * src_stride; d += 4 * dst_stride; - h -= 4; - } while (h != 0); - } else { - const uint16x8_t max = vdupq_n_u16((1 << bd) - 1); - - do { - const int16_t *s = (const int16_t *)src; - uint16_t *d = dst; - int height = h; - - int16x8_t s0, s1, s2, s3, s4, s5, s6; - load_s16_8x7(s, src_stride, &s0, &s1, &s2, &s3, &s4, &s5, &s6); - s += 7 * src_stride; - - int16x8_t s0123[4], s1234[4], s2345[4], s3456[4]; - transpose_concat_s16_8x4(s0, s1, s2, s3, &s0123[0], &s0123[1], &s0123[2], - &s0123[3]); - transpose_concat_s16_8x4(s1, s2, s3, s4, &s1234[0], &s1234[1], &s1234[2], - &s1234[3]); - transpose_concat_s16_8x4(s2, s3, s4, s5, &s2345[0], &s2345[1], &s2345[2], - &s2345[3]); - transpose_concat_s16_8x4(s3, s4, s5, s6, &s3456[0], &s3456[1], &s3456[2], - &s3456[3]); + height -= 4; + } while (height != 0); - do { - int16x8_t s7, s8, s9, sA; - load_s16_8x4(s, src_stride, &s7, &s8, &s9, &sA); - - int16x8_t s4567[4], s5678[5], s6789[4], s789A[4]; - transpose_concat_s16_8x4(s7, s8, s9, sA, &s789A[0], &s789A[1], - &s789A[2], &s789A[3]); - - vpx_tbl2x4_s16(s3456, s789A, s4567, merge_tbl_idx.val[0]); - vpx_tbl2x4_s16(s3456, s789A, s5678, merge_tbl_idx.val[1]); - vpx_tbl2x4_s16(s3456, s789A, s6789, merge_tbl_idx.val[2]); - - uint16x8_t d0 = highbd_convolve8_8_v(s0123, s4567, filter, max); - uint16x8_t d1 = highbd_convolve8_8_v(s1234, s5678, filter, max); - uint16x8_t d2 = highbd_convolve8_8_v(s2345, s6789, filter, max); - uint16x8_t d3 = highbd_convolve8_8_v(s3456, s789A, filter, max); - - store_u16_8x4(d, dst_stride, d0, d1, d2, d3); - - s0123[0] = s4567[0]; - s0123[1] = s4567[1]; - s0123[2] = s4567[2]; - s0123[3] = s4567[3]; - s1234[0] = s5678[0]; - s1234[1] = s5678[1]; - s1234[2] = s5678[2]; - s1234[3] = s5678[3]; - s2345[0] = s6789[0]; - s2345[1] = s6789[1]; - s2345[2] = s6789[2]; - s2345[3] = s6789[3]; - s3456[0] = s789A[0]; - s3456[1] = s789A[1]; - s3456[2] = s789A[2]; - s3456[3] = s789A[3]; - - s += 4 * src_stride; - d += 4 * dst_stride; - height -= 4; - } while (height != 0); - src += 8; - dst += 8; - w -= 8; - } while (w != 0); - } + src += 4; + dst += 4; + w -= 4; + } while (w != 0); } void vpx_highbd_convolve8_vert_sve2(const uint16_t *src, ptrdiff_t src_stride, diff --git a/media/libvpx/libvpx/vpx_ports/aarch64_cpudetect.c b/media/libvpx/libvpx/vpx_ports/aarch64_cpudetect.c @@ -16,7 +16,7 @@ #include <sys/sysctl.h> #endif -#if !CONFIG_RUNTIME_CPU_DETECT || defined(__OpenBSD__) +#if !CONFIG_RUNTIME_CPU_DETECT static int arm_get_cpu_caps(void) { // This function should actually be a no-op. There is no way to adjust any of @@ -29,7 +29,7 @@ static int arm_get_cpu_caps(void) { return flags; } -#elif defined(__APPLE__) // end !CONFIG_RUNTIME_CPU_DETECT || defined(__OpenBSD__) +#elif defined(__APPLE__) // end !CONFIG_RUNTIME_CPU_DETECT // sysctlbyname() parameter documentation for instruction set characteristics: // https://developer.apple.com/documentation/kernel/1387446-sysctlbyname/determining_instruction_set_characteristics diff --git a/media/libvpx/moz.yaml b/media/libvpx/moz.yaml @@ -20,11 +20,11 @@ origin: # Human-readable identifier for this version/release # Generally "version NNN", "tag SSS", "bookmark SSS" - release: 9a7674e1a83d1261a49776c8794b87c9bccc85d7 (Tue Nov 04 19:55:43 2025). + release: 98a119c2c67d41f6354281f2cb719c8229c30601 (Wed Dec 03 16:08:53 2025). # Revision to pull in # Must be a long or short commit SHA (long preferred) - revision: 9a7674e1a83d1261a49776c8794b87c9bccc85d7 + revision: 98a119c2c67d41f6354281f2cb719c8229c30601 # The package's license, where possible using the mnemonic from # https://spdx.org/licenses/