Coverage Report

Created: 2026-06-07 06:59

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libvpx/third_party/nalloc/nalloc.h
Line
Count
Source
1
/*
2
 MIT License
3
4
 Copyright (c) 2025 Catena cyber
5
6
 Permission is hereby granted, free of charge, to any person obtaining a copy
7
 of this software and associated documentation files (the "Software"), to deal
8
 in the Software without restriction, including without limitation the rights
9
 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
 copies of the Software, and to permit persons to whom the Software is
11
 furnished to do so, subject to the following conditions:
12
13
 The above copyright notice and this permission notice shall be included in all
14
 copies or substantial portions of the Software.
15
16
 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22
 SOFTWARE.
23
*/
24
25
#ifndef NALLOC_H_
26
#define NALLOC_H_
27
28
#if defined(__clang__) && defined(__has_feature)
29
#if __has_feature(address_sanitizer)
30
#define NALLOC_ASAN 1
31
#endif
32
#if __has_feature(memory_sanitizer)
33
#define FUZZER_DISABLE_NALLOC 1
34
#endif
35
#endif
36
37
#if defined(FUZZER_DISABLE_NALLOC)
38
#define nalloc_init(x)
39
#define nalloc_restrict_file_prefix(x)
40
#define nalloc_start(x, y)
41
#define nalloc_end()
42
#else
43
44
#include <errno.h>
45
#include <stdbool.h>
46
#include <stdint.h>
47
#include <stdio.h>
48
#include <stdlib.h>
49
#include <string.h>
50
51
#ifdef __cplusplus
52
extern "C" {
53
#endif
54
55
static const uint32_t nalloc_crc32_table[] = {
56
  0x00000000, 0x04c11db7, 0x09823b6e, 0x0d4326d9, 0x130476dc, 0x17c56b6b,
57
  0x1a864db2, 0x1e475005, 0x2608edb8, 0x22c9f00f, 0x2f8ad6d6, 0x2b4bcb61,
58
  0x350c9b64, 0x31cd86d3, 0x3c8ea00a, 0x384fbdbd, 0x4c11db70, 0x48d0c6c7,
59
  0x4593e01e, 0x4152fda9, 0x5f15adac, 0x5bd4b01b, 0x569796c2, 0x52568b75,
60
  0x6a1936c8, 0x6ed82b7f, 0x639b0da6, 0x675a1011, 0x791d4014, 0x7ddc5da3,
61
  0x709f7b7a, 0x745e66cd, 0x9823b6e0, 0x9ce2ab57, 0x91a18d8e, 0x95609039,
62
  0x8b27c03c, 0x8fe6dd8b, 0x82a5fb52, 0x8664e6e5, 0xbe2b5b58, 0xbaea46ef,
63
  0xb7a96036, 0xb3687d81, 0xad2f2d84, 0xa9ee3033, 0xa4ad16ea, 0xa06c0b5d,
64
  0xd4326d90, 0xd0f37027, 0xddb056fe, 0xd9714b49, 0xc7361b4c, 0xc3f706fb,
65
  0xceb42022, 0xca753d95, 0xf23a8028, 0xf6fb9d9f, 0xfbb8bb46, 0xff79a6f1,
66
  0xe13ef6f4, 0xe5ffeb43, 0xe8bccd9a, 0xec7dd02d, 0x34867077, 0x30476dc0,
67
  0x3d044b19, 0x39c556ae, 0x278206ab, 0x23431b1c, 0x2e003dc5, 0x2ac12072,
68
  0x128e9dcf, 0x164f8078, 0x1b0ca6a1, 0x1fcdbb16, 0x018aeb13, 0x054bf6a4,
69
  0x0808d07d, 0x0cc9cdca, 0x7897ab07, 0x7c56b6b0, 0x71159069, 0x75d48dde,
70
  0x6b93dddb, 0x6f52c06c, 0x6211e6b5, 0x66d0fb02, 0x5e9f46bf, 0x5a5e5b08,
71
  0x571d7dd1, 0x53dc6066, 0x4d9b3063, 0x495a2dd4, 0x44190b0d, 0x40d816ba,
72
  0xaca5c697, 0xa864db20, 0xa527fdf9, 0xa1e6e04e, 0xbfa1b04b, 0xbb60adfc,
73
  0xb6238b25, 0xb2e29692, 0x8aad2b2f, 0x8e6c3698, 0x832f1041, 0x87ee0df6,
74
  0x99a95df3, 0x9d684044, 0x902b669d, 0x94ea7b2a, 0xe0b41de7, 0xe4750050,
75
  0xe9362689, 0xedf73b3e, 0xf3b06b3b, 0xf771768c, 0xfa325055, 0xfef34de2,
76
  0xc6bcf05f, 0xc27dede8, 0xcf3ecb31, 0xcbffd686, 0xd5b88683, 0xd1799b34,
77
  0xdc3abded, 0xd8fba05a, 0x690ce0ee, 0x6dcdfd59, 0x608edb80, 0x644fc637,
78
  0x7a089632, 0x7ec98b85, 0x738aad5c, 0x774bb0eb, 0x4f040d56, 0x4bc510e1,
79
  0x46863638, 0x42472b8f, 0x5c007b8a, 0x58c1663d, 0x558240e4, 0x51435d53,
80
  0x251d3b9e, 0x21dc2629, 0x2c9f00f0, 0x285e1d47, 0x36194d42, 0x32d850f5,
81
  0x3f9b762c, 0x3b5a6b9b, 0x0315d626, 0x07d4cb91, 0x0a97ed48, 0x0e56f0ff,
82
  0x1011a0fa, 0x14d0bd4d, 0x19939b94, 0x1d528623, 0xf12f560e, 0xf5ee4bb9,
83
  0xf8ad6d60, 0xfc6c70d7, 0xe22b20d2, 0xe6ea3d65, 0xeba91bbc, 0xef68060b,
84
  0xd727bbb6, 0xd3e6a601, 0xdea580d8, 0xda649d6f, 0xc423cd6a, 0xc0e2d0dd,
85
  0xcda1f604, 0xc960ebb3, 0xbd3e8d7e, 0xb9ff90c9, 0xb4bcb610, 0xb07daba7,
86
  0xae3afba2, 0xaafbe615, 0xa7b8c0cc, 0xa379dd7b, 0x9b3660c6, 0x9ff77d71,
87
  0x92b45ba8, 0x9675461f, 0x8832161a, 0x8cf30bad, 0x81b02d74, 0x857130c3,
88
  0x5d8a9099, 0x594b8d2e, 0x5408abf7, 0x50c9b640, 0x4e8ee645, 0x4a4ffbf2,
89
  0x470cdd2b, 0x43cdc09c, 0x7b827d21, 0x7f436096, 0x7200464f, 0x76c15bf8,
90
  0x68860bfd, 0x6c47164a, 0x61043093, 0x65c52d24, 0x119b4be9, 0x155a565e,
91
  0x18197087, 0x1cd86d30, 0x029f3d35, 0x065e2082, 0x0b1d065b, 0x0fdc1bec,
92
  0x3793a651, 0x3352bbe6, 0x3e119d3f, 0x3ad08088, 0x2497d08d, 0x2056cd3a,
93
  0x2d15ebe3, 0x29d4f654, 0xc5a92679, 0xc1683bce, 0xcc2b1d17, 0xc8ea00a0,
94
  0xd6ad50a5, 0xd26c4d12, 0xdf2f6bcb, 0xdbee767c, 0xe3a1cbc1, 0xe760d676,
95
  0xea23f0af, 0xeee2ed18, 0xf0a5bd1d, 0xf464a0aa, 0xf9278673, 0xfde69bc4,
96
  0x89b8fd09, 0x8d79e0be, 0x803ac667, 0x84fbdbd0, 0x9abc8bd5, 0x9e7d9662,
97
  0x933eb0bb, 0x97ffad0c, 0xafb010b1, 0xab710d06, 0xa6322bdf, 0xa2f33668,
98
  0xbcb4666d, 0xb8757bda, 0xb5365d03, 0xb1f740b4
99
};
100
101
// Nallocfuzz data to take a decision
102
uint32_t nalloc_random_state = 0;
103
__thread unsigned int nalloc_running = 0;
104
bool nalloc_initialized = false;
105
uint32_t nalloc_runs = 0;
106
107
// Nalloc fuzz parameters
108
uint32_t nalloc_bitmask = 0xFF;
109
bool nalloc_random_bitmask = true;
110
uint32_t nalloc_magic = 0x294cee63;
111
bool nalloc_verbose = false;
112
113
#ifdef NALLOC_ASAN
114
extern void __sanitizer_print_stack_trace(void);
115
#endif
116
117
// Generic init, using env variables to get parameters
118
71.7k
void nalloc_init(const char *prog) {
119
71.7k
  if (nalloc_initialized) {
120
71.7k
    return;
121
71.7k
  }
122
8
  nalloc_initialized = true;
123
8
  char *bitmask = getenv("NALLOC_FREQ");
124
8
  if (bitmask) {
125
0
    int shift = atoi(bitmask);
126
0
    if (shift > 0 && shift < 31) {
127
0
      nalloc_bitmask = 1 << shift;
128
0
      nalloc_random_bitmask = false;
129
0
    } else if (shift == 0) {
130
0
      nalloc_random_bitmask = false;
131
0
      nalloc_bitmask = 0;
132
0
    }
133
8
  } else if (prog == NULL || strstr(prog, "nalloc") == NULL) {
134
8
    nalloc_random_bitmask = false;
135
8
    nalloc_bitmask = 0;
136
8
    return;
137
8
  }
138
139
0
  char *magic = getenv("NALLOC_MAGIC");
140
0
  if (magic) {
141
0
    nalloc_magic = (uint32_t)strtol(magic, NULL, 0);
142
0
  }
143
144
0
  char *verbose = getenv("NALLOC_VERBOSE");
145
0
  if (verbose) {
146
0
    nalloc_verbose = true;
147
0
  }
148
0
}
149
150
// add one byte to the CRC
151
0
static inline void nalloc_random_update(uint8_t b) {
152
0
  nalloc_random_state =
153
0
      ((uint32_t)((uint32_t)nalloc_random_state << 8)) ^
154
0
      nalloc_crc32_table[((nalloc_random_state >> 24) ^ b) & 0xFF];
155
0
}
Unexecuted instantiation: vpx_dec_fuzzer.cc:nalloc_random_update(unsigned char)
Unexecuted instantiation: vpx_enc_fuzzer.cc:nalloc_random_update(unsigned char)
156
157
// Start the failure injections, using a buffer as seed
158
71.7k
static int nalloc_start(const uint8_t *data, size_t size) {
159
71.7k
  if (nalloc_random_bitmask) {
160
0
    if (nalloc_random_state & 0x10) {
161
0
      nalloc_bitmask = 0xFFFFFFFF;
162
0
    } else {
163
0
      nalloc_bitmask = 1 << (5 + (nalloc_random_state & 0xF));
164
0
    }
165
71.7k
  } else if (nalloc_bitmask == 0) {
166
    // nalloc disabled
167
71.7k
    return 0;
168
71.7k
  }
169
0
  nalloc_random_state = 0;
170
0
  for (size_t i = 0; i < size; i++) {
171
0
    nalloc_random_update(data[i]);
172
0
  }
173
0
  if (__sync_fetch_and_add(&nalloc_running, 1)) {
174
0
    __sync_fetch_and_sub(&nalloc_running, 1);
175
0
    return 0;
176
0
  }
177
0
  nalloc_runs++;
178
0
  return 1;
179
0
}
vpx_dec_fuzzer.cc:nalloc_start(unsigned char const*, unsigned long)
Line
Count
Source
158
47.7k
static int nalloc_start(const uint8_t *data, size_t size) {
159
47.7k
  if (nalloc_random_bitmask) {
160
0
    if (nalloc_random_state & 0x10) {
161
0
      nalloc_bitmask = 0xFFFFFFFF;
162
0
    } else {
163
0
      nalloc_bitmask = 1 << (5 + (nalloc_random_state & 0xF));
164
0
    }
165
47.7k
  } else if (nalloc_bitmask == 0) {
166
    // nalloc disabled
167
47.7k
    return 0;
168
47.7k
  }
169
0
  nalloc_random_state = 0;
170
0
  for (size_t i = 0; i < size; i++) {
171
0
    nalloc_random_update(data[i]);
172
0
  }
173
0
  if (__sync_fetch_and_add(&nalloc_running, 1)) {
174
0
    __sync_fetch_and_sub(&nalloc_running, 1);
175
0
    return 0;
176
0
  }
177
0
  nalloc_runs++;
178
0
  return 1;
179
0
}
vpx_enc_fuzzer.cc:nalloc_start(unsigned char const*, unsigned long)
Line
Count
Source
158
24.0k
static int nalloc_start(const uint8_t *data, size_t size) {
159
24.0k
  if (nalloc_random_bitmask) {
160
0
    if (nalloc_random_state & 0x10) {
161
0
      nalloc_bitmask = 0xFFFFFFFF;
162
0
    } else {
163
0
      nalloc_bitmask = 1 << (5 + (nalloc_random_state & 0xF));
164
0
    }
165
24.0k
  } else if (nalloc_bitmask == 0) {
166
    // nalloc disabled
167
24.0k
    return 0;
168
24.0k
  }
169
0
  nalloc_random_state = 0;
170
0
  for (size_t i = 0; i < size; i++) {
171
0
    nalloc_random_update(data[i]);
172
0
  }
173
0
  if (__sync_fetch_and_add(&nalloc_running, 1)) {
174
0
    __sync_fetch_and_sub(&nalloc_running, 1);
175
0
    return 0;
176
0
  }
177
0
  nalloc_runs++;
178
0
  return 1;
179
0
}
180
181
// Stop the failure injections
182
71.7k
static void nalloc_end() { __sync_fetch_and_sub(&nalloc_running, 1); }
vpx_dec_fuzzer.cc:nalloc_end()
Line
Count
Source
182
47.7k
static void nalloc_end() { __sync_fetch_and_sub(&nalloc_running, 1); }
vpx_enc_fuzzer.cc:nalloc_end()
Line
Count
Source
182
24.0k
static void nalloc_end() { __sync_fetch_and_sub(&nalloc_running, 1); }
183
184
0
static bool nalloc_backtrace_exclude(size_t size, const char *op) {
185
0
  if (nalloc_verbose) {
186
0
    fprintf(stderr, "failed %s(%zu) \n", op, size);
187
#ifdef NALLOC_ASAN
188
    __sanitizer_print_stack_trace();
189
#endif
190
0
  }
191
192
0
  return false;
193
0
}
Unexecuted instantiation: vpx_dec_fuzzer.cc:nalloc_backtrace_exclude(unsigned long, char const*)
Unexecuted instantiation: vpx_enc_fuzzer.cc:nalloc_backtrace_exclude(unsigned long, char const*)
194
195
//
196
183M
static bool nalloc_fail(size_t size, const char *op) {
197
  // do not fail before thread init
198
183M
  if (nalloc_runs == 0) {
199
183M
    return false;
200
183M
  }
201
0
  if (__sync_fetch_and_add(&nalloc_running, 1) != 1) {
202
    // do not fail allocations outside of fuzzer input
203
    // and do not fail inside of this function
204
0
    __sync_fetch_and_sub(&nalloc_running, 1);
205
0
    return false;
206
0
  }
207
0
  nalloc_random_update((uint8_t)size);
208
0
  if (size >= 0x100) {
209
0
    nalloc_random_update((uint8_t)(size >> 8));
210
0
    if (size >= 0x10000) {
211
0
      nalloc_random_update((uint8_t)(size >> 16));
212
      // bigger may already fail or oom
213
0
    }
214
0
  }
215
0
  if (((nalloc_random_state ^ nalloc_magic) & nalloc_bitmask) == 0) {
216
0
    if (nalloc_backtrace_exclude(size, op)) {
217
0
      __sync_fetch_and_sub(&nalloc_running, 1);
218
0
      return false;
219
0
    }
220
0
    __sync_fetch_and_sub(&nalloc_running, 1);
221
0
    return true;
222
0
  }
223
0
  __sync_fetch_and_sub(&nalloc_running, 1);
224
0
  return false;
225
0
}
vpx_dec_fuzzer.cc:nalloc_fail(unsigned long, char const*)
Line
Count
Source
196
55.5M
static bool nalloc_fail(size_t size, const char *op) {
197
  // do not fail before thread init
198
55.5M
  if (nalloc_runs == 0) {
199
55.5M
    return false;
200
55.5M
  }
201
0
  if (__sync_fetch_and_add(&nalloc_running, 1) != 1) {
202
    // do not fail allocations outside of fuzzer input
203
    // and do not fail inside of this function
204
0
    __sync_fetch_and_sub(&nalloc_running, 1);
205
0
    return false;
206
0
  }
207
0
  nalloc_random_update((uint8_t)size);
208
0
  if (size >= 0x100) {
209
0
    nalloc_random_update((uint8_t)(size >> 8));
210
0
    if (size >= 0x10000) {
211
0
      nalloc_random_update((uint8_t)(size >> 16));
212
      // bigger may already fail or oom
213
0
    }
214
0
  }
215
0
  if (((nalloc_random_state ^ nalloc_magic) & nalloc_bitmask) == 0) {
216
0
    if (nalloc_backtrace_exclude(size, op)) {
217
0
      __sync_fetch_and_sub(&nalloc_running, 1);
218
0
      return false;
219
0
    }
220
0
    __sync_fetch_and_sub(&nalloc_running, 1);
221
0
    return true;
222
0
  }
223
0
  __sync_fetch_and_sub(&nalloc_running, 1);
224
0
  return false;
225
0
}
vpx_enc_fuzzer.cc:nalloc_fail(unsigned long, char const*)
Line
Count
Source
196
128M
static bool nalloc_fail(size_t size, const char *op) {
197
  // do not fail before thread init
198
128M
  if (nalloc_runs == 0) {
199
128M
    return false;
200
128M
  }
201
0
  if (__sync_fetch_and_add(&nalloc_running, 1) != 1) {
202
    // do not fail allocations outside of fuzzer input
203
    // and do not fail inside of this function
204
0
    __sync_fetch_and_sub(&nalloc_running, 1);
205
0
    return false;
206
0
  }
207
0
  nalloc_random_update((uint8_t)size);
208
0
  if (size >= 0x100) {
209
0
    nalloc_random_update((uint8_t)(size >> 8));
210
0
    if (size >= 0x10000) {
211
0
      nalloc_random_update((uint8_t)(size >> 16));
212
      // bigger may already fail or oom
213
0
    }
214
0
  }
215
0
  if (((nalloc_random_state ^ nalloc_magic) & nalloc_bitmask) == 0) {
216
0
    if (nalloc_backtrace_exclude(size, op)) {
217
0
      __sync_fetch_and_sub(&nalloc_running, 1);
218
0
      return false;
219
0
    }
220
0
    __sync_fetch_and_sub(&nalloc_running, 1);
221
0
    return true;
222
0
  }
223
0
  __sync_fetch_and_sub(&nalloc_running, 1);
224
0
  return false;
225
0
}
226
227
// ASAN interceptor for libc routines
228
#ifdef NALLOC_ASAN
229
extern void *__interceptor_malloc(size_t);
230
extern void *__interceptor_calloc(size_t, size_t);
231
extern void *__interceptor_realloc(void *, size_t);
232
extern void *__interceptor_reallocarray(void *, size_t, size_t);
233
234
extern ssize_t __interceptor_read(int, void *, size_t);
235
extern ssize_t __interceptor_write(int, const void *, size_t);
236
extern ssize_t __interceptor_recv(int, void *, size_t, int);
237
extern ssize_t __interceptor_send(int, const void *, size_t, int);
238
239
#define nalloc_malloc(s) __interceptor_malloc(s)
240
#define nalloc_calloc(s, n) __interceptor_calloc(s, n)
241
#define nalloc_realloc(p, s) __interceptor_realloc(p, s)
242
#define nalloc_reallocarray(p, s, n) __interceptor_reallocarray(p, s, n)
243
244
#define nalloc_read(f, b, s) __interceptor_read(f, b, s)
245
#define nalloc_write(f, b, s) __interceptor_write(f, b, s)
246
#define nalloc_recv(f, b, s, x) __interceptor_recv(f, b, s, x)
247
#define nalloc_send(f, b, s, x) __interceptor_send(f, b, s, x)
248
249
#else
250
extern void *__libc_malloc(size_t);
251
extern void *__libc_calloc(size_t, size_t);
252
extern void *__libc_realloc(void *, size_t);
253
extern void *__libc_reallocarray(void *, size_t, size_t);
254
255
extern ssize_t __read(int, void *, size_t);
256
extern ssize_t __write(int, const void *, size_t);
257
extern ssize_t __recv(int, void *, size_t, int);
258
extern ssize_t __send(int, const void *, size_t, int);
259
260
183M
#define nalloc_malloc(s) __libc_malloc(s)
261
173k
#define nalloc_calloc(s, n) __libc_calloc(s, n)
262
8
#define nalloc_realloc(p, s) __libc_realloc(p, s)
263
0
#define nalloc_reallocarray(p, s, n) __libc_reallocarray(p, s, n)
264
265
0
#define nalloc_read(f, b, s) __read(f, b, s)
266
0
#define nalloc_write(f, b, s) __write(f, b, s)
267
0
#define nalloc_recv(f, b, s, x) __recv(f, b, s, x)
268
0
#define nalloc_send(f, b, s, x) __send(f, b, s, x)
269
#endif
270
271
// nalloc standard function overwrites with pseudo-random failures
272
0
ssize_t read(int fd, void *buf, size_t count) {
273
0
  if (nalloc_fail(count, "read")) {
274
0
    errno = EIO;
275
0
    return -1;
276
0
  }
277
0
  return nalloc_read(fd, buf, count);
278
0
}
279
280
0
ssize_t write(int fd, const void *buf, size_t count) {
281
0
  if (nalloc_fail(count, "write")) {
282
0
    errno = EIO;
283
0
    return -1;
284
0
  }
285
0
  return nalloc_write(fd, buf, count);
286
0
}
287
288
0
ssize_t recv(int fd, void *buf, size_t count, int flags) {
289
0
  if (nalloc_fail(count, "recv")) {
290
0
    errno = EIO;
291
0
    return -1;
292
0
  }
293
0
  return nalloc_recv(fd, buf, count, flags);
294
0
}
295
296
0
ssize_t send(int fd, const void *buf, size_t count, int flags) {
297
0
  if (nalloc_fail(count, "send")) {
298
0
    errno = EIO;
299
0
    return -1;
300
0
  }
301
0
  return nalloc_send(fd, buf, count, flags);
302
0
}
303
304
173k
void *calloc(size_t nmemb, size_t size) {
305
173k
  if (nalloc_fail(size, "calloc")) {
306
0
    errno = ENOMEM;
307
0
    return NULL;
308
0
  }
309
173k
  return nalloc_calloc(nmemb, size);
310
173k
}
311
312
183M
void *malloc(size_t size) {
313
183M
  if (nalloc_fail(size, "malloc")) {
314
0
    errno = ENOMEM;
315
0
    return NULL;
316
0
  }
317
183M
  return nalloc_malloc(size);
318
183M
}
319
320
8
void *realloc(void *ptr, size_t size) {
321
8
  if (nalloc_fail(size, "realloc")) {
322
0
    errno = ENOMEM;
323
0
    return NULL;
324
0
  }
325
8
  return nalloc_realloc(ptr, size);
326
8
}
327
328
0
void *reallocarray(void *ptr, size_t nmemb, size_t size) {
329
0
  if (nalloc_fail(size, "reallocarray")) {
330
0
    errno = ENOMEM;
331
0
    return NULL;
332
0
  }
333
0
  return nalloc_reallocarray(ptr, nmemb, size);
334
0
}
335
336
#ifdef __cplusplus
337
}  // extern "C" {
338
#endif
339
340
#endif // FUZZER_DISABLE_NALLOC
341
342
#endif  // NALLOC_H_