/src/libheif/fuzzing/sequence_fuzzer.cc
Line | Count | Source |
1 | | /* |
2 | | * HEIF codec. |
3 | | * Copyright (c) 2026 struktur AG, Arthur SC Chan <arthur.chan@adalogics.com> |
4 | | * |
5 | | * This file is part of libheif. |
6 | | * |
7 | | * libheif is free software: you can redistribute it and/or modify |
8 | | * it under the terms of the GNU Lesser General Public License as |
9 | | * published by the Free Software Foundation, either version 3 of |
10 | | * the License, or (at your option) any later version. |
11 | | * |
12 | | * libheif is distributed in the hope that it will be useful, |
13 | | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
14 | | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
15 | | * GNU Lesser General Public License for more details. |
16 | | * |
17 | | * You should have received a copy of the GNU Lesser General Public License |
18 | | * along with libheif. If not, see <http://www.gnu.org/licenses/>. |
19 | | */ |
20 | | |
21 | | #include <stdint.h> |
22 | | #include <stdlib.h> |
23 | | |
24 | | #include "libheif/heif.h" |
25 | | #include "libheif/heif_sequences.h" |
26 | | |
27 | 1.44k | #define MAX_FRAMES 32 |
28 | | |
29 | | extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) |
30 | 10.9k | { |
31 | 10.9k | heif_context* ctx = heif_context_alloc(); |
32 | 10.9k | if (!ctx) { |
33 | 0 | return 0; |
34 | 0 | } |
35 | | |
36 | 10.9k | auto* limits = heif_context_get_security_limits(ctx); |
37 | 10.9k | limits->max_total_memory = UINT64_C(2) * 1024 * 1024 * 1024; |
38 | 10.9k | limits->max_memory_block_size = 128 * 1024 * 1024; |
39 | | // Also bound the image size itself. libheif's memory accounting only covers its own |
40 | | // allocations, but the codec libraries allocate their frame buffers before libheif |
41 | | // sees anything (dav1d needs ~12.5 bytes/pixel for a frame header alone). Under MSan, |
42 | | // where every allocation costs about three times its size in RSS, a 56 Mpixel AV1 frame |
43 | | // header was enough to exceed libFuzzer's 2560 MB limit. |
44 | 10.9k | limits->max_image_size_pixels = 16 * 1024 * 1024; // 16 Mpixel |
45 | | |
46 | 10.9k | heif_error err = heif_context_read_from_memory(ctx, data, size, nullptr); |
47 | 10.9k | if (err.code != heif_error_Ok) { |
48 | 9.57k | heif_context_free(ctx); |
49 | 9.57k | return 0; |
50 | 9.57k | } |
51 | | |
52 | 1.33k | if (heif_context_has_sequence(ctx)) { |
53 | 1.01k | heif_track* track = heif_context_get_track(ctx, 0); |
54 | 1.01k | if (track) { |
55 | 1.01k | uint16_t w = 0, h = 0; |
56 | 1.01k | heif_track_get_image_resolution(track, &w, &h); |
57 | 1.01k | heif_track_get_timescale(track); |
58 | 1.01k | heif_track_get_track_handler_type(track); |
59 | | |
60 | 1.01k | int frames = 0; |
61 | 1.44k | while (frames++ < MAX_FRAMES) { |
62 | 1.44k | heif_image* img = nullptr; |
63 | 1.44k | err = heif_track_decode_next_image(track, &img, |
64 | 1.44k | heif_colorspace_YCbCr, |
65 | 1.44k | heif_chroma_420, nullptr); |
66 | 1.44k | if (err.code != heif_error_Ok || img == nullptr) { |
67 | 1.01k | break; |
68 | 1.01k | } |
69 | 427 | heif_image_release(img); |
70 | 427 | } |
71 | | |
72 | 1.01k | heif_track_release(track); |
73 | 1.01k | } |
74 | 1.01k | } |
75 | | |
76 | 1.33k | heif_context_free(ctx); |
77 | 1.33k | return 0; |
78 | 10.9k | } |