1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
|
/* Fuzz target: the shader expression language (src/expr.c).
*
* Compiles arbitrary text, and when a program comes back actually runs it:
* once per hand-picked environment (zeros, a plausible pane, and extremes)
* and once as an amount map over a small rect. The language is documented as
* total -- no way to hang, div/mod by zero is 0 -- so anything ASan/UBSan
* catches in eval is a real bug, including signed overflow in the arithmetic.
*/
#include "expr.h"
#include <limits.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
char *text = malloc(size + 1);
if (!text) return 0;
memcpy(text, data, size);
text[size] = '\0';
char err[256];
expr_prog_t *p = expr_compile(text, err, sizeof err);
if (p) {
unsigned deps = expr_deps(p);
if (deps == 0) (void)expr_constant(p);
(void)expr_source(p);
const expr_env_t envs[] = {
{0},
{.x = 79,
.y = 23,
.cols = 80,
.rows = 24,
.curx = 40,
.cury = 12,
.cursor = 1,
.focused = 1,
.t = 1234567890123LL,
.since = 42,
.above = 10000,
.below = 3},
{.x = INT_MAX,
.y = INT_MIN,
.cols = INT_MAX,
.rows = INT_MAX,
.curx = -1,
.cury = -1,
.cursor = -1,
.focused = -1,
.t = INT64_MAX,
.since = INT64_MIN,
.above = INT_MAX,
.below = INT_MIN},
};
for (size_t i = 0; i < sizeof envs / sizeof envs[0]; i++)
(void)expr_eval(p, &envs[i]);
/* the cached per-cell map, over a rect small enough to fill twice */
expr_env_t env = {.cols = 8, .rows = 4, .cursor = 1, .t = 17};
uint8_t *map = NULL;
(void)expr_amount_map(p, &env, &map);
env.curx = 3;
env.cury = 2;
(void)expr_amount_map(p, &env, &map); /* map is owned by the program */
expr_free(p);
}
free(text);
return 0;
}
|