├── .gitignore ├── LICENSE ├── README.md ├── checkout_build_install_llvm.sh ├── lessons ├── 10 │ ├── README.md │ ├── re2.tgz │ └── re2_fuzzer.cc ├── 11 │ ├── README.md │ ├── pcre2-10.00.tgz │ ├── pcre2.tgz │ └── pcre2_fuzzer.cc ├── 12 │ ├── Modern_Fuzzing_of_C_C++_projects_slides_63-70.pdf │ └── README.md ├── 01 │ ├── Modern_Fuzzing_of_C_C++_projects_slides_1-23.pdf │ └── README.md ├── 02 │ ├── README.md │ ├── bin │ │ ├── asan.tgz │ │ └── radamsa │ ├── generate_testcases.py │ ├── run_fuzzing.py │ └── seed_corpus │ │ ├── TALOS-CAN-0174 - Google Chrome PDFium jpeg2000 SIZ Code Execution Vulnerability_POC.pdf │ │ ├── a.pdf │ │ ├── b.pdf │ │ ├── chromeUrls.pdf │ │ ├── cr.pdf │ │ ├── formsubmit.pdf │ │ ├── global-buffer-overflow-61f-ada-9ec.pdf │ │ ├── global-buffer-overflow.pdf │ │ ├── heap-buffer-overflow-b19-c75-64e.pdf │ │ ├── heap-use-after-free-8d2-641-d6d.pdf │ │ ├── jbig2-overflow-4.pdf │ │ ├── pageviewtest.pdf │ │ ├── pdf_crash.pdf │ │ ├── pdf_crash1.pdf │ │ ├── pdfium-parseSymbolDict-Overflow.pdf │ │ ├── poc (1).pdf │ │ ├── poc.pdf │ │ ├── poc_1.pdf │ │ ├── poc_2.pdf │ │ ├── poc_3.pdf │ │ ├── poc_32bit.pdf │ │ ├── poc_64bit.pdf │ │ ├── poc_stable.pdf │ │ ├── poc_tot.pdf │ │ ├── pocxx.pdf │ │ ├── repro (1).pdf │ │ ├── repro (2).pdf │ │ ├── repro.pdf │ │ ├── soiax0001_repro.pdf │ │ ├── test (1).pdf │ │ ├── test (2).pdf │ │ ├── test.pdf │ │ ├── testcase (1).pdf │ │ ├── testcase.pdf │ │ ├── testcase_focus.pdf │ │ ├── uaf_2.pdf │ │ ├── xxx.pdf │ │ └── xxx2.pdf ├── 03 │ ├── Modern_Fuzzing_of_C_C++_projects_slides_24-39.pdf │ └── README.md ├── 04 │ ├── README.md │ ├── first_fuzzer.cc │ ├── fourth_fuzzer.cc │ ├── second_fuzzer.cc │ ├── third_fuzzer.cc │ └── vulnerable_functions.h ├── 05 │ ├── README.md │ ├── openssl1.0.1f.tgz │ ├── openssl_fuzzer.cc │ ├── server.key │ └── server.pem ├── 06 │ ├── README.md │ ├── c-ares.tgz │ └── c_ares_fuzzer.cc ├── 07 │ ├── Modern_Fuzzing_of_C_C++_projects_slides_40-62.pdf │ └── README.md ├── 08 │ ├── README.md │ ├── coverage-report-server.py │ ├── libxml2.tgz │ ├── png.dict │ ├── xml.dict │ ├── xml_compile_regexp_fuzzer.cc │ └── xml_read_memory_fuzzer.cc └── 09 │ ├── README.md │ ├── libpng.tgz │ ├── libpng_read_fuzzer.cc │ ├── png.dict │ ├── seed_corpus │ ├── anti_aliasing.png │ ├── anti_aliasing_perspective.png │ ├── axis_aligned.png │ ├── background_filter.png │ ├── background_filter_blur.png │ ├── background_filter_blur_off_axis.png │ ├── background_filter_blur_outsets.png │ ├── background_filter_on_scaled_layer_gl.png │ ├── background_filter_on_scaled_layer_sw.png │ ├── background_filter_rotated_gl.png │ ├── background_filter_rotated_sw.png │ ├── black.png │ ├── blending_and_filter.png │ ├── blending_render_pass.png │ ├── blending_render_pass_cm.png │ ├── blending_render_pass_mask.png │ ├── blending_render_pass_mask_cm.png │ ├── blending_transparent.png │ ├── blending_with_root.png │ ├── blue_yellow.png │ ├── blue_yellow_alpha.png │ ├── blue_yellow_alpha_translate.png │ ├── blue_yellow_anti_aliasing.png │ ├── blue_yellow_filter_chain.png │ ├── blue_yellow_flipped.png │ ├── blue_yellow_partial_flipped.png │ ├── blur_filter_with_clip_gl.png │ ├── blur_filter_with_clip_sw.png │ ├── checkers.png │ ├── checkers_big.png │ ├── dark_grey.png │ ├── enlarged_texture_on_crop_offset.png │ ├── enlarged_texture_on_threshold.png │ ├── filter_with_giant_crop_rect.png │ ├── force_anti_aliasing_off.png │ ├── four_blue_green_checkers.png │ ├── four_blue_green_checkers_linear.png │ ├── green.png │ ├── green_alpha.png │ ├── green_small.png │ ├── green_small_with_blue_corner.png │ ├── green_with_blue_corner.png │ ├── image_mask_of_layer.png │ ├── intersecting_blue_green.png │ ├── intersecting_blue_green_squares.png │ ├── intersecting_blue_green_squares_video.png │ ├── intersecting_light_dark_squares_video.png │ ├── mask_bottom_right.png │ ├── mask_middle.png │ ├── mask_of_background_filter.png │ ├── mask_of_clipped_layer.png │ ├── mask_of_layer.png │ ├── mask_of_layer_with_blend.png │ ├── mask_of_replica.png │ ├── mask_of_replica_of_clipped_layer.png │ ├── mask_with_replica.png │ ├── mask_with_replica_of_clipped_layer.png │ ├── offset_background_filter_1x.png │ ├── offset_background_filter_2x.png │ ├── rotated_drop_shadow_filter_gl.png │ ├── rotated_drop_shadow_filter_sw.png │ ├── rotated_filter_gl.png │ ├── rotated_filter_sw.png │ ├── scaled_render_surface_layer_gl.png │ ├── scaled_render_surface_layer_sw.png │ ├── spiral.png │ ├── spiral_64_scale.png │ ├── spiral_double_scale.png │ ├── white.png │ ├── wrap_mode_repeat.png │ ├── yuv_stripes.png │ ├── yuv_stripes_alpha.png │ ├── yuv_stripes_clipped.png │ ├── yuv_stripes_offset.png │ ├── zoom_filter_gl.png │ └── zoom_filter_sw.png │ └── single_seed │ └── seed.png └── libFuzzer └── Fuzzer ├── CMakeLists.txt ├── FuzzerBuiltins.h ├── FuzzerBuiltinsMsvc.h ├── FuzzerCommand.h ├── FuzzerCorpus.h ├── FuzzerCrossOver.cpp ├── FuzzerDataFlowTrace.cpp ├── FuzzerDataFlowTrace.h ├── FuzzerDefs.h ├── FuzzerDictionary.h ├── FuzzerDriver.cpp ├── FuzzerExtFunctions.def ├── FuzzerExtFunctions.h ├── FuzzerExtFunctionsDlsym.cpp ├── FuzzerExtFunctionsWeak.cpp ├── FuzzerExtFunctionsWindows.cpp ├── FuzzerExtraCounters.cpp ├── FuzzerFlags.def ├── FuzzerFork.cpp ├── FuzzerFork.h ├── FuzzerIO.cpp ├── FuzzerIO.h ├── FuzzerIOPosix.cpp ├── FuzzerIOWindows.cpp ├── FuzzerInterface.h ├── FuzzerInternal.h ├── FuzzerLoop.cpp ├── FuzzerMain.cpp ├── FuzzerMerge.cpp ├── FuzzerMerge.h ├── FuzzerMutate.cpp ├── FuzzerMutate.h ├── FuzzerOptions.h ├── FuzzerRandom.h ├── FuzzerSHA1.cpp ├── FuzzerSHA1.h ├── FuzzerTracePC.cpp ├── FuzzerTracePC.h ├── FuzzerUtil.cpp ├── FuzzerUtil.h ├── FuzzerUtilDarwin.cpp ├── FuzzerUtilFuchsia.cpp ├── FuzzerUtilLinux.cpp ├── FuzzerUtilPosix.cpp ├── FuzzerUtilWindows.cpp ├── FuzzerValueBitMap.h ├── README.txt ├── afl └── afl_driver.cpp ├── build.sh ├── dataflow ├── DataFlow.cpp ├── DataFlow.h └── DataFlowCallbacks.cpp ├── scripts └── unbalanced_allocs.py ├── standalone └── StandaloneFuzzTargetMain.c └── tests ├── CMakeLists.txt ├── FuzzedDataProviderUnittest.cpp └── FuzzerUnittest.cpp /.gitignore: -------------------------------------------------------------------------------- 1 | # My local notes 2 | plan.txt 3 | 4 | # Work directories. 5 | work 6 | 7 | # libFuzzer library. Should be built during the workshop. 8 | libFuzzer.a 9 | 10 | # clang and other binaries. 11 | bin/ 12 | 13 | # corpus directories. 14 | corpus* 15 | 16 | # crash testcases 17 | crash* 18 | 19 | # fuzzers binaries. 20 | *_fuzzer 21 | 22 | # openssl sources after unpacking. 23 | openssl1.0.1f 24 | 25 | # c-ares sources after unpacking. 26 | c-ares 27 | 28 | # libxml2 sources after unpacking. 29 | libxml2 30 | 31 | # coverage files. 32 | *sancov 33 | *symcov 34 | 35 | # oom crashes. 36 | oom-* 37 | 38 | # libpng sources after unpacking. 39 | libpng 40 | 41 | # timeout crashes. 42 | timeout-* 43 | 44 | # re2 sources after unpacking. 45 | re2 46 | 47 | # pcre2 sources after unpacking. 48 | pcre2 49 | pcre2-10.00 -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # libfuzzer-workshop 2 | Materials of *"Modern fuzzing of C/C++ Projects"* workshop. 3 | 4 | The first version of the workshop had been presented at [ZeroNights'16] security 5 | conference. 6 | 7 | ## Disclaimer 8 | 9 | This workshop was originally developed in 2016. As of today (2021 and beyond), 10 | the practical side of the workshop might be not working right away, because 11 | libFuzzer greatly evolved over the years. The theoretical part of the workshop 12 | is a good learning material still, but for the practical lessons it is 13 | recommended to follow the most recent version of the [libFuzzer tutorial]. 14 | 15 | ## Requirements 16 | 17 | * 2-3 hours of your time 18 | * Linux-based OS 19 | * C/C++ experience (nothing special, but you need to be able to read, write and 20 | compile C/C++ code) 21 | * a recent version of **clang** compiler. Distributions from 22 | package managers are too old and most likely won't work (the workshop 23 | called "modern", right?), you have two options: 24 | * checkout **llvm** repository and build it yourself. To make it easy, 25 | feel free to use [checkout_build_install_llvm.sh] script, it has been 26 | tested on clean Ubuntu 16.04 27 | * a [VirtualBox VM] with working environment is available, credentials: 28 | `fuzzer:zeronights` 29 | * `sudo apt-get install -y make autoconf automake libtool pkg-config zlib1g-dev` 30 | 31 | 32 | Fuzzing experience is not required. 33 | 34 | ## Contents 35 | 1. An introduction to fuzz testing 36 | 2. An example of traditional fuzzing 37 | 3. Coverage-guided fuzzing 38 | 4. Writing fuzzers (simple examples) 39 | 5. Finding Heartbleed (CVE-2014-0160) 40 | 6. Finding c-ares $100,000 bug (CVE-2016-5180) 41 | 7. How to improve your fuzzer 42 | 8. Fuzzing libxml2, learning how to improve the fuzzer and analyze performance 43 | 9. Fuzzing libpng, learning an importance of seed corpus and other stuff 44 | 10. Fuzzing re2 45 | 11. Fuzzing pcre2 46 | 12. Chromium integration & homework assignment 47 | 48 | 49 | Most of the examples have been taken from [libFuzzer tutorial] and 50 | [Fuzzer Test Suite]. 51 | 52 | ## Prerequisites 53 | 54 | ### libFuzzer 55 | Building libFuzzer is extreemly easy: 56 | ```bash 57 | cd libFuzzer 58 | Fuzzer/build.sh 59 | ``` 60 | 61 | libFuzzer repository could be found inside LLVM's compiler-rt project. 62 | 63 | 64 | ## Links 65 | 66 | * all slides in a single presentation: [Modern Fuzzing of C/C++ Projects](https://docs.google.com/presentation/d/1pbbXRL7HaNSjyCHWgGkbpNotJuiC4O7L_PDZoGqDf5Q/edit?usp=sharing) 67 | * libFuzzer documentation: [http://libfuzzer.info](http://libfuzzer.info) 68 | * libFuzzer tutorial: [http://tutorial.libfuzzer.info](http://tutorial.libfuzzer.info) 69 | * Google Online Security Blog: [Guided in-process fuzzing of Chrome components](https://security.googleblog.com/2016/08/guided-in-process-fuzzing-of-chrome.html) 70 | 71 | 72 | 73 | [Fuzzer Test Suite]: https://github.com/google/fuzzer-test-suite 74 | [VirtualBox VM]: https://drive.google.com/file/d/0B19rvTqcOBfTZHZseDk3ZkNjWHc/view?usp=sharing 75 | [ZeroNights'16]: https://2016.zeronights.org/program/workshops/#ws1 76 | [checkout_build_install_llvm.sh]: checkout_build_install_llvm.sh 77 | [libFuzzer tutorial]: http://tutorial.libfuzzer.info 78 | -------------------------------------------------------------------------------- /checkout_build_install_llvm.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash -eux 2 | # Copyright 2016 Google Inc. 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | # 16 | ################################################################################ 17 | 18 | sudo apt-get update 19 | sudo apt-get upgrade -y 20 | sudo apt-get autoremove -y 21 | 22 | sudo apt-get install -y libc6-dev binutils libgcc-5-dev 23 | 24 | LLVM_DEP_PACKAGES="build-essential make cmake ninja-build git python2.7" 25 | sudo apt-get install -y $LLVM_DEP_PACKAGES 26 | 27 | WORK_DIR=$PWD 28 | mkdir -p $WORK_DIR/src 29 | 30 | # Checkout 31 | cd $WORK_DIR/src && git clone --depth 1 http://llvm.org/git/llvm.git 32 | cd $WORK_DIR/src/llvm/tools && git clone --depth 1 http://llvm.org/git/clang.git 33 | cd $WORK_DIR/src/llvm/projects && git clone --depth 1 http://llvm.org/git/compiler-rt.git 34 | cd $WORK_DIR/src/llvm/projects && git clone --depth 1 http://llvm.org/git/libcxx.git 35 | cd $WORK_DIR/src/llvm/projects && git clone --depth 1 http://llvm.org/git/libcxxabi.git 36 | 37 | # Uncomment if you want *fresh* libFuzzer from checkouted repository. 38 | #rm -r $WORK_DIR/libFuzzer/Fuzzer 39 | #cp -r $WORK_DIR/src/llvm/projects/compiler-rt/lib/fuzzer/ $WORK_DIR/libFuzzer/Fuzzer 40 | 41 | # Build & Install 42 | mkdir -p $WORK_DIR/work/llvm 43 | cd $WORK_DIR/work/llvm 44 | 45 | # Consider adding of -DCMAKE_INSTALL_PREFIX=%PATH% flag, if you do not want to 46 | # install fresh llvm binaries into standard system paths. 47 | cmake -G "Ninja" \ 48 | -DLIBCXX_ENABLE_SHARED=OFF -DLIBCXX_ENABLE_STATIC_ABI_LIBRARY=ON \ 49 | -DCMAKE_BUILD_TYPE=Release -DLLVM_TARGETS_TO_BUILD="X86" \ 50 | $WORK_DIR/src/llvm 51 | ninja -j$(nproc) 52 | sudo ninja install 53 | rm -rf $WORK_DIR/work/llvm 54 | 55 | 56 | -------------------------------------------------------------------------------- /lessons/01/Modern_Fuzzing_of_C_C++_projects_slides_1-23.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dor1s/libfuzzer-workshop/35dd05ed4edce6b80a296d8d6b4579becec4d824/lessons/01/Modern_Fuzzing_of_C_C++_projects_slides_1-23.pdf -------------------------------------------------------------------------------- /lessons/01/README.md: -------------------------------------------------------------------------------- 1 | # Lesson 01 2 | 3 | This is a theorethical introduction, see the slides. 4 | -------------------------------------------------------------------------------- /lessons/02/README.md: -------------------------------------------------------------------------------- 1 | # Lesson 02 2 | 3 | ## Traditional out-of-process fuzzing 4 | 5 | **Target**: [pdfium] 6 | 7 | **Mutation engine**: [radamsa] 8 | 9 | **Seed corpus**: collected from previous [PDFium bugs] 10 | 11 | 12 | ## Instruction 13 | 14 | Take a look at [generate_testcases.py](generate_testcases.py) scripts. Then use 15 | `radamsa` to generate testcases from `seed_corpus`: 16 | ```bash 17 | cd lessons/02 18 | ./generate_testcases.py 19 | ``` 20 | 21 | Verify number of files generated: 22 | ```bash 23 | ls work/corpus/ | wc -l 24 | 1000 25 | ``` 26 | 27 | Take a look at [run_fuzzing.py](run_fuzzing.py) script. Then run fuzzing: 28 | ```bash 29 | tar xzf bin/asan.tgz 30 | ./run_fuzzing.py 31 | ``` 32 | 33 | If you don't see any output, no crash has been found. Feel free to re-generate 34 | testcases many more times. Though it should take for a while to find a crash. 35 | 36 | 37 | [pdfium]: https://pdfium.googlesource.com/pdfium/ 38 | [radamsa]: https://github.com/aoh/radamsa 39 | [PDFium bugs]: https://bugs.chromium.org/p/chromium/issues/list?can=1&q=Type%3DBug-Security+component%3AInternals%3EPlugins%3EPDF+label%3Aallpublic+opened%3E2015-04-09&colspec=ID+Pri+M+Stars+ReleaseBlock+Component+Status+Owner+Summary+OS+Modified&x=m&y=releaseblock&cells=ids 40 | -------------------------------------------------------------------------------- /lessons/02/bin/asan.tgz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dor1s/libfuzzer-workshop/35dd05ed4edce6b80a296d8d6b4579becec4d824/lessons/02/bin/asan.tgz -------------------------------------------------------------------------------- /lessons/02/bin/radamsa: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dor1s/libfuzzer-workshop/35dd05ed4edce6b80a296d8d6b4579becec4d824/lessons/02/bin/radamsa -------------------------------------------------------------------------------- /lessons/02/generate_testcases.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python2 2 | import os 3 | import random 4 | 5 | WORK_DIR = 'work' 6 | 7 | # Create work `directory` and `corpus` subdirectory. 8 | if not os.path.exists(WORK_DIR): 9 | os.mkdir(WORK_DIR) 10 | 11 | corpus_dir = os.path.join(WORK_DIR, 'corpus') 12 | if not os.path.exists(corpus_dir): 13 | os.mkdir(corpus_dir) 14 | 15 | seed_corpus_filenames = os.listdir('seed_corpus') 16 | 17 | for i in xrange(1000): 18 | random_seed_filename = random.choice(seed_corpus_filenames) 19 | random_seed_filename = os.path.join('seed_corpus', random_seed_filename) 20 | output_filename = os.path.join(WORK_DIR, 'corpus', 'testcase-%06d' % i) 21 | cmd = 'bin/radamsa "%s" > "%s"' % (random_seed_filename, output_filename) 22 | os.popen(cmd) 23 | 24 | -------------------------------------------------------------------------------- /lessons/02/run_fuzzing.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python2 2 | import os 3 | import subprocess 4 | 5 | WORK_DIR = 'work' 6 | 7 | def checkOutput(s): 8 | if 'Segmentation fault' in s or 'error' in s.lower(): 9 | return False 10 | else: 11 | return True 12 | 13 | corpus_dir = os.path.join(WORK_DIR, 'corpus') 14 | corpus_filenames = os.listdir(corpus_dir) 15 | 16 | for f in corpus_filenames: 17 | testcase_path = os.path.join(corpus_dir, f) 18 | cmd = ['bin/asan/pdfium_test', testcase_path] 19 | process = subprocess.Popen(cmd, stdin=subprocess.PIPE, stdout=subprocess.PIPE, 20 | stderr=subprocess.STDOUT) 21 | output = process.communicate()[0] 22 | if not checkOutput(output): 23 | print testcase_path 24 | print output 25 | print '-' * 80 26 | -------------------------------------------------------------------------------- /lessons/02/seed_corpus/TALOS-CAN-0174 - Google Chrome PDFium jpeg2000 SIZ Code Execution Vulnerability_POC.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dor1s/libfuzzer-workshop/35dd05ed4edce6b80a296d8d6b4579becec4d824/lessons/02/seed_corpus/TALOS-CAN-0174 - Google Chrome PDFium jpeg2000 SIZ Code Execution Vulnerability_POC.pdf -------------------------------------------------------------------------------- /lessons/02/seed_corpus/a.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dor1s/libfuzzer-workshop/35dd05ed4edce6b80a296d8d6b4579becec4d824/lessons/02/seed_corpus/a.pdf -------------------------------------------------------------------------------- /lessons/02/seed_corpus/b.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dor1s/libfuzzer-workshop/35dd05ed4edce6b80a296d8d6b4579becec4d824/lessons/02/seed_corpus/b.pdf -------------------------------------------------------------------------------- /lessons/02/seed_corpus/chromeUrls.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dor1s/libfuzzer-workshop/35dd05ed4edce6b80a296d8d6b4579becec4d824/lessons/02/seed_corpus/chromeUrls.pdf -------------------------------------------------------------------------------- /lessons/02/seed_corpus/cr.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dor1s/libfuzzer-workshop/35dd05ed4edce6b80a296d8d6b4579becec4d824/lessons/02/seed_corpus/cr.pdf -------------------------------------------------------------------------------- /lessons/02/seed_corpus/formsubmit.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dor1s/libfuzzer-workshop/35dd05ed4edce6b80a296d8d6b4579becec4d824/lessons/02/seed_corpus/formsubmit.pdf -------------------------------------------------------------------------------- /lessons/02/seed_corpus/global-buffer-overflow-61f-ada-9ec.pdf: -------------------------------------------------------------------------------- 1 | %PDF 2 | 2 0 obj<>6 0 obj<>/Subtype/Widget/T(F)/BS<> [>>33 0 obj<>138 0 obj< 3 | trailer<> -------------------------------------------------------------------------------- /lessons/02/seed_corpus/global-buffer-overflow.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dor1s/libfuzzer-workshop/35dd05ed4edce6b80a296d8d6b4579becec4d824/lessons/02/seed_corpus/global-buffer-overflow.pdf -------------------------------------------------------------------------------- /lessons/02/seed_corpus/heap-buffer-overflow-b19-c75-64e.pdf: -------------------------------------------------------------------------------- 1 | %PDF 2 | 24 0 obj<>27 0 obj<>/FT/Tx/Kids[30 0 R]/) 3 | /T(q)29 0 obj<>30 0 obj<<) 4 | /Subtype/Widget 0/AA<>/Annots 276 0 R/Resources<>>>/Contents 281 0 R>>289 0 obj<>290 0 obj<>292 0 obj<>/T(t)/FT/Tx>>293 0 obj<>/FT/Tx/Subtype/Widget/V(1)/T(2)endobj 294 0 obj<>/T(l)/AP<<>>/FT/Tx>>298 0 obj<>/T( )/FT/Tx>>299 0 obj<>/T(0)/FT/Tx()()<>>//>>303 0 obj<>/T(pp7)/V(.1)/FT/Tx 5 | endobj 311 0 obj<>/T(7)/FT/Tx>>275 0 obj<>276 0 obj[311 0 R 292 0 R 26 0 R 30 0 R 298 0 R 299 0 R 30 0 R 303 0 R 294 0 R 293 0 R j 278 0 obj<>281 0 obj<<>>stream /F1 1 Tf 6 | endstream 361 0 obj<>362 0 obj<>322 0 obj<>336 0 obj<>337 0 obj<>338 0 obj<>342 0 obj<327 0 obj<>324 0 obj< 8 | trailer<> -------------------------------------------------------------------------------- /lessons/02/seed_corpus/heap-use-after-free-8d2-641-d6d.pdf: -------------------------------------------------------------------------------- 1 | %PDF 2 | 35 0 obj<>3 0 obj<>/T(p)/FT/Tx>>311 0 obj<>/T(7)/FT/Tx>>276 0 obj[3 0 R 311 0 R b 361 0 obj<> -------------------------------------------------------------------------------- /lessons/02/seed_corpus/jbig2-overflow-4.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dor1s/libfuzzer-workshop/35dd05ed4edce6b80a296d8d6b4579becec4d824/lessons/02/seed_corpus/jbig2-overflow-4.pdf -------------------------------------------------------------------------------- /lessons/02/seed_corpus/pageviewtest.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dor1s/libfuzzer-workshop/35dd05ed4edce6b80a296d8d6b4579becec4d824/lessons/02/seed_corpus/pageviewtest.pdf -------------------------------------------------------------------------------- /lessons/02/seed_corpus/pdf_crash.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dor1s/libfuzzer-workshop/35dd05ed4edce6b80a296d8d6b4579becec4d824/lessons/02/seed_corpus/pdf_crash.pdf -------------------------------------------------------------------------------- /lessons/02/seed_corpus/pdf_crash1.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dor1s/libfuzzer-workshop/35dd05ed4edce6b80a296d8d6b4579becec4d824/lessons/02/seed_corpus/pdf_crash1.pdf -------------------------------------------------------------------------------- /lessons/02/seed_corpus/pdfium-parseSymbolDict-Overflow.pdf: -------------------------------------------------------------------------------- 1 | %PDF 2 | 1 0 obj 3 | << /Pages 3 0 R >> 4 | endobj 5 | 6 | 3 0 obj 7 | << /Kids [8 0 R] >> 8 | endobj 9 | 10 | 5 0 obj 11 | << 12 | /Width 1 13 | /Height 1 14 | /Filter /JBIG2Decode 15 | /Subtype /Image 16 | >> 17 | stream 18 | F(GF(G0ÿýÿþþþ ïFG&) $0G&$ žpå?ÿ 19 | endstream 20 | endobj 21 | 22 | 6 0 obj 23 | <<>> 24 | stream 25 | q 1920.000000 1080.000000 0 0 cm /Im1 Do 26 | endstream 27 | endobj 28 | 29 | 7 0 obj 30 | << /XObject << /Im1 5 0 R >> >> 31 | endobj 32 | 33 | 8 0 obj 34 | << 35 | /Contents 6 0 R 36 | /Resources 7 0 R 37 | >> 38 | endobj 39 | trailer << /Root 1 0 R >> 40 | -------------------------------------------------------------------------------- /lessons/02/seed_corpus/poc (1).pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dor1s/libfuzzer-workshop/35dd05ed4edce6b80a296d8d6b4579becec4d824/lessons/02/seed_corpus/poc (1).pdf -------------------------------------------------------------------------------- /lessons/02/seed_corpus/poc.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dor1s/libfuzzer-workshop/35dd05ed4edce6b80a296d8d6b4579becec4d824/lessons/02/seed_corpus/poc.pdf -------------------------------------------------------------------------------- /lessons/02/seed_corpus/poc_1.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dor1s/libfuzzer-workshop/35dd05ed4edce6b80a296d8d6b4579becec4d824/lessons/02/seed_corpus/poc_1.pdf -------------------------------------------------------------------------------- /lessons/02/seed_corpus/poc_2.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dor1s/libfuzzer-workshop/35dd05ed4edce6b80a296d8d6b4579becec4d824/lessons/02/seed_corpus/poc_2.pdf -------------------------------------------------------------------------------- /lessons/02/seed_corpus/poc_3.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dor1s/libfuzzer-workshop/35dd05ed4edce6b80a296d8d6b4579becec4d824/lessons/02/seed_corpus/poc_3.pdf -------------------------------------------------------------------------------- /lessons/02/seed_corpus/poc_32bit.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dor1s/libfuzzer-workshop/35dd05ed4edce6b80a296d8d6b4579becec4d824/lessons/02/seed_corpus/poc_32bit.pdf -------------------------------------------------------------------------------- /lessons/02/seed_corpus/poc_64bit.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dor1s/libfuzzer-workshop/35dd05ed4edce6b80a296d8d6b4579becec4d824/lessons/02/seed_corpus/poc_64bit.pdf -------------------------------------------------------------------------------- /lessons/02/seed_corpus/poc_stable.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dor1s/libfuzzer-workshop/35dd05ed4edce6b80a296d8d6b4579becec4d824/lessons/02/seed_corpus/poc_stable.pdf -------------------------------------------------------------------------------- /lessons/02/seed_corpus/poc_tot.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dor1s/libfuzzer-workshop/35dd05ed4edce6b80a296d8d6b4579becec4d824/lessons/02/seed_corpus/poc_tot.pdf -------------------------------------------------------------------------------- /lessons/02/seed_corpus/pocxx.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dor1s/libfuzzer-workshop/35dd05ed4edce6b80a296d8d6b4579becec4d824/lessons/02/seed_corpus/pocxx.pdf -------------------------------------------------------------------------------- /lessons/02/seed_corpus/repro (1).pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dor1s/libfuzzer-workshop/35dd05ed4edce6b80a296d8d6b4579becec4d824/lessons/02/seed_corpus/repro (1).pdf -------------------------------------------------------------------------------- /lessons/02/seed_corpus/repro (2).pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dor1s/libfuzzer-workshop/35dd05ed4edce6b80a296d8d6b4579becec4d824/lessons/02/seed_corpus/repro (2).pdf -------------------------------------------------------------------------------- /lessons/02/seed_corpus/repro.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dor1s/libfuzzer-workshop/35dd05ed4edce6b80a296d8d6b4579becec4d824/lessons/02/seed_corpus/repro.pdf -------------------------------------------------------------------------------- /lessons/02/seed_corpus/soiax0001_repro.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dor1s/libfuzzer-workshop/35dd05ed4edce6b80a296d8d6b4579becec4d824/lessons/02/seed_corpus/soiax0001_repro.pdf -------------------------------------------------------------------------------- /lessons/02/seed_corpus/test (1).pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dor1s/libfuzzer-workshop/35dd05ed4edce6b80a296d8d6b4579becec4d824/lessons/02/seed_corpus/test (1).pdf -------------------------------------------------------------------------------- /lessons/02/seed_corpus/test (2).pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dor1s/libfuzzer-workshop/35dd05ed4edce6b80a296d8d6b4579becec4d824/lessons/02/seed_corpus/test (2).pdf -------------------------------------------------------------------------------- /lessons/02/seed_corpus/test.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dor1s/libfuzzer-workshop/35dd05ed4edce6b80a296d8d6b4579becec4d824/lessons/02/seed_corpus/test.pdf -------------------------------------------------------------------------------- /lessons/02/seed_corpus/testcase (1).pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dor1s/libfuzzer-workshop/35dd05ed4edce6b80a296d8d6b4579becec4d824/lessons/02/seed_corpus/testcase (1).pdf -------------------------------------------------------------------------------- /lessons/02/seed_corpus/testcase.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dor1s/libfuzzer-workshop/35dd05ed4edce6b80a296d8d6b4579becec4d824/lessons/02/seed_corpus/testcase.pdf -------------------------------------------------------------------------------- /lessons/02/seed_corpus/testcase_focus.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dor1s/libfuzzer-workshop/35dd05ed4edce6b80a296d8d6b4579becec4d824/lessons/02/seed_corpus/testcase_focus.pdf -------------------------------------------------------------------------------- /lessons/02/seed_corpus/uaf_2.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dor1s/libfuzzer-workshop/35dd05ed4edce6b80a296d8d6b4579becec4d824/lessons/02/seed_corpus/uaf_2.pdf -------------------------------------------------------------------------------- /lessons/02/seed_corpus/xxx.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dor1s/libfuzzer-workshop/35dd05ed4edce6b80a296d8d6b4579becec4d824/lessons/02/seed_corpus/xxx.pdf -------------------------------------------------------------------------------- /lessons/02/seed_corpus/xxx2.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dor1s/libfuzzer-workshop/35dd05ed4edce6b80a296d8d6b4579becec4d824/lessons/02/seed_corpus/xxx2.pdf -------------------------------------------------------------------------------- /lessons/03/Modern_Fuzzing_of_C_C++_projects_slides_24-39.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dor1s/libfuzzer-workshop/35dd05ed4edce6b80a296d8d6b4579becec4d824/lessons/03/Modern_Fuzzing_of_C_C++_projects_slides_24-39.pdf -------------------------------------------------------------------------------- /lessons/03/README.md: -------------------------------------------------------------------------------- 1 | # Lesson 03 2 | 3 | This is a theorethical lesson, see the slides. 4 | -------------------------------------------------------------------------------- /lessons/04/first_fuzzer.cc: -------------------------------------------------------------------------------- 1 | // Copyright 2016 Google Inc. All Rights Reserved. 2 | // Licensed under the Apache License, Version 2.0 (the "License"); 3 | 4 | #include 5 | #include 6 | 7 | #include "vulnerable_functions.h" 8 | 9 | extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { 10 | VulnerableFunction1(data, size); 11 | return 0; 12 | } 13 | -------------------------------------------------------------------------------- /lessons/04/fourth_fuzzer.cc: -------------------------------------------------------------------------------- 1 | // Copyright 2016 Google Inc. All Rights Reserved. 2 | // Licensed under the Apache License, Version 2.0 (the "License"); 3 | 4 | #include 5 | #include 6 | 7 | #include "vulnerable_functions.h" 8 | 9 | #include 10 | #include 11 | 12 | extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { 13 | std::string data_string(reinterpret_cast(data), size); 14 | auto data_hash = std::hash()(data_string); 15 | 16 | std::size_t flags = static_cast(data_hash); 17 | VulnerableFunction3(data, size, flags); 18 | return 0; 19 | } 20 | -------------------------------------------------------------------------------- /lessons/04/second_fuzzer.cc: -------------------------------------------------------------------------------- 1 | // Copyright 2016 Google Inc. All Rights Reserved. 2 | // Licensed under the Apache License, Version 2.0 (the "License"); 3 | 4 | #include 5 | #include 6 | 7 | #include "vulnerable_functions.h" 8 | 9 | extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { 10 | VulnerableFunction2(data, size, false); 11 | return 0; 12 | } 13 | -------------------------------------------------------------------------------- /lessons/04/third_fuzzer.cc: -------------------------------------------------------------------------------- 1 | // Copyright 2016 Google Inc. All Rights Reserved. 2 | // Licensed under the Apache License, Version 2.0 (the "License"); 3 | 4 | #include 5 | #include 6 | 7 | #include "vulnerable_functions.h" 8 | 9 | extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { 10 | bool verify_hash_flags[] = { false, true }; 11 | 12 | for (auto flag : verify_hash_flags) 13 | VulnerableFunction2(data, size, flag); 14 | return 0; 15 | } 16 | -------------------------------------------------------------------------------- /lessons/04/vulnerable_functions.h: -------------------------------------------------------------------------------- 1 | // Copyright 2016 Google Inc. All Rights Reserved. 2 | // Licensed under the Apache License, Version 2.0 (the "License"); 3 | 4 | #ifndef LESSONS_04_VULNERABLE_FUNCTIONS_H_ 5 | #define LESSONS_04_VULNERABLE_FUNCTIONS_H_ 6 | 7 | #include 8 | #include 9 | #include 10 | 11 | #include 12 | #include 13 | #include 14 | 15 | 16 | bool VulnerableFunction1(const uint8_t* data, size_t size) { 17 | bool result = false; 18 | if (size >= 3) { 19 | result = data[0] == 'F' && 20 | data[1] == 'U' && 21 | data[2] == 'Z' && 22 | data[3] == 'Z'; 23 | } 24 | 25 | return result; 26 | } 27 | 28 | 29 | template 30 | typename T::value_type DummyHash(const T& buffer) { 31 | typename T::value_type hash = 0; 32 | for (auto value : buffer) 33 | hash ^= value; 34 | 35 | return hash; 36 | } 37 | 38 | constexpr auto kMagicHeader = "ZN_2016"; 39 | constexpr std::size_t kMaxPacketLen = 1024; 40 | constexpr std::size_t kMaxBodyLength = 1024 - sizeof(kMagicHeader); 41 | 42 | bool VulnerableFunction2(const uint8_t* data, size_t size, bool verify_hash) { 43 | if (size < sizeof(kMagicHeader)) 44 | return false; 45 | 46 | std::string header(reinterpret_cast(data), sizeof(kMagicHeader)); 47 | 48 | std::array body; 49 | 50 | if (strcmp(kMagicHeader, header.c_str())) 51 | return false; 52 | 53 | auto target_hash = data[--size]; 54 | 55 | if (size > kMaxPacketLen) 56 | return false; 57 | 58 | if (!verify_hash) 59 | return true; 60 | 61 | std::copy(data, data + size, body.data()); 62 | auto real_hash = DummyHash(body); 63 | return real_hash == target_hash; 64 | } 65 | 66 | 67 | constexpr std::size_t kZn2016VerifyHashFlag = 0x0001000; 68 | 69 | bool VulnerableFunction3(const uint8_t* data, size_t size, std::size_t flags) { 70 | bool verify_hash = flags & kZn2016VerifyHashFlag; 71 | return VulnerableFunction2(data, size, verify_hash); 72 | } 73 | 74 | 75 | #endif // LESSONS_04_VULNERABLE_FUNCTIONS_H_ 76 | -------------------------------------------------------------------------------- /lessons/05/README.md: -------------------------------------------------------------------------------- 1 | # Lesson 05 2 | 3 | Here we will find Heartbleed vulnerability (CVE-2014-0160). 4 | 5 | *** 6 | This example has been taken from [google/fuzzer-stest-suite] repository. 7 | *** 8 | 9 | 10 | ### Build vulnerable openssl version 11 | 12 | ```bash 13 | tar xzf openssl1.0.1f.tgz 14 | cd openssl1.0.1f/ 15 | 16 | ./config 17 | make clean 18 | make CC="clang -O2 -fno-omit-frame-pointer -g -fsanitize=address,fuzzer-no-link -fsanitize-coverage=trace-cmp,trace-gep,trace-div" -j$(nproc) 19 | ``` 20 | 21 | ### Build and run the fuzzer 22 | 23 | Take a look into the fuzzer: 24 | 25 | ```c 26 | // Copyright 2016 Google Inc. All Rights Reserved. 27 | // Licensed under the Apache License, Version 2.0 (the "License"); 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | 34 | #ifndef CERT_PATH 35 | # define CERT_PATH 36 | #endif 37 | 38 | SSL_CTX *Init() { 39 | SSL_library_init(); 40 | SSL_load_error_strings(); 41 | ERR_load_BIO_strings(); 42 | OpenSSL_add_all_algorithms(); 43 | SSL_CTX *sctx; 44 | assert (sctx = SSL_CTX_new(TLSv1_method())); 45 | /* These two file were created with this command: 46 | openssl req -x509 -newkey rsa:512 -keyout server.key \ 47 | -out server.pem -days 9999 -nodes -subj /CN=a/ 48 | */ 49 | assert(SSL_CTX_use_certificate_file(sctx, CERT_PATH "server.pem", 50 | SSL_FILETYPE_PEM)); 51 | assert(SSL_CTX_use_PrivateKey_file(sctx, CERT_PATH "server.key", 52 | SSL_FILETYPE_PEM)); 53 | return sctx; 54 | } 55 | 56 | extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { 57 | static SSL_CTX *sctx = Init(); 58 | SSL *server = SSL_new(sctx); 59 | BIO *sinbio = BIO_new(BIO_s_mem()); 60 | BIO *soutbio = BIO_new(BIO_s_mem()); 61 | SSL_set_bio(server, sinbio, soutbio); 62 | SSL_set_accept_state(server); 63 | BIO_write(sinbio, Data, Size); 64 | SSL_do_handshake(server); 65 | SSL_free(server); 66 | return 0; 67 | } 68 | ``` 69 | 70 | Build the fuzzer: 71 | 72 | ```bash 73 | cd .. 74 | clang++ -g openssl_fuzzer.cc -O2 -fno-omit-frame-pointer -fsanitize=address,fuzzer \ 75 | -fsanitize-coverage=trace-cmp,trace-gep,trace-div \ 76 | -Iopenssl1.0.1f/include openssl1.0.1f/libssl.a openssl1.0.1f/libcrypto.a \ 77 | -o openssl_fuzzer 78 | ``` 79 | 80 | Run the fuzzer: 81 | 82 | ```bash 83 | mkdir corpus1 84 | ./openssl_fuzzer ./corpus1/ 85 | ``` 86 | 87 | After some time: 88 | 89 | ``` 90 | INFO: Seed: 3620533608 91 | INFO: Loaded 1 modules (88608 guards): [0xcad4c0, 0xd03d40), 92 | Loading corpus dir: ./corpus1/ 93 | INFO: -max_len is not provided, using 64 94 | INFO: A corpus is not provided, starting from an empty corpus 95 | #0 READ units: 1 96 | #1 INITED cov: 1473 ft: 385 corp: 1/1b exec/s: 0 rss: 31Mb 97 | #2 NEW cov: 1479 ft: 414 corp: 2/36b exec/s: 0 rss: 31Mb L: 35 MS: 1 InsertRepeatedBytes- 98 | #111 NEW cov: 1479 ft: 417 corp: 3/79b exec/s: 0 rss: 36Mb L: 43 MS: 5 ShuffleBytes-CrossOver-CMP-EraseBytes-EraseBytes- DE: "\x00\x00"- 99 | #2256 NEW cov: 1490 ft: 439 corp: 4/128b exec/s: 0 rss: 127Mb L: 49 MS: 5 PersAutoDict-ChangeBit-ChangeBinInt-ChangeBinInt-InsertRepeatedBytes- DE: "\x00\x00"- 100 | 101 | <...> 102 | 103 | #120643 NEW cov: 1563 ft: 721 corp: 37/1736b exec/s: 24128 rss: 373Mb L: 46 MS: 2 CopyPart-CMP- DE: "\x00\x00\x00\x00\x00\x00\x00v"- 104 | #121008 NEW cov: 1565 ft: 723 corp: 38/1758b exec/s: 24201 rss: 373Mb L: 22 MS: 2 ChangeBinInt-EraseBytes- 105 | ================================================================= 106 | ==32104==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x629000009748 at pc 0x0000004aad87 bp 0x7fff9266d020 sp 0x7fff9266c7d0 107 | READ of size 25344 at 0x629000009748 thread T0 108 | #0 0x4aad86 in __asan_memcpy (/usr/local/google/home/mmoroz/Projects/libfuzzer-workshop/lessons/HB/openssl_fuzzer+0x4aad86) 109 | #1 0x4ff232 in tls1_process_heartbeat /usr/local/google/home/mmoroz/Projects/libfuzzer-workshop/lessons/HB/openssl1.0.1f/ssl/t1_lib.c:2586:3 110 | #2 0x580be0 in ssl3_read_bytes /usr/local/google/home/mmoroz/Projects/libfuzzer-workshop/lessons/HB/openssl1.0.1f/ssl/s3_pkt.c:1092:4 111 | #3 0x585c37 in ssl3_get_message /usr/local/google/home/mmoroz/Projects/libfuzzer-workshop/lessons/HB/openssl1.0.1f/ssl/s3_both.c:457:7 112 | #4 0x548a54 in ssl3_get_client_hello /usr/local/google/home/mmoroz/Projects/libfuzzer-workshop/lessons/HB/openssl1.0.1f/ssl/s3_srvr.c:941:4 113 | #5 0x544a4e in ssl3_accept /usr/local/google/home/mmoroz/Projects/libfuzzer-workshop/lessons/HB/openssl1.0.1f/ssl/s3_srvr.c:357:9 114 | #6 0x4f0d42 in LLVMFuzzerTestOneInput /usr/local/google/home/mmoroz/Projects/libfuzzer-workshop/lessons/HB/openssl_fuzzer.cc:39:3 115 | <...> 116 | ``` 117 | 118 | **READ** of size **25344** due to **heap-buffer-overflow** in 119 | `tls1_process_heartbeat` function. Here it is. One of the scariest 120 | vulnerabilities can be found in a few minutes. Fuzzing is awesome. 121 | 122 | 123 | [Heartbleed]: https://en.wikipedia.org/wiki/Heartbleed 124 | [google/fuzzer-stest-suite]: https://github.com/google/fuzzer-test-suite/blob/master/tutorial/libFuzzerTutorial.md#heartbleed 125 | -------------------------------------------------------------------------------- /lessons/05/openssl1.0.1f.tgz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dor1s/libfuzzer-workshop/35dd05ed4edce6b80a296d8d6b4579becec4d824/lessons/05/openssl1.0.1f.tgz -------------------------------------------------------------------------------- /lessons/05/openssl_fuzzer.cc: -------------------------------------------------------------------------------- 1 | // Copyright 2016 Google Inc. All Rights Reserved. 2 | // Licensed under the Apache License, Version 2.0 (the "License"); 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #ifndef CERT_PATH 10 | # define CERT_PATH 11 | #endif 12 | 13 | SSL_CTX *Init() { 14 | SSL_library_init(); 15 | SSL_load_error_strings(); 16 | ERR_load_BIO_strings(); 17 | OpenSSL_add_all_algorithms(); 18 | SSL_CTX *sctx; 19 | assert (sctx = SSL_CTX_new(TLSv1_method())); 20 | /* These two file were created with this command: 21 | openssl req -x509 -newkey rsa:512 -keyout server.key \ 22 | -out server.pem -days 9999 -nodes -subj /CN=a/ 23 | */ 24 | assert(SSL_CTX_use_certificate_file(sctx, CERT_PATH "server.pem", 25 | SSL_FILETYPE_PEM)); 26 | assert(SSL_CTX_use_PrivateKey_file(sctx, CERT_PATH "server.key", 27 | SSL_FILETYPE_PEM)); 28 | return sctx; 29 | } 30 | 31 | extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { 32 | static SSL_CTX *sctx = Init(); 33 | SSL *server = SSL_new(sctx); 34 | BIO *sinbio = BIO_new(BIO_s_mem()); 35 | BIO *soutbio = BIO_new(BIO_s_mem()); 36 | SSL_set_bio(server, sinbio, soutbio); 37 | SSL_set_accept_state(server); 38 | BIO_write(sinbio, data, size); 39 | SSL_do_handshake(server); 40 | SSL_free(server); 41 | return 0; 42 | } 43 | -------------------------------------------------------------------------------- /lessons/05/server.key: -------------------------------------------------------------------------------- 1 | -----BEGIN PRIVATE KEY----- 2 | MIIBVAIBADANBgkqhkiG9w0BAQEFAASCAT4wggE6AgEAAkEA1AdZNDVOA9cXm97f 3 | erp1bukz2kohjToJS6Ma8fOb36VV9lQGmDNsJanXFiqafOgV+kh1HXqZ3l1I0JmZ 4 | 71b+QQIDAQABAkAHGfPn5r0lLcgRpWZQwvv56f+dmQwEoeP7z4uwfNtEo0JcRD66 5 | 1WRCvx3LE0VbNeaEdNmSPiRXhlwIggjfrBi9AiEA9UusPBcEp/QcPGs96nQQdQzE 6 | fw4x0HL/eSV3qHimT6MCIQDdSAiX4Ouxoiwn/9KhDMcZXRYX/OPzj6w8u1YIH7BI 7 | ywIgSozbJdAhHCJ2ym4VfUIVFl3xAmSAA0hQGLOocE1qzl0CIQDRicOxZmhqBiKA 8 | IgznOn1StEYWov+MhRFZVSBLgw5gbwIgJzOlSlu0Y22hEUsLCKyHBrCAZZHcZ020 9 | 20pfogmQYn0= 10 | -----END PRIVATE KEY----- -------------------------------------------------------------------------------- /lessons/05/server.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIBYTCCAQugAwIBAgIJAMPQQtUHkx+KMA0GCSqGSIb3DQEBCwUAMAwxCjAIBgNV 3 | BAMMAWEwHhcNMTYwOTI0MjIyMDUyWhcNNDQwMjA5MjIyMDUyWjAMMQowCAYDVQQD 4 | DAFhMFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBANQHWTQ1TgPXF5ve33q6dW7pM9pK 5 | IY06CUujGvHzm9+lVfZUBpgzbCWp1xYqmnzoFfpIdR16md5dSNCZme9W/kECAwEA 6 | AaNQME4wHQYDVR0OBBYEFCXtEo9rkLuKGSlm0mFE4Yk/HDJVMB8GA1UdIwQYMBaA 7 | FCXtEo9rkLuKGSlm0mFE4Yk/HDJVMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEL 8 | BQADQQCnldOnbdNJZxBO/J+979Urg8qDp8MnlN0979AmK1P5/YzPnAF4BU7QTOTE 9 | imS5qZ0MvziBa81nVlnnFRkIezcD 10 | -----END CERTIFICATE----- -------------------------------------------------------------------------------- /lessons/06/README.md: -------------------------------------------------------------------------------- 1 | # Lesson 06 2 | 3 | Here we will find [c-ares] vulnerability (CVE-2016-5180) that has been exploited 4 | to obtain [remote code execution] with root privileges on ChromeOS. 5 | 6 | *** 7 | This example has been taken from [google/fuzzer-stest-suite] repository. 8 | *** 9 | 10 | 11 | ### Build vulnerable c-ares version 12 | 13 | ```bash 14 | tar xzvf c-ares.tgz 15 | cd c-ares 16 | 17 | ./buildconf 18 | ./configure 19 | make CC="clang -O2 -fno-omit-frame-pointer -g -fsanitize=address -fsanitize-coverage=trace-cmp,trace-gep,trace-div" 20 | ``` 21 | 22 | ### Build and run the fuzzer 23 | 24 | 25 | Take a look into the fuzzer: 26 | 27 | ```cpp 28 | #include 29 | 30 | extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { 31 | unsigned char *buf; 32 | int buflen; 33 | std::string s(reinterpret_cast(data), size); 34 | ares_create_query(s.c_str(), ns_c_in, ns_t_a, 0x1234, 0, &buf, &buflen, 0); 35 | ares_free_string(buf); 36 | return 0; 37 | } 38 | ``` 39 | 40 | Build the fuzzer: 41 | 42 | ```bash 43 | cd .. 44 | clang++ -g c_ares_fuzzer.cc -O2 -fno-omit-frame-pointer -fsanitize=address,fuzzer \ 45 | -fsanitize-coverage=trace-cmp,trace-gep,trace-div \ 46 | -Ic-ares c-ares/.libs/libcares.a -o c_ares_fuzzer 47 | ``` 48 | 49 | And run it: 50 | 51 | ```bash 52 | mkdir corpus1 53 | ./c_ares_fuzzer corpus1 54 | ``` 55 | 56 | Let's look into its output: 57 | 58 | ```bash 59 | INFO: Seed: 250951835 60 | INFO: Loaded 1 modules (152 guards): [0x747340, 0x7475a0), 61 | Loading corpus dir: corpus1 62 | INFO: -max_len is not provided, using 64 63 | INFO: A corpus is not provided, starting from an empty corpus 64 | #0 READ units: 1 65 | #1 INITED cov: 12 ft: 11 corp: 1/1b exec/s: 0 rss: 26Mb 66 | #2 NEW cov: 18 ft: 17 corp: 2/2b exec/s: 0 rss: 26Mb L: 1 MS: 1 ChangeBit- 67 | #5 NEW cov: 19 ft: 21 corp: 3/4b exec/s: 0 rss: 27Mb L: 2 MS: 4 ChangeBit-CrossOver-ShuffleBytes-ChangeByte- 68 | #8 NEW cov: 19 ft: 25 corp: 4/52b exec/s: 0 rss: 27Mb L: 48 MS: 2 CopyPart-InsertRepeatedBytes- 69 | #10 NEW cov: 20 ft: 26 corp: 5/109b exec/s: 0 rss: 29Mb L: 57 MS: 4 CopyPart-InsertRepeatedBytes-InsertByte-CMP- DE: ".\x00\x00\x00\x00\x00\x00\x00"- 70 | #26 NEW cov: 20 ft: 30 corp: 6/148b exec/s: 0 rss: 29Mb L: 39 MS: 5 InsertRepeatedBytes-EraseBytes-ChangeBit-ChangeByte-CMP- DE: "\x01\x00"- 71 | #28 NEW cov: 22 ft: 32 corp: 7/199b exec/s: 0 rss: 29Mb L: 51 MS: 2 InsertRepeatedBytes-PersAutoDict- DE: ".\x00\x00\x00\x00\x00\x00\x00"- 72 | #43 NEW cov: 22 ft: 36 corp: 8/238b exec/s: 0 rss: 29Mb L: 39 MS: 2 ShuffleBytes-PersAutoDict- DE: ".\x00\x00\x00\x00\x00\x00\x00"- 73 | #48 NEW cov: 23 ft: 37 corp: 9/273b exec/s: 0 rss: 29Mb L: 35 MS: 2 CrossOver-PersAutoDict- DE: ".\x00\x00\x00\x00\x00\x00\x00"- 74 | #62 NEW cov: 23 ft: 41 corp: 10/312b exec/s: 0 rss: 29Mb L: 39 MS: 1 CMP- DE: "\x00\x00\x00\x00\x00\x00\x00\x01"- 75 | #84 NEW cov: 23 ft: 44 corp: 11/336b exec/s: 0 rss: 29Mb L: 24 MS: 3 ChangeByte-CrossOver-PersAutoDict- DE: ".\x00\x00\x00\x00\x00\x00\x00"- 76 | #87 NEW cov: 23 ft: 45 corp: 12/367b exec/s: 0 rss: 29Mb L: 31 MS: 1 EraseBytes- 77 | #212 NEW cov: 23 ft: 47 corp: 13/423b exec/s: 0 rss: 29Mb L: 56 MS: 1 CopyPart- 78 | #224 NEW cov: 23 ft: 48 corp: 14/487b exec/s: 0 rss: 29Mb L: 64 MS: 3 ChangeByte-PersAutoDict-CrossOver- DE: ".\x00\x00\x00\x00\x00\x00\x00"- 79 | #899 NEW cov: 23 ft: 50 corp: 15/547b exec/s: 0 rss: 29Mb L: 60 MS: 3 EraseBytes-ChangeByte-CopyPart- 80 | #1019 NEW cov: 26 ft: 53 corp: 16/602b exec/s: 0 rss: 29Mb L: 55 MS: 3 CopyPart-PersAutoDict-CMP- DE: ".\x00\x00\x00\x00\x00\x00\x00"-"\\\x00\x00\x00\x00\x00\x00\x00"- 81 | #1483 NEW cov: 26 ft: 55 corp: 17/658b exec/s: 0 rss: 29Mb L: 56 MS: 2 EraseBytes-CopyPart- 82 | #2760 NEW cov: 27 ft: 56 corp: 18/722b exec/s: 0 rss: 30Mb L: 64 MS: 4 InsertRepeatedBytes-ChangeByte-CopyPart-InsertByte- 83 | ================================================================= 84 | ==15515==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x6030000470f5 at pc 0x0000004f1acf bp 0x7fff4e5b1310 sp 0x7fff4e5b1308 85 | WRITE of size 1 at 0x6030000470f5 thread T0 86 | #0 0x4f1ace in ares_create_query /home/mmoroz/projects/libfuzzer-workshop/lessons/06/c-ares/ares_create_query.c:196:3 87 | #1 0x4f0684 in LLVMFuzzerTestOneInput /home/mmoroz/projects/libfuzzer-workshop/lessons/06/c_ares_fuzzer.cc:16:3 88 | <...> 89 | ``` 90 | 91 | 92 | 93 | [c-ares]: https://c-ares.haxx.se/ 94 | [remote code execution]: https://googlechromereleases.blogspot.com/2016/09/stable-channel-updates-for-chrome-os.html 95 | [google/fuzzer-stest-suite]: https://github.com/google/fuzzer-test-suite/blob/master/tutorial/libFuzzerTutorial.md#heartbleed 96 | -------------------------------------------------------------------------------- /lessons/06/c-ares.tgz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dor1s/libfuzzer-workshop/35dd05ed4edce6b80a296d8d6b4579becec4d824/lessons/06/c-ares.tgz -------------------------------------------------------------------------------- /lessons/06/c_ares_fuzzer.cc: -------------------------------------------------------------------------------- 1 | // Copyright 2016 Google Inc. All Rights Reserved. 2 | // Licensed under the Apache License, Version 2.0 (the "License"); 3 | #include 4 | #include 5 | 6 | #include 7 | 8 | #include 9 | 10 | #include 11 | 12 | extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { 13 | unsigned char *buf; 14 | int buflen; 15 | std::string s(reinterpret_cast(data), size); 16 | ares_create_query(s.c_str(), ns_c_in, ns_t_a, 0x1234, 0, &buf, &buflen, 0); 17 | ares_free_string(buf); 18 | return 0; 19 | } 20 | -------------------------------------------------------------------------------- /lessons/07/Modern_Fuzzing_of_C_C++_projects_slides_40-62.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dor1s/libfuzzer-workshop/35dd05ed4edce6b80a296d8d6b4579becec4d824/lessons/07/Modern_Fuzzing_of_C_C++_projects_slides_40-62.pdf -------------------------------------------------------------------------------- /lessons/07/README.md: -------------------------------------------------------------------------------- 1 | # Lesson 07 2 | 3 | This is a theorethical lesson, see the slides. 4 | -------------------------------------------------------------------------------- /lessons/08/libxml2.tgz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dor1s/libfuzzer-workshop/35dd05ed4edce6b80a296d8d6b4579becec4d824/lessons/08/libxml2.tgz -------------------------------------------------------------------------------- /lessons/08/png.dict: -------------------------------------------------------------------------------- 1 | # Copyright 2016 Google Inc. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | # 15 | ################################################################################ 16 | # 17 | # AFL dictionary for PNG images 18 | # ----------------------------- 19 | # 20 | # Just the basic, standard-originating sections; does not include vendor 21 | # extensions. 22 | # 23 | # Created by Michal Zalewski 24 | # 25 | 26 | header_png="\x89PNG\x0d\x0a\x1a\x0a" 27 | 28 | section_IDAT="IDAT" 29 | section_IEND="IEND" 30 | section_IHDR="IHDR" 31 | section_PLTE="PLTE" 32 | section_bKGD="bKGD" 33 | section_cHRM="cHRM" 34 | section_fRAc="fRAc" 35 | section_gAMA="gAMA" 36 | section_gIFg="gIFg" 37 | section_gIFt="gIFt" 38 | section_gIFx="gIFx" 39 | section_hIST="hIST" 40 | section_iCCP="iCCP" 41 | section_iTXt="iTXt" 42 | section_oFFs="oFFs" 43 | section_pCAL="pCAL" 44 | section_pHYs="pHYs" 45 | section_sBIT="sBIT" 46 | section_sCAL="sCAL" 47 | section_sPLT="sPLT" 48 | section_sRGB="sRGB" 49 | section_sTER="sTER" 50 | section_tEXt="tEXt" 51 | section_tIME="tIME" 52 | section_tRNS="tRNS" 53 | section_zTXt="zTXt" -------------------------------------------------------------------------------- /lessons/08/xml.dict: -------------------------------------------------------------------------------- 1 | # Copyright 2016 Google Inc. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | # 15 | ################################################################################ 16 | # 17 | # AFL dictionary for XML 18 | # ---------------------- 19 | # 20 | # Several basic syntax elements and attributes, modeled on libxml2. 21 | # 22 | # Created by Michal Zalewski 23 | # 24 | 25 | attr_encoding=" encoding=\"1\"" 26 | attr_generic=" a=\"1\"" 27 | attr_href=" href=\"1\"" 28 | attr_standalone=" standalone=\"no\"" 29 | attr_version=" version=\"1\"" 30 | attr_xml_base=" xml:base=\"1\"" 31 | attr_xml_id=" xml:id=\"1\"" 32 | attr_xml_lang=" xml:lang=\"1\"" 33 | attr_xml_space=" xml:space=\"1\"" 34 | attr_xmlns=" xmlns=\"1\"" 35 | 36 | entity_builtin="<" 37 | entity_decimal="" 38 | entity_external="&a;" 39 | entity_hex="" 40 | 41 | string_any="ANY" 42 | string_brackets="[]" 43 | string_cdata="CDATA" 44 | string_col_fallback=":fallback" 45 | string_col_generic=":a" 46 | string_col_include=":include" 47 | string_dashes="--" 48 | string_empty="EMPTY" 49 | string_empty_dblquotes="\"\"" 50 | string_empty_quotes="''" 51 | string_entities="ENTITIES" 52 | string_entity="ENTITY" 53 | string_fixed="#FIXED" 54 | string_id="ID" 55 | string_idref="IDREF" 56 | string_idrefs="IDREFS" 57 | string_implied="#IMPLIED" 58 | string_nmtoken="NMTOKEN" 59 | string_nmtokens="NMTOKENS" 60 | string_notation="NOTATION" 61 | string_parentheses="()" 62 | string_pcdata="#PCDATA" 63 | string_percent="%a" 64 | string_public="PUBLIC" 65 | string_required="#REQUIRED" 66 | string_schema=":schema" 67 | string_system="SYSTEM" 68 | string_ucs4="UCS-4" 69 | string_utf16="UTF-16" 70 | string_utf8="UTF-8" 71 | string_xmlns="xmlns:" 72 | 73 | tag_attlist="" 76 | tag_doctype="" 83 | tag_open_close="" 84 | tag_open_exclamation="" 87 | tag_xml_q="" 88 | -------------------------------------------------------------------------------- /lessons/08/xml_compile_regexp_fuzzer.cc: -------------------------------------------------------------------------------- 1 | // Copyright 2016 The Chromium Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style license that can be 3 | // found in the LICENSE file. 4 | 5 | #include 6 | #include 7 | 8 | #include 9 | #include 10 | #include 11 | 12 | #include "libxml/parser.h" 13 | #include "libxml/tree.h" 14 | #include "libxml/xmlversion.h" 15 | 16 | void ignore (void * ctx, const char * msg, ...) { 17 | // Error handler to avoid spam of error messages from libxml parser. 18 | } 19 | 20 | // Entry point for LibFuzzer. 21 | extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { 22 | xmlSetGenericErrorFunc(NULL, &ignore); 23 | 24 | std::vector buffer(size + 1, 0); 25 | std::copy(data, data + size, buffer.data()); 26 | 27 | xmlRegexpPtr x = xmlRegexpCompile(buffer.data()); 28 | if (x) 29 | xmlRegFreeRegexp(x); 30 | 31 | return 0; 32 | } 33 | -------------------------------------------------------------------------------- /lessons/08/xml_read_memory_fuzzer.cc: -------------------------------------------------------------------------------- 1 | // Copyright 2015 The Chromium Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style license that can be 3 | // found in the LICENSE file. 4 | 5 | #include 6 | #include 7 | 8 | #include "libxml/parser.h" 9 | 10 | void ignore (void* ctx, const char* msg, ...) { 11 | // Error handler to avoid spam of error messages from libxml parser. 12 | } 13 | 14 | extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { 15 | xmlSetGenericErrorFunc(NULL, &ignore); 16 | 17 | if (auto doc = xmlReadMemory(reinterpret_cast(data), 18 | static_cast(size), "noname.xml", NULL, 0)) { 19 | xmlFreeDoc(doc); 20 | } 21 | 22 | return 0; 23 | } 24 | -------------------------------------------------------------------------------- /lessons/09/README.md: -------------------------------------------------------------------------------- 1 | # Lesson 09 2 | 3 | Here we will be fuzzing [libpng]. During this lesson we will: 4 | * see an importance of seed corpus 5 | 6 | ### Build the target 7 | 8 | Disabling of error messages is a bit tricky here and need to be done before the 9 | compilation" 10 | 11 | ```bash 12 | tar xzf libpng.tgz 13 | cd libpng 14 | 15 | # Disable logging via library build configuration control. 16 | cat scripts/pnglibconf.dfa | sed -e "s/option STDIO/option STDIO disabled/" \ 17 | > scripts/pnglibconf.dfa.temp 18 | mv scripts/pnglibconf.dfa.temp scripts/pnglibconf.dfa 19 | 20 | # build the library. 21 | autoreconf -f -i 22 | 23 | export FUZZ_CXXFLAGS="-O2 -fno-omit-frame-pointer -g -fsanitize=address,fuzzer-no-link \ 24 | -fsanitize-coverage=trace-cmp,trace-gep,trace-div" 25 | 26 | ./configure CC="clang" CFLAGS="$FUZZ_CXXFLAGS" 27 | make -j2 28 | ``` 29 | 30 | ### Build and run the fuzzer 31 | 32 | Take a look at [the fuzzer]. Please note how we disable CRC check. Otherwise, 33 | the fuzzer would almost always exit because of invalid checksum of PNG chunks. 34 | 35 | 36 | Build the fuzzer: 37 | 38 | ```bash 39 | cd .. 40 | clang++ -std=c++11 libpng_read_fuzzer.cc -O2 -fno-omit-frame-pointer -g -fsanitize=address,fuzzer\ 41 | -fsanitize-coverage=trace-cmp,trace-gep,trace-div -I libpng \ 42 | libpng/.libs/libpng16.a -lz \ 43 | -o libpng_read_fuzzer 44 | ``` 45 | 46 | Run the fuzzer on empty corpus with `-mxa_len=2048` for 5 minutes: 47 | 48 | ```bash 49 | mkdir corpus1 50 | ./libpng_read_fuzzer -max_len=2048 -max_total_time=300 -print_final_stats=1 \ 51 | corpus1 52 | ``` 53 | 54 | Open a new terminal and run the fuzzer with a dictionary: 55 | 56 | ```bash 57 | mkdir corpus2 58 | ./libpng_read_fuzzer -max_len=2048 -max_total_time=300 -dict=png.dict \ 59 | -print_final_stats=1 corpus2 60 | ``` 61 | 62 | Then let's wait until both processes end :) 63 | 64 | 65 | Let's run the fuzzer using a seed corpus. For seed corpus we will use some [test 66 | images] from Chromium repo. 67 | 68 | Run two more fuzzer instances. One with the seed corpus: 69 | 70 | ```bash 71 | mkdir corpus3 72 | ./libpng_read_fuzzer -max_len=2048 -max_total_time=300 -print_final_stats=1 \ 73 | -timeout=5 corpus3 seed_corpus 74 | ``` 75 | 76 | And another one with the seed corpus and the dictionary (super-combo!): 77 | 78 | ```bash 79 | mkdir corpus4 80 | ./libpng_read_fuzzer -max_len=2048 -max_total_time=300 -dict=png.dict \ 81 | -print_final_stats=1 -timeout=5 corpus4 seed_corpus 82 | ``` 83 | 84 | Compare and analyze the output of four fuzzers being run with different 85 | configurations. 86 | 87 | 88 | 89 | [libpng]: http://www.libpng.org/pub/png/libpng.html 90 | [test images]: https://cs.chromium.org/chromium/src/cc/test/data/ 91 | [the fuzzer]: libpng_read_fuzzer.cc 92 | 93 | -------------------------------------------------------------------------------- /lessons/09/libpng.tgz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dor1s/libfuzzer-workshop/35dd05ed4edce6b80a296d8d6b4579becec4d824/lessons/09/libpng.tgz -------------------------------------------------------------------------------- /lessons/09/libpng_read_fuzzer.cc: -------------------------------------------------------------------------------- 1 | // Copyright 2015 The Chromium Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style license that can be 3 | // found in the LICENSE file. 4 | 5 | #include 6 | #include 7 | #include 8 | 9 | #include 10 | 11 | #define PNG_INTERNAL 12 | #include "png.h" 13 | 14 | struct BufState { 15 | const uint8_t* data; 16 | size_t bytes_left; 17 | }; 18 | 19 | struct PngObjectHandler { 20 | png_infop info_ptr = nullptr; 21 | png_structp png_ptr = nullptr; 22 | png_voidp row_ptr = nullptr; 23 | BufState* buf_state = nullptr; 24 | 25 | ~PngObjectHandler() { 26 | if (row_ptr && png_ptr) { 27 | png_free(png_ptr, row_ptr); 28 | } 29 | if (png_ptr && info_ptr) { 30 | png_destroy_read_struct(&png_ptr, &info_ptr, nullptr); 31 | } 32 | delete buf_state; 33 | } 34 | }; 35 | 36 | void user_read_data(png_structp png_ptr, png_bytep data, png_size_t length) { 37 | BufState* buf_state = static_cast(png_get_io_ptr(png_ptr)); 38 | if (length > buf_state->bytes_left) { 39 | png_error(png_ptr, "read error"); 40 | } 41 | memcpy(data, buf_state->data, length); 42 | buf_state->bytes_left -= length; 43 | buf_state->data += length; 44 | } 45 | 46 | static const int kPngHeaderSize = 8; 47 | 48 | // Entry point for LibFuzzer. 49 | // Roughly follows the libpng book example: 50 | // http://www.libpng.org/pub/png/book/chapter13.html 51 | extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { 52 | if (size < kPngHeaderSize) { 53 | return 0; 54 | } 55 | 56 | std::vector v(data, data + size); 57 | if (png_sig_cmp(v.data(), 0, kPngHeaderSize)) { 58 | // not a PNG. 59 | return 0; 60 | } 61 | 62 | PngObjectHandler png_handler; 63 | png_handler.png_ptr = png_create_read_struct 64 | (PNG_LIBPNG_VER_STRING, nullptr, nullptr, nullptr); 65 | if (!png_handler.png_ptr) { 66 | return 0; 67 | } 68 | 69 | png_set_user_limits(png_handler.png_ptr, 2048, 2048); 70 | 71 | png_set_crc_action(png_handler.png_ptr, PNG_CRC_QUIET_USE, PNG_CRC_QUIET_USE); 72 | 73 | png_handler.info_ptr = png_create_info_struct(png_handler.png_ptr); 74 | if (!png_handler.info_ptr) { 75 | return 0; 76 | } 77 | 78 | // Setting up reading from buffer. 79 | png_handler.buf_state = new BufState(); 80 | png_handler.buf_state->data = data + kPngHeaderSize; 81 | png_handler.buf_state->bytes_left = size - kPngHeaderSize; 82 | png_set_read_fn(png_handler.png_ptr, png_handler.buf_state, user_read_data); 83 | png_set_sig_bytes(png_handler.png_ptr, kPngHeaderSize); 84 | 85 | // libpng error handling. 86 | if (setjmp(png_jmpbuf(png_handler.png_ptr))) { 87 | return 0; 88 | } 89 | 90 | // Reading. 91 | png_read_info(png_handler.png_ptr, png_handler.info_ptr); 92 | png_handler.row_ptr = png_malloc( 93 | png_handler.png_ptr, png_get_rowbytes(png_handler.png_ptr, 94 | png_handler.info_ptr)); 95 | 96 | // reset error handler to put png_deleter into scope. 97 | if (setjmp(png_jmpbuf(png_handler.png_ptr))) { 98 | return 0; 99 | } 100 | 101 | png_uint_32 width, height; 102 | int bit_depth, color_type, interlace_type, compression_type; 103 | int filter_type; 104 | 105 | if (!png_get_IHDR(png_handler.png_ptr, png_handler.info_ptr, &width, 106 | &height, &bit_depth, &color_type, &interlace_type, 107 | &compression_type, &filter_type)) { 108 | return 0; 109 | } 110 | 111 | // This is going to be too slow. 112 | if (width && height > 100000000 / width) 113 | return 0; 114 | 115 | if (width > 2048 || height > 2048) 116 | return 0; 117 | 118 | int passes = png_set_interlace_handling(png_handler.png_ptr); 119 | png_start_read_image(png_handler.png_ptr); 120 | 121 | for (int pass = 0; pass < passes; ++pass) { 122 | for (png_uint_32 y = 0; y < height; ++y) { 123 | png_read_row(png_handler.png_ptr, 124 | static_cast(png_handler.row_ptr), NULL); 125 | } 126 | } 127 | 128 | return 0; 129 | } 130 | -------------------------------------------------------------------------------- /lessons/09/png.dict: -------------------------------------------------------------------------------- 1 | # Copyright 2016 Google Inc. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | # 15 | ################################################################################ 16 | # 17 | # AFL dictionary for PNG images 18 | # ----------------------------- 19 | # 20 | # Just the basic, standard-originating sections; does not include vendor 21 | # extensions. 22 | # 23 | # Created by Michal Zalewski 24 | # 25 | 26 | header_png="\x89PNG\x0d\x0a\x1a\x0a" 27 | 28 | section_IDAT="IDAT" 29 | section_IEND="IEND" 30 | section_IHDR="IHDR" 31 | section_PLTE="PLTE" 32 | section_bKGD="bKGD" 33 | section_cHRM="cHRM" 34 | section_fRAc="fRAc" 35 | section_gAMA="gAMA" 36 | section_gIFg="gIFg" 37 | section_gIFt="gIFt" 38 | section_gIFx="gIFx" 39 | section_hIST="hIST" 40 | section_iCCP="iCCP" 41 | section_iTXt="iTXt" 42 | section_oFFs="oFFs" 43 | section_pCAL="pCAL" 44 | section_pHYs="pHYs" 45 | section_sBIT="sBIT" 46 | section_sCAL="sCAL" 47 | section_sPLT="sPLT" 48 | section_sRGB="sRGB" 49 | section_sTER="sTER" 50 | section_tEXt="tEXt" 51 | section_tIME="tIME" 52 | section_tRNS="tRNS" 53 | section_zTXt="zTXt" -------------------------------------------------------------------------------- /lessons/09/seed_corpus/anti_aliasing.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dor1s/libfuzzer-workshop/35dd05ed4edce6b80a296d8d6b4579becec4d824/lessons/09/seed_corpus/anti_aliasing.png -------------------------------------------------------------------------------- /lessons/09/seed_corpus/anti_aliasing_perspective.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dor1s/libfuzzer-workshop/35dd05ed4edce6b80a296d8d6b4579becec4d824/lessons/09/seed_corpus/anti_aliasing_perspective.png -------------------------------------------------------------------------------- /lessons/09/seed_corpus/axis_aligned.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dor1s/libfuzzer-workshop/35dd05ed4edce6b80a296d8d6b4579becec4d824/lessons/09/seed_corpus/axis_aligned.png -------------------------------------------------------------------------------- /lessons/09/seed_corpus/background_filter.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dor1s/libfuzzer-workshop/35dd05ed4edce6b80a296d8d6b4579becec4d824/lessons/09/seed_corpus/background_filter.png -------------------------------------------------------------------------------- /lessons/09/seed_corpus/background_filter_blur.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dor1s/libfuzzer-workshop/35dd05ed4edce6b80a296d8d6b4579becec4d824/lessons/09/seed_corpus/background_filter_blur.png -------------------------------------------------------------------------------- /lessons/09/seed_corpus/background_filter_blur_off_axis.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dor1s/libfuzzer-workshop/35dd05ed4edce6b80a296d8d6b4579becec4d824/lessons/09/seed_corpus/background_filter_blur_off_axis.png -------------------------------------------------------------------------------- /lessons/09/seed_corpus/background_filter_blur_outsets.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dor1s/libfuzzer-workshop/35dd05ed4edce6b80a296d8d6b4579becec4d824/lessons/09/seed_corpus/background_filter_blur_outsets.png -------------------------------------------------------------------------------- /lessons/09/seed_corpus/background_filter_on_scaled_layer_gl.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dor1s/libfuzzer-workshop/35dd05ed4edce6b80a296d8d6b4579becec4d824/lessons/09/seed_corpus/background_filter_on_scaled_layer_gl.png -------------------------------------------------------------------------------- /lessons/09/seed_corpus/background_filter_on_scaled_layer_sw.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dor1s/libfuzzer-workshop/35dd05ed4edce6b80a296d8d6b4579becec4d824/lessons/09/seed_corpus/background_filter_on_scaled_layer_sw.png -------------------------------------------------------------------------------- /lessons/09/seed_corpus/background_filter_rotated_gl.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dor1s/libfuzzer-workshop/35dd05ed4edce6b80a296d8d6b4579becec4d824/lessons/09/seed_corpus/background_filter_rotated_gl.png -------------------------------------------------------------------------------- /lessons/09/seed_corpus/background_filter_rotated_sw.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dor1s/libfuzzer-workshop/35dd05ed4edce6b80a296d8d6b4579becec4d824/lessons/09/seed_corpus/background_filter_rotated_sw.png -------------------------------------------------------------------------------- /lessons/09/seed_corpus/black.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dor1s/libfuzzer-workshop/35dd05ed4edce6b80a296d8d6b4579becec4d824/lessons/09/seed_corpus/black.png -------------------------------------------------------------------------------- /lessons/09/seed_corpus/blending_and_filter.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dor1s/libfuzzer-workshop/35dd05ed4edce6b80a296d8d6b4579becec4d824/lessons/09/seed_corpus/blending_and_filter.png -------------------------------------------------------------------------------- /lessons/09/seed_corpus/blending_render_pass.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dor1s/libfuzzer-workshop/35dd05ed4edce6b80a296d8d6b4579becec4d824/lessons/09/seed_corpus/blending_render_pass.png -------------------------------------------------------------------------------- /lessons/09/seed_corpus/blending_render_pass_cm.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dor1s/libfuzzer-workshop/35dd05ed4edce6b80a296d8d6b4579becec4d824/lessons/09/seed_corpus/blending_render_pass_cm.png -------------------------------------------------------------------------------- /lessons/09/seed_corpus/blending_render_pass_mask.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dor1s/libfuzzer-workshop/35dd05ed4edce6b80a296d8d6b4579becec4d824/lessons/09/seed_corpus/blending_render_pass_mask.png -------------------------------------------------------------------------------- /lessons/09/seed_corpus/blending_render_pass_mask_cm.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dor1s/libfuzzer-workshop/35dd05ed4edce6b80a296d8d6b4579becec4d824/lessons/09/seed_corpus/blending_render_pass_mask_cm.png -------------------------------------------------------------------------------- /lessons/09/seed_corpus/blending_transparent.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dor1s/libfuzzer-workshop/35dd05ed4edce6b80a296d8d6b4579becec4d824/lessons/09/seed_corpus/blending_transparent.png -------------------------------------------------------------------------------- /lessons/09/seed_corpus/blending_with_root.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dor1s/libfuzzer-workshop/35dd05ed4edce6b80a296d8d6b4579becec4d824/lessons/09/seed_corpus/blending_with_root.png -------------------------------------------------------------------------------- /lessons/09/seed_corpus/blue_yellow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dor1s/libfuzzer-workshop/35dd05ed4edce6b80a296d8d6b4579becec4d824/lessons/09/seed_corpus/blue_yellow.png -------------------------------------------------------------------------------- /lessons/09/seed_corpus/blue_yellow_alpha.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dor1s/libfuzzer-workshop/35dd05ed4edce6b80a296d8d6b4579becec4d824/lessons/09/seed_corpus/blue_yellow_alpha.png -------------------------------------------------------------------------------- /lessons/09/seed_corpus/blue_yellow_alpha_translate.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dor1s/libfuzzer-workshop/35dd05ed4edce6b80a296d8d6b4579becec4d824/lessons/09/seed_corpus/blue_yellow_alpha_translate.png -------------------------------------------------------------------------------- /lessons/09/seed_corpus/blue_yellow_anti_aliasing.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dor1s/libfuzzer-workshop/35dd05ed4edce6b80a296d8d6b4579becec4d824/lessons/09/seed_corpus/blue_yellow_anti_aliasing.png -------------------------------------------------------------------------------- /lessons/09/seed_corpus/blue_yellow_filter_chain.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dor1s/libfuzzer-workshop/35dd05ed4edce6b80a296d8d6b4579becec4d824/lessons/09/seed_corpus/blue_yellow_filter_chain.png -------------------------------------------------------------------------------- /lessons/09/seed_corpus/blue_yellow_flipped.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dor1s/libfuzzer-workshop/35dd05ed4edce6b80a296d8d6b4579becec4d824/lessons/09/seed_corpus/blue_yellow_flipped.png -------------------------------------------------------------------------------- /lessons/09/seed_corpus/blue_yellow_partial_flipped.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dor1s/libfuzzer-workshop/35dd05ed4edce6b80a296d8d6b4579becec4d824/lessons/09/seed_corpus/blue_yellow_partial_flipped.png -------------------------------------------------------------------------------- /lessons/09/seed_corpus/blur_filter_with_clip_gl.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dor1s/libfuzzer-workshop/35dd05ed4edce6b80a296d8d6b4579becec4d824/lessons/09/seed_corpus/blur_filter_with_clip_gl.png -------------------------------------------------------------------------------- /lessons/09/seed_corpus/blur_filter_with_clip_sw.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dor1s/libfuzzer-workshop/35dd05ed4edce6b80a296d8d6b4579becec4d824/lessons/09/seed_corpus/blur_filter_with_clip_sw.png -------------------------------------------------------------------------------- /lessons/09/seed_corpus/checkers.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dor1s/libfuzzer-workshop/35dd05ed4edce6b80a296d8d6b4579becec4d824/lessons/09/seed_corpus/checkers.png -------------------------------------------------------------------------------- /lessons/09/seed_corpus/checkers_big.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dor1s/libfuzzer-workshop/35dd05ed4edce6b80a296d8d6b4579becec4d824/lessons/09/seed_corpus/checkers_big.png -------------------------------------------------------------------------------- /lessons/09/seed_corpus/dark_grey.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dor1s/libfuzzer-workshop/35dd05ed4edce6b80a296d8d6b4579becec4d824/lessons/09/seed_corpus/dark_grey.png -------------------------------------------------------------------------------- /lessons/09/seed_corpus/enlarged_texture_on_crop_offset.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dor1s/libfuzzer-workshop/35dd05ed4edce6b80a296d8d6b4579becec4d824/lessons/09/seed_corpus/enlarged_texture_on_crop_offset.png -------------------------------------------------------------------------------- /lessons/09/seed_corpus/enlarged_texture_on_threshold.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dor1s/libfuzzer-workshop/35dd05ed4edce6b80a296d8d6b4579becec4d824/lessons/09/seed_corpus/enlarged_texture_on_threshold.png -------------------------------------------------------------------------------- /lessons/09/seed_corpus/filter_with_giant_crop_rect.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dor1s/libfuzzer-workshop/35dd05ed4edce6b80a296d8d6b4579becec4d824/lessons/09/seed_corpus/filter_with_giant_crop_rect.png -------------------------------------------------------------------------------- /lessons/09/seed_corpus/force_anti_aliasing_off.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dor1s/libfuzzer-workshop/35dd05ed4edce6b80a296d8d6b4579becec4d824/lessons/09/seed_corpus/force_anti_aliasing_off.png -------------------------------------------------------------------------------- /lessons/09/seed_corpus/four_blue_green_checkers.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dor1s/libfuzzer-workshop/35dd05ed4edce6b80a296d8d6b4579becec4d824/lessons/09/seed_corpus/four_blue_green_checkers.png -------------------------------------------------------------------------------- /lessons/09/seed_corpus/four_blue_green_checkers_linear.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dor1s/libfuzzer-workshop/35dd05ed4edce6b80a296d8d6b4579becec4d824/lessons/09/seed_corpus/four_blue_green_checkers_linear.png -------------------------------------------------------------------------------- /lessons/09/seed_corpus/green.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dor1s/libfuzzer-workshop/35dd05ed4edce6b80a296d8d6b4579becec4d824/lessons/09/seed_corpus/green.png -------------------------------------------------------------------------------- /lessons/09/seed_corpus/green_alpha.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dor1s/libfuzzer-workshop/35dd05ed4edce6b80a296d8d6b4579becec4d824/lessons/09/seed_corpus/green_alpha.png -------------------------------------------------------------------------------- /lessons/09/seed_corpus/green_small.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dor1s/libfuzzer-workshop/35dd05ed4edce6b80a296d8d6b4579becec4d824/lessons/09/seed_corpus/green_small.png -------------------------------------------------------------------------------- /lessons/09/seed_corpus/green_small_with_blue_corner.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dor1s/libfuzzer-workshop/35dd05ed4edce6b80a296d8d6b4579becec4d824/lessons/09/seed_corpus/green_small_with_blue_corner.png -------------------------------------------------------------------------------- /lessons/09/seed_corpus/green_with_blue_corner.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dor1s/libfuzzer-workshop/35dd05ed4edce6b80a296d8d6b4579becec4d824/lessons/09/seed_corpus/green_with_blue_corner.png -------------------------------------------------------------------------------- /lessons/09/seed_corpus/image_mask_of_layer.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dor1s/libfuzzer-workshop/35dd05ed4edce6b80a296d8d6b4579becec4d824/lessons/09/seed_corpus/image_mask_of_layer.png -------------------------------------------------------------------------------- /lessons/09/seed_corpus/intersecting_blue_green.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dor1s/libfuzzer-workshop/35dd05ed4edce6b80a296d8d6b4579becec4d824/lessons/09/seed_corpus/intersecting_blue_green.png -------------------------------------------------------------------------------- /lessons/09/seed_corpus/intersecting_blue_green_squares.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dor1s/libfuzzer-workshop/35dd05ed4edce6b80a296d8d6b4579becec4d824/lessons/09/seed_corpus/intersecting_blue_green_squares.png -------------------------------------------------------------------------------- /lessons/09/seed_corpus/intersecting_blue_green_squares_video.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dor1s/libfuzzer-workshop/35dd05ed4edce6b80a296d8d6b4579becec4d824/lessons/09/seed_corpus/intersecting_blue_green_squares_video.png -------------------------------------------------------------------------------- /lessons/09/seed_corpus/intersecting_light_dark_squares_video.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dor1s/libfuzzer-workshop/35dd05ed4edce6b80a296d8d6b4579becec4d824/lessons/09/seed_corpus/intersecting_light_dark_squares_video.png -------------------------------------------------------------------------------- /lessons/09/seed_corpus/mask_bottom_right.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dor1s/libfuzzer-workshop/35dd05ed4edce6b80a296d8d6b4579becec4d824/lessons/09/seed_corpus/mask_bottom_right.png -------------------------------------------------------------------------------- /lessons/09/seed_corpus/mask_middle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dor1s/libfuzzer-workshop/35dd05ed4edce6b80a296d8d6b4579becec4d824/lessons/09/seed_corpus/mask_middle.png -------------------------------------------------------------------------------- /lessons/09/seed_corpus/mask_of_background_filter.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dor1s/libfuzzer-workshop/35dd05ed4edce6b80a296d8d6b4579becec4d824/lessons/09/seed_corpus/mask_of_background_filter.png -------------------------------------------------------------------------------- /lessons/09/seed_corpus/mask_of_clipped_layer.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dor1s/libfuzzer-workshop/35dd05ed4edce6b80a296d8d6b4579becec4d824/lessons/09/seed_corpus/mask_of_clipped_layer.png -------------------------------------------------------------------------------- /lessons/09/seed_corpus/mask_of_layer.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dor1s/libfuzzer-workshop/35dd05ed4edce6b80a296d8d6b4579becec4d824/lessons/09/seed_corpus/mask_of_layer.png -------------------------------------------------------------------------------- /lessons/09/seed_corpus/mask_of_layer_with_blend.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dor1s/libfuzzer-workshop/35dd05ed4edce6b80a296d8d6b4579becec4d824/lessons/09/seed_corpus/mask_of_layer_with_blend.png -------------------------------------------------------------------------------- /lessons/09/seed_corpus/mask_of_replica.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dor1s/libfuzzer-workshop/35dd05ed4edce6b80a296d8d6b4579becec4d824/lessons/09/seed_corpus/mask_of_replica.png -------------------------------------------------------------------------------- /lessons/09/seed_corpus/mask_of_replica_of_clipped_layer.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dor1s/libfuzzer-workshop/35dd05ed4edce6b80a296d8d6b4579becec4d824/lessons/09/seed_corpus/mask_of_replica_of_clipped_layer.png -------------------------------------------------------------------------------- /lessons/09/seed_corpus/mask_with_replica.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dor1s/libfuzzer-workshop/35dd05ed4edce6b80a296d8d6b4579becec4d824/lessons/09/seed_corpus/mask_with_replica.png -------------------------------------------------------------------------------- /lessons/09/seed_corpus/mask_with_replica_of_clipped_layer.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dor1s/libfuzzer-workshop/35dd05ed4edce6b80a296d8d6b4579becec4d824/lessons/09/seed_corpus/mask_with_replica_of_clipped_layer.png -------------------------------------------------------------------------------- /lessons/09/seed_corpus/offset_background_filter_1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dor1s/libfuzzer-workshop/35dd05ed4edce6b80a296d8d6b4579becec4d824/lessons/09/seed_corpus/offset_background_filter_1x.png -------------------------------------------------------------------------------- /lessons/09/seed_corpus/offset_background_filter_2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dor1s/libfuzzer-workshop/35dd05ed4edce6b80a296d8d6b4579becec4d824/lessons/09/seed_corpus/offset_background_filter_2x.png -------------------------------------------------------------------------------- /lessons/09/seed_corpus/rotated_drop_shadow_filter_gl.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dor1s/libfuzzer-workshop/35dd05ed4edce6b80a296d8d6b4579becec4d824/lessons/09/seed_corpus/rotated_drop_shadow_filter_gl.png -------------------------------------------------------------------------------- /lessons/09/seed_corpus/rotated_drop_shadow_filter_sw.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dor1s/libfuzzer-workshop/35dd05ed4edce6b80a296d8d6b4579becec4d824/lessons/09/seed_corpus/rotated_drop_shadow_filter_sw.png -------------------------------------------------------------------------------- /lessons/09/seed_corpus/rotated_filter_gl.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dor1s/libfuzzer-workshop/35dd05ed4edce6b80a296d8d6b4579becec4d824/lessons/09/seed_corpus/rotated_filter_gl.png -------------------------------------------------------------------------------- /lessons/09/seed_corpus/rotated_filter_sw.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dor1s/libfuzzer-workshop/35dd05ed4edce6b80a296d8d6b4579becec4d824/lessons/09/seed_corpus/rotated_filter_sw.png -------------------------------------------------------------------------------- /lessons/09/seed_corpus/scaled_render_surface_layer_gl.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dor1s/libfuzzer-workshop/35dd05ed4edce6b80a296d8d6b4579becec4d824/lessons/09/seed_corpus/scaled_render_surface_layer_gl.png -------------------------------------------------------------------------------- /lessons/09/seed_corpus/scaled_render_surface_layer_sw.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dor1s/libfuzzer-workshop/35dd05ed4edce6b80a296d8d6b4579becec4d824/lessons/09/seed_corpus/scaled_render_surface_layer_sw.png -------------------------------------------------------------------------------- /lessons/09/seed_corpus/spiral.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dor1s/libfuzzer-workshop/35dd05ed4edce6b80a296d8d6b4579becec4d824/lessons/09/seed_corpus/spiral.png -------------------------------------------------------------------------------- /lessons/09/seed_corpus/spiral_64_scale.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dor1s/libfuzzer-workshop/35dd05ed4edce6b80a296d8d6b4579becec4d824/lessons/09/seed_corpus/spiral_64_scale.png -------------------------------------------------------------------------------- /lessons/09/seed_corpus/spiral_double_scale.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dor1s/libfuzzer-workshop/35dd05ed4edce6b80a296d8d6b4579becec4d824/lessons/09/seed_corpus/spiral_double_scale.png -------------------------------------------------------------------------------- /lessons/09/seed_corpus/white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dor1s/libfuzzer-workshop/35dd05ed4edce6b80a296d8d6b4579becec4d824/lessons/09/seed_corpus/white.png -------------------------------------------------------------------------------- /lessons/09/seed_corpus/wrap_mode_repeat.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dor1s/libfuzzer-workshop/35dd05ed4edce6b80a296d8d6b4579becec4d824/lessons/09/seed_corpus/wrap_mode_repeat.png -------------------------------------------------------------------------------- /lessons/09/seed_corpus/yuv_stripes.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dor1s/libfuzzer-workshop/35dd05ed4edce6b80a296d8d6b4579becec4d824/lessons/09/seed_corpus/yuv_stripes.png -------------------------------------------------------------------------------- /lessons/09/seed_corpus/yuv_stripes_alpha.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dor1s/libfuzzer-workshop/35dd05ed4edce6b80a296d8d6b4579becec4d824/lessons/09/seed_corpus/yuv_stripes_alpha.png -------------------------------------------------------------------------------- /lessons/09/seed_corpus/yuv_stripes_clipped.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dor1s/libfuzzer-workshop/35dd05ed4edce6b80a296d8d6b4579becec4d824/lessons/09/seed_corpus/yuv_stripes_clipped.png -------------------------------------------------------------------------------- /lessons/09/seed_corpus/yuv_stripes_offset.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dor1s/libfuzzer-workshop/35dd05ed4edce6b80a296d8d6b4579becec4d824/lessons/09/seed_corpus/yuv_stripes_offset.png -------------------------------------------------------------------------------- /lessons/09/seed_corpus/zoom_filter_gl.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dor1s/libfuzzer-workshop/35dd05ed4edce6b80a296d8d6b4579becec4d824/lessons/09/seed_corpus/zoom_filter_gl.png -------------------------------------------------------------------------------- /lessons/09/seed_corpus/zoom_filter_sw.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dor1s/libfuzzer-workshop/35dd05ed4edce6b80a296d8d6b4579becec4d824/lessons/09/seed_corpus/zoom_filter_sw.png -------------------------------------------------------------------------------- /lessons/09/single_seed/seed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dor1s/libfuzzer-workshop/35dd05ed4edce6b80a296d8d6b4579becec4d824/lessons/09/single_seed/seed.png -------------------------------------------------------------------------------- /lessons/10/README.md: -------------------------------------------------------------------------------- 1 | # Lesson 10 2 | 3 | Here we will be fuzzing [re2]. During this lesson we will: 4 | * learn how `max_len` parameter may affect execution speed 5 | 6 | 7 | ### Build the target 8 | 9 | ``` 10 | tar xzf re2.tgz 11 | cd re2 12 | 13 | export FUZZ_CXXFLAGS="-O2 -fno-omit-frame-pointer -g -fsanitize=address,fuzzer-no-link \ 14 | -fsanitize-coverage=trace-cmp,trace-gep,trace-div" 15 | 16 | make clean 17 | CXX=clang++ CXXFLAGS="$FUZZ_CXXFLAGS" make -j 18 | ``` 19 | 20 | ### Build and run the fuzzer 21 | 22 | ```bash 23 | cd .. 24 | 25 | clang++ -std=c++11 re2_fuzzer.cc -O2 -fno-omit-frame-pointer -g -fsanitize=address,fuzzer \ 26 | -fsanitize-coverage=trace-cmp,trace-gep,trace-div -I re2 \ 27 | re2/obj/libre2.a -lz \ 28 | -o re2_fuzzer 29 | 30 | mkdir corpus1 31 | ./re2_fuzzer ./corpus1 -print_final_stats=1 -max_total_time=300 32 | ``` 33 | 34 | Play with different `-max_len` parameter values and other adjustments. 35 | 36 | [re2]: https://github.com/google/re2 37 | -------------------------------------------------------------------------------- /lessons/10/re2.tgz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dor1s/libfuzzer-workshop/35dd05ed4edce6b80a296d8d6b4579becec4d824/lessons/10/re2.tgz -------------------------------------------------------------------------------- /lessons/10/re2_fuzzer.cc: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2016 The Chromium Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style license that can be 3 | // found in the LICENSE file. 4 | 5 | #include 6 | #include 7 | 8 | #include 9 | 10 | #include "re2/re2.h" 11 | #include "util/logging.h" 12 | 13 | using std::string; 14 | 15 | void Test(const string& buffer, const string& pattern, 16 | const RE2::Options& options) { 17 | RE2 re(pattern, options); 18 | if (!re.ok()) 19 | return; 20 | 21 | string m1, m2; 22 | int i1, i2; 23 | double d1; 24 | 25 | if (re.NumberOfCapturingGroups() == 0) { 26 | RE2::FullMatch(buffer, re); 27 | RE2::PartialMatch(buffer, re); 28 | } else if (re.NumberOfCapturingGroups() == 1) { 29 | RE2::FullMatch(buffer, re, &m1); 30 | RE2::PartialMatch(buffer, re, &i1); 31 | } else if (re.NumberOfCapturingGroups() == 2) { 32 | RE2::FullMatch(buffer, re, &i1, &i2); 33 | RE2::PartialMatch(buffer, re, &m1, &m2); 34 | } 35 | 36 | re2::StringPiece input(buffer); 37 | RE2::Consume(&input, re, &m1); 38 | RE2::FindAndConsume(&input, re, &d1); 39 | string tmp1(buffer); 40 | RE2::Replace(&tmp1, re, "zz"); 41 | string tmp2(buffer); 42 | RE2::GlobalReplace(&tmp2, re, "xx"); 43 | RE2::QuoteMeta(re2::StringPiece(pattern)); 44 | } 45 | 46 | // Entry point for LibFuzzer. 47 | extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { 48 | if (size < 1) 49 | return 0; 50 | 51 | RE2::Options options; 52 | 53 | size_t options_randomizer = 0; 54 | for (size_t i = 0; i < size; i++) 55 | options_randomizer += data[i]; 56 | 57 | if (options_randomizer & 1) 58 | options.set_encoding(RE2::Options::EncodingLatin1); 59 | 60 | options.set_posix_syntax(options_randomizer & 2); 61 | options.set_longest_match(options_randomizer & 4); 62 | options.set_literal(options_randomizer & 8); 63 | options.set_never_nl(options_randomizer & 16); 64 | options.set_dot_nl(options_randomizer & 32); 65 | options.set_never_capture(options_randomizer & 64); 66 | options.set_case_sensitive(options_randomizer & 128); 67 | options.set_perl_classes(options_randomizer & 256); 68 | options.set_word_boundary(options_randomizer & 512); 69 | options.set_one_line(options_randomizer & 1024); 70 | 71 | options.set_log_errors(false); 72 | 73 | const char* data_input = reinterpret_cast(data); 74 | { 75 | string pattern(data_input, size); 76 | string buffer(data_input, size); 77 | Test(buffer, pattern, options); 78 | } 79 | 80 | if (size >= 3) { 81 | string pattern(data_input, size / 3); 82 | string buffer(data_input + size / 3, size - size / 3); 83 | Test(buffer, pattern, options); 84 | } 85 | 86 | return 0; 87 | } 88 | -------------------------------------------------------------------------------- /lessons/11/README.md: -------------------------------------------------------------------------------- 1 | # Lesson 11 2 | 3 | Here we will be fuzzing [pcre2]. During this lesson we will: 4 | * compare fuzzing of different regexp libraries 5 | * find known bugs and feel like a l33t h4x0r :) 6 | 7 | 8 | ### Build the target 9 | 10 | ``` 11 | tar xzf pcre2.tgz 12 | cd pcre2 13 | 14 | ./autogen.sh 15 | 16 | export FUZZ_CXXFLAGS="-O2 -fno-omit-frame-pointer -g -fsanitize=address,fuzzer-no-link \ 17 | -fsanitize-coverage=trace-cmp,trace-gep,trace-div" 18 | 19 | CXX="clang++ $FUZZ_CXXFLAGS" CC="clang $FUZZ_CXXFLAGS" \ 20 | CCLD="clang++ $FUZZ_CXXFLAGS" ./configure --enable-never-backslash-C \ 21 | --with-match-limit=1000 --with-match-limit-recursion=1000 22 | 23 | make -j2 24 | ``` 25 | 26 | ### Build and run the fuzzer 27 | 28 | ```bash 29 | cd .. 30 | 31 | clang++ -std=c++11 pcre2_fuzzer.cc -I pcre2/src \ 32 | -Wl,--whole-archive pcre2/.libs/*.a -Wl,-no-whole-archive \ 33 | -O2 -fno-omit-frame-pointer -g -fsanitize=address,fuzzer \ 34 | -fsanitize-coverage=trace-cmp,trace-gep,trace-div -o pcre2_fuzzer 35 | 36 | mkdir corpus1 37 | ./pcre2_fuzzer ./corpus1 -print_final_stats=1 -max_total_time=300 38 | ``` 39 | 40 | Play with different parameters (see how speed changes with different `max_len` 41 | values). 42 | 43 | 44 | ### Fuzzing pcre2-10.00 45 | 46 | *** 47 | This section has been added to let everybody to feel like a l33t h4x0r again :) 48 | *** 49 | 50 | ```bash 51 | tar xzf pcre2-10.00.tgz 52 | cd pcre2-10.00 53 | 54 | ./autogen.sh 55 | 56 | export FUZZ_CXXFLAGS="-O2 -fno-omit-frame-pointer -g -fsanitize=address,fuzzer-no-link \ 57 | -fsanitize-coverage=trace-cmp,trace-gep,trace-div" 58 | 59 | CXX="clang++ $FUZZ_CXXFLAGS" CC="clang $FUZZ_CXXFLAGS" \ 60 | CCLD="clang++ $FUZZ_CXXFLAGS" ./configure --enable-never-backslash-C \ 61 | --with-match-limit=1000 --with-match-limit-recursion=1000 62 | 63 | make -j2 64 | 65 | cd .. 66 | 67 | clang++ -std=c++11 pcre2_fuzzer.cc -I pcre2-10.00/src \ 68 | -Wl,--whole-archive pcre2-10.00/.libs/*.a -Wl,-no-whole-archive \ 69 | -O2 -fno-omit-frame-pointer -g -fsanitize=address,fuzzer \ 70 | -fsanitize-coverage=trace-cmp,trace-gep,trace-div -o pcre2_10.00_fuzzer 71 | 72 | mkdir corpus2 73 | ./pcre2_10.00_fuzzer ./corpus2 -print_final_stats=1 -max_total_time=300 74 | ``` 75 | 76 | Feel free to re-run the last command to see several crashes, for example: 77 | 78 | ```bash 79 | #290587 NEW cov: 1884 ft: 7593 corp: 2868/129Kb exec/s: 5381 rss: 522Mb L: 62 MS: 1 ChangeBit- 80 | ================================================================= 81 | ==17288==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x6040005d164f at pc 0x000000585f99 bp 0x7fff827c53d0 sp 0x7fff827c53c8 82 | READ of size 1 at 0x6040005d164f thread T0 83 | #0 0x585f98 in match /home/mmoroz/projects/libfuzzer-workshop/lessons/10/pcre2-10.00/src/pcre2_match.c:5968:11 84 | #1 0x549d4b in pcre2_match_8 /home/mmoroz/projects/libfuzzer-workshop/lessons/10/pcre2-10.00/src/pcre2_match.c:6876:8 85 | #2 0x59bfa5 in regexec /home/mmoroz/projects/libfuzzer-workshop/lessons/10/pcre2-10.00/src/pcre2posix.c:291:6 86 | #3 0x4f093a in LLVMFuzzerTestOneInput /home/mmoroz/projects/libfuzzer-workshop/lessons/10/pcre2_fuzzer.cc:21:5 87 | <...> 88 | ``` 89 | 90 | and 91 | 92 | ```bash 93 | #473083 NEW cov: 2325 ft: 9716 corp: 3963/184Kb exec/s: 2263 rss: 697Mb L: 64 MS: 2 ChangeBinInt-ShuffleBytes- 94 | ================================================================= 95 | ==17265==ERROR: AddressSanitizer: heap-use-after-free on address 0x61000012caca at pc 0x000000585e83 bp 0x7ffcb3379bd0 sp 0x7ffcb3379bc8 96 | READ of size 1 at 0x61000012caca thread T0 97 | #0 0x585e82 in match /home/mmoroz/projects/libfuzzer-workshop/lessons/10/pcre2-10.00/src/pcre2_match.c:1426:16 98 | #1 0x549d4b in pcre2_match_8 /home/mmoroz/projects/libfuzzer-workshop/lessons/10/pcre2-10.00/src/pcre2_match.c:6876:8 99 | #2 0x59bfa5 in regexec /home/mmoroz/projects/libfuzzer-workshop/lessons/10/pcre2-10.00/src/pcre2posix.c:291:6 100 | #3 0x4f093a in LLVMFuzzerTestOneInput /home/mmoroz/projects/libfuzzer-workshop/lessons/10/pcre2_fuzzer.cc:21:5 101 | <...> 102 | ``` 103 | 104 | 105 | 106 | [pcre2]: http://www.pcre.org/current/doc/html/pcre2.html 107 | -------------------------------------------------------------------------------- /lessons/11/pcre2-10.00.tgz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dor1s/libfuzzer-workshop/35dd05ed4edce6b80a296d8d6b4579becec4d824/lessons/11/pcre2-10.00.tgz -------------------------------------------------------------------------------- /lessons/11/pcre2.tgz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dor1s/libfuzzer-workshop/35dd05ed4edce6b80a296d8d6b4579becec4d824/lessons/11/pcre2.tgz -------------------------------------------------------------------------------- /lessons/11/pcre2_fuzzer.cc: -------------------------------------------------------------------------------- 1 | // Copyright 2016 Google Inc. All Rights Reserved. 2 | // Licensed under the Apache License, Version 2.0 (the "License"); 3 | 4 | #include 5 | #include 6 | 7 | #include 8 | 9 | #include "pcre2posix.h" 10 | 11 | using std::string; 12 | 13 | extern "C" int LLVMFuzzerTestOneInput(const unsigned char *data, size_t size) { 14 | if (size < 1) return 0; 15 | regex_t preg; 16 | string str(reinterpret_cast(data), size); 17 | string pat(str); 18 | int flags = data[size/2] - 'a'; // Make it 0 when the byte is 'a'. 19 | if (0 == regcomp(&preg, pat.c_str(), flags)) { 20 | regmatch_t pmatch[5]; 21 | regexec(&preg, str.c_str(), 5, pmatch, 0); 22 | regfree(&preg); 23 | } 24 | return 0; 25 | } 26 | -------------------------------------------------------------------------------- /lessons/12/Modern_Fuzzing_of_C_C++_projects_slides_63-70.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dor1s/libfuzzer-workshop/35dd05ed4edce6b80a296d8d6b4579becec4d824/lessons/12/Modern_Fuzzing_of_C_C++_projects_slides_63-70.pdf -------------------------------------------------------------------------------- /lessons/12/README.md: -------------------------------------------------------------------------------- 1 | # Lesson 12 2 | 3 | This is a theoretical lesson with a homework assignment, see the slides. 4 | 5 | ## Assignment: 6 | 7 | 1. check out [Chromium] repository 8 | 2. try to [build existing fuzzers] 9 | 3. write a new one 10 | 11 | [Codesearch] is a pretty useful instrument to find [existing targets] and to 12 | search for [new ones] as well. 13 | 14 | Once you find a bug with it, submit your fuzzer to [Chrome Fuzzer Program]. 15 | 16 | **Happy fuzzing!** 17 | 18 | 19 | [Chromium]: https://www.chromium.org/developers/how-tos/get-the-code 20 | [Chrome Fuzzer Program]: https://www.google.com/about/appsecurity/chrome-rewards/index.html#fuzzerprogram 21 | [Codesearch]: https://cs.chromium.org/ 22 | [build existing fuzzers]: https://chromium.googlesource.com/chromium/src/+/master/testing/libfuzzer/reproducing.md#Reproducing-LibFuzzer-ASan-bugs 23 | [existing targets]: https://cs.chromium.org/search/?q=LLVMFuzzerTestOneInput&sq=package:chromium&type=cs 24 | [new ones]: https://cs.chromium.org/search/?q=file:.*%5C.h+%22const+uint8_t*%22&sq=package:chromium&type=cs 25 | -------------------------------------------------------------------------------- /libFuzzer/Fuzzer/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(LIBFUZZER_SOURCES 2 | FuzzerCrossOver.cpp 3 | FuzzerDataFlowTrace.cpp 4 | FuzzerDriver.cpp 5 | FuzzerExtFunctionsDlsym.cpp 6 | FuzzerExtFunctionsWeak.cpp 7 | FuzzerExtFunctionsWindows.cpp 8 | FuzzerExtraCounters.cpp 9 | FuzzerFork.cpp 10 | FuzzerIO.cpp 11 | FuzzerIOPosix.cpp 12 | FuzzerIOWindows.cpp 13 | FuzzerLoop.cpp 14 | FuzzerMerge.cpp 15 | FuzzerMutate.cpp 16 | FuzzerSHA1.cpp 17 | FuzzerTracePC.cpp 18 | FuzzerUtil.cpp 19 | FuzzerUtilDarwin.cpp 20 | FuzzerUtilFuchsia.cpp 21 | FuzzerUtilLinux.cpp 22 | FuzzerUtilPosix.cpp 23 | FuzzerUtilWindows.cpp) 24 | 25 | set(LIBFUZZER_HEADERS 26 | FuzzerBuiltins.h 27 | FuzzerBuiltinsMsvc.h 28 | FuzzerCommand.h 29 | FuzzerCorpus.h 30 | FuzzerDataFlowTrace.h 31 | FuzzerDefs.h 32 | FuzzerDictionary.h 33 | FuzzerExtFunctions.def 34 | FuzzerExtFunctions.h 35 | FuzzerFlags.def 36 | FuzzerFork.h 37 | FuzzerIO.h 38 | FuzzerInterface.h 39 | FuzzerInternal.h 40 | FuzzerMerge.h 41 | FuzzerMutate.h 42 | FuzzerOptions.h 43 | FuzzerRandom.h 44 | FuzzerSHA1.h 45 | FuzzerTracePC.h 46 | FuzzerUtil.h 47 | FuzzerValueBitMap.h) 48 | 49 | CHECK_CXX_SOURCE_COMPILES(" 50 | static thread_local int blah; 51 | int main() { 52 | return 0; 53 | } 54 | " HAS_THREAD_LOCAL) 55 | 56 | set(LIBFUZZER_CFLAGS ${SANITIZER_COMMON_CFLAGS}) 57 | 58 | if(OS_NAME MATCHES "Linux|Fuchsia" AND 59 | COMPILER_RT_LIBCXX_PATH AND 60 | COMPILER_RT_LIBCXXABI_PATH) 61 | list(APPEND LIBFUZZER_CFLAGS -nostdinc++ -D_LIBCPP_ABI_VERSION=Fuzzer) 62 | # Remove -stdlib= which is unused when passing -nostdinc++. 63 | string(REGEX REPLACE "-stdlib=[a-zA-Z+]*" "" CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS}) 64 | elseif(TARGET cxx-headers OR HAVE_LIBCXX) 65 | set(LIBFUZZER_DEPS cxx-headers) 66 | endif() 67 | 68 | append_list_if(COMPILER_RT_HAS_OMIT_FRAME_POINTER_FLAG -fno-omit-frame-pointer LIBFUZZER_CFLAGS) 69 | 70 | if (CMAKE_CXX_FLAGS MATCHES "fsanitize-coverage") 71 | list(APPEND LIBFUZZER_CFLAGS -fno-sanitize-coverage=trace-pc-guard,edge,trace-cmp,indirect-calls,8bit-counters) 72 | endif() 73 | 74 | if(MSVC) 75 | # Silence warnings by turning off exceptions in MSVC headers and avoid an 76 | # error by unecessarily defining thread_local when it isn't even used on 77 | # Windows. 78 | list(APPEND LIBFUZZER_CFLAGS -D_HAS_EXCEPTIONS=0) 79 | else() 80 | if(NOT HAS_THREAD_LOCAL) 81 | list(APPEND LIBFUZZER_CFLAGS -Dthread_local=__thread) 82 | endif() 83 | endif() 84 | 85 | set(FUZZER_SUPPORTED_OS ${SANITIZER_COMMON_SUPPORTED_OS}) 86 | 87 | add_compiler_rt_component(fuzzer) 88 | 89 | add_compiler_rt_object_libraries(RTfuzzer 90 | OS ${FUZZER_SUPPORTED_OS} 91 | ARCHS ${FUZZER_SUPPORTED_ARCH} 92 | SOURCES ${LIBFUZZER_SOURCES} 93 | ADDITIONAL_HEADERS ${LIBFUZZER_HEADERS} 94 | CFLAGS ${LIBFUZZER_CFLAGS} 95 | DEPS ${LIBFUZZER_DEPS}) 96 | 97 | add_compiler_rt_object_libraries(RTfuzzer_main 98 | OS ${FUZZER_SUPPORTED_OS} 99 | ARCHS ${FUZZER_SUPPORTED_ARCH} 100 | SOURCES FuzzerMain.cpp 101 | CFLAGS ${LIBFUZZER_CFLAGS} 102 | DEPS ${LIBFUZZER_DEPS}) 103 | 104 | add_compiler_rt_runtime(clang_rt.fuzzer 105 | STATIC 106 | OS ${FUZZER_SUPPORTED_OS} 107 | ARCHS ${FUZZER_SUPPORTED_ARCH} 108 | OBJECT_LIBS RTfuzzer RTfuzzer_main 109 | CFLAGS ${LIBFUZZER_CFLAGS} 110 | PARENT_TARGET fuzzer) 111 | 112 | add_compiler_rt_runtime(clang_rt.fuzzer_no_main 113 | STATIC 114 | OS ${FUZZER_SUPPORTED_OS} 115 | ARCHS ${FUZZER_SUPPORTED_ARCH} 116 | OBJECT_LIBS RTfuzzer 117 | CFLAGS ${LIBFUZZER_CFLAGS} 118 | PARENT_TARGET fuzzer) 119 | 120 | if(OS_NAME MATCHES "Linux|Fuchsia" AND 121 | COMPILER_RT_LIBCXX_PATH AND 122 | COMPILER_RT_LIBCXXABI_PATH) 123 | macro(partially_link_libcxx name dir arch) 124 | if(${arch} MATCHES "i386") 125 | set(EMULATION_ARGUMENT "-m" "elf_i386") 126 | else() 127 | set(EMULATION_ARGUMENT "") 128 | endif() 129 | set(cxx_${arch}_merge_dir "${CMAKE_CURRENT_BINARY_DIR}/cxx_${arch}_merge.dir") 130 | file(MAKE_DIRECTORY ${cxx_${arch}_merge_dir}) 131 | add_custom_command(TARGET clang_rt.${name}-${arch} POST_BUILD 132 | COMMAND ${CMAKE_LINKER} ${EMULATION_ARGUMENT} --whole-archive "$" --no-whole-archive ${dir}/lib/libc++.a -r -o ${name}.o 133 | COMMAND ${CMAKE_OBJCOPY} --localize-hidden ${name}.o 134 | COMMAND ${CMAKE_COMMAND} -E remove "$" 135 | COMMAND ${CMAKE_AR} qcs "$" ${name}.o 136 | WORKING_DIRECTORY ${cxx_${arch}_merge_dir} 137 | ) 138 | endmacro() 139 | 140 | foreach(arch ${FUZZER_SUPPORTED_ARCH}) 141 | get_target_flags_for_arch(${arch} TARGET_CFLAGS) 142 | set(LIBCXX_${arch}_PREFIX ${CMAKE_CURRENT_BINARY_DIR}/libcxx_fuzzer_${arch}) 143 | add_custom_libcxx(libcxx_fuzzer_${arch} ${LIBCXX_${arch}_PREFIX} 144 | CFLAGS ${TARGET_CFLAGS} 145 | CMAKE_ARGS -DCMAKE_CXX_COMPILER_WORKS=ON 146 | -DCMAKE_POSITION_INDEPENDENT_CODE=ON 147 | -DLIBCXX_ABI_NAMESPACE=Fuzzer) 148 | target_compile_options(RTfuzzer.${arch} PRIVATE -isystem ${LIBCXX_${arch}_PREFIX}/include/c++/v1) 149 | add_dependencies(RTfuzzer.${arch} libcxx_fuzzer_${arch}-build) 150 | target_compile_options(RTfuzzer_main.${arch} PRIVATE -isystem ${LIBCXX_${arch}_PREFIX}/include/c++/v1) 151 | add_dependencies(RTfuzzer_main.${arch} libcxx_fuzzer_${arch}-build) 152 | partially_link_libcxx(fuzzer_no_main ${LIBCXX_${arch}_PREFIX} ${arch}) 153 | partially_link_libcxx(fuzzer ${LIBCXX_${arch}_PREFIX} ${arch}) 154 | endforeach() 155 | endif() 156 | 157 | if(COMPILER_RT_INCLUDE_TESTS) 158 | add_subdirectory(tests) 159 | endif() 160 | -------------------------------------------------------------------------------- /libFuzzer/Fuzzer/FuzzerBuiltins.h: -------------------------------------------------------------------------------- 1 | //===- FuzzerBuiltins.h - Internal header for builtins ----------*- C++ -* ===// 2 | // 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 | // See https://llvm.org/LICENSE.txt for license information. 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 | // 7 | //===----------------------------------------------------------------------===// 8 | // Wrapper functions and marcos around builtin functions. 9 | //===----------------------------------------------------------------------===// 10 | 11 | #ifndef LLVM_FUZZER_BUILTINS_H 12 | #define LLVM_FUZZER_BUILTINS_H 13 | 14 | #include "FuzzerDefs.h" 15 | 16 | #if !LIBFUZZER_MSVC 17 | #include 18 | 19 | #define GET_CALLER_PC() __builtin_return_address(0) 20 | 21 | namespace fuzzer { 22 | 23 | inline uint8_t Bswap(uint8_t x) { return x; } 24 | inline uint16_t Bswap(uint16_t x) { return __builtin_bswap16(x); } 25 | inline uint32_t Bswap(uint32_t x) { return __builtin_bswap32(x); } 26 | inline uint64_t Bswap(uint64_t x) { return __builtin_bswap64(x); } 27 | 28 | inline uint32_t Clzll(unsigned long long X) { return __builtin_clzll(X); } 29 | inline uint32_t Clz(unsigned long long X) { return __builtin_clz(X); } 30 | inline int Popcountll(unsigned long long X) { return __builtin_popcountll(X); } 31 | 32 | } // namespace fuzzer 33 | 34 | #endif // !LIBFUZZER_MSVC 35 | #endif // LLVM_FUZZER_BUILTINS_H 36 | -------------------------------------------------------------------------------- /libFuzzer/Fuzzer/FuzzerBuiltinsMsvc.h: -------------------------------------------------------------------------------- 1 | //===- FuzzerBuiltinsMSVC.h - Internal header for builtins ------*- C++ -* ===// 2 | // 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 | // See https://llvm.org/LICENSE.txt for license information. 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 | // 7 | //===----------------------------------------------------------------------===// 8 | // Wrapper functions and marcos that use intrinsics instead of builtin functions 9 | // which cannot be compiled by MSVC. 10 | //===----------------------------------------------------------------------===// 11 | 12 | #ifndef LLVM_FUZZER_BUILTINS_MSVC_H 13 | #define LLVM_FUZZER_BUILTINS_MSVC_H 14 | 15 | #include "FuzzerDefs.h" 16 | 17 | #if LIBFUZZER_MSVC 18 | #include 19 | #include 20 | #include 21 | 22 | // __builtin_return_address() cannot be compiled with MSVC. Use the equivalent 23 | // from 24 | #define GET_CALLER_PC() _ReturnAddress() 25 | 26 | namespace fuzzer { 27 | 28 | inline uint8_t Bswap(uint8_t x) { return x; } 29 | // Use alternatives to __builtin functions from and on 30 | // Windows since the builtins are not supported by MSVC. 31 | inline uint16_t Bswap(uint16_t x) { return _byteswap_ushort(x); } 32 | inline uint32_t Bswap(uint32_t x) { return _byteswap_ulong(x); } 33 | inline uint64_t Bswap(uint64_t x) { return _byteswap_uint64(x); } 34 | 35 | // The functions below were mostly copied from 36 | // compiler-rt/lib/builtins/int_lib.h which defines the __builtin functions used 37 | // outside of Windows. 38 | inline uint32_t Clzll(uint64_t X) { 39 | unsigned long LeadZeroIdx = 0; 40 | 41 | #if !defined(_M_ARM) && !defined(_M_X64) 42 | // Scan the high 32 bits. 43 | if (_BitScanReverse(&LeadZeroIdx, static_cast(X >> 32))) 44 | return static_cast(63 - (LeadZeroIdx + 32)); // Create a bit offset from the MSB. 45 | // Scan the low 32 bits. 46 | if (_BitScanReverse(&LeadZeroIdx, static_cast(X))) 47 | return static_cast(63 - LeadZeroIdx); 48 | 49 | #else 50 | if (_BitScanReverse64(&LeadZeroIdx, X)) return 63 - LeadZeroIdx; 51 | #endif 52 | return 64; 53 | } 54 | 55 | inline uint32_t Clz(uint32_t X) { 56 | unsigned long LeadZeroIdx = 0; 57 | if (_BitScanReverse(&LeadZeroIdx, X)) return 31 - LeadZeroIdx; 58 | return 32; 59 | } 60 | 61 | inline int Popcountll(unsigned long long X) { 62 | #if !defined(_M_ARM) && !defined(_M_X64) 63 | return __popcnt(X) + __popcnt(X >> 32); 64 | #else 65 | return __popcnt64(X); 66 | #endif 67 | } 68 | 69 | } // namespace fuzzer 70 | 71 | #endif // LIBFUZER_MSVC 72 | #endif // LLVM_FUZZER_BUILTINS_MSVC_H 73 | -------------------------------------------------------------------------------- /libFuzzer/Fuzzer/FuzzerCommand.h: -------------------------------------------------------------------------------- 1 | //===- FuzzerCommand.h - Interface representing a process -------*- C++ -* ===// 2 | // 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 | // See https://llvm.org/LICENSE.txt for license information. 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 | // 7 | //===----------------------------------------------------------------------===// 8 | // FuzzerCommand represents a command to run in a subprocess. It allows callers 9 | // to manage command line arguments and output and error streams. 10 | //===----------------------------------------------------------------------===// 11 | 12 | #ifndef LLVM_FUZZER_COMMAND_H 13 | #define LLVM_FUZZER_COMMAND_H 14 | 15 | #include "FuzzerDefs.h" 16 | #include "FuzzerIO.h" 17 | 18 | #include 19 | #include 20 | #include 21 | #include 22 | 23 | namespace fuzzer { 24 | 25 | class Command final { 26 | public: 27 | // This command line flag is used to indicate that the remaining command line 28 | // is immutable, meaning this flag effectively marks the end of the mutable 29 | // argument list. 30 | static inline const char *ignoreRemainingArgs() { 31 | return "-ignore_remaining_args=1"; 32 | } 33 | 34 | Command() : CombinedOutAndErr(false) {} 35 | 36 | explicit Command(const Vector &ArgsToAdd) 37 | : Args(ArgsToAdd), CombinedOutAndErr(false) {} 38 | 39 | explicit Command(const Command &Other) 40 | : Args(Other.Args), CombinedOutAndErr(Other.CombinedOutAndErr), 41 | OutputFile(Other.OutputFile) {} 42 | 43 | Command &operator=(const Command &Other) { 44 | Args = Other.Args; 45 | CombinedOutAndErr = Other.CombinedOutAndErr; 46 | OutputFile = Other.OutputFile; 47 | return *this; 48 | } 49 | 50 | ~Command() {} 51 | 52 | // Returns true if the given Arg is present in Args. Only checks up to 53 | // "-ignore_remaining_args=1". 54 | bool hasArgument(const std::string &Arg) const { 55 | auto i = endMutableArgs(); 56 | return std::find(Args.begin(), i, Arg) != i; 57 | } 58 | 59 | // Gets all of the current command line arguments, **including** those after 60 | // "-ignore-remaining-args=1". 61 | const Vector &getArguments() const { return Args; } 62 | 63 | // Adds the given argument before "-ignore_remaining_args=1", or at the end 64 | // if that flag isn't present. 65 | void addArgument(const std::string &Arg) { 66 | Args.insert(endMutableArgs(), Arg); 67 | } 68 | 69 | // Adds all given arguments before "-ignore_remaining_args=1", or at the end 70 | // if that flag isn't present. 71 | void addArguments(const Vector &ArgsToAdd) { 72 | Args.insert(endMutableArgs(), ArgsToAdd.begin(), ArgsToAdd.end()); 73 | } 74 | 75 | // Removes the given argument from the command argument list. Ignores any 76 | // occurrences after "-ignore_remaining_args=1", if present. 77 | void removeArgument(const std::string &Arg) { 78 | auto i = endMutableArgs(); 79 | Args.erase(std::remove(Args.begin(), i, Arg), i); 80 | } 81 | 82 | // Like hasArgument, but checks for "-[Flag]=...". 83 | bool hasFlag(const std::string &Flag) const { 84 | std::string Arg("-" + Flag + "="); 85 | auto IsMatch = [&](const std::string &Other) { 86 | return Arg.compare(0, std::string::npos, Other, 0, Arg.length()) == 0; 87 | }; 88 | return std::any_of(Args.begin(), endMutableArgs(), IsMatch); 89 | } 90 | 91 | // Returns the value of the first instance of a given flag, or an empty string 92 | // if the flag isn't present. Ignores any occurrences after 93 | // "-ignore_remaining_args=1", if present. 94 | std::string getFlagValue(const std::string &Flag) const { 95 | std::string Arg("-" + Flag + "="); 96 | auto IsMatch = [&](const std::string &Other) { 97 | return Arg.compare(0, std::string::npos, Other, 0, Arg.length()) == 0; 98 | }; 99 | auto i = endMutableArgs(); 100 | auto j = std::find_if(Args.begin(), i, IsMatch); 101 | std::string result; 102 | if (j != i) { 103 | result = j->substr(Arg.length()); 104 | } 105 | return result; 106 | } 107 | 108 | // Like AddArgument, but adds "-[Flag]=[Value]". 109 | void addFlag(const std::string &Flag, const std::string &Value) { 110 | addArgument("-" + Flag + "=" + Value); 111 | } 112 | 113 | // Like RemoveArgument, but removes "-[Flag]=...". 114 | void removeFlag(const std::string &Flag) { 115 | std::string Arg("-" + Flag + "="); 116 | auto IsMatch = [&](const std::string &Other) { 117 | return Arg.compare(0, std::string::npos, Other, 0, Arg.length()) == 0; 118 | }; 119 | auto i = endMutableArgs(); 120 | Args.erase(std::remove_if(Args.begin(), i, IsMatch), i); 121 | } 122 | 123 | // Returns whether the command's stdout is being written to an output file. 124 | bool hasOutputFile() const { return !OutputFile.empty(); } 125 | 126 | // Returns the currently set output file. 127 | const std::string &getOutputFile() const { return OutputFile; } 128 | 129 | // Configures the command to redirect its output to the name file. 130 | void setOutputFile(const std::string &FileName) { OutputFile = FileName; } 131 | 132 | // Returns whether the command's stderr is redirected to stdout. 133 | bool isOutAndErrCombined() const { return CombinedOutAndErr; } 134 | 135 | // Sets whether to redirect the command's stderr to its stdout. 136 | void combineOutAndErr(bool combine = true) { CombinedOutAndErr = combine; } 137 | 138 | // Returns a string representation of the command. On many systems this will 139 | // be the equivalent command line. 140 | std::string toString() const { 141 | std::stringstream SS; 142 | for (auto arg : getArguments()) 143 | SS << arg << " "; 144 | if (hasOutputFile()) 145 | SS << ">" << getOutputFile() << " "; 146 | if (isOutAndErrCombined()) 147 | SS << "2>&1 "; 148 | std::string result = SS.str(); 149 | if (!result.empty()) 150 | result = result.substr(0, result.length() - 1); 151 | return result; 152 | } 153 | 154 | private: 155 | Command(Command &&Other) = delete; 156 | Command &operator=(Command &&Other) = delete; 157 | 158 | Vector::iterator endMutableArgs() { 159 | return std::find(Args.begin(), Args.end(), ignoreRemainingArgs()); 160 | } 161 | 162 | Vector::const_iterator endMutableArgs() const { 163 | return std::find(Args.begin(), Args.end(), ignoreRemainingArgs()); 164 | } 165 | 166 | // The command arguments. Args[0] is the command name. 167 | Vector Args; 168 | 169 | // True indicates stderr is redirected to stdout. 170 | bool CombinedOutAndErr; 171 | 172 | // If not empty, stdout is redirected to the named file. 173 | std::string OutputFile; 174 | }; 175 | 176 | } // namespace fuzzer 177 | 178 | #endif // LLVM_FUZZER_COMMAND_H 179 | -------------------------------------------------------------------------------- /libFuzzer/Fuzzer/FuzzerCrossOver.cpp: -------------------------------------------------------------------------------- 1 | //===- FuzzerCrossOver.cpp - Cross over two test inputs -------------------===// 2 | // 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 | // See https://llvm.org/LICENSE.txt for license information. 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 | // 7 | //===----------------------------------------------------------------------===// 8 | // Cross over test inputs. 9 | //===----------------------------------------------------------------------===// 10 | 11 | #include "FuzzerDefs.h" 12 | #include "FuzzerMutate.h" 13 | #include "FuzzerRandom.h" 14 | #include 15 | 16 | namespace fuzzer { 17 | 18 | // Cross Data1 and Data2, store the result (up to MaxOutSize bytes) in Out. 19 | size_t MutationDispatcher::CrossOver(const uint8_t *Data1, size_t Size1, 20 | const uint8_t *Data2, size_t Size2, 21 | uint8_t *Out, size_t MaxOutSize) { 22 | assert(Size1 || Size2); 23 | MaxOutSize = Rand(MaxOutSize) + 1; 24 | size_t OutPos = 0; 25 | size_t Pos1 = 0; 26 | size_t Pos2 = 0; 27 | size_t *InPos = &Pos1; 28 | size_t InSize = Size1; 29 | const uint8_t *Data = Data1; 30 | bool CurrentlyUsingFirstData = true; 31 | while (OutPos < MaxOutSize && (Pos1 < Size1 || Pos2 < Size2)) { 32 | // Merge a part of Data into Out. 33 | size_t OutSizeLeft = MaxOutSize - OutPos; 34 | if (*InPos < InSize) { 35 | size_t InSizeLeft = InSize - *InPos; 36 | size_t MaxExtraSize = std::min(OutSizeLeft, InSizeLeft); 37 | size_t ExtraSize = Rand(MaxExtraSize) + 1; 38 | memcpy(Out + OutPos, Data + *InPos, ExtraSize); 39 | OutPos += ExtraSize; 40 | (*InPos) += ExtraSize; 41 | } 42 | // Use the other input data on the next iteration. 43 | InPos = CurrentlyUsingFirstData ? &Pos2 : &Pos1; 44 | InSize = CurrentlyUsingFirstData ? Size2 : Size1; 45 | Data = CurrentlyUsingFirstData ? Data2 : Data1; 46 | CurrentlyUsingFirstData = !CurrentlyUsingFirstData; 47 | } 48 | return OutPos; 49 | } 50 | 51 | } // namespace fuzzer 52 | -------------------------------------------------------------------------------- /libFuzzer/Fuzzer/FuzzerDataFlowTrace.h: -------------------------------------------------------------------------------- 1 | //===- FuzzerDataFlowTrace.h - Internal header for the Fuzzer ---*- C++ -* ===// 2 | // 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 | // See https://llvm.org/LICENSE.txt for license information. 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 | // 7 | //===----------------------------------------------------------------------===// 8 | // fuzzer::DataFlowTrace; reads and handles a data-flow trace. 9 | // 10 | // A data flow trace is generated by e.g. dataflow/DataFlow.cpp 11 | // and is stored on disk in a separate directory. 12 | // 13 | // The trace dir contains a file 'functions.txt' which lists function names, 14 | // oner per line, e.g. 15 | // ==> functions.txt <== 16 | // Func2 17 | // LLVMFuzzerTestOneInput 18 | // Func1 19 | // 20 | // All other files in the dir are the traces, see dataflow/DataFlow.cpp. 21 | // The name of the file is sha1 of the input used to generate the trace. 22 | // 23 | // Current status: 24 | // the data is parsed and the summary is printed, but the data is not yet 25 | // used in any other way. 26 | //===----------------------------------------------------------------------===// 27 | 28 | #ifndef LLVM_FUZZER_DATA_FLOW_TRACE 29 | #define LLVM_FUZZER_DATA_FLOW_TRACE 30 | 31 | #include "FuzzerDefs.h" 32 | #include "FuzzerIO.h" 33 | 34 | #include 35 | #include 36 | #include 37 | #include 38 | 39 | namespace fuzzer { 40 | 41 | int CollectDataFlow(const std::string &DFTBinary, const std::string &DirPath, 42 | const Vector &CorporaFiles); 43 | 44 | class BlockCoverage { 45 | public: 46 | bool AppendCoverage(std::istream &IN); 47 | bool AppendCoverage(const std::string &S); 48 | 49 | size_t NumCoveredFunctions() const { return Functions.size(); } 50 | 51 | uint32_t GetCounter(size_t FunctionId, size_t BasicBlockId) { 52 | auto It = Functions.find(FunctionId); 53 | if (It == Functions.end()) return 0; 54 | const auto &Counters = It->second; 55 | if (BasicBlockId < Counters.size()) 56 | return Counters[BasicBlockId]; 57 | return 0; 58 | } 59 | 60 | uint32_t GetNumberOfBlocks(size_t FunctionId) { 61 | auto It = Functions.find(FunctionId); 62 | if (It == Functions.end()) return 0; 63 | const auto &Counters = It->second; 64 | return Counters.size(); 65 | } 66 | 67 | uint32_t GetNumberOfCoveredBlocks(size_t FunctionId) { 68 | auto It = Functions.find(FunctionId); 69 | if (It == Functions.end()) return 0; 70 | const auto &Counters = It->second; 71 | uint32_t Result = 0; 72 | for (auto Cnt: Counters) 73 | if (Cnt) 74 | Result++; 75 | return Result; 76 | } 77 | 78 | Vector FunctionWeights(size_t NumFunctions) const; 79 | void clear() { Functions.clear(); } 80 | 81 | private: 82 | 83 | typedef Vector CoverageVector; 84 | 85 | uint32_t NumberOfCoveredBlocks(const CoverageVector &Counters) const { 86 | uint32_t Res = 0; 87 | for (auto Cnt : Counters) 88 | if (Cnt) 89 | Res++; 90 | return Res; 91 | } 92 | 93 | uint32_t NumberOfUncoveredBlocks(const CoverageVector &Counters) const { 94 | return Counters.size() - NumberOfCoveredBlocks(Counters); 95 | } 96 | 97 | uint32_t SmallestNonZeroCounter(const CoverageVector &Counters) const { 98 | assert(!Counters.empty()); 99 | uint32_t Res = Counters[0]; 100 | for (auto Cnt : Counters) 101 | if (Cnt) 102 | Res = Min(Res, Cnt); 103 | assert(Res); 104 | return Res; 105 | } 106 | 107 | // Function ID => vector of counters. 108 | // Each counter represents how many input files trigger the given basic block. 109 | std::unordered_map Functions; 110 | // Functions that have DFT entry. 111 | std::unordered_set FunctionsWithDFT; 112 | }; 113 | 114 | class DataFlowTrace { 115 | public: 116 | void ReadCoverage(const std::string &DirPath); 117 | bool Init(const std::string &DirPath, std::string *FocusFunction, 118 | Vector &CorporaFiles, Random &Rand); 119 | void Clear() { Traces.clear(); } 120 | const Vector *Get(const std::string &InputSha1) const { 121 | auto It = Traces.find(InputSha1); 122 | if (It != Traces.end()) 123 | return &It->second; 124 | return nullptr; 125 | } 126 | 127 | private: 128 | // Input's sha1 => DFT for the FocusFunction. 129 | std::unordered_map > Traces; 130 | BlockCoverage Coverage; 131 | std::unordered_set CorporaHashes; 132 | }; 133 | } // namespace fuzzer 134 | 135 | #endif // LLVM_FUZZER_DATA_FLOW_TRACE 136 | -------------------------------------------------------------------------------- /libFuzzer/Fuzzer/FuzzerDefs.h: -------------------------------------------------------------------------------- 1 | //===- FuzzerDefs.h - Internal header for the Fuzzer ------------*- C++ -* ===// 2 | // 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 | // See https://llvm.org/LICENSE.txt for license information. 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 | // 7 | //===----------------------------------------------------------------------===// 8 | // Basic definitions. 9 | //===----------------------------------------------------------------------===// 10 | 11 | #ifndef LLVM_FUZZER_DEFS_H 12 | #define LLVM_FUZZER_DEFS_H 13 | 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | 23 | 24 | // Platform detection. 25 | #ifdef __linux__ 26 | #define LIBFUZZER_APPLE 0 27 | #define LIBFUZZER_FUCHSIA 0 28 | #define LIBFUZZER_LINUX 1 29 | #define LIBFUZZER_NETBSD 0 30 | #define LIBFUZZER_FREEBSD 0 31 | #define LIBFUZZER_OPENBSD 0 32 | #define LIBFUZZER_WINDOWS 0 33 | #elif __APPLE__ 34 | #define LIBFUZZER_APPLE 1 35 | #define LIBFUZZER_FUCHSIA 0 36 | #define LIBFUZZER_LINUX 0 37 | #define LIBFUZZER_NETBSD 0 38 | #define LIBFUZZER_FREEBSD 0 39 | #define LIBFUZZER_OPENBSD 0 40 | #define LIBFUZZER_WINDOWS 0 41 | #elif __NetBSD__ 42 | #define LIBFUZZER_APPLE 0 43 | #define LIBFUZZER_FUCHSIA 0 44 | #define LIBFUZZER_LINUX 0 45 | #define LIBFUZZER_NETBSD 1 46 | #define LIBFUZZER_FREEBSD 0 47 | #define LIBFUZZER_OPENBSD 0 48 | #define LIBFUZZER_WINDOWS 0 49 | #elif __FreeBSD__ 50 | #define LIBFUZZER_APPLE 0 51 | #define LIBFUZZER_FUCHSIA 0 52 | #define LIBFUZZER_LINUX 0 53 | #define LIBFUZZER_NETBSD 0 54 | #define LIBFUZZER_FREEBSD 1 55 | #define LIBFUZZER_OPENBSD 0 56 | #define LIBFUZZER_WINDOWS 0 57 | #elif __OpenBSD__ 58 | #define LIBFUZZER_APPLE 0 59 | #define LIBFUZZER_FUCHSIA 0 60 | #define LIBFUZZER_LINUX 0 61 | #define LIBFUZZER_NETBSD 0 62 | #define LIBFUZZER_FREEBSD 0 63 | #define LIBFUZZER_OPENBSD 1 64 | #define LIBFUZZER_WINDOWS 0 65 | #elif _WIN32 66 | #define LIBFUZZER_APPLE 0 67 | #define LIBFUZZER_FUCHSIA 0 68 | #define LIBFUZZER_LINUX 0 69 | #define LIBFUZZER_NETBSD 0 70 | #define LIBFUZZER_FREEBSD 0 71 | #define LIBFUZZER_OPENBSD 0 72 | #define LIBFUZZER_WINDOWS 1 73 | #elif __Fuchsia__ 74 | #define LIBFUZZER_APPLE 0 75 | #define LIBFUZZER_FUCHSIA 1 76 | #define LIBFUZZER_LINUX 0 77 | #define LIBFUZZER_NETBSD 0 78 | #define LIBFUZZER_FREEBSD 0 79 | #define LIBFUZZER_OPENBSD 0 80 | #define LIBFUZZER_WINDOWS 0 81 | #else 82 | #error "Support for your platform has not been implemented" 83 | #endif 84 | 85 | #if defined(_MSC_VER) && !defined(__clang__) 86 | // MSVC compiler is being used. 87 | #define LIBFUZZER_MSVC 1 88 | #else 89 | #define LIBFUZZER_MSVC 0 90 | #endif 91 | 92 | #ifndef __has_attribute 93 | # define __has_attribute(x) 0 94 | #endif 95 | 96 | #define LIBFUZZER_POSIX \ 97 | (LIBFUZZER_APPLE || LIBFUZZER_LINUX || LIBFUZZER_NETBSD || \ 98 | LIBFUZZER_FREEBSD || LIBFUZZER_OPENBSD) 99 | 100 | #ifdef __x86_64 101 | # if __has_attribute(target) 102 | # define ATTRIBUTE_TARGET_POPCNT __attribute__((target("popcnt"))) 103 | # else 104 | # define ATTRIBUTE_TARGET_POPCNT 105 | # endif 106 | #else 107 | # define ATTRIBUTE_TARGET_POPCNT 108 | #endif 109 | 110 | 111 | #ifdef __clang__ // avoid gcc warning. 112 | # if __has_attribute(no_sanitize) 113 | # define ATTRIBUTE_NO_SANITIZE_MEMORY __attribute__((no_sanitize("memory"))) 114 | # else 115 | # define ATTRIBUTE_NO_SANITIZE_MEMORY 116 | # endif 117 | # define ALWAYS_INLINE __attribute__((always_inline)) 118 | #else 119 | # define ATTRIBUTE_NO_SANITIZE_MEMORY 120 | # define ALWAYS_INLINE 121 | #endif // __clang__ 122 | 123 | #if LIBFUZZER_WINDOWS 124 | #define ATTRIBUTE_NO_SANITIZE_ADDRESS 125 | #else 126 | #define ATTRIBUTE_NO_SANITIZE_ADDRESS __attribute__((no_sanitize_address)) 127 | #endif 128 | 129 | #if LIBFUZZER_WINDOWS 130 | #define ATTRIBUTE_ALIGNED(X) __declspec(align(X)) 131 | #define ATTRIBUTE_INTERFACE __declspec(dllexport) 132 | // This is used for __sancov_lowest_stack which is needed for 133 | // -fsanitize-coverage=stack-depth. That feature is not yet available on 134 | // Windows, so make the symbol static to avoid linking errors. 135 | #define ATTRIBUTES_INTERFACE_TLS_INITIAL_EXEC static 136 | #define ATTRIBUTE_NOINLINE __declspec(noinline) 137 | #else 138 | #define ATTRIBUTE_ALIGNED(X) __attribute__((aligned(X))) 139 | #define ATTRIBUTE_INTERFACE __attribute__((visibility("default"))) 140 | #define ATTRIBUTES_INTERFACE_TLS_INITIAL_EXEC \ 141 | ATTRIBUTE_INTERFACE __attribute__((tls_model("initial-exec"))) thread_local 142 | 143 | #define ATTRIBUTE_NOINLINE __attribute__((noinline)) 144 | #endif 145 | 146 | #if defined(__has_feature) 147 | # if __has_feature(address_sanitizer) 148 | # define ATTRIBUTE_NO_SANITIZE_ALL ATTRIBUTE_NO_SANITIZE_ADDRESS 149 | # elif __has_feature(memory_sanitizer) 150 | # define ATTRIBUTE_NO_SANITIZE_ALL ATTRIBUTE_NO_SANITIZE_MEMORY 151 | # else 152 | # define ATTRIBUTE_NO_SANITIZE_ALL 153 | # endif 154 | #else 155 | # define ATTRIBUTE_NO_SANITIZE_ALL 156 | #endif 157 | 158 | namespace fuzzer { 159 | 160 | template T Min(T a, T b) { return a < b ? a : b; } 161 | template T Max(T a, T b) { return a > b ? a : b; } 162 | 163 | class Random; 164 | class Dictionary; 165 | class DictionaryEntry; 166 | class MutationDispatcher; 167 | struct FuzzingOptions; 168 | class InputCorpus; 169 | struct InputInfo; 170 | struct ExternalFunctions; 171 | 172 | // Global interface to functions that may or may not be available. 173 | extern ExternalFunctions *EF; 174 | 175 | // We are using a custom allocator to give a different symbol name to STL 176 | // containers in order to avoid ODR violations. 177 | template 178 | class fuzzer_allocator: public std::allocator { 179 | public: 180 | fuzzer_allocator() = default; 181 | 182 | template 183 | fuzzer_allocator(const fuzzer_allocator&) {} 184 | 185 | template 186 | struct rebind { typedef fuzzer_allocator other; }; 187 | }; 188 | 189 | template 190 | using Vector = std::vector>; 191 | 192 | template 193 | using Set = std::set, fuzzer_allocator>; 194 | 195 | typedef Vector Unit; 196 | typedef Vector UnitVector; 197 | typedef int (*UserCallback)(const uint8_t *Data, size_t Size); 198 | 199 | int FuzzerDriver(int *argc, char ***argv, UserCallback Callback); 200 | 201 | uint8_t *ExtraCountersBegin(); 202 | uint8_t *ExtraCountersEnd(); 203 | void ClearExtraCounters(); 204 | 205 | extern bool RunningUserCallback; 206 | 207 | } // namespace fuzzer 208 | 209 | #endif // LLVM_FUZZER_DEFS_H 210 | -------------------------------------------------------------------------------- /libFuzzer/Fuzzer/FuzzerDictionary.h: -------------------------------------------------------------------------------- 1 | //===- FuzzerDictionary.h - Internal header for the Fuzzer ------*- C++ -* ===// 2 | // 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 | // See https://llvm.org/LICENSE.txt for license information. 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 | // 7 | //===----------------------------------------------------------------------===// 8 | // fuzzer::Dictionary 9 | //===----------------------------------------------------------------------===// 10 | 11 | #ifndef LLVM_FUZZER_DICTIONARY_H 12 | #define LLVM_FUZZER_DICTIONARY_H 13 | 14 | #include "FuzzerDefs.h" 15 | #include "FuzzerIO.h" 16 | #include "FuzzerUtil.h" 17 | #include 18 | #include 19 | 20 | namespace fuzzer { 21 | // A simple POD sized array of bytes. 22 | template class FixedWord { 23 | public: 24 | static const size_t kMaxSize = kMaxSizeT; 25 | FixedWord() {} 26 | FixedWord(const uint8_t *B, uint8_t S) { Set(B, S); } 27 | 28 | void Set(const uint8_t *B, uint8_t S) { 29 | assert(S <= kMaxSize); 30 | memcpy(Data, B, S); 31 | Size = S; 32 | } 33 | 34 | bool operator==(const FixedWord &w) const { 35 | return Size == w.Size && 0 == memcmp(Data, w.Data, Size); 36 | } 37 | 38 | static size_t GetMaxSize() { return kMaxSize; } 39 | const uint8_t *data() const { return Data; } 40 | uint8_t size() const { return Size; } 41 | 42 | private: 43 | uint8_t Size = 0; 44 | uint8_t Data[kMaxSize]; 45 | }; 46 | 47 | typedef FixedWord<64> Word; 48 | 49 | class DictionaryEntry { 50 | public: 51 | DictionaryEntry() {} 52 | DictionaryEntry(Word W) : W(W) {} 53 | DictionaryEntry(Word W, size_t PositionHint) : W(W), PositionHint(PositionHint) {} 54 | const Word &GetW() const { return W; } 55 | 56 | bool HasPositionHint() const { return PositionHint != std::numeric_limits::max(); } 57 | size_t GetPositionHint() const { 58 | assert(HasPositionHint()); 59 | return PositionHint; 60 | } 61 | void IncUseCount() { UseCount++; } 62 | void IncSuccessCount() { SuccessCount++; } 63 | size_t GetUseCount() const { return UseCount; } 64 | size_t GetSuccessCount() const {return SuccessCount; } 65 | 66 | void Print(const char *PrintAfter = "\n") { 67 | PrintASCII(W.data(), W.size()); 68 | if (HasPositionHint()) 69 | Printf("@%zd", GetPositionHint()); 70 | Printf("%s", PrintAfter); 71 | } 72 | 73 | private: 74 | Word W; 75 | size_t PositionHint = std::numeric_limits::max(); 76 | size_t UseCount = 0; 77 | size_t SuccessCount = 0; 78 | }; 79 | 80 | class Dictionary { 81 | public: 82 | static const size_t kMaxDictSize = 1 << 14; 83 | 84 | bool ContainsWord(const Word &W) const { 85 | return std::any_of(begin(), end(), [&](const DictionaryEntry &DE) { 86 | return DE.GetW() == W; 87 | }); 88 | } 89 | const DictionaryEntry *begin() const { return &DE[0]; } 90 | const DictionaryEntry *end() const { return begin() + Size; } 91 | DictionaryEntry & operator[] (size_t Idx) { 92 | assert(Idx < Size); 93 | return DE[Idx]; 94 | } 95 | void push_back(DictionaryEntry DE) { 96 | if (Size < kMaxDictSize) 97 | this->DE[Size++] = DE; 98 | } 99 | void clear() { Size = 0; } 100 | bool empty() const { return Size == 0; } 101 | size_t size() const { return Size; } 102 | 103 | private: 104 | DictionaryEntry DE[kMaxDictSize]; 105 | size_t Size = 0; 106 | }; 107 | 108 | // Parses one dictionary entry. 109 | // If successful, write the enty to Unit and returns true, 110 | // otherwise returns false. 111 | bool ParseOneDictionaryEntry(const std::string &Str, Unit *U); 112 | // Parses the dictionary file, fills Units, returns true iff all lines 113 | // were parsed successfully. 114 | bool ParseDictionaryFile(const std::string &Text, Vector *Units); 115 | 116 | } // namespace fuzzer 117 | 118 | #endif // LLVM_FUZZER_DICTIONARY_H 119 | -------------------------------------------------------------------------------- /libFuzzer/Fuzzer/FuzzerExtFunctions.def: -------------------------------------------------------------------------------- 1 | //===- FuzzerExtFunctions.def - External functions --------------*- C++ -* ===// 2 | // 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 | // See https://llvm.org/LICENSE.txt for license information. 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 | // 7 | //===----------------------------------------------------------------------===// 8 | // This defines the external function pointers that 9 | // ``fuzzer::ExternalFunctions`` should contain and try to initialize. The 10 | // EXT_FUNC macro must be defined at the point of inclusion. The signature of 11 | // the macro is: 12 | // 13 | // EXT_FUNC(, , , ) 14 | //===----------------------------------------------------------------------===// 15 | 16 | // Optional user functions 17 | EXT_FUNC(LLVMFuzzerInitialize, int, (int *argc, char ***argv), false); 18 | EXT_FUNC(LLVMFuzzerCustomMutator, size_t, 19 | (uint8_t *Data, size_t Size, size_t MaxSize, unsigned int Seed), 20 | false); 21 | EXT_FUNC(LLVMFuzzerCustomCrossOver, size_t, 22 | (const uint8_t *Data1, size_t Size1, 23 | const uint8_t *Data2, size_t Size2, 24 | uint8_t *Out, size_t MaxOutSize, unsigned int Seed), 25 | false); 26 | 27 | // Sanitizer functions 28 | EXT_FUNC(__lsan_enable, void, (), false); 29 | EXT_FUNC(__lsan_disable, void, (), false); 30 | EXT_FUNC(__lsan_do_recoverable_leak_check, int, (), false); 31 | EXT_FUNC(__sanitizer_acquire_crash_state, int, (), true); 32 | EXT_FUNC(__sanitizer_install_malloc_and_free_hooks, int, 33 | (void (*malloc_hook)(const volatile void *, size_t), 34 | void (*free_hook)(const volatile void *)), 35 | false); 36 | EXT_FUNC(__sanitizer_log_write, void, (const char *buf, size_t len), false); 37 | EXT_FUNC(__sanitizer_purge_allocator, void, (), false); 38 | EXT_FUNC(__sanitizer_print_memory_profile, void, (size_t, size_t), false); 39 | EXT_FUNC(__sanitizer_print_stack_trace, void, (), true); 40 | EXT_FUNC(__sanitizer_symbolize_pc, void, 41 | (void *, const char *fmt, char *out_buf, size_t out_buf_size), false); 42 | EXT_FUNC(__sanitizer_get_module_and_offset_for_pc, int, 43 | (void *pc, char *module_path, 44 | size_t module_path_len,void **pc_offset), false); 45 | EXT_FUNC(__sanitizer_set_death_callback, void, (void (*)(void)), true); 46 | EXT_FUNC(__sanitizer_set_report_fd, void, (void*), false); 47 | EXT_FUNC(__msan_scoped_disable_interceptor_checks, void, (), false); 48 | EXT_FUNC(__msan_scoped_enable_interceptor_checks, void, (), false); 49 | EXT_FUNC(__msan_unpoison, void, (const volatile void *, size_t size), false); 50 | EXT_FUNC(__msan_unpoison_param, void, (size_t n), false); 51 | -------------------------------------------------------------------------------- /libFuzzer/Fuzzer/FuzzerExtFunctions.h: -------------------------------------------------------------------------------- 1 | //===- FuzzerExtFunctions.h - Interface to external functions ---*- C++ -* ===// 2 | // 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 | // See https://llvm.org/LICENSE.txt for license information. 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 | // 7 | //===----------------------------------------------------------------------===// 8 | // Defines an interface to (possibly optional) functions. 9 | //===----------------------------------------------------------------------===// 10 | 11 | #ifndef LLVM_FUZZER_EXT_FUNCTIONS_H 12 | #define LLVM_FUZZER_EXT_FUNCTIONS_H 13 | 14 | #include 15 | #include 16 | 17 | namespace fuzzer { 18 | 19 | struct ExternalFunctions { 20 | // Initialize function pointers. Functions that are not available will be set 21 | // to nullptr. Do not call this constructor before ``main()`` has been 22 | // entered. 23 | ExternalFunctions(); 24 | 25 | #define EXT_FUNC(NAME, RETURN_TYPE, FUNC_SIG, WARN) \ 26 | RETURN_TYPE(*NAME) FUNC_SIG = nullptr 27 | 28 | #include "FuzzerExtFunctions.def" 29 | 30 | #undef EXT_FUNC 31 | }; 32 | } // namespace fuzzer 33 | 34 | #endif 35 | -------------------------------------------------------------------------------- /libFuzzer/Fuzzer/FuzzerExtFunctionsDlsym.cpp: -------------------------------------------------------------------------------- 1 | //===- FuzzerExtFunctionsDlsym.cpp - Interface to external functions ------===// 2 | // 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 | // See https://llvm.org/LICENSE.txt for license information. 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 | // 7 | //===----------------------------------------------------------------------===// 8 | // Implementation for operating systems that support dlsym(). We only use it on 9 | // Apple platforms for now. We don't use this approach on Linux because it 10 | // requires that clients of LibFuzzer pass ``--export-dynamic`` to the linker. 11 | // That is a complication we don't wish to expose to clients right now. 12 | //===----------------------------------------------------------------------===// 13 | #include "FuzzerDefs.h" 14 | #if LIBFUZZER_APPLE 15 | 16 | #include "FuzzerExtFunctions.h" 17 | #include "FuzzerIO.h" 18 | #include 19 | 20 | using namespace fuzzer; 21 | 22 | template 23 | static T GetFnPtr(const char *FnName, bool WarnIfMissing) { 24 | dlerror(); // Clear any previous errors. 25 | void *Fn = dlsym(RTLD_DEFAULT, FnName); 26 | if (Fn == nullptr) { 27 | if (WarnIfMissing) { 28 | const char *ErrorMsg = dlerror(); 29 | Printf("WARNING: Failed to find function \"%s\".", FnName); 30 | if (ErrorMsg) 31 | Printf(" Reason %s.", ErrorMsg); 32 | Printf("\n"); 33 | } 34 | } 35 | return reinterpret_cast(Fn); 36 | } 37 | 38 | namespace fuzzer { 39 | 40 | ExternalFunctions::ExternalFunctions() { 41 | #define EXT_FUNC(NAME, RETURN_TYPE, FUNC_SIG, WARN) \ 42 | this->NAME = GetFnPtr(#NAME, WARN) 43 | 44 | #include "FuzzerExtFunctions.def" 45 | 46 | #undef EXT_FUNC 47 | } 48 | 49 | } // namespace fuzzer 50 | 51 | #endif // LIBFUZZER_APPLE 52 | -------------------------------------------------------------------------------- /libFuzzer/Fuzzer/FuzzerExtFunctionsWeak.cpp: -------------------------------------------------------------------------------- 1 | //===- FuzzerExtFunctionsWeak.cpp - Interface to external functions -------===// 2 | // 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 | // See https://llvm.org/LICENSE.txt for license information. 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 | // 7 | //===----------------------------------------------------------------------===// 8 | // Implementation for Linux. This relies on the linker's support for weak 9 | // symbols. We don't use this approach on Apple platforms because it requires 10 | // clients of LibFuzzer to pass ``-U _`` to the linker to allow 11 | // weak symbols to be undefined. That is a complication we don't want to expose 12 | // to clients right now. 13 | //===----------------------------------------------------------------------===// 14 | #include "FuzzerDefs.h" 15 | #if LIBFUZZER_LINUX || LIBFUZZER_NETBSD || LIBFUZZER_FUCHSIA || \ 16 | LIBFUZZER_FREEBSD || LIBFUZZER_OPENBSD 17 | 18 | #include "FuzzerExtFunctions.h" 19 | #include "FuzzerIO.h" 20 | 21 | extern "C" { 22 | // Declare these symbols as weak to allow them to be optionally defined. 23 | #define EXT_FUNC(NAME, RETURN_TYPE, FUNC_SIG, WARN) \ 24 | __attribute__((weak, visibility("default"))) RETURN_TYPE NAME FUNC_SIG 25 | 26 | #include "FuzzerExtFunctions.def" 27 | 28 | #undef EXT_FUNC 29 | } 30 | 31 | using namespace fuzzer; 32 | 33 | static void CheckFnPtr(void *FnPtr, const char *FnName, bool WarnIfMissing) { 34 | if (FnPtr == nullptr && WarnIfMissing) { 35 | Printf("WARNING: Failed to find function \"%s\".\n", FnName); 36 | } 37 | } 38 | 39 | namespace fuzzer { 40 | 41 | ExternalFunctions::ExternalFunctions() { 42 | #define EXT_FUNC(NAME, RETURN_TYPE, FUNC_SIG, WARN) \ 43 | this->NAME = ::NAME; \ 44 | CheckFnPtr(reinterpret_cast(reinterpret_cast(::NAME)), \ 45 | #NAME, WARN); 46 | 47 | #include "FuzzerExtFunctions.def" 48 | 49 | #undef EXT_FUNC 50 | } 51 | 52 | } // namespace fuzzer 53 | 54 | #endif 55 | -------------------------------------------------------------------------------- /libFuzzer/Fuzzer/FuzzerExtFunctionsWindows.cpp: -------------------------------------------------------------------------------- 1 | //=== FuzzerExtWindows.cpp - Interface to external functions --------------===// 2 | // 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 | // See https://llvm.org/LICENSE.txt for license information. 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 | // 7 | //===----------------------------------------------------------------------===// 8 | // Implementation of FuzzerExtFunctions for Windows. Uses alternatename when 9 | // compiled with MSVC. Uses weak aliases when compiled with clang. Unfortunately 10 | // the method each compiler supports is not supported by the other. 11 | //===----------------------------------------------------------------------===// 12 | #include "FuzzerDefs.h" 13 | #if LIBFUZZER_WINDOWS 14 | 15 | #include "FuzzerExtFunctions.h" 16 | #include "FuzzerIO.h" 17 | 18 | using namespace fuzzer; 19 | 20 | // Intermediate macro to ensure the parameter is expanded before stringified. 21 | #define STRINGIFY_(A) #A 22 | #define STRINGIFY(A) STRINGIFY_(A) 23 | 24 | #if LIBFUZZER_MSVC 25 | // Copied from compiler-rt/lib/sanitizer_common/sanitizer_win_defs.h 26 | #if defined(_M_IX86) || defined(__i386__) 27 | #define WIN_SYM_PREFIX "_" 28 | #else 29 | #define WIN_SYM_PREFIX 30 | #endif 31 | 32 | // Declare external functions as having alternativenames, so that we can 33 | // determine if they are not defined. 34 | #define EXTERNAL_FUNC(Name, Default) \ 35 | __pragma(comment(linker, "/alternatename:" WIN_SYM_PREFIX STRINGIFY( \ 36 | Name) "=" WIN_SYM_PREFIX STRINGIFY(Default))) 37 | #else 38 | // Declare external functions as weak to allow them to default to a specified 39 | // function if not defined explicitly. We must use weak symbols because clang's 40 | // support for alternatename is not 100%, see 41 | // https://bugs.llvm.org/show_bug.cgi?id=40218 for more details. 42 | #define EXTERNAL_FUNC(Name, Default) \ 43 | __attribute__((weak, alias(STRINGIFY(Default)))) 44 | #endif // LIBFUZZER_MSVC 45 | 46 | extern "C" { 47 | #define EXT_FUNC(NAME, RETURN_TYPE, FUNC_SIG, WARN) \ 48 | RETURN_TYPE NAME##Def FUNC_SIG { \ 49 | Printf("ERROR: Function \"%s\" not defined.\n", #NAME); \ 50 | exit(1); \ 51 | } \ 52 | EXTERNAL_FUNC(NAME, NAME##Def) RETURN_TYPE NAME FUNC_SIG 53 | 54 | #include "FuzzerExtFunctions.def" 55 | 56 | #undef EXT_FUNC 57 | } 58 | 59 | template 60 | static T *GetFnPtr(T *Fun, T *FunDef, const char *FnName, bool WarnIfMissing) { 61 | if (Fun == FunDef) { 62 | if (WarnIfMissing) 63 | Printf("WARNING: Failed to find function \"%s\".\n", FnName); 64 | return nullptr; 65 | } 66 | return Fun; 67 | } 68 | 69 | namespace fuzzer { 70 | 71 | ExternalFunctions::ExternalFunctions() { 72 | #define EXT_FUNC(NAME, RETURN_TYPE, FUNC_SIG, WARN) \ 73 | this->NAME = GetFnPtr(::NAME, ::NAME##Def, #NAME, WARN); 74 | 75 | #include "FuzzerExtFunctions.def" 76 | 77 | #undef EXT_FUNC 78 | } 79 | 80 | } // namespace fuzzer 81 | 82 | #endif // LIBFUZZER_WINDOWS 83 | -------------------------------------------------------------------------------- /libFuzzer/Fuzzer/FuzzerExtraCounters.cpp: -------------------------------------------------------------------------------- 1 | //===- FuzzerExtraCounters.cpp - Extra coverage counters ------------------===// 2 | // 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 | // See https://llvm.org/LICENSE.txt for license information. 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 | // 7 | //===----------------------------------------------------------------------===// 8 | // Extra coverage counters defined by user code. 9 | //===----------------------------------------------------------------------===// 10 | 11 | #include "FuzzerDefs.h" 12 | 13 | #if LIBFUZZER_LINUX || LIBFUZZER_NETBSD || LIBFUZZER_FREEBSD || \ 14 | LIBFUZZER_OPENBSD 15 | __attribute__((weak)) extern uint8_t __start___libfuzzer_extra_counters; 16 | __attribute__((weak)) extern uint8_t __stop___libfuzzer_extra_counters; 17 | 18 | namespace fuzzer { 19 | uint8_t *ExtraCountersBegin() { return &__start___libfuzzer_extra_counters; } 20 | uint8_t *ExtraCountersEnd() { return &__stop___libfuzzer_extra_counters; } 21 | ATTRIBUTE_NO_SANITIZE_ALL 22 | void ClearExtraCounters() { // hand-written memset, don't asan-ify. 23 | uintptr_t *Beg = reinterpret_cast(ExtraCountersBegin()); 24 | uintptr_t *End = reinterpret_cast(ExtraCountersEnd()); 25 | for (; Beg < End; Beg++) { 26 | *Beg = 0; 27 | __asm__ __volatile__("" : : : "memory"); 28 | } 29 | } 30 | 31 | } // namespace fuzzer 32 | 33 | #else 34 | // TODO: implement for other platforms. 35 | namespace fuzzer { 36 | uint8_t *ExtraCountersBegin() { return nullptr; } 37 | uint8_t *ExtraCountersEnd() { return nullptr; } 38 | void ClearExtraCounters() {} 39 | } // namespace fuzzer 40 | 41 | #endif 42 | -------------------------------------------------------------------------------- /libFuzzer/Fuzzer/FuzzerFork.h: -------------------------------------------------------------------------------- 1 | //===- FuzzerFork.h - run fuzzing in sub-processes --------------*- C++ -* ===// 2 | // 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 | // See https://llvm.org/LICENSE.txt for license information. 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 | // 7 | //===----------------------------------------------------------------------===// 8 | 9 | #ifndef LLVM_FUZZER_FORK_H 10 | #define LLVM_FUZZER_FORK_H 11 | 12 | #include "FuzzerDefs.h" 13 | #include "FuzzerOptions.h" 14 | #include "FuzzerRandom.h" 15 | 16 | #include 17 | 18 | namespace fuzzer { 19 | void FuzzWithFork(Random &Rand, const FuzzingOptions &Options, 20 | const Vector &Args, 21 | const Vector &CorpusDirs, int NumJobs); 22 | } // namespace fuzzer 23 | 24 | #endif // LLVM_FUZZER_FORK_H 25 | -------------------------------------------------------------------------------- /libFuzzer/Fuzzer/FuzzerIO.cpp: -------------------------------------------------------------------------------- 1 | //===- FuzzerIO.cpp - IO utils. -------------------------------------------===// 2 | // 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 | // See https://llvm.org/LICENSE.txt for license information. 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 | // 7 | //===----------------------------------------------------------------------===// 8 | // IO functions. 9 | //===----------------------------------------------------------------------===// 10 | 11 | #include "FuzzerDefs.h" 12 | #include "FuzzerExtFunctions.h" 13 | #include "FuzzerIO.h" 14 | #include "FuzzerUtil.h" 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | 22 | namespace fuzzer { 23 | 24 | static FILE *OutputFile = stderr; 25 | 26 | long GetEpoch(const std::string &Path) { 27 | struct stat St; 28 | if (stat(Path.c_str(), &St)) 29 | return 0; // Can't stat, be conservative. 30 | return St.st_mtime; 31 | } 32 | 33 | Unit FileToVector(const std::string &Path, size_t MaxSize, bool ExitOnError) { 34 | std::ifstream T(Path, std::ios::binary); 35 | if (ExitOnError && !T) { 36 | Printf("No such directory: %s; exiting\n", Path.c_str()); 37 | exit(1); 38 | } 39 | 40 | T.seekg(0, T.end); 41 | auto EndPos = T.tellg(); 42 | if (EndPos < 0) return {}; 43 | size_t FileLen = EndPos; 44 | if (MaxSize) 45 | FileLen = std::min(FileLen, MaxSize); 46 | 47 | T.seekg(0, T.beg); 48 | Unit Res(FileLen); 49 | T.read(reinterpret_cast(Res.data()), FileLen); 50 | return Res; 51 | } 52 | 53 | std::string FileToString(const std::string &Path) { 54 | std::ifstream T(Path, std::ios::binary); 55 | return std::string((std::istreambuf_iterator(T)), 56 | std::istreambuf_iterator()); 57 | } 58 | 59 | void CopyFileToErr(const std::string &Path) { 60 | Printf("%s", FileToString(Path).c_str()); 61 | } 62 | 63 | void WriteToFile(const Unit &U, const std::string &Path) { 64 | WriteToFile(U.data(), U.size(), Path); 65 | } 66 | 67 | void WriteToFile(const std::string &Data, const std::string &Path) { 68 | WriteToFile(reinterpret_cast(Data.c_str()), Data.size(), 69 | Path); 70 | } 71 | 72 | void WriteToFile(const uint8_t *Data, size_t Size, const std::string &Path) { 73 | // Use raw C interface because this function may be called from a sig handler. 74 | FILE *Out = fopen(Path.c_str(), "wb"); 75 | if (!Out) return; 76 | fwrite(Data, sizeof(Data[0]), Size, Out); 77 | fclose(Out); 78 | } 79 | 80 | void ReadDirToVectorOfUnits(const char *Path, Vector *V, 81 | long *Epoch, size_t MaxSize, bool ExitOnError) { 82 | long E = Epoch ? *Epoch : 0; 83 | Vector Files; 84 | ListFilesInDirRecursive(Path, Epoch, &Files, /*TopDir*/true); 85 | size_t NumLoaded = 0; 86 | for (size_t i = 0; i < Files.size(); i++) { 87 | auto &X = Files[i]; 88 | if (Epoch && GetEpoch(X) < E) continue; 89 | NumLoaded++; 90 | if ((NumLoaded & (NumLoaded - 1)) == 0 && NumLoaded >= 1024) 91 | Printf("Loaded %zd/%zd files from %s\n", NumLoaded, Files.size(), Path); 92 | auto S = FileToVector(X, MaxSize, ExitOnError); 93 | if (!S.empty()) 94 | V->push_back(S); 95 | } 96 | } 97 | 98 | 99 | void GetSizedFilesFromDir(const std::string &Dir, Vector *V) { 100 | Vector Files; 101 | ListFilesInDirRecursive(Dir, 0, &Files, /*TopDir*/true); 102 | for (auto &File : Files) 103 | if (size_t Size = FileSize(File)) 104 | V->push_back({File, Size}); 105 | } 106 | 107 | std::string DirPlusFile(const std::string &DirPath, 108 | const std::string &FileName) { 109 | return DirPath + GetSeparator() + FileName; 110 | } 111 | 112 | void DupAndCloseStderr() { 113 | int OutputFd = DuplicateFile(2); 114 | if (OutputFd > 0) { 115 | FILE *NewOutputFile = OpenFile(OutputFd, "w"); 116 | if (NewOutputFile) { 117 | OutputFile = NewOutputFile; 118 | if (EF->__sanitizer_set_report_fd) 119 | EF->__sanitizer_set_report_fd( 120 | reinterpret_cast(GetHandleFromFd(OutputFd))); 121 | DiscardOutput(2); 122 | } 123 | } 124 | } 125 | 126 | void CloseStdout() { 127 | DiscardOutput(1); 128 | } 129 | 130 | void Printf(const char *Fmt, ...) { 131 | va_list ap; 132 | va_start(ap, Fmt); 133 | vfprintf(OutputFile, Fmt, ap); 134 | va_end(ap); 135 | fflush(OutputFile); 136 | } 137 | 138 | void VPrintf(bool Verbose, const char *Fmt, ...) { 139 | if (!Verbose) return; 140 | va_list ap; 141 | va_start(ap, Fmt); 142 | vfprintf(OutputFile, Fmt, ap); 143 | va_end(ap); 144 | fflush(OutputFile); 145 | } 146 | 147 | void RmDirRecursive(const std::string &Dir) { 148 | IterateDirRecursive( 149 | Dir, [](const std::string &Path) {}, 150 | [](const std::string &Path) { RmDir(Path); }, 151 | [](const std::string &Path) { RemoveFile(Path); }); 152 | } 153 | 154 | std::string TempPath(const char *Extension) { 155 | return DirPlusFile(TmpDir(), 156 | "libFuzzerTemp." + std::to_string(GetPid()) + Extension); 157 | } 158 | 159 | } // namespace fuzzer 160 | -------------------------------------------------------------------------------- /libFuzzer/Fuzzer/FuzzerIO.h: -------------------------------------------------------------------------------- 1 | //===- FuzzerIO.h - Internal header for IO utils ----------------*- C++ -* ===// 2 | // 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 | // See https://llvm.org/LICENSE.txt for license information. 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 | // 7 | //===----------------------------------------------------------------------===// 8 | // IO interface. 9 | //===----------------------------------------------------------------------===// 10 | 11 | #ifndef LLVM_FUZZER_IO_H 12 | #define LLVM_FUZZER_IO_H 13 | 14 | #include "FuzzerDefs.h" 15 | 16 | namespace fuzzer { 17 | 18 | long GetEpoch(const std::string &Path); 19 | 20 | Unit FileToVector(const std::string &Path, size_t MaxSize = 0, 21 | bool ExitOnError = true); 22 | 23 | std::string FileToString(const std::string &Path); 24 | 25 | void CopyFileToErr(const std::string &Path); 26 | 27 | void WriteToFile(const uint8_t *Data, size_t Size, const std::string &Path); 28 | // Write Data.c_str() to the file without terminating null character. 29 | void WriteToFile(const std::string &Data, const std::string &Path); 30 | void WriteToFile(const Unit &U, const std::string &Path); 31 | 32 | void ReadDirToVectorOfUnits(const char *Path, Vector *V, 33 | long *Epoch, size_t MaxSize, bool ExitOnError); 34 | 35 | // Returns "Dir/FileName" or equivalent for the current OS. 36 | std::string DirPlusFile(const std::string &DirPath, 37 | const std::string &FileName); 38 | 39 | // Returns the name of the dir, similar to the 'dirname' utility. 40 | std::string DirName(const std::string &FileName); 41 | 42 | // Returns path to a TmpDir. 43 | std::string TmpDir(); 44 | 45 | std::string TempPath(const char *Extension); 46 | 47 | bool IsInterestingCoverageFile(const std::string &FileName); 48 | 49 | void DupAndCloseStderr(); 50 | 51 | void CloseStdout(); 52 | 53 | void Printf(const char *Fmt, ...); 54 | void VPrintf(bool Verbose, const char *Fmt, ...); 55 | 56 | // Print using raw syscalls, useful when printing at early init stages. 57 | void RawPrint(const char *Str); 58 | 59 | // Platform specific functions: 60 | bool IsFile(const std::string &Path); 61 | size_t FileSize(const std::string &Path); 62 | 63 | void ListFilesInDirRecursive(const std::string &Dir, long *Epoch, 64 | Vector *V, bool TopDir); 65 | 66 | void RmDirRecursive(const std::string &Dir); 67 | 68 | // Iterate files and dirs inside Dir, recursively. 69 | // Call DirPreCallback/DirPostCallback on dirs before/after 70 | // calling FileCallback on files. 71 | void IterateDirRecursive(const std::string &Dir, 72 | void (*DirPreCallback)(const std::string &Dir), 73 | void (*DirPostCallback)(const std::string &Dir), 74 | void (*FileCallback)(const std::string &Dir)); 75 | 76 | struct SizedFile { 77 | std::string File; 78 | size_t Size; 79 | bool operator<(const SizedFile &B) const { return Size < B.Size; } 80 | }; 81 | 82 | void GetSizedFilesFromDir(const std::string &Dir, Vector *V); 83 | 84 | char GetSeparator(); 85 | // Similar to the basename utility: returns the file name w/o the dir prefix. 86 | std::string Basename(const std::string &Path); 87 | 88 | FILE* OpenFile(int Fd, const char *Mode); 89 | 90 | int CloseFile(int Fd); 91 | 92 | int DuplicateFile(int Fd); 93 | 94 | void RemoveFile(const std::string &Path); 95 | void RenameFile(const std::string &OldPath, const std::string &NewPath); 96 | 97 | void DiscardOutput(int Fd); 98 | 99 | intptr_t GetHandleFromFd(int fd); 100 | 101 | void MkDir(const std::string &Path); 102 | void RmDir(const std::string &Path); 103 | 104 | const std::string &getDevNull(); 105 | 106 | } // namespace fuzzer 107 | 108 | #endif // LLVM_FUZZER_IO_H 109 | -------------------------------------------------------------------------------- /libFuzzer/Fuzzer/FuzzerIOPosix.cpp: -------------------------------------------------------------------------------- 1 | //===- FuzzerIOPosix.cpp - IO utils for Posix. ----------------------------===// 2 | // 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 | // See https://llvm.org/LICENSE.txt for license information. 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 | // 7 | //===----------------------------------------------------------------------===// 8 | // IO functions implementation using Posix API. 9 | //===----------------------------------------------------------------------===// 10 | #include "FuzzerDefs.h" 11 | #if LIBFUZZER_POSIX || LIBFUZZER_FUCHSIA 12 | 13 | #include "FuzzerExtFunctions.h" 14 | #include "FuzzerIO.h" 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | 25 | namespace fuzzer { 26 | 27 | bool IsFile(const std::string &Path) { 28 | struct stat St; 29 | if (stat(Path.c_str(), &St)) 30 | return false; 31 | return S_ISREG(St.st_mode); 32 | } 33 | 34 | static bool IsDirectory(const std::string &Path) { 35 | struct stat St; 36 | if (stat(Path.c_str(), &St)) 37 | return false; 38 | return S_ISDIR(St.st_mode); 39 | } 40 | 41 | size_t FileSize(const std::string &Path) { 42 | struct stat St; 43 | if (stat(Path.c_str(), &St)) 44 | return 0; 45 | return St.st_size; 46 | } 47 | 48 | std::string Basename(const std::string &Path) { 49 | size_t Pos = Path.rfind(GetSeparator()); 50 | if (Pos == std::string::npos) return Path; 51 | assert(Pos < Path.size()); 52 | return Path.substr(Pos + 1); 53 | } 54 | 55 | void ListFilesInDirRecursive(const std::string &Dir, long *Epoch, 56 | Vector *V, bool TopDir) { 57 | auto E = GetEpoch(Dir); 58 | if (Epoch) 59 | if (E && *Epoch >= E) return; 60 | 61 | DIR *D = opendir(Dir.c_str()); 62 | if (!D) { 63 | Printf("%s: %s; exiting\n", strerror(errno), Dir.c_str()); 64 | exit(1); 65 | } 66 | while (auto E = readdir(D)) { 67 | std::string Path = DirPlusFile(Dir, E->d_name); 68 | if (E->d_type == DT_REG || E->d_type == DT_LNK || 69 | (E->d_type == DT_UNKNOWN && IsFile(Path))) 70 | V->push_back(Path); 71 | else if ((E->d_type == DT_DIR || 72 | (E->d_type == DT_UNKNOWN && IsDirectory(Path))) && 73 | *E->d_name != '.') 74 | ListFilesInDirRecursive(Path, Epoch, V, false); 75 | } 76 | closedir(D); 77 | if (Epoch && TopDir) 78 | *Epoch = E; 79 | } 80 | 81 | 82 | void IterateDirRecursive(const std::string &Dir, 83 | void (*DirPreCallback)(const std::string &Dir), 84 | void (*DirPostCallback)(const std::string &Dir), 85 | void (*FileCallback)(const std::string &Dir)) { 86 | DirPreCallback(Dir); 87 | DIR *D = opendir(Dir.c_str()); 88 | if (!D) return; 89 | while (auto E = readdir(D)) { 90 | std::string Path = DirPlusFile(Dir, E->d_name); 91 | if (E->d_type == DT_REG || E->d_type == DT_LNK || 92 | (E->d_type == DT_UNKNOWN && IsFile(Path))) 93 | FileCallback(Path); 94 | else if ((E->d_type == DT_DIR || 95 | (E->d_type == DT_UNKNOWN && IsDirectory(Path))) && 96 | *E->d_name != '.') 97 | IterateDirRecursive(Path, DirPreCallback, DirPostCallback, FileCallback); 98 | } 99 | closedir(D); 100 | DirPostCallback(Dir); 101 | } 102 | 103 | char GetSeparator() { 104 | return '/'; 105 | } 106 | 107 | FILE* OpenFile(int Fd, const char* Mode) { 108 | return fdopen(Fd, Mode); 109 | } 110 | 111 | int CloseFile(int fd) { 112 | return close(fd); 113 | } 114 | 115 | int DuplicateFile(int Fd) { 116 | return dup(Fd); 117 | } 118 | 119 | void RemoveFile(const std::string &Path) { 120 | unlink(Path.c_str()); 121 | } 122 | 123 | void RenameFile(const std::string &OldPath, const std::string &NewPath) { 124 | rename(OldPath.c_str(), NewPath.c_str()); 125 | } 126 | 127 | void DiscardOutput(int Fd) { 128 | FILE* Temp = fopen("/dev/null", "w"); 129 | if (!Temp) 130 | return; 131 | dup2(fileno(Temp), Fd); 132 | fclose(Temp); 133 | } 134 | 135 | intptr_t GetHandleFromFd(int fd) { 136 | return static_cast(fd); 137 | } 138 | 139 | std::string DirName(const std::string &FileName) { 140 | char *Tmp = new char[FileName.size() + 1]; 141 | memcpy(Tmp, FileName.c_str(), FileName.size() + 1); 142 | std::string Res = dirname(Tmp); 143 | delete [] Tmp; 144 | return Res; 145 | } 146 | 147 | std::string TmpDir() { 148 | if (auto Env = getenv("TMPDIR")) 149 | return Env; 150 | return "/tmp"; 151 | } 152 | 153 | bool IsInterestingCoverageFile(const std::string &FileName) { 154 | if (FileName.find("compiler-rt/lib/") != std::string::npos) 155 | return false; // sanitizer internal. 156 | if (FileName.find("/usr/lib/") != std::string::npos) 157 | return false; 158 | if (FileName.find("/usr/include/") != std::string::npos) 159 | return false; 160 | if (FileName == "") 161 | return false; 162 | return true; 163 | } 164 | 165 | void RawPrint(const char *Str) { 166 | write(2, Str, strlen(Str)); 167 | } 168 | 169 | void MkDir(const std::string &Path) { 170 | mkdir(Path.c_str(), 0700); 171 | } 172 | 173 | void RmDir(const std::string &Path) { 174 | rmdir(Path.c_str()); 175 | } 176 | 177 | const std::string &getDevNull() { 178 | static const std::string devNull = "/dev/null"; 179 | return devNull; 180 | } 181 | 182 | } // namespace fuzzer 183 | 184 | #endif // LIBFUZZER_POSIX 185 | -------------------------------------------------------------------------------- /libFuzzer/Fuzzer/FuzzerInterface.h: -------------------------------------------------------------------------------- 1 | //===- FuzzerInterface.h - Interface header for the Fuzzer ------*- C++ -* ===// 2 | // 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 | // See https://llvm.org/LICENSE.txt for license information. 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 | // 7 | //===----------------------------------------------------------------------===// 8 | // Define the interface between libFuzzer and the library being tested. 9 | //===----------------------------------------------------------------------===// 10 | 11 | // NOTE: the libFuzzer interface is thin and in the majority of cases 12 | // you should not include this file into your target. In 95% of cases 13 | // all you need is to define the following function in your file: 14 | // extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size); 15 | 16 | // WARNING: keep the interface in C. 17 | 18 | #ifndef LLVM_FUZZER_INTERFACE_H 19 | #define LLVM_FUZZER_INTERFACE_H 20 | 21 | #include 22 | #include 23 | 24 | #ifdef __cplusplus 25 | extern "C" { 26 | #endif // __cplusplus 27 | 28 | // Define FUZZER_INTERFACE_VISIBILITY to set default visibility in a way that 29 | // doesn't break MSVC. 30 | #if defined(_WIN32) 31 | #define FUZZER_INTERFACE_VISIBILITY __declspec(dllexport) 32 | #else 33 | #define FUZZER_INTERFACE_VISIBILITY __attribute__((visibility("default"))) 34 | #endif 35 | 36 | // Mandatory user-provided target function. 37 | // Executes the code under test with [Data, Data+Size) as the input. 38 | // libFuzzer will invoke this function *many* times with different inputs. 39 | // Must return 0. 40 | FUZZER_INTERFACE_VISIBILITY int 41 | LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size); 42 | 43 | // Optional user-provided initialization function. 44 | // If provided, this function will be called by libFuzzer once at startup. 45 | // It may read and modify argc/argv. 46 | // Must return 0. 47 | FUZZER_INTERFACE_VISIBILITY int LLVMFuzzerInitialize(int *argc, char ***argv); 48 | 49 | // Optional user-provided custom mutator. 50 | // Mutates raw data in [Data, Data+Size) inplace. 51 | // Returns the new size, which is not greater than MaxSize. 52 | // Given the same Seed produces the same mutation. 53 | FUZZER_INTERFACE_VISIBILITY size_t 54 | LLVMFuzzerCustomMutator(uint8_t *Data, size_t Size, size_t MaxSize, 55 | unsigned int Seed); 56 | 57 | // Optional user-provided custom cross-over function. 58 | // Combines pieces of Data1 & Data2 together into Out. 59 | // Returns the new size, which is not greater than MaxOutSize. 60 | // Should produce the same mutation given the same Seed. 61 | FUZZER_INTERFACE_VISIBILITY size_t 62 | LLVMFuzzerCustomCrossOver(const uint8_t *Data1, size_t Size1, 63 | const uint8_t *Data2, size_t Size2, uint8_t *Out, 64 | size_t MaxOutSize, unsigned int Seed); 65 | 66 | // Experimental, may go away in future. 67 | // libFuzzer-provided function to be used inside LLVMFuzzerCustomMutator. 68 | // Mutates raw data in [Data, Data+Size) inplace. 69 | // Returns the new size, which is not greater than MaxSize. 70 | FUZZER_INTERFACE_VISIBILITY size_t 71 | LLVMFuzzerMutate(uint8_t *Data, size_t Size, size_t MaxSize); 72 | 73 | #undef FUZZER_INTERFACE_VISIBILITY 74 | 75 | #ifdef __cplusplus 76 | } // extern "C" 77 | #endif // __cplusplus 78 | 79 | #endif // LLVM_FUZZER_INTERFACE_H 80 | -------------------------------------------------------------------------------- /libFuzzer/Fuzzer/FuzzerInternal.h: -------------------------------------------------------------------------------- 1 | //===- FuzzerInternal.h - Internal header for the Fuzzer --------*- C++ -* ===// 2 | // 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 | // See https://llvm.org/LICENSE.txt for license information. 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 | // 7 | //===----------------------------------------------------------------------===// 8 | // Define the main class fuzzer::Fuzzer and most functions. 9 | //===----------------------------------------------------------------------===// 10 | 11 | #ifndef LLVM_FUZZER_INTERNAL_H 12 | #define LLVM_FUZZER_INTERNAL_H 13 | 14 | #include "FuzzerDataFlowTrace.h" 15 | #include "FuzzerDefs.h" 16 | #include "FuzzerExtFunctions.h" 17 | #include "FuzzerInterface.h" 18 | #include "FuzzerOptions.h" 19 | #include "FuzzerSHA1.h" 20 | #include "FuzzerValueBitMap.h" 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | 28 | namespace fuzzer { 29 | 30 | using namespace std::chrono; 31 | 32 | class Fuzzer { 33 | public: 34 | 35 | Fuzzer(UserCallback CB, InputCorpus &Corpus, MutationDispatcher &MD, 36 | FuzzingOptions Options); 37 | ~Fuzzer(); 38 | void Loop(Vector &CorporaFiles); 39 | void ReadAndExecuteSeedCorpora(Vector &CorporaFiles); 40 | void MinimizeCrashLoop(const Unit &U); 41 | void RereadOutputCorpus(size_t MaxSize); 42 | 43 | size_t secondsSinceProcessStartUp() { 44 | return duration_cast(system_clock::now() - ProcessStartTime) 45 | .count(); 46 | } 47 | 48 | bool TimedOut() { 49 | return Options.MaxTotalTimeSec > 0 && 50 | secondsSinceProcessStartUp() > 51 | static_cast(Options.MaxTotalTimeSec); 52 | } 53 | 54 | size_t execPerSec() { 55 | size_t Seconds = secondsSinceProcessStartUp(); 56 | return Seconds ? TotalNumberOfRuns / Seconds : 0; 57 | } 58 | 59 | size_t getTotalNumberOfRuns() { return TotalNumberOfRuns; } 60 | 61 | static void StaticAlarmCallback(); 62 | static void StaticCrashSignalCallback(); 63 | static void StaticExitCallback(); 64 | static void StaticInterruptCallback(); 65 | static void StaticFileSizeExceedCallback(); 66 | static void StaticGracefulExitCallback(); 67 | 68 | void ExecuteCallback(const uint8_t *Data, size_t Size); 69 | bool RunOne(const uint8_t *Data, size_t Size, bool MayDeleteFile = false, 70 | InputInfo *II = nullptr, bool *FoundUniqFeatures = nullptr); 71 | 72 | // Merge Corpora[1:] into Corpora[0]. 73 | void Merge(const Vector &Corpora); 74 | void CrashResistantMergeInternalStep(const std::string &ControlFilePath); 75 | MutationDispatcher &GetMD() { return MD; } 76 | void PrintFinalStats(); 77 | void SetMaxInputLen(size_t MaxInputLen); 78 | void SetMaxMutationLen(size_t MaxMutationLen); 79 | void RssLimitCallback(); 80 | 81 | bool InFuzzingThread() const { return IsMyThread; } 82 | size_t GetCurrentUnitInFuzzingThead(const uint8_t **Data) const; 83 | void TryDetectingAMemoryLeak(const uint8_t *Data, size_t Size, 84 | bool DuringInitialCorpusExecution); 85 | 86 | void HandleMalloc(size_t Size); 87 | static void MaybeExitGracefully(); 88 | std::string WriteToOutputCorpus(const Unit &U); 89 | 90 | private: 91 | void AlarmCallback(); 92 | void CrashCallback(); 93 | void ExitCallback(); 94 | void CrashOnOverwrittenData(); 95 | void InterruptCallback(); 96 | void MutateAndTestOne(); 97 | void PurgeAllocator(); 98 | void ReportNewCoverage(InputInfo *II, const Unit &U); 99 | void PrintPulseAndReportSlowInput(const uint8_t *Data, size_t Size); 100 | void WriteUnitToFileWithPrefix(const Unit &U, const char *Prefix); 101 | void PrintStats(const char *Where, const char *End = "\n", size_t Units = 0, 102 | size_t Features = 0); 103 | void PrintStatusForNewUnit(const Unit &U, const char *Text); 104 | void CheckExitOnSrcPosOrItem(); 105 | 106 | static void StaticDeathCallback(); 107 | void DumpCurrentUnit(const char *Prefix); 108 | void DeathCallback(); 109 | 110 | void AllocateCurrentUnitData(); 111 | uint8_t *CurrentUnitData = nullptr; 112 | std::atomic CurrentUnitSize; 113 | uint8_t BaseSha1[kSHA1NumBytes]; // Checksum of the base unit. 114 | 115 | bool GracefulExitRequested = false; 116 | 117 | size_t TotalNumberOfRuns = 0; 118 | size_t NumberOfNewUnitsAdded = 0; 119 | 120 | size_t LastCorpusUpdateRun = 0; 121 | 122 | bool HasMoreMallocsThanFrees = false; 123 | size_t NumberOfLeakDetectionAttempts = 0; 124 | 125 | system_clock::time_point LastAllocatorPurgeAttemptTime = system_clock::now(); 126 | 127 | UserCallback CB; 128 | InputCorpus &Corpus; 129 | MutationDispatcher &MD; 130 | FuzzingOptions Options; 131 | DataFlowTrace DFT; 132 | 133 | system_clock::time_point ProcessStartTime = system_clock::now(); 134 | system_clock::time_point UnitStartTime, UnitStopTime; 135 | long TimeOfLongestUnitInSeconds = 0; 136 | long EpochOfLastReadOfOutputCorpus = 0; 137 | 138 | size_t MaxInputLen = 0; 139 | size_t MaxMutationLen = 0; 140 | size_t TmpMaxMutationLen = 0; 141 | 142 | Vector UniqFeatureSetTmp; 143 | 144 | // Need to know our own thread. 145 | static thread_local bool IsMyThread; 146 | }; 147 | 148 | struct ScopedEnableMsanInterceptorChecks { 149 | ScopedEnableMsanInterceptorChecks() { 150 | if (EF->__msan_scoped_enable_interceptor_checks) 151 | EF->__msan_scoped_enable_interceptor_checks(); 152 | } 153 | ~ScopedEnableMsanInterceptorChecks() { 154 | if (EF->__msan_scoped_disable_interceptor_checks) 155 | EF->__msan_scoped_disable_interceptor_checks(); 156 | } 157 | }; 158 | 159 | struct ScopedDisableMsanInterceptorChecks { 160 | ScopedDisableMsanInterceptorChecks() { 161 | if (EF->__msan_scoped_disable_interceptor_checks) 162 | EF->__msan_scoped_disable_interceptor_checks(); 163 | } 164 | ~ScopedDisableMsanInterceptorChecks() { 165 | if (EF->__msan_scoped_enable_interceptor_checks) 166 | EF->__msan_scoped_enable_interceptor_checks(); 167 | } 168 | }; 169 | 170 | } // namespace fuzzer 171 | 172 | #endif // LLVM_FUZZER_INTERNAL_H 173 | -------------------------------------------------------------------------------- /libFuzzer/Fuzzer/FuzzerMain.cpp: -------------------------------------------------------------------------------- 1 | //===- FuzzerMain.cpp - main() function and flags -------------------------===// 2 | // 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 | // See https://llvm.org/LICENSE.txt for license information. 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 | // 7 | //===----------------------------------------------------------------------===// 8 | // main() and flags. 9 | //===----------------------------------------------------------------------===// 10 | 11 | #include "FuzzerDefs.h" 12 | 13 | extern "C" { 14 | // This function should be defined by the user. 15 | int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size); 16 | } // extern "C" 17 | 18 | ATTRIBUTE_INTERFACE int main(int argc, char **argv) { 19 | return fuzzer::FuzzerDriver(&argc, &argv, LLVMFuzzerTestOneInput); 20 | } 21 | -------------------------------------------------------------------------------- /libFuzzer/Fuzzer/FuzzerMerge.h: -------------------------------------------------------------------------------- 1 | //===- FuzzerMerge.h - merging corpa ----------------------------*- C++ -* ===// 2 | // 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 | // See https://llvm.org/LICENSE.txt for license information. 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 | // 7 | //===----------------------------------------------------------------------===// 8 | // Merging Corpora. 9 | // 10 | // The task: 11 | // Take the existing corpus (possibly empty) and merge new inputs into 12 | // it so that only inputs with new coverage ('features') are added. 13 | // The process should tolerate the crashes, OOMs, leaks, etc. 14 | // 15 | // Algorithm: 16 | // The outter process collects the set of files and writes their names 17 | // into a temporary "control" file, then repeatedly launches the inner 18 | // process until all inputs are processed. 19 | // The outer process does not actually execute the target code. 20 | // 21 | // The inner process reads the control file and sees a) list of all the inputs 22 | // and b) the last processed input. Then it starts processing the inputs one 23 | // by one. Before processing every input it writes one line to control file: 24 | // STARTED INPUT_ID INPUT_SIZE 25 | // After processing an input it write another line: 26 | // DONE INPUT_ID Feature1 Feature2 Feature3 ... 27 | // If a crash happens while processing an input the last line in the control 28 | // file will be "STARTED INPUT_ID" and so the next process will know 29 | // where to resume. 30 | // 31 | // Once all inputs are processed by the innner process(es) the outer process 32 | // reads the control files and does the merge based entirely on the contents 33 | // of control file. 34 | // It uses a single pass greedy algorithm choosing first the smallest inputs 35 | // within the same size the inputs that have more new features. 36 | // 37 | //===----------------------------------------------------------------------===// 38 | 39 | #ifndef LLVM_FUZZER_MERGE_H 40 | #define LLVM_FUZZER_MERGE_H 41 | 42 | #include "FuzzerDefs.h" 43 | 44 | #include 45 | #include 46 | #include 47 | #include 48 | 49 | namespace fuzzer { 50 | 51 | struct MergeFileInfo { 52 | std::string Name; 53 | size_t Size = 0; 54 | Vector Features, Cov; 55 | }; 56 | 57 | struct Merger { 58 | Vector Files; 59 | size_t NumFilesInFirstCorpus = 0; 60 | size_t FirstNotProcessedFile = 0; 61 | std::string LastFailure; 62 | 63 | bool Parse(std::istream &IS, bool ParseCoverage); 64 | bool Parse(const std::string &Str, bool ParseCoverage); 65 | void ParseOrExit(std::istream &IS, bool ParseCoverage); 66 | size_t Merge(const Set &InitialFeatures, Set *NewFeatures, 67 | const Set &InitialCov, Set *NewCov, 68 | Vector *NewFiles); 69 | size_t ApproximateMemoryConsumption() const; 70 | Set AllFeatures() const; 71 | }; 72 | 73 | void CrashResistantMerge(const Vector &Args, 74 | const Vector &OldCorpus, 75 | const Vector &NewCorpus, 76 | Vector *NewFiles, 77 | const Set &InitialFeatures, 78 | Set *NewFeatures, 79 | const Set &InitialCov, 80 | Set *NewCov, 81 | const std::string &CFPath, 82 | bool Verbose); 83 | 84 | } // namespace fuzzer 85 | 86 | #endif // LLVM_FUZZER_MERGE_H 87 | -------------------------------------------------------------------------------- /libFuzzer/Fuzzer/FuzzerOptions.h: -------------------------------------------------------------------------------- 1 | // 2 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 3 | // See https://llvm.org/LICENSE.txt for license information. 4 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 5 | // 6 | //===----------------------------------------------------------------------===// 7 | // fuzzer::FuzzingOptions 8 | //===----------------------------------------------------------------------===// 9 | 10 | #ifndef LLVM_FUZZER_OPTIONS_H 11 | #define LLVM_FUZZER_OPTIONS_H 12 | 13 | #include "FuzzerDefs.h" 14 | 15 | namespace fuzzer { 16 | 17 | struct FuzzingOptions { 18 | int Verbosity = 1; 19 | size_t MaxLen = 0; 20 | size_t LenControl = 1000; 21 | int UnitTimeoutSec = 300; 22 | int TimeoutExitCode = 70; 23 | int OOMExitCode = 71; 24 | int InterruptExitCode = 72; 25 | int ErrorExitCode = 77; 26 | bool IgnoreTimeouts = true; 27 | bool IgnoreOOMs = true; 28 | bool IgnoreCrashes = false; 29 | int MaxTotalTimeSec = 0; 30 | int RssLimitMb = 0; 31 | int MallocLimitMb = 0; 32 | bool DoCrossOver = true; 33 | int MutateDepth = 5; 34 | bool ReduceDepth = false; 35 | bool UseCounters = false; 36 | bool UseMemmem = true; 37 | bool UseCmp = false; 38 | int UseValueProfile = false; 39 | bool Shrink = false; 40 | bool ReduceInputs = false; 41 | int ReloadIntervalSec = 1; 42 | bool ShuffleAtStartUp = true; 43 | bool PreferSmall = true; 44 | size_t MaxNumberOfRuns = -1L; 45 | int ReportSlowUnits = 10; 46 | bool OnlyASCII = false; 47 | std::string OutputCorpus; 48 | std::string ArtifactPrefix = "./"; 49 | std::string ExactArtifactPath; 50 | std::string ExitOnSrcPos; 51 | std::string ExitOnItem; 52 | std::string FocusFunction; 53 | std::string DataFlowTrace; 54 | std::string CollectDataFlow; 55 | std::string FeaturesDir; 56 | std::string StopFile; 57 | bool SaveArtifacts = true; 58 | bool PrintNEW = true; // Print a status line when new units are found; 59 | bool PrintNewCovPcs = false; 60 | int PrintNewCovFuncs = 0; 61 | bool PrintFinalStats = false; 62 | bool PrintCorpusStats = false; 63 | bool PrintCoverage = false; 64 | bool DumpCoverage = false; 65 | bool DetectLeaks = true; 66 | int PurgeAllocatorIntervalSec = 1; 67 | int TraceMalloc = 0; 68 | bool HandleAbrt = false; 69 | bool HandleBus = false; 70 | bool HandleFpe = false; 71 | bool HandleIll = false; 72 | bool HandleInt = false; 73 | bool HandleSegv = false; 74 | bool HandleTerm = false; 75 | bool HandleXfsz = false; 76 | bool HandleUsr1 = false; 77 | bool HandleUsr2 = false; 78 | }; 79 | 80 | } // namespace fuzzer 81 | 82 | #endif // LLVM_FUZZER_OPTIONS_H 83 | -------------------------------------------------------------------------------- /libFuzzer/Fuzzer/FuzzerRandom.h: -------------------------------------------------------------------------------- 1 | //===- FuzzerRandom.h - Internal header for the Fuzzer ----------*- C++ -* ===// 2 | // 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 | // See https://llvm.org/LICENSE.txt for license information. 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 | // 7 | //===----------------------------------------------------------------------===// 8 | // fuzzer::Random 9 | //===----------------------------------------------------------------------===// 10 | 11 | #ifndef LLVM_FUZZER_RANDOM_H 12 | #define LLVM_FUZZER_RANDOM_H 13 | 14 | #include 15 | 16 | namespace fuzzer { 17 | class Random : public std::minstd_rand { 18 | public: 19 | Random(unsigned int seed) : std::minstd_rand(seed) {} 20 | result_type operator()() { return this->std::minstd_rand::operator()(); } 21 | size_t Rand() { return this->operator()(); } 22 | size_t RandBool() { return Rand() % 2; } 23 | size_t SkewTowardsLast(size_t n) { 24 | size_t T = this->operator()(n * n); 25 | size_t Res = sqrt(T); 26 | return Res; 27 | } 28 | size_t operator()(size_t n) { return n ? Rand() % n : 0; } 29 | intptr_t operator()(intptr_t From, intptr_t To) { 30 | assert(From < To); 31 | intptr_t RangeSize = To - From + 1; 32 | return operator()(RangeSize) + From; 33 | } 34 | }; 35 | 36 | } // namespace fuzzer 37 | 38 | #endif // LLVM_FUZZER_RANDOM_H 39 | -------------------------------------------------------------------------------- /libFuzzer/Fuzzer/FuzzerSHA1.cpp: -------------------------------------------------------------------------------- 1 | //===- FuzzerSHA1.h - Private copy of the SHA1 implementation ---*- C++ -* ===// 2 | // 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 | // See https://llvm.org/LICENSE.txt for license information. 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 | // 7 | //===----------------------------------------------------------------------===// 8 | // This code is taken from public domain 9 | // (http://oauth.googlecode.com/svn/code/c/liboauth/src/sha1.c) 10 | // and modified by adding anonymous namespace, adding an interface 11 | // function fuzzer::ComputeSHA1() and removing unnecessary code. 12 | // 13 | // lib/Fuzzer can not use SHA1 implementation from openssl because 14 | // openssl may not be available and because we may be fuzzing openssl itself. 15 | // For the same reason we do not want to depend on SHA1 from LLVM tree. 16 | //===----------------------------------------------------------------------===// 17 | 18 | #include "FuzzerSHA1.h" 19 | #include "FuzzerDefs.h" 20 | 21 | /* This code is public-domain - it is based on libcrypt 22 | * placed in the public domain by Wei Dai and other contributors. 23 | */ 24 | 25 | #include 26 | #include 27 | #include 28 | #include 29 | 30 | namespace { // Added for LibFuzzer 31 | 32 | #ifdef __BIG_ENDIAN__ 33 | # define SHA_BIG_ENDIAN 34 | // Windows is always little endian and MSVC doesn't have 35 | #elif defined __LITTLE_ENDIAN__ || LIBFUZZER_WINDOWS 36 | /* override */ 37 | #elif defined __BYTE_ORDER 38 | # if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ 39 | # define SHA_BIG_ENDIAN 40 | # endif 41 | #else // ! defined __LITTLE_ENDIAN__ 42 | # include // machine/endian.h 43 | # if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ 44 | # define SHA_BIG_ENDIAN 45 | # endif 46 | #endif 47 | 48 | 49 | /* header */ 50 | 51 | #define HASH_LENGTH 20 52 | #define BLOCK_LENGTH 64 53 | 54 | typedef struct sha1nfo { 55 | uint32_t buffer[BLOCK_LENGTH/4]; 56 | uint32_t state[HASH_LENGTH/4]; 57 | uint32_t byteCount; 58 | uint8_t bufferOffset; 59 | uint8_t keyBuffer[BLOCK_LENGTH]; 60 | uint8_t innerHash[HASH_LENGTH]; 61 | } sha1nfo; 62 | 63 | /* public API - prototypes - TODO: doxygen*/ 64 | 65 | /** 66 | */ 67 | void sha1_init(sha1nfo *s); 68 | /** 69 | */ 70 | void sha1_writebyte(sha1nfo *s, uint8_t data); 71 | /** 72 | */ 73 | void sha1_write(sha1nfo *s, const char *data, size_t len); 74 | /** 75 | */ 76 | uint8_t* sha1_result(sha1nfo *s); 77 | 78 | 79 | /* code */ 80 | #define SHA1_K0 0x5a827999 81 | #define SHA1_K20 0x6ed9eba1 82 | #define SHA1_K40 0x8f1bbcdc 83 | #define SHA1_K60 0xca62c1d6 84 | 85 | void sha1_init(sha1nfo *s) { 86 | s->state[0] = 0x67452301; 87 | s->state[1] = 0xefcdab89; 88 | s->state[2] = 0x98badcfe; 89 | s->state[3] = 0x10325476; 90 | s->state[4] = 0xc3d2e1f0; 91 | s->byteCount = 0; 92 | s->bufferOffset = 0; 93 | } 94 | 95 | uint32_t sha1_rol32(uint32_t number, uint8_t bits) { 96 | return ((number << bits) | (number >> (32-bits))); 97 | } 98 | 99 | void sha1_hashBlock(sha1nfo *s) { 100 | uint8_t i; 101 | uint32_t a,b,c,d,e,t; 102 | 103 | a=s->state[0]; 104 | b=s->state[1]; 105 | c=s->state[2]; 106 | d=s->state[3]; 107 | e=s->state[4]; 108 | for (i=0; i<80; i++) { 109 | if (i>=16) { 110 | t = s->buffer[(i+13)&15] ^ s->buffer[(i+8)&15] ^ s->buffer[(i+2)&15] ^ s->buffer[i&15]; 111 | s->buffer[i&15] = sha1_rol32(t,1); 112 | } 113 | if (i<20) { 114 | t = (d ^ (b & (c ^ d))) + SHA1_K0; 115 | } else if (i<40) { 116 | t = (b ^ c ^ d) + SHA1_K20; 117 | } else if (i<60) { 118 | t = ((b & c) | (d & (b | c))) + SHA1_K40; 119 | } else { 120 | t = (b ^ c ^ d) + SHA1_K60; 121 | } 122 | t+=sha1_rol32(a,5) + e + s->buffer[i&15]; 123 | e=d; 124 | d=c; 125 | c=sha1_rol32(b,30); 126 | b=a; 127 | a=t; 128 | } 129 | s->state[0] += a; 130 | s->state[1] += b; 131 | s->state[2] += c; 132 | s->state[3] += d; 133 | s->state[4] += e; 134 | } 135 | 136 | void sha1_addUncounted(sha1nfo *s, uint8_t data) { 137 | uint8_t * const b = (uint8_t*) s->buffer; 138 | #ifdef SHA_BIG_ENDIAN 139 | b[s->bufferOffset] = data; 140 | #else 141 | b[s->bufferOffset ^ 3] = data; 142 | #endif 143 | s->bufferOffset++; 144 | if (s->bufferOffset == BLOCK_LENGTH) { 145 | sha1_hashBlock(s); 146 | s->bufferOffset = 0; 147 | } 148 | } 149 | 150 | void sha1_writebyte(sha1nfo *s, uint8_t data) { 151 | ++s->byteCount; 152 | sha1_addUncounted(s, data); 153 | } 154 | 155 | void sha1_write(sha1nfo *s, const char *data, size_t len) { 156 | for (;len--;) sha1_writebyte(s, (uint8_t) *data++); 157 | } 158 | 159 | void sha1_pad(sha1nfo *s) { 160 | // Implement SHA-1 padding (fips180-2 §5.1.1) 161 | 162 | // Pad with 0x80 followed by 0x00 until the end of the block 163 | sha1_addUncounted(s, 0x80); 164 | while (s->bufferOffset != 56) sha1_addUncounted(s, 0x00); 165 | 166 | // Append length in the last 8 bytes 167 | sha1_addUncounted(s, 0); // We're only using 32 bit lengths 168 | sha1_addUncounted(s, 0); // But SHA-1 supports 64 bit lengths 169 | sha1_addUncounted(s, 0); // So zero pad the top bits 170 | sha1_addUncounted(s, s->byteCount >> 29); // Shifting to multiply by 8 171 | sha1_addUncounted(s, s->byteCount >> 21); // as SHA-1 supports bitstreams as well as 172 | sha1_addUncounted(s, s->byteCount >> 13); // byte. 173 | sha1_addUncounted(s, s->byteCount >> 5); 174 | sha1_addUncounted(s, s->byteCount << 3); 175 | } 176 | 177 | uint8_t* sha1_result(sha1nfo *s) { 178 | // Pad to complete the last block 179 | sha1_pad(s); 180 | 181 | #ifndef SHA_BIG_ENDIAN 182 | // Swap byte order back 183 | int i; 184 | for (i=0; i<5; i++) { 185 | s->state[i]= 186 | (((s->state[i])<<24)& 0xff000000) 187 | | (((s->state[i])<<8) & 0x00ff0000) 188 | | (((s->state[i])>>8) & 0x0000ff00) 189 | | (((s->state[i])>>24)& 0x000000ff); 190 | } 191 | #endif 192 | 193 | // Return pointer to hash (20 characters) 194 | return (uint8_t*) s->state; 195 | } 196 | 197 | } // namespace; Added for LibFuzzer 198 | 199 | namespace fuzzer { 200 | 201 | // The rest is added for LibFuzzer 202 | void ComputeSHA1(const uint8_t *Data, size_t Len, uint8_t *Out) { 203 | sha1nfo s; 204 | sha1_init(&s); 205 | sha1_write(&s, (const char*)Data, Len); 206 | memcpy(Out, sha1_result(&s), HASH_LENGTH); 207 | } 208 | 209 | std::string Sha1ToString(const uint8_t Sha1[kSHA1NumBytes]) { 210 | std::stringstream SS; 211 | for (int i = 0; i < kSHA1NumBytes; i++) 212 | SS << std::hex << std::setfill('0') << std::setw(2) << (unsigned)Sha1[i]; 213 | return SS.str(); 214 | } 215 | 216 | std::string Hash(const Unit &U) { 217 | uint8_t Hash[kSHA1NumBytes]; 218 | ComputeSHA1(U.data(), U.size(), Hash); 219 | return Sha1ToString(Hash); 220 | } 221 | 222 | } 223 | -------------------------------------------------------------------------------- /libFuzzer/Fuzzer/FuzzerSHA1.h: -------------------------------------------------------------------------------- 1 | //===- FuzzerSHA1.h - Internal header for the SHA1 utils --------*- C++ -* ===// 2 | // 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 | // See https://llvm.org/LICENSE.txt for license information. 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 | // 7 | //===----------------------------------------------------------------------===// 8 | // SHA1 utils. 9 | //===----------------------------------------------------------------------===// 10 | 11 | #ifndef LLVM_FUZZER_SHA1_H 12 | #define LLVM_FUZZER_SHA1_H 13 | 14 | #include "FuzzerDefs.h" 15 | #include 16 | #include 17 | 18 | namespace fuzzer { 19 | 20 | // Private copy of SHA1 implementation. 21 | static const int kSHA1NumBytes = 20; 22 | 23 | // Computes SHA1 hash of 'Len' bytes in 'Data', writes kSHA1NumBytes to 'Out'. 24 | void ComputeSHA1(const uint8_t *Data, size_t Len, uint8_t *Out); 25 | 26 | std::string Sha1ToString(const uint8_t Sha1[kSHA1NumBytes]); 27 | 28 | std::string Hash(const Unit &U); 29 | 30 | } // namespace fuzzer 31 | 32 | #endif // LLVM_FUZZER_SHA1_H 33 | -------------------------------------------------------------------------------- /libFuzzer/Fuzzer/FuzzerUtil.h: -------------------------------------------------------------------------------- 1 | //===- FuzzerUtil.h - Internal header for the Fuzzer Utils ------*- C++ -* ===// 2 | // 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 | // See https://llvm.org/LICENSE.txt for license information. 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 | // 7 | //===----------------------------------------------------------------------===// 8 | // Util functions. 9 | //===----------------------------------------------------------------------===// 10 | 11 | #ifndef LLVM_FUZZER_UTIL_H 12 | #define LLVM_FUZZER_UTIL_H 13 | 14 | #include "FuzzerBuiltins.h" 15 | #include "FuzzerBuiltinsMsvc.h" 16 | #include "FuzzerCommand.h" 17 | #include "FuzzerDefs.h" 18 | 19 | namespace fuzzer { 20 | 21 | void PrintHexArray(const Unit &U, const char *PrintAfter = ""); 22 | 23 | void PrintHexArray(const uint8_t *Data, size_t Size, 24 | const char *PrintAfter = ""); 25 | 26 | void PrintASCII(const uint8_t *Data, size_t Size, const char *PrintAfter = ""); 27 | 28 | void PrintASCII(const Unit &U, const char *PrintAfter = ""); 29 | 30 | // Changes U to contain only ASCII (isprint+isspace) characters. 31 | // Returns true iff U has been changed. 32 | bool ToASCII(uint8_t *Data, size_t Size); 33 | 34 | bool IsASCII(const Unit &U); 35 | 36 | bool IsASCII(const uint8_t *Data, size_t Size); 37 | 38 | std::string Base64(const Unit &U); 39 | 40 | void PrintPC(const char *SymbolizedFMT, const char *FallbackFMT, uintptr_t PC); 41 | 42 | std::string DescribePC(const char *SymbolizedFMT, uintptr_t PC); 43 | 44 | void PrintStackTrace(); 45 | 46 | void PrintMemoryProfile(); 47 | 48 | unsigned NumberOfCpuCores(); 49 | 50 | // Platform specific functions. 51 | void SetSignalHandler(const FuzzingOptions& Options); 52 | 53 | void SleepSeconds(int Seconds); 54 | 55 | unsigned long GetPid(); 56 | 57 | size_t GetPeakRSSMb(); 58 | 59 | int ExecuteCommand(const Command &Cmd); 60 | 61 | FILE *OpenProcessPipe(const char *Command, const char *Mode); 62 | 63 | const void *SearchMemory(const void *haystack, size_t haystacklen, 64 | const void *needle, size_t needlelen); 65 | 66 | std::string CloneArgsWithoutX(const Vector &Args, 67 | const char *X1, const char *X2); 68 | 69 | inline std::string CloneArgsWithoutX(const Vector &Args, 70 | const char *X) { 71 | return CloneArgsWithoutX(Args, X, X); 72 | } 73 | 74 | inline std::pair SplitBefore(std::string X, 75 | std::string S) { 76 | auto Pos = S.find(X); 77 | if (Pos == std::string::npos) 78 | return std::make_pair(S, ""); 79 | return std::make_pair(S.substr(0, Pos), S.substr(Pos)); 80 | } 81 | 82 | std::string DisassembleCmd(const std::string &FileName); 83 | 84 | std::string SearchRegexCmd(const std::string &Regex); 85 | 86 | size_t SimpleFastHash(const uint8_t *Data, size_t Size); 87 | 88 | inline uint32_t Log(uint32_t X) { return 32 - Clz(X) - 1; } 89 | 90 | inline size_t PageSize() { return 4096; } 91 | inline uint8_t *RoundUpByPage(uint8_t *P) { 92 | uintptr_t X = reinterpret_cast(P); 93 | size_t Mask = PageSize() - 1; 94 | X = (X + Mask) & ~Mask; 95 | return reinterpret_cast(X); 96 | } 97 | inline uint8_t *RoundDownByPage(uint8_t *P) { 98 | uintptr_t X = reinterpret_cast(P); 99 | size_t Mask = PageSize() - 1; 100 | X = X & ~Mask; 101 | return reinterpret_cast(X); 102 | } 103 | 104 | } // namespace fuzzer 105 | 106 | #endif // LLVM_FUZZER_UTIL_H 107 | -------------------------------------------------------------------------------- /libFuzzer/Fuzzer/FuzzerUtilDarwin.cpp: -------------------------------------------------------------------------------- 1 | //===- FuzzerUtilDarwin.cpp - Misc utils ----------------------------------===// 2 | // 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 | // See https://llvm.org/LICENSE.txt for license information. 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 | // 7 | //===----------------------------------------------------------------------===// 8 | // Misc utils for Darwin. 9 | //===----------------------------------------------------------------------===// 10 | #include "FuzzerDefs.h" 11 | #if LIBFUZZER_APPLE 12 | #include "FuzzerCommand.h" 13 | #include "FuzzerIO.h" 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | 21 | // There is no header for this on macOS so declare here 22 | extern "C" char **environ; 23 | 24 | namespace fuzzer { 25 | 26 | static std::mutex SignalMutex; 27 | // Global variables used to keep track of how signal handling should be 28 | // restored. They should **not** be accessed without holding `SignalMutex`. 29 | static int ActiveThreadCount = 0; 30 | static struct sigaction OldSigIntAction; 31 | static struct sigaction OldSigQuitAction; 32 | static sigset_t OldBlockedSignalsSet; 33 | 34 | // This is a reimplementation of Libc's `system()`. On Darwin the Libc 35 | // implementation contains a mutex which prevents it from being used 36 | // concurrently. This implementation **can** be used concurrently. It sets the 37 | // signal handlers when the first thread enters and restores them when the last 38 | // thread finishes execution of the function and ensures this is not racey by 39 | // using a mutex. 40 | int ExecuteCommand(const Command &Cmd) { 41 | std::string CmdLine = Cmd.toString(); 42 | posix_spawnattr_t SpawnAttributes; 43 | if (posix_spawnattr_init(&SpawnAttributes)) 44 | return -1; 45 | // Block and ignore signals of the current process when the first thread 46 | // enters. 47 | { 48 | std::lock_guard Lock(SignalMutex); 49 | if (ActiveThreadCount == 0) { 50 | static struct sigaction IgnoreSignalAction; 51 | sigset_t BlockedSignalsSet; 52 | memset(&IgnoreSignalAction, 0, sizeof(IgnoreSignalAction)); 53 | IgnoreSignalAction.sa_handler = SIG_IGN; 54 | 55 | if (sigaction(SIGINT, &IgnoreSignalAction, &OldSigIntAction) == -1) { 56 | Printf("Failed to ignore SIGINT\n"); 57 | (void)posix_spawnattr_destroy(&SpawnAttributes); 58 | return -1; 59 | } 60 | if (sigaction(SIGQUIT, &IgnoreSignalAction, &OldSigQuitAction) == -1) { 61 | Printf("Failed to ignore SIGQUIT\n"); 62 | // Try our best to restore the signal handlers. 63 | (void)sigaction(SIGINT, &OldSigIntAction, NULL); 64 | (void)posix_spawnattr_destroy(&SpawnAttributes); 65 | return -1; 66 | } 67 | 68 | (void)sigemptyset(&BlockedSignalsSet); 69 | (void)sigaddset(&BlockedSignalsSet, SIGCHLD); 70 | if (sigprocmask(SIG_BLOCK, &BlockedSignalsSet, &OldBlockedSignalsSet) == 71 | -1) { 72 | Printf("Failed to block SIGCHLD\n"); 73 | // Try our best to restore the signal handlers. 74 | (void)sigaction(SIGQUIT, &OldSigQuitAction, NULL); 75 | (void)sigaction(SIGINT, &OldSigIntAction, NULL); 76 | (void)posix_spawnattr_destroy(&SpawnAttributes); 77 | return -1; 78 | } 79 | } 80 | ++ActiveThreadCount; 81 | } 82 | 83 | // NOTE: Do not introduce any new `return` statements past this 84 | // point. It is important that `ActiveThreadCount` always be decremented 85 | // when leaving this function. 86 | 87 | // Make sure the child process uses the default handlers for the 88 | // following signals rather than inheriting what the parent has. 89 | sigset_t DefaultSigSet; 90 | (void)sigemptyset(&DefaultSigSet); 91 | (void)sigaddset(&DefaultSigSet, SIGQUIT); 92 | (void)sigaddset(&DefaultSigSet, SIGINT); 93 | (void)posix_spawnattr_setsigdefault(&SpawnAttributes, &DefaultSigSet); 94 | // Make sure the child process doesn't block SIGCHLD 95 | (void)posix_spawnattr_setsigmask(&SpawnAttributes, &OldBlockedSignalsSet); 96 | short SpawnFlags = POSIX_SPAWN_SETSIGDEF | POSIX_SPAWN_SETSIGMASK; 97 | (void)posix_spawnattr_setflags(&SpawnAttributes, SpawnFlags); 98 | 99 | pid_t Pid; 100 | char **Environ = environ; // Read from global 101 | const char *CommandCStr = CmdLine.c_str(); 102 | char *const Argv[] = { 103 | strdup("sh"), 104 | strdup("-c"), 105 | strdup(CommandCStr), 106 | NULL 107 | }; 108 | int ErrorCode = 0, ProcessStatus = 0; 109 | // FIXME: We probably shouldn't hardcode the shell path. 110 | ErrorCode = posix_spawn(&Pid, "/bin/sh", NULL, &SpawnAttributes, 111 | Argv, Environ); 112 | (void)posix_spawnattr_destroy(&SpawnAttributes); 113 | if (!ErrorCode) { 114 | pid_t SavedPid = Pid; 115 | do { 116 | // Repeat until call completes uninterrupted. 117 | Pid = waitpid(SavedPid, &ProcessStatus, /*options=*/0); 118 | } while (Pid == -1 && errno == EINTR); 119 | if (Pid == -1) { 120 | // Fail for some other reason. 121 | ProcessStatus = -1; 122 | } 123 | } else if (ErrorCode == ENOMEM || ErrorCode == EAGAIN) { 124 | // Fork failure. 125 | ProcessStatus = -1; 126 | } else { 127 | // Shell execution failure. 128 | ProcessStatus = W_EXITCODE(127, 0); 129 | } 130 | for (unsigned i = 0, n = sizeof(Argv) / sizeof(Argv[0]); i < n; ++i) 131 | free(Argv[i]); 132 | 133 | // Restore the signal handlers of the current process when the last thread 134 | // using this function finishes. 135 | { 136 | std::lock_guard Lock(SignalMutex); 137 | --ActiveThreadCount; 138 | if (ActiveThreadCount == 0) { 139 | bool FailedRestore = false; 140 | if (sigaction(SIGINT, &OldSigIntAction, NULL) == -1) { 141 | Printf("Failed to restore SIGINT handling\n"); 142 | FailedRestore = true; 143 | } 144 | if (sigaction(SIGQUIT, &OldSigQuitAction, NULL) == -1) { 145 | Printf("Failed to restore SIGQUIT handling\n"); 146 | FailedRestore = true; 147 | } 148 | if (sigprocmask(SIG_BLOCK, &OldBlockedSignalsSet, NULL) == -1) { 149 | Printf("Failed to unblock SIGCHLD\n"); 150 | FailedRestore = true; 151 | } 152 | if (FailedRestore) 153 | ProcessStatus = -1; 154 | } 155 | } 156 | return ProcessStatus; 157 | } 158 | 159 | } // namespace fuzzer 160 | 161 | #endif // LIBFUZZER_APPLE 162 | -------------------------------------------------------------------------------- /libFuzzer/Fuzzer/FuzzerUtilLinux.cpp: -------------------------------------------------------------------------------- 1 | //===- FuzzerUtilLinux.cpp - Misc utils for Linux. ------------------------===// 2 | // 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 | // See https://llvm.org/LICENSE.txt for license information. 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 | // 7 | //===----------------------------------------------------------------------===// 8 | // Misc utils for Linux. 9 | //===----------------------------------------------------------------------===// 10 | #include "FuzzerDefs.h" 11 | #if LIBFUZZER_LINUX || LIBFUZZER_NETBSD || LIBFUZZER_FREEBSD || \ 12 | LIBFUZZER_OPENBSD 13 | #include "FuzzerCommand.h" 14 | 15 | #include 16 | #include 17 | #include 18 | 19 | 20 | namespace fuzzer { 21 | 22 | int ExecuteCommand(const Command &Cmd) { 23 | std::string CmdLine = Cmd.toString(); 24 | int exit_code = system(CmdLine.c_str()); 25 | if (WIFEXITED(exit_code)) 26 | return WEXITSTATUS(exit_code); 27 | return exit_code; 28 | } 29 | 30 | } // namespace fuzzer 31 | 32 | #endif 33 | -------------------------------------------------------------------------------- /libFuzzer/Fuzzer/FuzzerUtilPosix.cpp: -------------------------------------------------------------------------------- 1 | //===- FuzzerUtilPosix.cpp - Misc utils for Posix. ------------------------===// 2 | // 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 | // See https://llvm.org/LICENSE.txt for license information. 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 | // 7 | //===----------------------------------------------------------------------===// 8 | // Misc utils implementation using Posix API. 9 | //===----------------------------------------------------------------------===// 10 | #include "FuzzerDefs.h" 11 | #if LIBFUZZER_POSIX 12 | #include "FuzzerIO.h" 13 | #include "FuzzerInternal.h" 14 | #include "FuzzerTracePC.h" 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | 30 | namespace fuzzer { 31 | 32 | static void AlarmHandler(int, siginfo_t *, void *) { 33 | Fuzzer::StaticAlarmCallback(); 34 | } 35 | 36 | static void (*upstream_segv_handler)(int, siginfo_t *, void *); 37 | 38 | static void SegvHandler(int sig, siginfo_t *si, void *ucontext) { 39 | assert(si->si_signo == SIGSEGV); 40 | if (upstream_segv_handler) 41 | return upstream_segv_handler(sig, si, ucontext); 42 | Fuzzer::StaticCrashSignalCallback(); 43 | } 44 | 45 | static void CrashHandler(int, siginfo_t *, void *) { 46 | Fuzzer::StaticCrashSignalCallback(); 47 | } 48 | 49 | static void InterruptHandler(int, siginfo_t *, void *) { 50 | Fuzzer::StaticInterruptCallback(); 51 | } 52 | 53 | static void GracefulExitHandler(int, siginfo_t *, void *) { 54 | Fuzzer::StaticGracefulExitCallback(); 55 | } 56 | 57 | static void FileSizeExceedHandler(int, siginfo_t *, void *) { 58 | Fuzzer::StaticFileSizeExceedCallback(); 59 | } 60 | 61 | static void SetSigaction(int signum, 62 | void (*callback)(int, siginfo_t *, void *)) { 63 | struct sigaction sigact = {}; 64 | if (sigaction(signum, nullptr, &sigact)) { 65 | Printf("libFuzzer: sigaction failed with %d\n", errno); 66 | exit(1); 67 | } 68 | if (sigact.sa_flags & SA_SIGINFO) { 69 | if (sigact.sa_sigaction) { 70 | if (signum != SIGSEGV) 71 | return; 72 | upstream_segv_handler = sigact.sa_sigaction; 73 | } 74 | } else { 75 | if (sigact.sa_handler != SIG_DFL && sigact.sa_handler != SIG_IGN && 76 | sigact.sa_handler != SIG_ERR) 77 | return; 78 | } 79 | 80 | sigact = {}; 81 | sigact.sa_flags = SA_SIGINFO; 82 | sigact.sa_sigaction = callback; 83 | if (sigaction(signum, &sigact, 0)) { 84 | Printf("libFuzzer: sigaction failed with %d\n", errno); 85 | exit(1); 86 | } 87 | } 88 | 89 | void SetTimer(int Seconds) { 90 | struct itimerval T { 91 | {Seconds, 0}, { Seconds, 0 } 92 | }; 93 | if (setitimer(ITIMER_REAL, &T, nullptr)) { 94 | Printf("libFuzzer: setitimer failed with %d\n", errno); 95 | exit(1); 96 | } 97 | SetSigaction(SIGALRM, AlarmHandler); 98 | } 99 | 100 | void SetSignalHandler(const FuzzingOptions& Options) { 101 | if (Options.UnitTimeoutSec > 0) 102 | SetTimer(Options.UnitTimeoutSec / 2 + 1); 103 | if (Options.HandleInt) 104 | SetSigaction(SIGINT, InterruptHandler); 105 | if (Options.HandleTerm) 106 | SetSigaction(SIGTERM, InterruptHandler); 107 | if (Options.HandleSegv) 108 | SetSigaction(SIGSEGV, SegvHandler); 109 | if (Options.HandleBus) 110 | SetSigaction(SIGBUS, CrashHandler); 111 | if (Options.HandleAbrt) 112 | SetSigaction(SIGABRT, CrashHandler); 113 | if (Options.HandleIll) 114 | SetSigaction(SIGILL, CrashHandler); 115 | if (Options.HandleFpe) 116 | SetSigaction(SIGFPE, CrashHandler); 117 | if (Options.HandleXfsz) 118 | SetSigaction(SIGXFSZ, FileSizeExceedHandler); 119 | if (Options.HandleUsr1) 120 | SetSigaction(SIGUSR1, GracefulExitHandler); 121 | if (Options.HandleUsr2) 122 | SetSigaction(SIGUSR2, GracefulExitHandler); 123 | } 124 | 125 | void SleepSeconds(int Seconds) { 126 | sleep(Seconds); // Use C API to avoid coverage from instrumented libc++. 127 | } 128 | 129 | unsigned long GetPid() { return (unsigned long)getpid(); } 130 | 131 | size_t GetPeakRSSMb() { 132 | struct rusage usage; 133 | if (getrusage(RUSAGE_SELF, &usage)) 134 | return 0; 135 | if (LIBFUZZER_LINUX || LIBFUZZER_FREEBSD || LIBFUZZER_NETBSD || 136 | LIBFUZZER_OPENBSD) { 137 | // ru_maxrss is in KiB 138 | return usage.ru_maxrss >> 10; 139 | } else if (LIBFUZZER_APPLE) { 140 | // ru_maxrss is in bytes 141 | return usage.ru_maxrss >> 20; 142 | } 143 | assert(0 && "GetPeakRSSMb() is not implemented for your platform"); 144 | return 0; 145 | } 146 | 147 | FILE *OpenProcessPipe(const char *Command, const char *Mode) { 148 | return popen(Command, Mode); 149 | } 150 | 151 | const void *SearchMemory(const void *Data, size_t DataLen, const void *Patt, 152 | size_t PattLen) { 153 | return memmem(Data, DataLen, Patt, PattLen); 154 | } 155 | 156 | std::string DisassembleCmd(const std::string &FileName) { 157 | return "objdump -d " + FileName; 158 | } 159 | 160 | std::string SearchRegexCmd(const std::string &Regex) { 161 | return "grep '" + Regex + "'"; 162 | } 163 | 164 | } // namespace fuzzer 165 | 166 | #endif // LIBFUZZER_POSIX 167 | -------------------------------------------------------------------------------- /libFuzzer/Fuzzer/FuzzerUtilWindows.cpp: -------------------------------------------------------------------------------- 1 | //===- FuzzerUtilWindows.cpp - Misc utils for Windows. --------------------===// 2 | // 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 | // See https://llvm.org/LICENSE.txt for license information. 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 | // 7 | //===----------------------------------------------------------------------===// 8 | // Misc utils implementation for Windows. 9 | //===----------------------------------------------------------------------===// 10 | #include "FuzzerDefs.h" 11 | #if LIBFUZZER_WINDOWS 12 | #include "FuzzerCommand.h" 13 | #include "FuzzerIO.h" 14 | #include "FuzzerInternal.h" 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | 25 | // This must be included after windows.h. 26 | #include 27 | 28 | namespace fuzzer { 29 | 30 | static const FuzzingOptions* HandlerOpt = nullptr; 31 | 32 | static LONG CALLBACK ExceptionHandler(PEXCEPTION_POINTERS ExceptionInfo) { 33 | switch (ExceptionInfo->ExceptionRecord->ExceptionCode) { 34 | case EXCEPTION_ACCESS_VIOLATION: 35 | case EXCEPTION_ARRAY_BOUNDS_EXCEEDED: 36 | case EXCEPTION_STACK_OVERFLOW: 37 | if (HandlerOpt->HandleSegv) 38 | Fuzzer::StaticCrashSignalCallback(); 39 | break; 40 | case EXCEPTION_DATATYPE_MISALIGNMENT: 41 | case EXCEPTION_IN_PAGE_ERROR: 42 | if (HandlerOpt->HandleBus) 43 | Fuzzer::StaticCrashSignalCallback(); 44 | break; 45 | case EXCEPTION_ILLEGAL_INSTRUCTION: 46 | case EXCEPTION_PRIV_INSTRUCTION: 47 | if (HandlerOpt->HandleIll) 48 | Fuzzer::StaticCrashSignalCallback(); 49 | break; 50 | case EXCEPTION_FLT_DENORMAL_OPERAND: 51 | case EXCEPTION_FLT_DIVIDE_BY_ZERO: 52 | case EXCEPTION_FLT_INEXACT_RESULT: 53 | case EXCEPTION_FLT_INVALID_OPERATION: 54 | case EXCEPTION_FLT_OVERFLOW: 55 | case EXCEPTION_FLT_STACK_CHECK: 56 | case EXCEPTION_FLT_UNDERFLOW: 57 | case EXCEPTION_INT_DIVIDE_BY_ZERO: 58 | case EXCEPTION_INT_OVERFLOW: 59 | if (HandlerOpt->HandleFpe) 60 | Fuzzer::StaticCrashSignalCallback(); 61 | break; 62 | // TODO: handle (Options.HandleXfsz) 63 | } 64 | return EXCEPTION_CONTINUE_SEARCH; 65 | } 66 | 67 | BOOL WINAPI CtrlHandler(DWORD dwCtrlType) { 68 | switch (dwCtrlType) { 69 | case CTRL_C_EVENT: 70 | if (HandlerOpt->HandleInt) 71 | Fuzzer::StaticInterruptCallback(); 72 | return TRUE; 73 | case CTRL_BREAK_EVENT: 74 | if (HandlerOpt->HandleTerm) 75 | Fuzzer::StaticInterruptCallback(); 76 | return TRUE; 77 | } 78 | return FALSE; 79 | } 80 | 81 | void CALLBACK AlarmHandler(PVOID, BOOLEAN) { 82 | Fuzzer::StaticAlarmCallback(); 83 | } 84 | 85 | class TimerQ { 86 | HANDLE TimerQueue; 87 | public: 88 | TimerQ() : TimerQueue(NULL) {} 89 | ~TimerQ() { 90 | if (TimerQueue) 91 | DeleteTimerQueueEx(TimerQueue, NULL); 92 | } 93 | void SetTimer(int Seconds) { 94 | if (!TimerQueue) { 95 | TimerQueue = CreateTimerQueue(); 96 | if (!TimerQueue) { 97 | Printf("libFuzzer: CreateTimerQueue failed.\n"); 98 | exit(1); 99 | } 100 | } 101 | HANDLE Timer; 102 | if (!CreateTimerQueueTimer(&Timer, TimerQueue, AlarmHandler, NULL, 103 | Seconds*1000, Seconds*1000, 0)) { 104 | Printf("libFuzzer: CreateTimerQueueTimer failed.\n"); 105 | exit(1); 106 | } 107 | } 108 | }; 109 | 110 | static TimerQ Timer; 111 | 112 | static void CrashHandler(int) { Fuzzer::StaticCrashSignalCallback(); } 113 | 114 | void SetSignalHandler(const FuzzingOptions& Options) { 115 | HandlerOpt = &Options; 116 | 117 | if (Options.UnitTimeoutSec > 0) 118 | Timer.SetTimer(Options.UnitTimeoutSec / 2 + 1); 119 | 120 | if (Options.HandleInt || Options.HandleTerm) 121 | if (!SetConsoleCtrlHandler(CtrlHandler, TRUE)) { 122 | DWORD LastError = GetLastError(); 123 | Printf("libFuzzer: SetConsoleCtrlHandler failed (Error code: %lu).\n", 124 | LastError); 125 | exit(1); 126 | } 127 | 128 | if (Options.HandleSegv || Options.HandleBus || Options.HandleIll || 129 | Options.HandleFpe) 130 | SetUnhandledExceptionFilter(ExceptionHandler); 131 | 132 | if (Options.HandleAbrt) 133 | if (SIG_ERR == signal(SIGABRT, CrashHandler)) { 134 | Printf("libFuzzer: signal failed with %d\n", errno); 135 | exit(1); 136 | } 137 | } 138 | 139 | void SleepSeconds(int Seconds) { Sleep(Seconds * 1000); } 140 | 141 | unsigned long GetPid() { return GetCurrentProcessId(); } 142 | 143 | size_t GetPeakRSSMb() { 144 | PROCESS_MEMORY_COUNTERS info; 145 | if (!GetProcessMemoryInfo(GetCurrentProcess(), &info, sizeof(info))) 146 | return 0; 147 | return info.PeakWorkingSetSize >> 20; 148 | } 149 | 150 | FILE *OpenProcessPipe(const char *Command, const char *Mode) { 151 | return _popen(Command, Mode); 152 | } 153 | 154 | int ExecuteCommand(const Command &Cmd) { 155 | std::string CmdLine = Cmd.toString(); 156 | return system(CmdLine.c_str()); 157 | } 158 | 159 | const void *SearchMemory(const void *Data, size_t DataLen, const void *Patt, 160 | size_t PattLen) { 161 | // TODO: make this implementation more efficient. 162 | const char *Cdata = (const char *)Data; 163 | const char *Cpatt = (const char *)Patt; 164 | 165 | if (!Data || !Patt || DataLen == 0 || PattLen == 0 || DataLen < PattLen) 166 | return NULL; 167 | 168 | if (PattLen == 1) 169 | return memchr(Data, *Cpatt, DataLen); 170 | 171 | const char *End = Cdata + DataLen - PattLen + 1; 172 | 173 | for (const char *It = Cdata; It < End; ++It) 174 | if (It[0] == Cpatt[0] && memcmp(It, Cpatt, PattLen) == 0) 175 | return It; 176 | 177 | return NULL; 178 | } 179 | 180 | std::string DisassembleCmd(const std::string &FileName) { 181 | Vector command_vector; 182 | command_vector.push_back("dumpbin /summary > nul"); 183 | if (ExecuteCommand(Command(command_vector)) == 0) 184 | return "dumpbin /disasm " + FileName; 185 | Printf("libFuzzer: couldn't find tool to disassemble (dumpbin)\n"); 186 | exit(1); 187 | } 188 | 189 | std::string SearchRegexCmd(const std::string &Regex) { 190 | return "findstr /r \"" + Regex + "\""; 191 | } 192 | 193 | } // namespace fuzzer 194 | 195 | #endif // LIBFUZZER_WINDOWS 196 | -------------------------------------------------------------------------------- /libFuzzer/Fuzzer/FuzzerValueBitMap.h: -------------------------------------------------------------------------------- 1 | //===- FuzzerValueBitMap.h - INTERNAL - Bit map -----------------*- C++ -* ===// 2 | // 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 | // See https://llvm.org/LICENSE.txt for license information. 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 | // 7 | //===----------------------------------------------------------------------===// 8 | // ValueBitMap. 9 | //===----------------------------------------------------------------------===// 10 | 11 | #ifndef LLVM_FUZZER_VALUE_BIT_MAP_H 12 | #define LLVM_FUZZER_VALUE_BIT_MAP_H 13 | 14 | #include "FuzzerDefs.h" 15 | 16 | namespace fuzzer { 17 | 18 | // A bit map containing kMapSizeInWords bits. 19 | struct ValueBitMap { 20 | static const size_t kMapSizeInBits = 1 << 16; 21 | static const size_t kMapPrimeMod = 65371; // Largest Prime < kMapSizeInBits; 22 | static const size_t kBitsInWord = (sizeof(uintptr_t) * 8); 23 | static const size_t kMapSizeInWords = kMapSizeInBits / kBitsInWord; 24 | public: 25 | 26 | // Clears all bits. 27 | void Reset() { memset(Map, 0, sizeof(Map)); } 28 | 29 | // Computes a hash function of Value and sets the corresponding bit. 30 | // Returns true if the bit was changed from 0 to 1. 31 | ATTRIBUTE_NO_SANITIZE_ALL 32 | inline bool AddValue(uintptr_t Value) { 33 | uintptr_t Idx = Value % kMapSizeInBits; 34 | uintptr_t WordIdx = Idx / kBitsInWord; 35 | uintptr_t BitIdx = Idx % kBitsInWord; 36 | uintptr_t Old = Map[WordIdx]; 37 | uintptr_t New = Old | (1ULL << BitIdx); 38 | Map[WordIdx] = New; 39 | return New != Old; 40 | } 41 | 42 | ATTRIBUTE_NO_SANITIZE_ALL 43 | inline bool AddValueModPrime(uintptr_t Value) { 44 | return AddValue(Value % kMapPrimeMod); 45 | } 46 | 47 | inline bool Get(uintptr_t Idx) { 48 | assert(Idx < kMapSizeInBits); 49 | uintptr_t WordIdx = Idx / kBitsInWord; 50 | uintptr_t BitIdx = Idx % kBitsInWord; 51 | return Map[WordIdx] & (1ULL << BitIdx); 52 | } 53 | 54 | size_t SizeInBits() const { return kMapSizeInBits; } 55 | 56 | template 57 | ATTRIBUTE_NO_SANITIZE_ALL 58 | void ForEach(Callback CB) const { 59 | for (size_t i = 0; i < kMapSizeInWords; i++) 60 | if (uintptr_t M = Map[i]) 61 | for (size_t j = 0; j < sizeof(M) * 8; j++) 62 | if (M & ((uintptr_t)1 << j)) 63 | CB(i * sizeof(M) * 8 + j); 64 | } 65 | 66 | private: 67 | ATTRIBUTE_ALIGNED(512) uintptr_t Map[kMapSizeInWords]; 68 | }; 69 | 70 | } // namespace fuzzer 71 | 72 | #endif // LLVM_FUZZER_VALUE_BIT_MAP_H 73 | -------------------------------------------------------------------------------- /libFuzzer/Fuzzer/README.txt: -------------------------------------------------------------------------------- 1 | See http://llvm.org/docs/LibFuzzer.html 2 | -------------------------------------------------------------------------------- /libFuzzer/Fuzzer/build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | LIBFUZZER_SRC_DIR=$(dirname $0) 3 | CXX="${CXX:-clang}" 4 | for f in $LIBFUZZER_SRC_DIR/*.cpp; do 5 | $CXX -g -O2 -fno-omit-frame-pointer -std=c++11 $f -c & 6 | done 7 | wait 8 | rm -f libFuzzer.a 9 | ar ru libFuzzer.a Fuzzer*.o 10 | rm -f Fuzzer*.o 11 | 12 | -------------------------------------------------------------------------------- /libFuzzer/Fuzzer/dataflow/DataFlow.h: -------------------------------------------------------------------------------- 1 | /*===- DataFlow.h - a standalone DataFlow trace -------===// 2 | // 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 | // See https://llvm.org/LICENSE.txt for license information. 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 | // 7 | //===----------------------------------------------------------------------===// 8 | // Internal header file to connect DataFlow.cpp and DataFlowCallbacks.cpp. 9 | //===----------------------------------------------------------------------===*/ 10 | 11 | #ifndef __LIBFUZZER_DATAFLOW_H 12 | #define __LIBFUZZER_DATAFLOW_H 13 | 14 | #include 15 | #include 16 | #include 17 | 18 | // This data is shared between DataFlowCallbacks.cpp and DataFlow.cpp. 19 | struct CallbackData { 20 | size_t NumFuncs, NumGuards; 21 | const uintptr_t *PCsBeg, *PCsEnd; 22 | dfsan_label *FuncLabels; // Array of NumFuncs elements. 23 | bool *BBExecuted; // Array of NumGuards elements. 24 | }; 25 | 26 | extern CallbackData __dft; 27 | 28 | enum { 29 | PCFLAG_FUNC_ENTRY = 1, 30 | }; 31 | 32 | #endif // __LIBFUZZER_DATAFLOW_H 33 | -------------------------------------------------------------------------------- /libFuzzer/Fuzzer/dataflow/DataFlowCallbacks.cpp: -------------------------------------------------------------------------------- 1 | /*===- DataFlowCallbacks.cpp - a standalone DataFlow trace -------===// 2 | // 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 | // See https://llvm.org/LICENSE.txt for license information. 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 | // 7 | //===----------------------------------------------------------------------===// 8 | // Instrumentation callbacks for DataFlow.cpp. 9 | // These functions should not be instrumented by DFSan, so we 10 | // keep them in a separate file and compile it w/o DFSan. 11 | //===----------------------------------------------------------------------===*/ 12 | #include "DataFlow.h" 13 | 14 | #include 15 | #include 16 | #include 17 | 18 | static __thread size_t CurrentFunc; 19 | static uint32_t *GuardsBeg, *GuardsEnd; 20 | static inline bool BlockIsEntry(size_t BlockIdx) { 21 | return __dft.PCsBeg[BlockIdx * 2 + 1] & PCFLAG_FUNC_ENTRY; 22 | } 23 | 24 | extern "C" { 25 | 26 | void __sanitizer_cov_trace_pc_guard_init(uint32_t *start, 27 | uint32_t *stop) { 28 | assert(__dft.NumFuncs == 0 && "This tool does not support DSOs"); 29 | assert(start < stop && "The code is not instrumented for coverage"); 30 | if (start == stop || *start) return; // Initialize only once. 31 | GuardsBeg = start; 32 | GuardsEnd = stop; 33 | } 34 | 35 | void __sanitizer_cov_pcs_init(const uintptr_t *pcs_beg, 36 | const uintptr_t *pcs_end) { 37 | if (__dft.NumGuards) return; // Initialize only once. 38 | __dft.NumGuards = GuardsEnd - GuardsBeg; 39 | __dft.PCsBeg = pcs_beg; 40 | __dft.PCsEnd = pcs_end; 41 | assert(__dft.NumGuards == (__dft.PCsEnd - __dft.PCsBeg) / 2); 42 | for (size_t i = 0; i < __dft.NumGuards; i++) { 43 | if (BlockIsEntry(i)) { 44 | __dft.NumFuncs++; 45 | GuardsBeg[i] = __dft.NumFuncs; 46 | } 47 | } 48 | __dft.BBExecuted = (bool*)calloc(__dft.NumGuards, sizeof(bool)); 49 | fprintf(stderr, "INFO: %zd instrumented function(s) observed " 50 | "and %zd basic blocks\n", __dft.NumFuncs, __dft.NumGuards); 51 | } 52 | 53 | void __sanitizer_cov_trace_pc_indir(uint64_t x){} // unused. 54 | 55 | void __sanitizer_cov_trace_pc_guard(uint32_t *guard) { 56 | size_t GuardIdx = guard - GuardsBeg; 57 | // assert(GuardIdx < __dft.NumGuards); 58 | __dft.BBExecuted[GuardIdx] = true; 59 | if (!*guard) return; // not a function entry. 60 | uint32_t FuncNum = *guard - 1; // Guards start from 1. 61 | // assert(FuncNum < __dft.NumFuncs); 62 | CurrentFunc = FuncNum; 63 | } 64 | 65 | void __dfsw___sanitizer_cov_trace_switch(uint64_t Val, uint64_t *Cases, 66 | dfsan_label L1, dfsan_label UnusedL) { 67 | assert(CurrentFunc < __dft.NumFuncs); 68 | __dft.FuncLabels[CurrentFunc] |= L1; 69 | } 70 | 71 | #define HOOK(Name, Type) \ 72 | void Name(Type Arg1, Type Arg2, dfsan_label L1, dfsan_label L2) { \ 73 | __dft.FuncLabels[CurrentFunc] |= L1 | L2; \ 74 | } 75 | //assert(CurrentFunc < __dft.NumFuncs); 76 | 77 | HOOK(__dfsw___sanitizer_cov_trace_const_cmp1, uint8_t) 78 | HOOK(__dfsw___sanitizer_cov_trace_const_cmp2, uint16_t) 79 | HOOK(__dfsw___sanitizer_cov_trace_const_cmp4, uint32_t) 80 | HOOK(__dfsw___sanitizer_cov_trace_const_cmp8, uint64_t) 81 | HOOK(__dfsw___sanitizer_cov_trace_cmp1, uint8_t) 82 | HOOK(__dfsw___sanitizer_cov_trace_cmp2, uint16_t) 83 | HOOK(__dfsw___sanitizer_cov_trace_cmp4, uint32_t) 84 | HOOK(__dfsw___sanitizer_cov_trace_cmp8, uint64_t) 85 | 86 | } // extern "C" 87 | -------------------------------------------------------------------------------- /libFuzzer/Fuzzer/scripts/unbalanced_allocs.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | #===- lib/fuzzer/scripts/unbalanced_allocs.py ------------------------------===# 3 | # 4 | # Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 5 | # See https://llvm.org/LICENSE.txt for license information. 6 | # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 7 | # 8 | #===------------------------------------------------------------------------===# 9 | # 10 | # Post-process -trace_malloc=2 output and printout only allocations and frees 11 | # unbalanced inside of fuzzer runs. 12 | # Usage: 13 | # my_fuzzer -trace_malloc=2 -runs=10 2>&1 | unbalanced_allocs.py -skip=5 14 | # 15 | #===------------------------------------------------------------------------===# 16 | 17 | import argparse 18 | import sys 19 | 20 | _skip = 0 21 | 22 | def PrintStack(line, stack): 23 | global _skip 24 | if _skip > 0: 25 | return 26 | print('Unbalanced ' + line.rstrip()); 27 | for l in stack: 28 | print(l.rstrip()) 29 | 30 | def ProcessStack(line, f): 31 | stack = [] 32 | while line and line.startswith(' #'): 33 | stack += [line] 34 | line = f.readline() 35 | return line, stack 36 | 37 | def ProcessFree(line, f, allocs): 38 | if not line.startswith('FREE['): 39 | return f.readline() 40 | 41 | addr = int(line.split()[1], 16) 42 | next_line, stack = ProcessStack(f.readline(), f) 43 | if addr in allocs: 44 | del allocs[addr] 45 | else: 46 | PrintStack(line, stack) 47 | return next_line 48 | 49 | def ProcessMalloc(line, f, allocs): 50 | if not line.startswith('MALLOC['): 51 | return ProcessFree(line, f, allocs) 52 | 53 | addr = int(line.split()[1], 16) 54 | assert not addr in allocs 55 | 56 | next_line, stack = ProcessStack(f.readline(), f) 57 | allocs[addr] = (line, stack) 58 | return next_line 59 | 60 | def ProcessRun(line, f): 61 | if not line.startswith('MallocFreeTracer: START'): 62 | return ProcessMalloc(line, f, {}) 63 | 64 | allocs = {} 65 | print(line.rstrip()) 66 | line = f.readline() 67 | while line: 68 | if line.startswith('MallocFreeTracer: STOP'): 69 | global _skip 70 | _skip = _skip - 1 71 | for _, (l, s) in allocs.items(): 72 | PrintStack(l, s) 73 | print(line.rstrip()) 74 | return f.readline() 75 | line = ProcessMalloc(line, f, allocs) 76 | return line 77 | 78 | def ProcessFile(f): 79 | line = f.readline() 80 | while line: 81 | line = ProcessRun(line, f); 82 | 83 | def main(argv): 84 | parser = argparse.ArgumentParser() 85 | parser.add_argument('--skip', default=0, help='number of runs to ignore') 86 | args = parser.parse_args() 87 | global _skip 88 | _skip = int(args.skip) + 1 89 | ProcessFile(sys.stdin) 90 | 91 | if __name__ == '__main__': 92 | main(sys.argv) 93 | -------------------------------------------------------------------------------- /libFuzzer/Fuzzer/standalone/StandaloneFuzzTargetMain.c: -------------------------------------------------------------------------------- 1 | /*===- StandaloneFuzzTargetMain.c - standalone main() for fuzz targets. ---===// 2 | // 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 | // See https://llvm.org/LICENSE.txt for license information. 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 | // 7 | //===----------------------------------------------------------------------===// 8 | // This main() function can be linked to a fuzz target (i.e. a library 9 | // that exports LLVMFuzzerTestOneInput() and possibly LLVMFuzzerInitialize()) 10 | // instead of libFuzzer. This main() function will not perform any fuzzing 11 | // but will simply feed all input files one by one to the fuzz target. 12 | // 13 | // Use this file to provide reproducers for bugs when linking against libFuzzer 14 | // or other fuzzing engine is undesirable. 15 | //===----------------------------------------------------------------------===*/ 16 | #include 17 | #include 18 | #include 19 | 20 | extern int LLVMFuzzerTestOneInput(const unsigned char *data, size_t size); 21 | __attribute__((weak)) extern int LLVMFuzzerInitialize(int *argc, char ***argv); 22 | int main(int argc, char **argv) { 23 | fprintf(stderr, "StandaloneFuzzTargetMain: running %d inputs\n", argc - 1); 24 | if (LLVMFuzzerInitialize) 25 | LLVMFuzzerInitialize(&argc, &argv); 26 | for (int i = 1; i < argc; i++) { 27 | fprintf(stderr, "Running: %s\n", argv[i]); 28 | FILE *f = fopen(argv[i], "r"); 29 | assert(f); 30 | fseek(f, 0, SEEK_END); 31 | size_t len = ftell(f); 32 | fseek(f, 0, SEEK_SET); 33 | unsigned char *buf = (unsigned char*)malloc(len); 34 | size_t n_read = fread(buf, 1, len, f); 35 | fclose(f); 36 | assert(n_read == len); 37 | LLVMFuzzerTestOneInput(buf, len); 38 | free(buf); 39 | fprintf(stderr, "Done: %s: (%zd bytes)\n", argv[i], n_read); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /libFuzzer/Fuzzer/tests/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | include(CompilerRTCompile) 2 | 3 | set(LIBFUZZER_UNITTEST_CFLAGS 4 | ${COMPILER_RT_UNITTEST_CFLAGS} 5 | ${COMPILER_RT_GTEST_CFLAGS} 6 | -I${COMPILER_RT_SOURCE_DIR}/lib/fuzzer 7 | -fno-rtti 8 | -O2) 9 | 10 | if (APPLE) 11 | set(FUZZER_SUPPORTED_OS osx) 12 | endif() 13 | 14 | add_custom_target(FuzzerUnitTests) 15 | set_target_properties(FuzzerUnitTests PROPERTIES FOLDER "Compiler-RT Tests") 16 | 17 | add_custom_target(FuzzedDataProviderUnitTests) 18 | set_target_properties(FuzzedDataProviderUnitTests PROPERTIES FOLDER "Compiler-RT Tests") 19 | 20 | set(LIBFUZZER_UNITTEST_LINK_FLAGS ${COMPILER_RT_UNITTEST_LINK_FLAGS}) 21 | list(APPEND LIBFUZZER_UNITTEST_LINK_FLAGS --driver-mode=g++) 22 | 23 | if(WIN32) 24 | list(APPEND LIBFUZZER_UNITTEST_LINK_FLAGS -Wl,-defaultlib:libcmt,-defaultlib:oldnames) 25 | else() 26 | list(APPEND LIBFUZZER_UNITTEST_LINK_FLAGS -lpthread) 27 | endif() 28 | 29 | if(CMAKE_SYSTEM_NAME STREQUAL "Linux" AND 30 | COMPILER_RT_LIBCXX_PATH AND 31 | COMPILER_RT_LIBCXXABI_PATH) 32 | list(APPEND LIBFUZZER_UNITTEST_CFLAGS -nostdinc++) 33 | endif() 34 | 35 | if ("-fvisibility=hidden" IN_LIST LIBFUZZER_CFLAGS) 36 | # Match visibility settings. 37 | list(APPEND LIBFUZZER_UNITTEST_CFLAGS "-fvisibility=hidden") 38 | endif() 39 | 40 | if(COMPILER_RT_DEFAULT_TARGET_ARCH IN_LIST FUZZER_SUPPORTED_ARCH) 41 | # libFuzzer unit tests are only run on the host machine. 42 | set(arch ${COMPILER_RT_DEFAULT_TARGET_ARCH}) 43 | 44 | set(LIBFUZZER_TEST_RUNTIME RTFuzzerTest.${arch}) 45 | if(APPLE) 46 | set(LIBFUZZER_TEST_RUNTIME_OBJECTS 47 | $) 48 | else() 49 | set(LIBFUZZER_TEST_RUNTIME_OBJECTS 50 | $) 51 | endif() 52 | add_library(${LIBFUZZER_TEST_RUNTIME} STATIC 53 | ${LIBFUZZER_TEST_RUNTIME_OBJECTS}) 54 | set_target_properties(${LIBFUZZER_TEST_RUNTIME} PROPERTIES 55 | ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} 56 | FOLDER "Compiler-RT Runtime tests") 57 | 58 | if(CMAKE_SYSTEM_NAME STREQUAL "Linux" AND 59 | COMPILER_RT_LIBCXX_PATH AND 60 | COMPILER_RT_LIBCXXABI_PATH) 61 | file(GLOB libfuzzer_headers ../*.h) 62 | set(LIBFUZZER_TEST_RUNTIME_DEPS libcxx_fuzzer_${arch}-build ${libfuzzer_headers}) 63 | set(LIBFUZZER_TEST_RUNTIME_CFLAGS -isystem ${LIBCXX_${arch}_PREFIX}/include/c++/v1) 64 | set(LIBFUZZER_TEST_RUNTIME_LINK_FLAGS ${LIBCXX_${arch}_PREFIX}/lib/libc++.a) 65 | endif() 66 | 67 | set(FuzzerTestObjects) 68 | generate_compiler_rt_tests(FuzzerTestObjects 69 | FuzzerUnitTests "Fuzzer-${arch}-Test" ${arch} 70 | SOURCES FuzzerUnittest.cpp ${COMPILER_RT_GTEST_SOURCE} 71 | RUNTIME ${LIBFUZZER_TEST_RUNTIME} 72 | DEPS gtest ${LIBFUZZER_TEST_RUNTIME_DEPS} 73 | CFLAGS ${LIBFUZZER_UNITTEST_CFLAGS} ${LIBFUZZER_TEST_RUNTIME_CFLAGS} 74 | LINK_FLAGS ${LIBFUZZER_UNITTEST_LINK_FLAGS} ${LIBFUZZER_TEST_RUNTIME_LINK_FLAGS}) 75 | set_target_properties(FuzzerUnitTests PROPERTIES 76 | RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}) 77 | 78 | set(FuzzedDataProviderTestObjects) 79 | generate_compiler_rt_tests(FuzzedDataProviderTestObjects 80 | FuzzedDataProviderUnitTests "FuzzerUtils-${arch}-Test" ${arch} 81 | SOURCES FuzzedDataProviderUnittest.cpp ${COMPILER_RT_GTEST_SOURCE} 82 | DEPS gtest ${LIBFUZZER_TEST_RUNTIME_DEPS} ${COMPILER_RT_SOURCE_DIR}/include/fuzzer/FuzzedDataProvider.h 83 | CFLAGS ${LIBFUZZER_UNITTEST_CFLAGS} ${LIBFUZZER_TEST_RUNTIME_CFLAGS} 84 | LINK_FLAGS ${LIBFUZZER_UNITTEST_LINK_FLAGS} ${LIBFUZZER_TEST_RUNTIME_LINK_FLAGS}) 85 | set_target_properties(FuzzedDataProviderUnitTests PROPERTIES 86 | RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}) 87 | endif() 88 | --------------------------------------------------------------------------------