summaryrefslogtreecommitdiff
path: root/apps/plugins/puzzles/src/fuzzpuzz.c
diff options
context:
space:
mode:
authorFranklin Wei <franklin@rockbox.org>2024-08-11 23:31:33 -0400
committerFranklin Wei <franklin@rockbox.org>2024-08-16 16:31:28 -0400
commit903e8c5b32285e50907e6525388162bd459cbef8 (patch)
tree7e23ce2646a31f80b1d6879d2b30cfc30eadace6 /apps/plugins/puzzles/src/fuzzpuzz.c
parentceea52ce0f4782466c3bcfb69c64c975515fe198 (diff)
downloadrockbox-903e8c5b32285e50907e6525388162bd459cbef8.tar.gz
rockbox-903e8c5b32285e50907e6525388162bd459cbef8.zip
puzzles: remove unnecessary files from the src/ directory.
This updates the resync.sh script to be more intelligent about which files it copies from the upstream tree. It now attempts some rudimentary parsing of the puzzles CMakeLists.txt file to figure out which files are actually necessary, and copies only those. This adds a new SOURCES.rockbox source file list for the Rockbox-specific parts of the port. Change-Id: I461f87ac712e3b2982dcbb0be9d70d278384a4e7
Diffstat (limited to 'apps/plugins/puzzles/src/fuzzpuzz.c')
-rw-r--r--apps/plugins/puzzles/src/fuzzpuzz.c250
1 files changed, 0 insertions, 250 deletions
diff --git a/apps/plugins/puzzles/src/fuzzpuzz.c b/apps/plugins/puzzles/src/fuzzpuzz.c
deleted file mode 100644
index 3fb632ec57..0000000000
--- a/apps/plugins/puzzles/src/fuzzpuzz.c
+++ /dev/null
@@ -1,250 +0,0 @@
1/*
2 * fuzzpuzz.c: Fuzzing frontend to all puzzles.
3 */
4
5/*
6 * The idea here is that this front-end supports all back-ends and can
7 * feed them save files. It then asks the back-end to draw the puzzle
8 * (through a null drawing API) and reserialises the state. This
9 * tests the deserialiser, the code for loading game descriptions, the
10 * processing of move strings, the redraw code, and the serialisation
11 * routines, but is still pretty quick.
12 *
13 * To use AFL++ to drive fuzzpuzz, you can do something like:
14 *
15 * CC=afl-cc cmake -B build-afl
16 * cmake --build build-afl --target fuzzpuzz
17 * mkdir fuzz-in && ln icons/''*.sav fuzz-in
18 * afl-fuzz -i fuzz-in -o fuzz-out -x fuzzpuzz.dict -- build-afl/fuzzpuzz
19 *
20 * Similarly with Honggfuzz:
21 *
22 * CC=hfuzz-cc cmake -B build-honggfuzz
23 * cmake --build build-honggfuzz --target fuzzpuzz
24 * mkdir fuzz-corpus && ln icons/''*.sav fuzz-corpus
25 * honggfuzz -s -i fuzz-corpus -w fuzzpuzz.dict -- build-honggfuzz/fuzzpuzz
26 *
27 * You can also use libFuzzer, though it's not really a good fit for
28 * Puzzles. The experimental forking mode seems to work OK:
29 *
30 * CC=clang cmake -B build-clang -DWITH_LIBFUZZER=Y
31 * cmake --build build-clang --target fuzzpuzz
32 * mkdir fuzz-corpus && ln icons/''*.sav fuzz-corpus
33 * build-clang/fuzzpuzz -fork=1 -ignore_crashes=1 -dict=fuzzpuzz.dict \
34 * fuzz-corpus
35 */
36
37#include <stdbool.h>
38#include <stdio.h>
39#include <stdlib.h>
40#include <string.h>
41#ifdef __AFL_FUZZ_TESTCASE_LEN
42# include <unistd.h> /* read() is used by __AFL_FUZZ_TESTCASE_LEN. */
43#endif
44
45#include "puzzles.h"
46
47#ifdef __AFL_FUZZ_INIT
48__AFL_FUZZ_INIT();
49#endif
50
51#ifdef HAVE_HF_ITER
52extern int HF_ITER(unsigned char **, size_t *);
53#endif
54
55/* This function is expected by libFuzzer. */
56
57int LLVMFuzzerTestOneInput(unsigned char *data, size_t size);
58
59static const char *fuzz_one(bool (*readfn)(void *, void *, int), void *rctx,
60 void (*rewindfn)(void *),
61 void (*writefn)(void *, const void *, int),
62 void *wctx)
63{
64 const char *err;
65 char *gamename;
66 int i, w, h;
67 const game *ourgame = NULL;
68 static const drawing_api drapi = { NULL };
69 midend *me;
70
71 err = identify_game(&gamename, readfn, rctx);
72 if (err != NULL) return err;
73
74 for (i = 0; i < gamecount; i++)
75 if (strcmp(gamename, gamelist[i]->name) == 0)
76 ourgame = gamelist[i];
77 sfree(gamename);
78 if (ourgame == NULL)
79 return "Game not recognised";
80
81 me = midend_new(NULL, ourgame, &drapi, NULL);
82
83 rewindfn(rctx);
84 err = midend_deserialise(me, readfn, rctx);
85 if (err != NULL) {
86 midend_free(me);
87 return err;
88 }
89 w = h = INT_MAX;
90 midend_size(me, &w, &h, false, 1);
91 midend_redraw(me);
92 midend_serialise(me, writefn, wctx);
93 midend_free(me);
94 return NULL;
95}
96
97#if defined(__AFL_FUZZ_TESTCASE_LEN) || defined(HAVE_HF_ITER) || \
98 !defined(OMIT_MAIN)
99static void savefile_write(void *wctx, const void *buf, int len)
100{
101 FILE *fp = (FILE *)wctx;
102
103 fwrite(buf, 1, len, fp);
104}
105#endif
106
107struct memread {
108 const unsigned char *buf;
109 size_t pos;
110 size_t len;
111};
112
113static bool mem_read(void *wctx, void *buf, int len)
114{
115 struct memread *ctx = wctx;
116
117 if (ctx->pos + len > ctx->len) return false;
118 memcpy(buf, ctx->buf + ctx->pos, len);
119 ctx->pos += len;
120 return true;
121}
122
123static void mem_rewind(void *wctx)
124{
125 struct memread *ctx = wctx;
126
127 ctx->pos = 0;
128}
129
130static void null_write(void *wctx, const void *buf, int len)
131{
132}
133
134int LLVMFuzzerTestOneInput(unsigned char *data, size_t size) {
135 struct memread ctx;
136
137 ctx.buf = data;
138 ctx.len = size;
139 ctx.pos = 0;
140 fuzz_one(mem_read, &ctx, mem_rewind, null_write, NULL);
141 return 0;
142}
143
144#if defined(__AFL_FUZZ_TESTCASE_LEN) || defined(HAVE_HF_ITER)
145static const char *fuzz_one_mem(unsigned char *data, size_t size) {
146 struct memread ctx;
147
148 ctx.buf = data;
149 ctx.len = size;
150 ctx.pos = 0;
151 return fuzz_one(mem_read, &ctx, mem_rewind, savefile_write, stdout);
152}
153#endif
154
155/*
156 * Three different versions of main(), for standalone, AFL, and
157 * Honggfuzz modes. LibFuzzer brings its own main().
158 */
159
160#ifdef OMIT_MAIN
161/* Nothing. */
162#elif defined(__AFL_FUZZ_TESTCASE_LEN)
163/*
164 * AFL persistent mode, where we fuzz from a RAM buffer provided
165 * by AFL in a loop. This version can still be run standalone if
166 * necessary, for instance to diagnose a crash.
167 */
168int main(int argc, char **argv)
169{
170 const char *err;
171 int ret;
172
173 if (argc != 1) {
174 fprintf(stderr, "usage: %s\n", argv[0]);
175 return 1;
176 }
177#ifdef __AFL_HAVE_MANUAL_CONTROL
178 __AFL_INIT();
179#endif
180 while (__AFL_LOOP(10000)) {
181 err = fuzz_one_mem(__AFL_FUZZ_TESTCASE_BUF, __AFL_FUZZ_TESTCASE_LEN);
182 if (err != NULL) {
183 fprintf(stderr, "%s\n", err);
184 ret = 1;
185 } else
186 ret = 0;
187 }
188 return ret;
189}
190#elif defined(HAVE_HF_ITER)
191/*
192 * Honggfuzz persistent mode. Unlike AFL persistent mode, the
193 * resulting executable cannot be run outside of Honggfuzz.
194 */
195int main(int argc, char **argv)
196{
197 if (argc != 1) {
198 fprintf(stderr, "usage: %s\n", argv[0]);
199 return 1;
200 }
201 while (true) {
202 unsigned char *testcase_buf;
203 size_t testcase_len;
204 HF_ITER(&testcase_buf, &testcase_len);
205 fuzz_one_mem(testcase_buf, testcase_len);
206 }
207}
208#else
209/*
210 * Stand-alone mode: just handle a single test case on stdin.
211 */
212static bool savefile_read(void *wctx, void *buf, int len)
213{
214 FILE *fp = (FILE *)wctx;
215 int ret;
216
217 ret = fread(buf, 1, len, fp);
218 return (ret == len);
219}
220
221static void savefile_rewind(void *wctx)
222{
223 FILE *fp = (FILE *)wctx;
224
225 rewind(fp);
226}
227
228int main(int argc, char **argv)
229{
230 const char *err;
231
232 if (argc != 1) {
233 fprintf(stderr, "usage: %s\n", argv[0]);
234 return 1;
235 }
236
237 /* Might in theory use this mode under AFL. */
238#ifdef __AFL_HAVE_MANUAL_CONTROL
239 __AFL_INIT();
240#endif
241
242 err = fuzz_one(savefile_read, stdin, savefile_rewind,
243 savefile_write, stdout);
244 if (err != NULL) {
245 fprintf(stderr, "%s\n", err);
246 return 1;
247 }
248 return 0;
249}
250#endif