/src/mercurial/contrib/fuzz/manifest.cc
Line | Count | Source |
1 | | #include <Python.h> |
2 | | #include <assert.h> |
3 | | #include <stdlib.h> |
4 | | #include <unistd.h> |
5 | | |
6 | | #include "FuzzedDataProvider.h" |
7 | | #include "pyutil.h" |
8 | | |
9 | | #include <string> |
10 | | |
11 | | extern "C" { |
12 | | |
13 | | static PYCODETYPE *code; |
14 | | |
15 | | extern "C" int LLVMFuzzerInitialize(int *argc, char ***argv) |
16 | 15 | { |
17 | 15 | contrib::initpy(*argv[0]); |
18 | 15 | code = (PYCODETYPE *)Py_CompileString(R"py( |
19 | 15 | try: |
20 | 15 | lm = parsers.lazymanifest(mdata) |
21 | 15 | # iterate the whole thing, which causes the code to fully parse |
22 | 15 | # every line in the manifest |
23 | 15 | for e, _, _ in lm.iterentries(): |
24 | 15 | # also exercise __getitem__ et al |
25 | 15 | lm[e] |
26 | 15 | e in lm |
27 | 15 | (e + 'nope') in lm |
28 | 15 | lm[b'xyzzy'] = (b'\0' * nlen, 'x') |
29 | 15 | # do an insert, text should change |
30 | 15 | assert lm.text() != mdata, "insert should change text and didn't: %r %r" % (lm.text(), mdata) |
31 | 15 | cloned = lm.filtercopy(lambda x: x != 'xyzzy') |
32 | 15 | assert cloned.text() == mdata, 'cloned text should equal mdata' |
33 | 15 | cloned.diff(lm) |
34 | 15 | del lm[b'xyzzy'] |
35 | 15 | cloned.diff(lm) |
36 | 15 | # should be back to the same |
37 | 15 | assert lm.text() == mdata, "delete should have restored text but didn't: %r %r" % (lm.text(), mdata) |
38 | 15 | except Exception as e: |
39 | 15 | pass |
40 | 15 | # uncomment this print if you're editing this Python code |
41 | 15 | # to debug failures. |
42 | 15 | # print e |
43 | 15 | )py", |
44 | 15 | "fuzzer", Py_file_input); |
45 | 15 | return 0; |
46 | 15 | } |
47 | | |
48 | | int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) |
49 | 122 | { |
50 | | // Don't allow fuzzer inputs larger than 100k, since we'll just bog |
51 | | // down and not accomplish much. |
52 | 122 | if (Size > 100000) { |
53 | 4 | return 0; |
54 | 4 | } |
55 | 118 | FuzzedDataProvider provider(Data, Size); |
56 | 118 | Py_ssize_t nodelength = provider.ConsumeBool() ? 20 : 32; |
57 | 118 | PyObject *nlen = PyLong_FromSsize_t(nodelength); |
58 | 118 | PyObject *mtext = |
59 | 118 | PyBytes_FromStringAndSize((const char *)Data, (Py_ssize_t)Size); |
60 | 118 | PyObject *locals = PyDict_New(); |
61 | 118 | PyDict_SetItemString(locals, "mdata", mtext); |
62 | 118 | PyDict_SetItemString(locals, "nlen", nlen); |
63 | 118 | PyObject *res = PyEval_EvalCode(code, contrib::pyglobals(), locals); |
64 | 118 | if (!res) { |
65 | 0 | PyErr_Print(); |
66 | 0 | } |
67 | 118 | Py_XDECREF(res); |
68 | 118 | Py_DECREF(locals); |
69 | 118 | Py_DECREF(mtext); |
70 | 118 | return 0; // Non-zero return values are reserved for future use. |
71 | 122 | } |
72 | | } |