##// END OF EJS Templates
fuzz: new fuzzer for cext/manifest.c...
Augie Fackler -
r40089:8c692a6b default
parent child Browse files
Show More
@@ -0,0 +1,75 b''
1 #include <Python.h>
2 #include <assert.h>
3 #include <stdlib.h>
4 #include <unistd.h>
5
6 #include <string>
7
8 extern "C" {
9
10 /* TODO: use Python 3 for this fuzzing? */
11 PyMODINIT_FUNC initparsers(void);
12
13 static char cpypath[8192] = "\0";
14
15 extern "C" int LLVMFuzzerInitialize(int *argc, char ***argv)
16 {
17 const std::string subdir = "/sanpy/lib/python2.7";
18 /* HACK ALERT: we need a full Python installation built without
19 pymalloc and with ASAN, so we dump one in
20 $OUT/sanpy/lib/python2.7. This helps us wire that up. */
21 std::string selfpath(*argv[0]);
22 std::string pypath;
23 auto pos = selfpath.rfind("/");
24 if (pos == std::string::npos) {
25 char wd[8192];
26 getcwd(wd, 8192);
27 pypath = std::string(wd) + subdir;
28 } else {
29 pypath = selfpath.substr(0, pos) + subdir;
30 }
31 strncpy(cpypath, pypath.c_str(), pypath.size());
32 setenv("PYTHONPATH", cpypath, 1);
33 Py_SetPythonHome(cpypath);
34 return 0;
35 }
36
37 int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size)
38 {
39 Py_InitializeEx(0);
40 initparsers();
41 PyObject *mtext =
42 PyBytes_FromStringAndSize((const char *)Data, (Py_ssize_t)Size);
43 PyObject *mainmod = PyImport_AddModule("__main__");
44 PyObject *globals = PyModule_GetDict(mainmod);
45 PyObject *locals = PyDict_New();
46 PyDict_SetItemString(locals, "mdata", mtext);
47 PyCodeObject *code =
48 (PyCodeObject *)Py_CompileString(R"py(
49 from parsers import lazymanifest
50 lm = lazymanifest(mdata)
51 try:
52 # iterate the whole thing, which causes the code to fully parse
53 # every line in the manifest
54 list(lm.iterentries())
55 lm[b'xyzzy'] = (b'\0' * 20, 'x')
56 # do an insert, text should change
57 assert lm.text() != mdata, "insert should change text and didn't: %r %r" % (lm.text(), mdata)
58 del lm[b'xyzzy']
59 # should be back to the same
60 assert lm.text() == mdata, "delete should have restored text but didn't: %r %r" % (lm.text(), mdata)
61 except Exception as e:
62 pass
63 # uncomment this print if you're editing this Python code
64 # to debug failures.
65 # print e
66 )py",
67 "fuzzer", Py_file_input);
68 PyEval_EvalCode(code, globals, locals);
69 Py_DECREF(code);
70 Py_DECREF(locals);
71 Py_DECREF(mtext);
72 Py_Finalize();
73 return 0; // Non-zero return values are reserved for future use.
74 }
75 }
@@ -0,0 +1,30 b''
1 from __future__ import absolute_import, print_function
2
3 import argparse
4 import zipfile
5
6 ap = argparse.ArgumentParser()
7 ap.add_argument("out", metavar="some.zip", type=str, nargs=1)
8 args = ap.parse_args()
9
10 with zipfile.ZipFile(args.out[0], "w", zipfile.ZIP_STORED) as zf:
11 zf.writestr("manifest_zero",
12 '''PKG-INFO\09b3ed8f2b81095a13064402e930565f083346e9a
13 README\080b6e76643dcb44d4bc729e932fc464b3e36dbe3
14 hg\0b6444347c629cc058d478023905cfb83b7f5bb9d
15 mercurial/__init__.py\0b80de5d138758541c5f05265ad144ab9fa86d1db
16 mercurial/byterange.py\017f5a9fbd99622f31a392c33ac1e903925dc80ed
17 mercurial/fancyopts.py\0b6f52e23e356748c5039313d8b639cda16bf67ba
18 mercurial/hg.py\023cc12f225f1b42f32dc0d897a4f95a38ddc8f4a
19 mercurial/mdiff.py\0a05f65c44bfbeec6a42336cd2ff0b30217899ca3
20 mercurial/revlog.py\0217bc3fde6d82c0210cf56aeae11d05a03f35b2b
21 mercurial/transaction.py\09d180df101dc14ce3dd582fd998b36c98b3e39aa
22 notes.txt\0703afcec5edb749cf5cec67831f554d6da13f2fb
23 setup.py\0ccf3f6daf0f13101ca73631f7a1769e328b472c9
24 tkmerge\03c922edb43a9c143682f7bc7b00f98b3c756ebe7
25 ''')
26 zf.writestr("badmanifest_shorthashes",
27 "narf\0aa\nnarf2\0aaa\n")
28 zf.writestr("badmanifest_nonull",
29 "narf\0cccccccccccccccccccccccccccccccccccccccc\n"
30 "narf2aaaaaaaaaaaaaaaaaaaa\n")
@@ -0,0 +1,2 b''
1 [libfuzzer]
2 detect_leaks = 0
@@ -1,81 +1,131 b''
1 1 CC = clang
2 2 CXX = clang++
3 3
4 4 all: bdiff mpatch xdiff
5 5
6 6 fuzzutil.o: fuzzutil.cc fuzzutil.h
7 7 $(CXX) $(CXXFLAGS) -g -O1 -fsanitize=fuzzer-no-link,address \
8 8 -std=c++17 \
9 9 -I../../mercurial -c -o fuzzutil.o fuzzutil.cc
10 10
11 11 fuzzutil-oss-fuzz.o: fuzzutil.cc fuzzutil.h
12 12 $(CXX) $(CXXFLAGS) -std=c++17 \
13 13 -I../../mercurial -c -o fuzzutil-oss-fuzz.o fuzzutil.cc
14 14
15 15 bdiff.o: ../../mercurial/bdiff.c
16 16 $(CC) $(CFLAGS) -fsanitize=fuzzer-no-link,address -c -o bdiff.o \
17 17 ../../mercurial/bdiff.c
18 18
19 19 bdiff: bdiff.cc bdiff.o fuzzutil.o
20 20 $(CXX) $(CXXFLAGS) -DHG_FUZZER_INCLUDE_MAIN=1 -g -O1 -fsanitize=fuzzer-no-link,address \
21 21 -std=c++17 \
22 22 -I../../mercurial bdiff.cc bdiff.o fuzzutil.o -o bdiff
23 23
24 24 bdiff-oss-fuzz.o: ../../mercurial/bdiff.c
25 25 $(CC) $(CFLAGS) -c -o bdiff-oss-fuzz.o ../../mercurial/bdiff.c
26 26
27 27 bdiff_fuzzer: bdiff.cc bdiff-oss-fuzz.o fuzzutil-oss-fuzz.o
28 28 $(CXX) $(CXXFLAGS) -std=c++17 -I../../mercurial bdiff.cc \
29 29 bdiff-oss-fuzz.o fuzzutil-oss-fuzz.o -lFuzzingEngine -o \
30 30 $$OUT/bdiff_fuzzer
31 31
32 32 mpatch.o: ../../mercurial/mpatch.c
33 33 $(CC) -g -O1 -fsanitize=fuzzer-no-link,address -c -o mpatch.o \
34 34 ../../mercurial/mpatch.c
35 35
36 36 mpatch: CXXFLAGS += -std=c++17
37 37 mpatch: mpatch.cc mpatch.o fuzzutil.o
38 38 $(CXX) $(CXXFLAGS) -DHG_FUZZER_INCLUDE_MAIN=1 -g -O1 -fsanitize=fuzzer-no-link,address \
39 39 -I../../mercurial mpatch.cc mpatch.o fuzzutil.o -o mpatch
40 40
41 41 mpatch-oss-fuzz.o: ../../mercurial/mpatch.c
42 42 $(CC) $(CFLAGS) -c -o mpatch-oss-fuzz.o ../../mercurial/mpatch.c
43 43
44 44 mpatch_fuzzer: mpatch.cc mpatch-oss-fuzz.o fuzzutil-oss-fuzz.o
45 45 $(CXX) $(CXXFLAGS) -std=c++17 -I../../mercurial mpatch.cc \
46 46 mpatch-oss-fuzz.o fuzzutil-oss-fuzz.o -lFuzzingEngine -o \
47 47 $$OUT/mpatch_fuzzer
48 48
49 49 mpatch_corpus.zip:
50 50 python mpatch_corpus.py $$OUT/mpatch_fuzzer_seed_corpus.zip
51 51
52 52 x%.o: ../../mercurial/thirdparty/xdiff/x%.c ../../mercurial/thirdparty/xdiff/*.h
53 53 $(CC) -g -O1 -fsanitize=fuzzer-no-link,address -c \
54 54 -o $@ \
55 55 $<
56 56
57 57 xdiff: CXXFLAGS += -std=c++17
58 58 xdiff: xdiff.cc xdiffi.o xprepare.o xutils.o fuzzutil.o
59 59 $(CXX) $(CXXFLAGS) -DHG_FUZZER_INCLUDE_MAIN=1 -g -O1 -fsanitize=fuzzer-no-link,address \
60 60 -I../../mercurial xdiff.cc \
61 61 xdiffi.o xprepare.o xutils.o fuzzutil.o -o xdiff
62 62
63 63 fuzz-x%.o: ../../mercurial/thirdparty/xdiff/x%.c ../../mercurial/thirdparty/xdiff/*.h
64 64 $(CC) $(CFLAGS) -c \
65 65 -o $@ \
66 66 $<
67 67
68 68 xdiff_fuzzer: xdiff.cc fuzz-xdiffi.o fuzz-xprepare.o fuzz-xutils.o fuzzutil-oss-fuzz.o
69 69 $(CXX) $(CXXFLAGS) -std=c++17 -I../../mercurial xdiff.cc \
70 70 fuzz-xdiffi.o fuzz-xprepare.o fuzz-xutils.o fuzzutil-oss-fuzz.o \
71 71 -lFuzzingEngine -o $$OUT/xdiff_fuzzer
72 72
73 # TODO use the $OUT env var instead of hardcoding /out
74 /out/sanpy/bin/python:
75 cd /Python-2.7.15/ && ./configure --without-pymalloc --prefix=$$OUT/sanpy CFLAGS='-O1 -fno-omit-frame-pointer -g -fwrapv -fstack-protector-strong' LDFLAGS=-lasan && ASAN_OPTIONS=detect_leaks=0 make && make install
76
77 sanpy: /out/sanpy/bin/python
78
79 manifest.o: sanpy ../../mercurial/cext/manifest.c
80 $(CC) $(CFLAGS) `$$OUT/sanpy/bin/python-config --cflags` \
81 -I../../mercurial \
82 -c -o manifest.o ../../mercurial/cext/manifest.c
83
84 charencode.o: sanpy ../../mercurial/cext/charencode.c
85 $(CC) $(CFLAGS) `$$OUT/sanpy/bin/python-config --cflags` \
86 -I../../mercurial \
87 -c -o charencode.o ../../mercurial/cext/charencode.c
88
89 parsers.o: sanpy ../../mercurial/cext/parsers.c
90 $(CC) $(CFLAGS) `$$OUT/sanpy/bin/python-config --cflags` \
91 -I../../mercurial \
92 -c -o parsers.o ../../mercurial/cext/parsers.c
93
94 dirs.o: sanpy ../../mercurial/cext/dirs.c
95 $(CC) $(CFLAGS) `$$OUT/sanpy/bin/python-config --cflags` \
96 -I../../mercurial \
97 -c -o dirs.o ../../mercurial/cext/dirs.c
98
99 pathencode.o: sanpy ../../mercurial/cext/pathencode.c
100 $(CC) $(CFLAGS) `$$OUT/sanpy/bin/python-config --cflags` \
101 -I../../mercurial \
102 -c -o pathencode.o ../../mercurial/cext/pathencode.c
103
104 revlog.o: sanpy ../../mercurial/cext/revlog.c
105 $(CC) $(CFLAGS) `$$OUT/sanpy/bin/python-config --cflags` \
106 -I../../mercurial \
107 -c -o revlog.o ../../mercurial/cext/revlog.c
108
109 manifest_fuzzer: sanpy manifest.cc manifest.o charencode.o parsers.o dirs.o pathencode.o revlog.o
110 $(CXX) $(CXXFLAGS) `$$OUT/sanpy/bin/python-config --cflags` \
111 -Wno-register -Wno-macro-redefined \
112 -I../../mercurial manifest.cc \
113 manifest.o charencode.o parsers.o dirs.o pathencode.o revlog.o \
114 -lFuzzingEngine `$$OUT/sanpy/bin/python-config --ldflags` \
115 -o $$OUT/manifest_fuzzer
116
117 manifest_corpus.zip:
118 python manifest_corpus.py $$OUT/manifest_fuzzer_seed_corpus.zip
119
120 copy_options:
121 cp *.options $$OUT
122
73 123 clean:
74 124 $(RM) *.o *_fuzzer \
75 125 bdiff \
76 126 mpatch \
77 127 xdiff
78 128
79 oss-fuzz: bdiff_fuzzer mpatch_fuzzer mpatch_corpus.zip xdiff_fuzzer
129 oss-fuzz: bdiff_fuzzer mpatch_fuzzer mpatch_corpus.zip xdiff_fuzzer manifest_fuzzer manifest_corpus.zip copy_options
80 130
81 .PHONY: all clean oss-fuzz
131 .PHONY: all clean oss-fuzz sanpy copy_options
General Comments 0
You need to be logged in to leave comments. Login now