Fuzzing Real Targets
In this post, I start using Fuzzilli on its currently supported targets and record some background notes on Swift.
Fuzzing Preparation
My Ubuntu environment is shown below:

Install Clang
The required version is >=4.0; I installed clang-10. I had installed this part before, but I ran into some problems after installing Swift.

The clang path pointed to the Swift installation folder, so I reinstalled Clang and added clang to update-alternative --config. Using sudo ln may also solve this issue, but I did not try it.
1 | sudo apt-get install clang-10 #or just simply install clang |
The llvm-dev is also needed:
1 | sudo apt install llvm-dev |
To switch to a different clang version:
1 | sudo update-alternatives --config clang |
To remove the link and its slave:
1 | sudo update-alternatives --display clang #or clang++ or others |
Do not install it like this, because it is easier to make mistakes:
1 | sudo update-alternatives --install /usr/bin/clang clang /usr/bin/clang-10 10000 |
Swift may already include clang, so installing clang separately might not be necessary. I am not fully sure, so I am keeping these clang installation notes here.
Install Swift
Make sure the package index and installed packages are up to date:
1 | sudo apt update && sudo apt upgrade |
Install the dependencies for Swift. I did not run this step, but it may be needed in a new Docker container or freshly installed system.
1 | sudo apt install binutils git gnupg2 libc6-dev libcurl4 libedit2 libgcc-9-dev libpython2.7 libsqlite3-0 libstdc++-9-dev libxml2 libz3-dev pkg-config tzdata zlib1g-dev |
Download toolchains from the Swift download page. For example, I chose swift-5.4.2-RELEASE-ubuntu18.04.tar.gz. Then extract the file into a folder such as /home/user_name/:
1 | tar -xvzf swift-5.4.2-RELEASE-ubuntu18.04.tar.gz -C ~ |
Add the path to ~/.bashrc and source it, or restart the environment:
1 | echo "PATH=~/swift-5.4.2-RELEASE-ubuntu18.04/usr/bin:$PATH" >> ~/.bashrc |
To verify Swift, you can enter:
1 | swift --version |
If the output looks like the screenshot below, Swift has been installed successfully.

Test Swift
To test Swift on the command line, enter swift; the terminal will launch a shell called REPL (Read-Eval-Print-Loop). I ran into the following errors when entering REPL:

After removing libc6-dbg, the error message was gone.
1 | sudo apt remove libc6-dbg |

Type the following code to check whether Swift works:
1 | let name = "LinuxConfig" |
After testing, you can exit with ctrl + d, :quit, or :q.
Build Fuzzilli
1 | git clone https://github.com/googleprojectzero/fuzzilli.git |
If it builds successfully, we can begin to fuzz the JavaScript engine.

Begin Fuzzing
After setting up the Swift and clang environment, Fuzzilli can be tried on the following JavaScript engines.
Fuzzing on JavaScriptCore
JavaScriptCore is the JS engine implemented in Safari. First, download the source code and patch it using Fuzzilli's patch.
1 | git clone https://github.com/WebKit/webkit |
After this, we can start running Fuzzilli:
1 | sysctl -w 'kernel.core_pattern=|/bin/false' #Run this if this is first time to use fuzzilli to fuzz |
The following error may appear on the command line:
1 | error: root manifest not found |
If so, run this command first:
1 | swift package init --type executable |

However, this does not always work. The "root manifest not found" error occurs because the project lacks package.swift. I eventually found the solution: clone the whole project inside Fuzzilli instead of somewhere else. In other words, all source code for a specific JavaScript engine, such as JavaScriptCore, should be under /Path/to/fuzzilli/Targets/xxx. This ensures that package.swift exists in the root folder of fuzzilli.
Therefore, I cloned WebKit under ~/coding_env/fuzzilli/Targets/JavaScriptCore and executed the following command under ~/coding_env/fuzzilli/Targets/JavaScriptCore/webkit:
1 | swift run -c release -Xlinker='-lrt' FuzzilliCli --profile=jsc FuzzBuild/Debug/bin/jsc #under fuzzilli's folder, in .../fuzzilli/Targets/JavaScriptCore/webkit |
Fuzzing begins. Initialization takes some time.

Once fuzzing starts, the console looks like this:

After fuzzing, we can perform crash analysis using gdb.
Fuzzing QuickJS
QuickJS is an embeddable JS engine. Use the following command to build it, or follow this link to download the code matching the version in Targets/QJS/REVISION.
1 | cd fuzzilli/Targets/QJS # Make sure this is under the fuzzilli directory |
I encountered some issues here, so I think this should be built on macOS (which uses clang as the default compiler):

The build on Ubuntu failed, and I am still figuring out why and how to fix it. It seems clang is not supported for building QuickJS on Ubuntu. GCC is the default compiler, but GCC does not support -fsanitize-coverage=trace-pc-guard; only clang supports it.

On Ubuntu, if you build using make qjs (following the instructions here), the error is different.

It seems very close to success, but I am stuck here.
Fuzzing V8
V8 is the open-source JS engine used in Chrome. First, we need to fetch the source code, so install depot_tools first.
1 | git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git |
Add depot_tools to the front of your PATH (you will probably want to put this in your ~/.bashrc or ~/.zshrc). Assuming you cloned depot_tools to /path/to/depot_tools:
1 | export PATH=/path/to/depot_tools:$PATH |
Update depot_tools by running the following command in your terminal:
1 | gclient |
Now, get the V8 source code, including all branches and dependencies:
1 | cd fuzzilli/Targets/V8 # Make sure this is under the fuzzilli directory |
If you want to update the code, you can use the following command:
1 | git pull |
Done. Now go to the v8 directory, copy fuzzbuild.sh into the v8 root directory, and execute it from there.

The build succeeded. Run this command to begin fuzzing:
1 | cd .. |
Now it works.

Note: sanitizer coverage for v8 is currently not supported on macOS as it is missing from v8's custom clang toolchain.
Fuzzing Duktape
Duktape is an embeddable JavaScript engine. First, fetch the code from GitHub:
1 | cd fuzzilli/Targets/duktape # Make sure this is under the fuzzilli directory |
The executable will be named duk-fuzzilli and will be located in the duktape directory. However, I got stuck after running make duk-fuzzilli.

Fuzzing SpiderMonkey
SpiderMonkey is an open-source JS engine implemented in Firefox. First, clone the repo and run the script in Fuzzilli.
1 | cd fuzzilli/Targets/Spidermonkey # Make sure this is under the fuzzilli directory |
After copying fuzzbuild.sh from Targets/Spidermonkey to the gecko-dev/js/src directory, run it:
1 | cd Targets/Spidermonkey/gecko-dev |
fuzzbuild_OPT.OBJ/dist/bin/js will be the JavaScript shell for the fuzzer.
1 | mkdir out #In gecko-dev/js/src |
Happy hacking!

Fuzzing JerryScript
JerryScript is a lightweight JavaScript engine for the Internet of Things. To fetch the code:
1 | cd fuzzilli/Targets/Jerryscript # Make sure this is under the fuzzilli directory |
Then apply the patch and run fuzzbuild.sh. Note that rustc may be needed for this step.
1 | cd jerryscript # Make sure this is under fuzzilli/Targets/Jerryscript/jerryscript |
./build/bin/jerry will be the JavaScript shell for the fuzzer.
1 | mkdir out # In Targets/Jerryscript/jerryscript |
Now we can begin fuzzing.

Swift Basic Knowledge (Optional)
Swift uses SPM (Swift Package Manager) to set up a new package project. Create a new folder called swift_test and use this command to initialize it:
1 | swift package init --type executable --name helloworld #swift build --init |
An executable Swift package called helloworld will be generated in this folder.

We can run it by building and executing it.

This creates a basic Command line tool.
Fuzzilli in Docker (Optional)
For this part, refer to this document. An available Docker image can be found here.
Install Rust (Optional)
1 | curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh #Choose 1 after this |
The output message is shown below:

All tools, including rustc, cargo, and rustup, will be located in ~/.cargo/bin. Add this directory to the PATH environment variable. Run rustc --version to check whether Rust has been installed. To uninstall it, run rustup self uninstall.