Coverage Report

Created: 2026-02-26 06:46

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
75.8k
void nalloc_init(const char *prog) {
119
75.8k
  if (nalloc_initialized) {
120
75.8k
    return;
121
75.8k
  }
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
75.8k
static int nalloc_start(const uint8_t *data, size_t size) {
159
75.8k
  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
75.8k
  } else if (nalloc_bitmask == 0) {
166
    // nalloc disabled
167
75.8k
    return 0;
168
75.8k
  }
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
46.5k
static int nalloc_start(const uint8_t *data, size_t size) {
159
46.5k
  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
46.5k
  } else if (nalloc_bitmask == 0) {
166
    // nalloc disabled
167
46.5k
    return 0;
168
46.5k
  }
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
29.2k
static int nalloc_start(const uint8_t *data, size_t size) {
159
29.2k
  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
29.2k
  } else if (nalloc_bitmask == 0) {
166
    // nalloc disabled
167
29.2k
    return 0;
168
29.2k
  }
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
75.8k
static void nalloc_end() { __sync_fetch_and_sub(&nalloc_running, 1); }
vpx_dec_fuzzer.cc:nalloc_end()
Line
Count
Source
182
46.5k
static void nalloc_end() { __sync_fetch_and_sub(&nalloc_running, 1); }
vpx_enc_fuzzer.cc:nalloc_end()
Line
Count
Source
182
29.2k
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
211M
static bool nalloc_fail(size_t size, const char *op) {
197
  // do not fail before thread init
198
211M
  if (nalloc_runs == 0) {
199
211M
    return false;
200
211M
  }
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
29.8M
static bool nalloc_fail(size_t size, const char *op) {
197
  // do not fail before thread init
198
29.8M
  if (nalloc_runs == 0) {
199
29.8M
    return false;
200
29.8M
  }
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
181M
static bool nalloc_fail(size_t size, const char *op) {
197
  // do not fail before thread init
198
181M
  if (nalloc_runs == 0) {
199
181M
    return false;
200
181M
  }
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
211M
#define nalloc_malloc(s) __libc_malloc(s)
261
151k
#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
151k
void *calloc(size_t nmemb, size_t size) {
305
151k
  if (nalloc_fail(size, "calloc")) {
306
0
    errno = ENOMEM;
307
0
    return NULL;
308
0
  }
309
151k
  return nalloc_calloc(nmemb, size);
310
151k
}
311
312
211M
void *malloc(size_t size) {
313
211M
  if (nalloc_fail(size, "malloc")) {
314
0
    errno = ENOMEM;
315
0
    return NULL;
316
0
  }
317
211M
  return nalloc_malloc(size);
318
211M
}
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_