summaryrefslogtreecommitdiffhomepage
path: root/fuzzing
diff options
context:
space:
mode:
authoroxpa <iippolitov@gmail.com>2024-09-17 14:21:10 +0100
committeroxpa <iippolitov@gmail.com>2024-09-17 14:21:10 +0100
commit2417826d8bebf921ee1be102ef8ce702f0683d66 (patch)
tree76d29a1705415ed7368870826dbb2f04942ee794 /fuzzing
parent0e79d961bb1ea68674961da1703ffedb1ddf6e43 (diff)
parent24ed91f40634372d99f67f0e4e3c2ac0abde81bd (diff)
downloadunit-2417826d8bebf921ee1be102ef8ce702f0683d66.tar.gz
unit-2417826d8bebf921ee1be102ef8ce702f0683d66.tar.bz2
Merge tag '1.33.0' into packaging.
Unit 1.33.0 release.
Diffstat (limited to 'fuzzing')
-rw-r--r--fuzzing/.gitattributes1
-rw-r--r--fuzzing/README.md68
-rw-r--r--fuzzing/build-fuzz.sh20
-rw-r--r--fuzzing/fuzz_basic_seed_corpus/base64_0.binbin0 -> 12 bytes
-rw-r--r--fuzzing/fuzz_basic_seed_corpus/term_0.binbin0 -> 26 bytes
-rw-r--r--fuzzing/fuzz_basic_seed_corpus/term_1.binbin0 -> 26 bytes
-rw-r--r--fuzzing/fuzz_basic_seed_corpus/utf8_0.binbin0 -> 26 bytes
-rw-r--r--fuzzing/fuzz_http.dict38
-rw-r--r--fuzzing/fuzz_http_seed_corpus/nxt_http_test_bench.bin16
-rw-r--r--fuzzing/fuzz_http_seed_corpus/nxt_http_test_run_0.bin2
-rw-r--r--fuzzing/fuzz_http_seed_corpus/nxt_http_test_run_1.bin2
-rw-r--r--fuzzing/fuzz_http_seed_corpus/nxt_http_test_run_10.bin2
-rw-r--r--fuzzing/fuzz_http_seed_corpus/nxt_http_test_run_11.bin2
-rw-r--r--fuzzing/fuzz_http_seed_corpus/nxt_http_test_run_12.bin3
-rw-r--r--fuzzing/fuzz_http_seed_corpus/nxt_http_test_run_13.bin3
-rw-r--r--fuzzing/fuzz_http_seed_corpus/nxt_http_test_run_14.bin3
-rw-r--r--fuzzing/fuzz_http_seed_corpus/nxt_http_test_run_15.bin3
-rw-r--r--fuzzing/fuzz_http_seed_corpus/nxt_http_test_run_16.bin4
-rw-r--r--fuzzing/fuzz_http_seed_corpus/nxt_http_test_run_17.bin3
-rw-r--r--fuzzing/fuzz_http_seed_corpus/nxt_http_test_run_18.bin3
-rw-r--r--fuzzing/fuzz_http_seed_corpus/nxt_http_test_run_19.bin3
-rw-r--r--fuzzing/fuzz_http_seed_corpus/nxt_http_test_run_2.bin3
-rw-r--r--fuzzing/fuzz_http_seed_corpus/nxt_http_test_run_20.bin3
-rw-r--r--fuzzing/fuzz_http_seed_corpus/nxt_http_test_run_21.bin4
-rw-r--r--fuzzing/fuzz_http_seed_corpus/nxt_http_test_run_22.bin3
-rw-r--r--fuzzing/fuzz_http_seed_corpus/nxt_http_test_run_23.bin5
-rw-r--r--fuzzing/fuzz_http_seed_corpus/nxt_http_test_run_24.bin5
-rw-r--r--fuzzing/fuzz_http_seed_corpus/nxt_http_test_run_3.bin1
-rw-r--r--fuzzing/fuzz_http_seed_corpus/nxt_http_test_run_4.bin1
-rw-r--r--fuzzing/fuzz_http_seed_corpus/nxt_http_test_run_5.bin2
-rw-r--r--fuzzing/fuzz_http_seed_corpus/nxt_http_test_run_6.bin2
-rw-r--r--fuzzing/fuzz_http_seed_corpus/nxt_http_test_run_7.bin2
-rw-r--r--fuzzing/fuzz_http_seed_corpus/nxt_http_test_run_8.bin2
-rw-r--r--fuzzing/fuzz_http_seed_corpus/nxt_http_test_run_9.bin2
-rw-r--r--fuzzing/fuzz_json_seed_corpus/json_0.bin1
-rw-r--r--fuzzing/fuzz_json_seed_corpus/json_1.bin1
-rw-r--r--fuzzing/fuzz_json_seed_corpus/json_2.bin1
-rw-r--r--fuzzing/fuzz_json_seed_corpus/json_3.bin1
-rw-r--r--fuzzing/fuzz_json_seed_corpus/json_4.bin1
-rw-r--r--fuzzing/nxt_basic_fuzz.c236
-rw-r--r--fuzzing/nxt_http_controller_fuzz.c98
-rw-r--r--fuzzing/nxt_http_h1p_fuzz.c106
-rw-r--r--fuzzing/nxt_http_h1p_peer_fuzz.c99
-rw-r--r--fuzzing/nxt_json_fuzz.c97
-rw-r--r--fuzzing/oss-fuzz.sh29
45 files changed, 881 insertions, 0 deletions
diff --git a/fuzzing/.gitattributes b/fuzzing/.gitattributes
new file mode 100644
index 00000000..70e0757b
--- /dev/null
+++ b/fuzzing/.gitattributes
@@ -0,0 +1 @@
+*.bin whitespace=-blank-at-eol,-blank-at-eof
diff --git a/fuzzing/README.md b/fuzzing/README.md
new file mode 100644
index 00000000..9c70c801
--- /dev/null
+++ b/fuzzing/README.md
@@ -0,0 +1,68 @@
+# Fuzzing unit
+
+These tests are generally advised to run only on GNU/Linux.
+
+## Build fuzzers using libFuzzer.
+
+Running `sh fuzzing/build-fuzz.sh` can build all the fuzzers with standard
+`ASan` and `UBSan`.
+
+### More comprehensive How-to Guide.
+
+#### Export flags that are to be used by Unit for fuzzing.
+
+Note that in `CFLAGS` and `CXXFLAGS`, any type of sanitizers can be added.
+
+- [AddressSanitizer](https://clang.llvm.org/docs/AddressSanitizer.html),
+ [ThreadSanitizer](https://clang.llvm.org/docs/ThreadSanitizer.html),
+ [MemorySanitizer](https://clang.llvm.org/docs/MemorySanitizer.html),
+ [UndefinedBehaviorSanitizer](https://clang.llvm.org/docs/UndefinedBehaviorSanitizer.html),
+ [LeakSanitizer](https://clang.llvm.org/docs/LeakSanitizer.html).
+
+```shell
+$ export CC=clang
+$ export CXX=clang++
+$ export CFLAGS="-g -DFUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION -fsanitize=fuzzer-no-link"
+$ export CXXFLAGS="-g -DFUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION -fsanitize=fuzzer-no-link"
+$ export LIB_FUZZING_ENGINE="-fsanitize=fuzzer"
+```
+
+#### Build Unit for Fuzzing.
+
+```shell
+$ ./configure --no-regex --no-pcre2 --fuzz=$LIB_FUZZING_ENGINE
+$ make fuzz -j$(nproc)
+```
+
+#### Running fuzzers.
+
+```shell
+$ mkdir -p build/fuzz_basic_seed
+$ mkdir -p build/fuzz_http_controller_seed
+$ mkdir -p build/fuzz_http_h1p_seed
+$ mkdir -p build/fuzz_http_h1p_peer_seed
+$ mkdir -p build/fuzz_json_seed
+
+$ ./build/fuzz_basic build/fuzz_basic_seed fuzzing/fuzz_basic_seed_corpus
+$ ./build/fuzz_http_controller build/fuzz_http_controller_seed fuzzing/fuzz_http_seed_corpus
+$ ./build/fuzz_http_h1p build/fuzz_http_h1p_seed fuzzing/fuzz_http_seed_corpus
+$ ./build/fuzz_http_h1p_peer build/fuzz_http_h1p_peer_seed fuzzing/fuzz_http_seed_corpus
+$ ./build/fuzz_json build/fuzz_json_seed fuzzing/fuzz_json_seed_corpus
+```
+
+Here is more information about [LibFuzzer](https://llvm.org/docs/LibFuzzer.html).
+
+## Build fuzzers using other fuzzing engines.
+
+- [Honggfuzz](https://github.com/google/honggfuzz/blob/master/docs/PersistentFuzzing.md).
+- [AFLplusplus](https://github.com/AFLplusplus/AFLplusplus/blob/stable/utils/aflpp_driver/README.md).
+
+
+## Requirements.
+
+You will likely need at least the following packages installed (package names
+may vary).
+
+```
+clang, llvm & compiler-rt
+```
diff --git a/fuzzing/build-fuzz.sh b/fuzzing/build-fuzz.sh
new file mode 100644
index 00000000..62f7a676
--- /dev/null
+++ b/fuzzing/build-fuzz.sh
@@ -0,0 +1,20 @@
+#!/usr/bin/env bash
+
+export CC=clang
+export CXX=clang++
+export CFLAGS="-g -DFUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION -fsanitize=address,undefined -fsanitize=fuzzer-no-link"
+export CXXFLAGS="-g -DFUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION -fsanitize=address,undefined -fsanitize=fuzzer-no-link"
+export LIB_FUZZING_ENGINE="-fsanitize=fuzzer"
+
+./configure --no-regex --no-pcre2 --fuzz=$LIB_FUZZING_ENGINE
+make fuzz -j$(nproc)
+
+mkdir -p build/fuzz_basic_seed
+mkdir -p build/fuzz_http_controller_seed
+mkdir -p build/fuzz_http_h1p_seed
+mkdir -p build/fuzz_http_h1p_peer_seed
+mkdir -p build/fuzz_json_seed
+
+echo ""
+echo "Run: ./build/\${fuzzer} build/\${fuzzer}_seed fuzzing/\${fuzzer}_seed_corpus"
+echo ""
diff --git a/fuzzing/fuzz_basic_seed_corpus/base64_0.bin b/fuzzing/fuzz_basic_seed_corpus/base64_0.bin
new file mode 100644
index 00000000..71501405
--- /dev/null
+++ b/fuzzing/fuzz_basic_seed_corpus/base64_0.bin
Binary files differ
diff --git a/fuzzing/fuzz_basic_seed_corpus/term_0.bin b/fuzzing/fuzz_basic_seed_corpus/term_0.bin
new file mode 100644
index 00000000..c7fff416
--- /dev/null
+++ b/fuzzing/fuzz_basic_seed_corpus/term_0.bin
Binary files differ
diff --git a/fuzzing/fuzz_basic_seed_corpus/term_1.bin b/fuzzing/fuzz_basic_seed_corpus/term_1.bin
new file mode 100644
index 00000000..bd03def0
--- /dev/null
+++ b/fuzzing/fuzz_basic_seed_corpus/term_1.bin
Binary files differ
diff --git a/fuzzing/fuzz_basic_seed_corpus/utf8_0.bin b/fuzzing/fuzz_basic_seed_corpus/utf8_0.bin
new file mode 100644
index 00000000..d395758e
--- /dev/null
+++ b/fuzzing/fuzz_basic_seed_corpus/utf8_0.bin
Binary files differ
diff --git a/fuzzing/fuzz_http.dict b/fuzzing/fuzz_http.dict
new file mode 100644
index 00000000..0a198414
--- /dev/null
+++ b/fuzzing/fuzz_http.dict
@@ -0,0 +1,38 @@
+"Accept-Encoding"
+"Accept-Language"
+"Accept"
+"Authorization"
+"Cache-Control"
+"Connection"
+"Content-Length"
+"Content-Range"
+"Content-Type"
+"Cookie"
+"Date"
+"Expect"
+"Host"
+"If-Match"
+"If-Modified-Since"
+"If-None-Match"
+"If-Range"
+"If-Unmodified-Since"
+"Keep-Alive"
+"Origin"
+"Pragma"
+"Range"
+"Referer"
+"Sec-WebSocket-Key"
+"Sec-WebSocket-Version"
+"Server"
+"TE"
+"Transfer-Encoding"
+"Upgrade-Insecure-Requests"
+"Upgrade"
+"User-Agent"
+"Via"
+"X-Forwarded-For"
+"X-Forwarded-Host"
+"X-Forwarded-Proto"
+"X-Http-Method-Override"
+"X-Real-IP"
+"X-Request-ID"
diff --git a/fuzzing/fuzz_http_seed_corpus/nxt_http_test_bench.bin b/fuzzing/fuzz_http_seed_corpus/nxt_http_test_bench.bin
new file mode 100644
index 00000000..64e2f7e8
--- /dev/null
+++ b/fuzzing/fuzz_http_seed_corpus/nxt_http_test_bench.bin
@@ -0,0 +1,16 @@
+POST /path/to/very/interesting/article/on.this.site?arg1=value&arg2=value2&very_big_arg=even_bigger_value HTTP/1.1
+Host: www.example.com
+User-Agent: Mozilla/5.0 (X11; Gentoo Linux x86_64; rv:42.0) Firefox/42.0
+Accept: text/html,application/json,application/xml;q=0.9,*/*;q=0.8
+Accept-Language: ru-RU,ru;q=0.8,en-US;q=0.6,en;q=0.4
+Accept-Encoding: gzip, deflate, br
+If-Modified-Since: Wed, 31 Dec 1986 16:00:00 GMT
+Referer: https://example.org/path/to/not-interesting/article.html
+Cookie: name=value; name2=value2; some_big_cookie=Olr+/9hoA0og/dAcHH1p8sEFAHAAAAAElFTkSuQmCC
+Connection: keep-alive
+Content-Length: 0
+Upgrade-Insecure-Requests: 1
+Pragma: no-cache
+Cache-Control: no-cache
+X-Forwarded-For: 192.0.2.0, 198.51.100.0, 203.0.113.0
+
diff --git a/fuzzing/fuzz_http_seed_corpus/nxt_http_test_run_0.bin b/fuzzing/fuzz_http_seed_corpus/nxt_http_test_run_0.bin
new file mode 100644
index 00000000..00ff084d
--- /dev/null
+++ b/fuzzing/fuzz_http_seed_corpus/nxt_http_test_run_0.bin
@@ -0,0 +1,2 @@
+XXX-METHOD /d.ir/fi+le.ext?key=val HTTP/1.2
+
diff --git a/fuzzing/fuzz_http_seed_corpus/nxt_http_test_run_1.bin b/fuzzing/fuzz_http_seed_corpus/nxt_http_test_run_1.bin
new file mode 100644
index 00000000..2f6c6149
--- /dev/null
+++ b/fuzzing/fuzz_http_seed_corpus/nxt_http_test_run_1.bin
@@ -0,0 +1,2 @@
+GEt / HTTP/1.0
+
diff --git a/fuzzing/fuzz_http_seed_corpus/nxt_http_test_run_10.bin b/fuzzing/fuzz_http_seed_corpus/nxt_http_test_run_10.bin
new file mode 100644
index 00000000..03337016
--- /dev/null
+++ b/fuzzing/fuzz_http_seed_corpus/nxt_http_test_run_10.bin
@@ -0,0 +1,2 @@
+GET /na %20me.ext?args HTTP/1.0
+
diff --git a/fuzzing/fuzz_http_seed_corpus/nxt_http_test_run_11.bin b/fuzzing/fuzz_http_seed_corpus/nxt_http_test_run_11.bin
new file mode 100644
index 00000000..bac5bc27
--- /dev/null
+++ b/fuzzing/fuzz_http_seed_corpus/nxt_http_test_run_11.bin
@@ -0,0 +1,2 @@
+GET / HTTP/1.0 HTTP/1.1
+
diff --git a/fuzzing/fuzz_http_seed_corpus/nxt_http_test_run_12.bin b/fuzzing/fuzz_http_seed_corpus/nxt_http_test_run_12.bin
new file mode 100644
index 00000000..75bd72e2
--- /dev/null
+++ b/fuzzing/fuzz_http_seed_corpus/nxt_http_test_run_12.bin
@@ -0,0 +1,3 @@
+GET / HTTP/1.1
+Host:example.com
+
diff --git a/fuzzing/fuzz_http_seed_corpus/nxt_http_test_run_13.bin b/fuzzing/fuzz_http_seed_corpus/nxt_http_test_run_13.bin
new file mode 100644
index 00000000..2216ec8d
--- /dev/null
+++ b/fuzzing/fuzz_http_seed_corpus/nxt_http_test_run_13.bin
@@ -0,0 +1,3 @@
+GET / HTTP/1.1
+Host:
+
diff --git a/fuzzing/fuzz_http_seed_corpus/nxt_http_test_run_14.bin b/fuzzing/fuzz_http_seed_corpus/nxt_http_test_run_14.bin
new file mode 100644
index 00000000..12435096
--- /dev/null
+++ b/fuzzing/fuzz_http_seed_corpus/nxt_http_test_run_14.bin
@@ -0,0 +1,3 @@
+GET / HTTP/1.1
+:Host: example.com
+
diff --git a/fuzzing/fuzz_http_seed_corpus/nxt_http_test_run_15.bin b/fuzzing/fuzz_http_seed_corpus/nxt_http_test_run_15.bin
new file mode 100644
index 00000000..88bb36f4
--- /dev/null
+++ b/fuzzing/fuzz_http_seed_corpus/nxt_http_test_run_15.bin
@@ -0,0 +1,3 @@
+GET / HTTP/1.1
+Ho_st: example.com
+
diff --git a/fuzzing/fuzz_http_seed_corpus/nxt_http_test_run_16.bin b/fuzzing/fuzz_http_seed_corpus/nxt_http_test_run_16.bin
new file mode 100644
index 00000000..ce7453c2
--- /dev/null
+++ b/fuzzing/fuzz_http_seed_corpus/nxt_http_test_run_16.bin
@@ -0,0 +1,4 @@
+GET / HTTP/1.1
+Ho
+st: example.com
+
diff --git a/fuzzing/fuzz_http_seed_corpus/nxt_http_test_run_17.bin b/fuzzing/fuzz_http_seed_corpus/nxt_http_test_run_17.bin
new file mode 100644
index 00000000..5016e0df
--- /dev/null
+++ b/fuzzing/fuzz_http_seed_corpus/nxt_http_test_run_17.bin
@@ -0,0 +1,3 @@
+GET / HTTP/1.1
+Host: exa mple.com
+
diff --git a/fuzzing/fuzz_http_seed_corpus/nxt_http_test_run_18.bin b/fuzzing/fuzz_http_seed_corpus/nxt_http_test_run_18.bin
new file mode 100644
index 00000000..d2409a88
--- /dev/null
+++ b/fuzzing/fuzz_http_seed_corpus/nxt_http_test_run_18.bin
@@ -0,0 +1,3 @@
+GET / HTTP/1.1
+Host: example.com
+
diff --git a/fuzzing/fuzz_http_seed_corpus/nxt_http_test_run_19.bin b/fuzzing/fuzz_http_seed_corpus/nxt_http_test_run_19.bin
new file mode 100644
index 00000000..40e39921
--- /dev/null
+++ b/fuzzing/fuzz_http_seed_corpus/nxt_http_test_run_19.bin
@@ -0,0 +1,3 @@
+GET / HTTP/1.1
+!#$%&'*+.^_`|~: allowed
+
diff --git a/fuzzing/fuzz_http_seed_corpus/nxt_http_test_run_2.bin b/fuzzing/fuzz_http_seed_corpus/nxt_http_test_run_2.bin
new file mode 100644
index 00000000..cfc0d81a
--- /dev/null
+++ b/fuzzing/fuzz_http_seed_corpus/nxt_http_test_run_2.bin
@@ -0,0 +1,3 @@
+GET /
+ HTTP/1.0
+
diff --git a/fuzzing/fuzz_http_seed_corpus/nxt_http_test_run_20.bin b/fuzzing/fuzz_http_seed_corpus/nxt_http_test_run_20.bin
new file mode 100644
index 00000000..b1deb571
--- /dev/null
+++ b/fuzzing/fuzz_http_seed_corpus/nxt_http_test_run_20.bin
@@ -0,0 +1,3 @@
+GET / HTTP/1.1
+Host: xn--e1afmkfd.xn--80akhbyknj4f
+
diff --git a/fuzzing/fuzz_http_seed_corpus/nxt_http_test_run_21.bin b/fuzzing/fuzz_http_seed_corpus/nxt_http_test_run_21.bin
new file mode 100644
index 00000000..89565fd8
--- /dev/null
+++ b/fuzzing/fuzz_http_seed_corpus/nxt_http_test_run_21.bin
@@ -0,0 +1,4 @@
+GET / HTTP/1.1
+Host: exa
+mple.com
+
diff --git a/fuzzing/fuzz_http_seed_corpus/nxt_http_test_run_22.bin b/fuzzing/fuzz_http_seed_corpus/nxt_http_test_run_22.bin
new file mode 100644
index 00000000..3e0f8f6a
--- /dev/null
+++ b/fuzzing/fuzz_http_seed_corpus/nxt_http_test_run_22.bin
@@ -0,0 +1,3 @@
+GET / HTTP/1.1
+Host: exa mple.com
+
diff --git a/fuzzing/fuzz_http_seed_corpus/nxt_http_test_run_23.bin b/fuzzing/fuzz_http_seed_corpus/nxt_http_test_run_23.bin
new file mode 100644
index 00000000..da0661e5
--- /dev/null
+++ b/fuzzing/fuzz_http_seed_corpus/nxt_http_test_run_23.bin
@@ -0,0 +1,5 @@
+GET / HTTP/1.1
+X-Unknown-Header: value
+X-Good-Header: value
+!#$%&'*+.^_`|~: skipped
+
diff --git a/fuzzing/fuzz_http_seed_corpus/nxt_http_test_run_24.bin b/fuzzing/fuzz_http_seed_corpus/nxt_http_test_run_24.bin
new file mode 100644
index 00000000..6b5232e3
--- /dev/null
+++ b/fuzzing/fuzz_http_seed_corpus/nxt_http_test_run_24.bin
@@ -0,0 +1,5 @@
+GET / HTTP/1.1
+X-Good-Header: value
+X-Unknown-Header: value
+X-Bad-Header: value
+
diff --git a/fuzzing/fuzz_http_seed_corpus/nxt_http_test_run_3.bin b/fuzzing/fuzz_http_seed_corpus/nxt_http_test_run_3.bin
new file mode 100644
index 00000000..20afdfb4
--- /dev/null
+++ b/fuzzing/fuzz_http_seed_corpus/nxt_http_test_run_3.bin
@@ -0,0 +1 @@
+GET / HTTP/1.0
diff --git a/fuzzing/fuzz_http_seed_corpus/nxt_http_test_run_4.bin b/fuzzing/fuzz_http_seed_corpus/nxt_http_test_run_4.bin
new file mode 100644
index 00000000..22b52346
--- /dev/null
+++ b/fuzzing/fuzz_http_seed_corpus/nxt_http_test_run_4.bin
@@ -0,0 +1 @@
+GET / HTTP/2.0
diff --git a/fuzzing/fuzz_http_seed_corpus/nxt_http_test_run_5.bin b/fuzzing/fuzz_http_seed_corpus/nxt_http_test_run_5.bin
new file mode 100644
index 00000000..2da59689
--- /dev/null
+++ b/fuzzing/fuzz_http_seed_corpus/nxt_http_test_run_5.bin
@@ -0,0 +1,2 @@
+GET /. HTTP/1.0
+
diff --git a/fuzzing/fuzz_http_seed_corpus/nxt_http_test_run_6.bin b/fuzzing/fuzz_http_seed_corpus/nxt_http_test_run_6.bin
new file mode 100644
index 00000000..9cf4c094
--- /dev/null
+++ b/fuzzing/fuzz_http_seed_corpus/nxt_http_test_run_6.bin
@@ -0,0 +1,2 @@
+GET /# HTTP/1.0
+
diff --git a/fuzzing/fuzz_http_seed_corpus/nxt_http_test_run_7.bin b/fuzzing/fuzz_http_seed_corpus/nxt_http_test_run_7.bin
new file mode 100644
index 00000000..d02576e0
--- /dev/null
+++ b/fuzzing/fuzz_http_seed_corpus/nxt_http_test_run_7.bin
@@ -0,0 +1,2 @@
+GET /?# HTTP/1.0
+
diff --git a/fuzzing/fuzz_http_seed_corpus/nxt_http_test_run_8.bin b/fuzzing/fuzz_http_seed_corpus/nxt_http_test_run_8.bin
new file mode 100644
index 00000000..fa246dc4
--- /dev/null
+++ b/fuzzing/fuzz_http_seed_corpus/nxt_http_test_run_8.bin
@@ -0,0 +1,2 @@
+GET // HTTP/1.0
+
diff --git a/fuzzing/fuzz_http_seed_corpus/nxt_http_test_run_9.bin b/fuzzing/fuzz_http_seed_corpus/nxt_http_test_run_9.bin
new file mode 100644
index 00000000..2668f283
--- /dev/null
+++ b/fuzzing/fuzz_http_seed_corpus/nxt_http_test_run_9.bin
@@ -0,0 +1,2 @@
+GET /%20 HTTP/1.0
+
diff --git a/fuzzing/fuzz_json_seed_corpus/json_0.bin b/fuzzing/fuzz_json_seed_corpus/json_0.bin
new file mode 100644
index 00000000..450e2283
--- /dev/null
+++ b/fuzzing/fuzz_json_seed_corpus/json_0.bin
@@ -0,0 +1 @@
+[{"container": 1000, "host": 0, "size": 1},{"container": 10000, "host": 10000, "size": 1}, {"container": 60000, "host": 60000, "size": 1}] \ No newline at end of file
diff --git a/fuzzing/fuzz_json_seed_corpus/json_1.bin b/fuzzing/fuzz_json_seed_corpus/json_1.bin
new file mode 100644
index 00000000..0637a088
--- /dev/null
+++ b/fuzzing/fuzz_json_seed_corpus/json_1.bin
@@ -0,0 +1 @@
+[] \ No newline at end of file
diff --git a/fuzzing/fuzz_json_seed_corpus/json_2.bin b/fuzzing/fuzz_json_seed_corpus/json_2.bin
new file mode 100644
index 00000000..5c1201b8
--- /dev/null
+++ b/fuzzing/fuzz_json_seed_corpus/json_2.bin
@@ -0,0 +1 @@
+[{"container": 0, "host": 0, "size": 1}] \ No newline at end of file
diff --git a/fuzzing/fuzz_json_seed_corpus/json_3.bin b/fuzzing/fuzz_json_seed_corpus/json_3.bin
new file mode 100644
index 00000000..e040c9b7
--- /dev/null
+++ b/fuzzing/fuzz_json_seed_corpus/json_3.bin
@@ -0,0 +1 @@
+[{"container": 1000, "host": 0, "size": 1}] \ No newline at end of file
diff --git a/fuzzing/fuzz_json_seed_corpus/json_4.bin b/fuzzing/fuzz_json_seed_corpus/json_4.bin
new file mode 100644
index 00000000..30a2bc50
--- /dev/null
+++ b/fuzzing/fuzz_json_seed_corpus/json_4.bin
@@ -0,0 +1 @@
+[{"container": 0, "host": 1000, "size": 1}, {"container": 1000, "host": 2000, "size": 1}] \ No newline at end of file
diff --git a/fuzzing/nxt_basic_fuzz.c b/fuzzing/nxt_basic_fuzz.c
new file mode 100644
index 00000000..5f71a909
--- /dev/null
+++ b/fuzzing/nxt_basic_fuzz.c
@@ -0,0 +1,236 @@
+/*
+ * Copyright (C) NGINX, Inc.
+ */
+
+#include <nxt_main.h>
+#include <nxt_sha1.h>
+#include <nxt_websocket.h>
+#include <nxt_websocket_header.h>
+
+/* DO NOT TRY THIS AT HOME! */
+#include <nxt_websocket_accept.c>
+
+
+#define KMININPUTLENGTH 4
+#define KMAXINPUTLENGTH 128
+
+
+extern int LLVMFuzzerInitialize(int *argc, char ***argv);
+extern int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size);
+
+void nxt_base64_fuzz(const u_char *data, size_t size);
+void nxt_djb_hash_fuzz(const u_char *data, size_t size);
+void nxt_murmur_hash2_fuzz(const u_char *data, size_t size);
+void nxt_parse_fuzz(const u_char *data, size_t size);
+void nxt_sha1_fuzz(const u_char *data, size_t size);
+void nxt_sha1_update_fuzz(const u_char *data, size_t size);
+void nxt_term_fuzz(const u_char *data, size_t size);
+void nxt_time_fuzz(const u_char *data, size_t size);
+void nxt_uri_fuzz(const u_char *data, size_t size);
+void nxt_utf8_fuzz(const u_char *data, size_t size);
+void nxt_websocket_base64_fuzz(const u_char *data, size_t size);
+void nxt_websocket_frame_fuzz(const u_char *data, size_t size);
+
+
+extern char **environ;
+
+
+int
+LLVMFuzzerInitialize(int *argc, char ***argv)
+{
+ if (nxt_lib_start("fuzzing", NULL, &environ) != NXT_OK) {
+ return NXT_ERROR;
+ }
+
+ return 0;
+}
+
+
+int
+LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
+{
+ if (size < KMININPUTLENGTH || size > KMAXINPUTLENGTH) {
+ return 0;
+ }
+
+ nxt_base64_fuzz(data, size);
+ nxt_djb_hash_fuzz(data, size);
+ nxt_murmur_hash2_fuzz(data, size);
+ nxt_parse_fuzz(data, size);
+ nxt_sha1_fuzz(data, size);
+ nxt_sha1_update_fuzz(data, size);
+ nxt_term_fuzz(data, size);
+ nxt_time_fuzz(data, size);
+ nxt_uri_fuzz(data, size);
+ nxt_utf8_fuzz(data, size);
+ nxt_websocket_base64_fuzz(data, size);
+ nxt_websocket_frame_fuzz(data, size);
+
+ return 0;
+}
+
+
+void
+nxt_base64_fuzz(const u_char *data, size_t size)
+{
+ u_char buf[256];
+ ssize_t ret;
+
+ /*
+ * Validate base64 data before decoding.
+ */
+ ret = nxt_base64_decode(NULL, (u_char *)data, size);
+ if (ret == NXT_ERROR) {
+ return;
+ }
+
+ nxt_base64_decode(buf, (u_char *)data, size);
+}
+
+
+void
+nxt_djb_hash_fuzz(const u_char *data, size_t size)
+{
+ nxt_djb_hash(data, size);
+ nxt_djb_hash_lowcase(data, size);
+}
+
+
+void
+nxt_murmur_hash2_fuzz(const u_char *data, size_t size)
+{
+ nxt_murmur_hash2(data, size);
+ nxt_murmur_hash2_uint32(data);
+}
+
+
+void
+nxt_parse_fuzz(const u_char *data, size_t size)
+{
+ nxt_str_t input;
+
+ input.start = (u_char *)data;
+ input.length = size;
+
+ nxt_int_parse(data, size);
+ nxt_size_t_parse(data, size);
+ nxt_size_parse(data, size);
+ nxt_off_t_parse(data, size);
+ nxt_str_int_parse(&input);
+ nxt_number_parse(&data, data + size);
+}
+
+
+void
+nxt_sha1_fuzz(const u_char *data, size_t size)
+{
+ u_char bin_accept[20];
+ nxt_sha1_t ctx;
+
+ nxt_sha1_init(&ctx);
+ nxt_sha1_update(&ctx, data, size);
+ nxt_sha1_final(bin_accept, &ctx);
+}
+
+
+void
+nxt_sha1_update_fuzz(const u_char *data, size_t size)
+{
+ u_char bin_accept[20];
+ nxt_sha1_t ctx;
+
+ nxt_sha1_init(&ctx);
+ nxt_sha1_update(&ctx, data, size);
+ nxt_sha1_update(&ctx, data, size);
+ nxt_sha1_final(bin_accept, &ctx);
+}
+
+
+void
+nxt_term_fuzz(const u_char *data, size_t size)
+{
+ nxt_term_parse(data, size, 0);
+ nxt_term_parse(data, size, 1);
+}
+
+
+void
+nxt_time_fuzz(const u_char *data, size_t size)
+{
+ nxt_time_parse(data, size);
+}
+
+
+void
+nxt_uri_fuzz(const u_char *data, size_t size)
+{
+ u_char *dst;
+
+ dst = nxt_zalloc(size * 3);
+ if (dst == NULL) {
+ return;
+ }
+
+ nxt_decode_uri(dst, (u_char *)data, size);
+ nxt_decode_uri_plus(dst, (u_char *)data, size);
+
+ nxt_memzero(dst, size * 3);
+ nxt_encode_uri(NULL, (u_char *)data, size);
+ nxt_encode_uri(dst, (u_char *)data, size);
+
+ nxt_free(dst);
+}
+
+
+void
+nxt_utf8_fuzz(const u_char *data, size_t size)
+{
+ const u_char *in;
+
+ in = data;
+ nxt_utf8_decode(&in, data + size);
+
+ nxt_utf8_casecmp((const u_char *)"ABC АБВ ΑΒΓ",
+ data,
+ nxt_length("ABC АБВ ΑΒΓ"),
+ size);
+}
+
+
+void
+nxt_websocket_base64_fuzz(const u_char *data, size_t size)
+{
+ u_char *out;
+
+ out = nxt_zalloc(size * 2);
+ if (out == NULL) {
+ return;
+ }
+
+ nxt_websocket_base64_encode(out, data, size);
+
+ nxt_free(out);
+}
+
+
+void
+nxt_websocket_frame_fuzz(const u_char *data, size_t size)
+{
+ u_char *input;
+
+ /*
+ * Resolve overwrites-const-input by using a copy of the data.
+ */
+ input = nxt_malloc(size);
+ if (input == NULL) {
+ return;
+ }
+
+ nxt_memcpy(input, data, size);
+
+ nxt_websocket_frame_init(input, 0);
+ nxt_websocket_frame_header_size(input);
+ nxt_websocket_frame_payload_len(input);
+
+ nxt_free(input);
+}
diff --git a/fuzzing/nxt_http_controller_fuzz.c b/fuzzing/nxt_http_controller_fuzz.c
new file mode 100644
index 00000000..25527ae1
--- /dev/null
+++ b/fuzzing/nxt_http_controller_fuzz.c
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) NGINX, Inc.
+ */
+
+#include <nxt_main.h>
+
+/* DO NOT TRY THIS AT HOME! */
+#include "nxt_controller.c"
+
+
+#define KMININPUTLENGTH 2
+#define KMAXINPUTLENGTH 1024
+
+
+extern int LLVMFuzzerInitialize(int *argc, char ***argv);
+extern int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size);
+
+
+extern char **environ;
+
+
+int
+LLVMFuzzerInitialize(int *argc, char ***argv)
+{
+ nxt_int_t ret;
+
+ if (nxt_lib_start("fuzzing", NULL, &environ) != NXT_OK) {
+ return NXT_ERROR;
+ }
+
+ ret = nxt_http_fields_hash(&nxt_controller_fields_hash,
+ nxt_controller_request_fields,
+ nxt_nitems(nxt_controller_request_fields));
+ if (ret != NXT_OK) {
+ return NXT_ERROR;
+ }
+
+ return 0;
+}
+
+
+int
+LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
+{
+ nxt_mp_t *mp;
+ nxt_int_t rc;
+ nxt_buf_mem_t buf;
+ nxt_controller_request_t *req;
+ nxt_http_request_parse_t rp;
+
+ if (size < KMININPUTLENGTH || size > KMAXINPUTLENGTH) {
+ return 0;
+ }
+
+ mp = nxt_mp_create(1024, 128, 256, 32);
+ if (mp == NULL) {
+ return 0;
+ }
+
+ req = nxt_mp_zget(mp, sizeof(nxt_controller_request_t));
+ if (req == NULL) {
+ goto failed;
+ }
+
+ req->conn = nxt_mp_zget(mp, sizeof(nxt_conn_t));
+ if (req->conn == NULL) {
+ goto failed;
+ }
+
+ buf.start = (u_char *)data;
+ buf.end = (u_char *)data + size;
+ buf.pos = buf.start;
+ buf.free = buf.end;
+
+ nxt_main_log.level = NXT_LOG_ALERT;
+ req->conn->log = nxt_main_log;
+
+ nxt_memzero(&rp, sizeof(nxt_http_request_parse_t));
+
+ rc = nxt_http_parse_request_init(&rp, mp);
+ if (rc != NXT_OK) {
+ goto failed;
+ }
+
+ rc = nxt_http_parse_request(&rp, &buf);
+ if (rc != NXT_DONE) {
+ goto failed;
+ }
+
+ nxt_http_fields_process(rp.fields, &nxt_controller_fields_hash,
+ req);
+
+failed:
+
+ nxt_mp_destroy(mp);
+
+ return 0;
+}
diff --git a/fuzzing/nxt_http_h1p_fuzz.c b/fuzzing/nxt_http_h1p_fuzz.c
new file mode 100644
index 00000000..b8893ad6
--- /dev/null
+++ b/fuzzing/nxt_http_h1p_fuzz.c
@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) NGINX, Inc.
+ */
+
+#include <nxt_main.h>
+
+/* DO NOT TRY THIS AT HOME! */
+#include "nxt_h1proto.c"
+
+
+#define KMININPUTLENGTH 2
+#define KMAXINPUTLENGTH 1024
+
+
+extern int LLVMFuzzerInitialize(int *argc, char ***argv);
+extern int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size);
+
+
+extern char **environ;
+
+
+int
+LLVMFuzzerInitialize(int *argc, char ***argv)
+{
+ nxt_int_t ret;
+
+ if (nxt_lib_start("fuzzing", NULL, &environ) != NXT_OK) {
+ return NXT_ERROR;
+ }
+
+ ret = nxt_http_fields_hash(&nxt_h1p_fields_hash,
+ nxt_h1p_fields, nxt_nitems(nxt_h1p_fields));
+ if (ret != NXT_OK) {
+ return NXT_ERROR;
+ }
+
+ return 0;
+}
+
+
+int
+LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
+{
+ nxt_mp_t *mp;
+ nxt_int_t rc;
+ nxt_buf_mem_t buf;
+ nxt_http_request_t *req;
+ nxt_http_request_parse_t rp;
+
+ if (size < KMININPUTLENGTH || size > KMAXINPUTLENGTH) {
+ return 0;
+ }
+
+ mp = nxt_mp_create(1024, 128, 256, 32);
+ if (mp == NULL) {
+ return 0;
+ }
+
+ req = nxt_mp_zget(mp, sizeof(nxt_http_request_t));
+ if (req == NULL) {
+ goto failed;
+ }
+
+ req->proto.h1 = nxt_mp_zget(mp, sizeof(nxt_h1proto_t));
+ if (req->proto.h1 == NULL) {
+ goto failed;
+ }
+
+ req->conf = nxt_mp_zget(mp, sizeof(nxt_socket_conf_joint_t));
+ if (req->conf == NULL) {
+ goto failed;
+ }
+
+ req->conf->socket_conf = nxt_mp_zget(mp, sizeof(nxt_socket_conf_t));
+ if (req->conf->socket_conf == NULL) {
+ goto failed;
+ }
+
+ buf.start = (u_char *)data;
+ buf.end = (u_char *)data + size;
+ buf.pos = buf.start;
+ buf.free = buf.end;
+
+ req->mem_pool = mp;
+ req->conf->socket_conf->max_body_size = 8 * 1024 * 1024;
+
+ nxt_memzero(&rp, sizeof(nxt_http_request_parse_t));
+
+ rc = nxt_http_parse_request_init(&rp, mp);
+ if (rc != NXT_OK) {
+ goto failed;
+ }
+
+ rc = nxt_http_parse_request(&rp, &buf);
+ if (rc != NXT_DONE) {
+ goto failed;
+ }
+
+ nxt_http_fields_process(rp.fields, &nxt_h1p_fields_hash, req);
+
+failed:
+
+ nxt_mp_destroy(mp);
+
+ return 0;
+}
diff --git a/fuzzing/nxt_http_h1p_peer_fuzz.c b/fuzzing/nxt_http_h1p_peer_fuzz.c
new file mode 100644
index 00000000..43786d0c
--- /dev/null
+++ b/fuzzing/nxt_http_h1p_peer_fuzz.c
@@ -0,0 +1,99 @@
+/*
+ * Copyright (C) NGINX, Inc.
+ */
+
+#include <nxt_main.h>
+
+/* DO NOT TRY THIS AT HOME! */
+#include "nxt_h1proto.c"
+
+
+#define KMININPUTLENGTH 2
+#define KMAXINPUTLENGTH 1024
+
+
+extern int LLVMFuzzerInitialize(int *argc, char ***argv);
+extern int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size);
+
+
+extern char **environ;
+
+
+int
+LLVMFuzzerInitialize(int *argc, char ***argv)
+{
+ nxt_int_t ret;
+
+ if (nxt_lib_start("fuzzing", NULL, &environ) != NXT_OK) {
+ return NXT_ERROR;
+ }
+
+ ret = nxt_http_fields_hash(&nxt_h1p_peer_fields_hash,
+ nxt_h1p_peer_fields,
+ nxt_nitems(nxt_h1p_peer_fields));
+ if (ret != NXT_OK) {
+ return NXT_ERROR;
+ }
+
+ return 0;
+}
+
+
+int
+LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
+{
+ nxt_mp_t *mp;
+ nxt_int_t rc;
+ nxt_buf_mem_t buf;
+ nxt_http_request_t *req;
+ nxt_http_request_parse_t rp;
+
+ if (size < KMININPUTLENGTH || size > KMAXINPUTLENGTH) {
+ return 0;
+ }
+
+ mp = nxt_mp_create(1024, 128, 256, 32);
+ if (mp == NULL) {
+ return 0;
+ }
+
+ req = nxt_mp_zget(mp, sizeof(nxt_http_request_t));
+ if (req == NULL) {
+ goto failed;
+ }
+
+ req->peer = nxt_mp_zalloc(mp, sizeof(nxt_http_peer_t));
+ if (req->peer == NULL) {
+ goto failed;
+ }
+
+ req->peer->proto.h1 = nxt_mp_zalloc(mp, sizeof(nxt_h1proto_t));
+ if (req->peer->proto.h1 == NULL) {
+ goto failed;
+ }
+
+ buf.start = (u_char *)data;
+ buf.end = (u_char *)data + size;
+ buf.pos = buf.start;
+ buf.free = buf.end;
+
+ nxt_memzero(&rp, sizeof(nxt_http_request_parse_t));
+
+ rc = nxt_http_parse_request_init(&rp, mp);
+ if (rc != NXT_OK) {
+ goto failed;
+ }
+
+ rc = nxt_http_parse_request(&rp, &buf);
+ if (rc != NXT_DONE) {
+ goto failed;
+ }
+
+ nxt_http_fields_process(rp.fields, &nxt_h1p_peer_fields_hash, req);
+
+failed:
+
+ nxt_mp_destroy(mp);
+
+ return 0;
+}
diff --git a/fuzzing/nxt_json_fuzz.c b/fuzzing/nxt_json_fuzz.c
new file mode 100644
index 00000000..fa222988
--- /dev/null
+++ b/fuzzing/nxt_json_fuzz.c
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) NGINX, Inc.
+ */
+
+#include <nxt_main.h>
+#include <nxt_conf.h>
+#include <nxt_router.h>
+
+#define KMININPUTLENGTH 2
+#define KMAXINPUTLENGTH 1024
+
+
+extern int LLVMFuzzerInitialize(int *argc, char ***argv);
+extern int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size);
+
+
+extern char **environ;
+
+
+int
+LLVMFuzzerInitialize(int *argc, char ***argv)
+{
+ if (nxt_lib_start("fuzzing", NULL, &environ) != NXT_OK) {
+ return NXT_ERROR;
+ }
+
+ return 0;
+}
+
+
+int
+LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
+{
+ nxt_mp_t *mp;
+ nxt_str_t input;
+ nxt_thread_t *thr;
+ nxt_runtime_t *rt;
+ nxt_conf_value_t *conf;
+ nxt_conf_validation_t vldt;
+ nxt_conf_json_pretty_t pretty;
+
+ if (size < KMININPUTLENGTH || size > KMAXINPUTLENGTH) {
+ return 0;
+ }
+
+ thr = nxt_thread();
+
+ mp = nxt_mp_create(1024, 128, 256, 32);
+ if (mp == NULL) {
+ return 0;
+ }
+
+ rt = nxt_mp_zget(mp, sizeof(nxt_runtime_t));
+ if (rt == NULL) {
+ goto failed;
+ }
+
+ rt->languages = nxt_array_create(mp, 1, sizeof(nxt_app_lang_module_t));
+ if (rt->languages == NULL) {
+ goto failed;
+ }
+
+ input.start = (u_char *)data;
+ input.length = size;
+
+ thr->runtime = rt;
+ rt->mem_pool = mp;
+
+ nxt_memzero(&pretty, sizeof(nxt_conf_json_pretty_t));
+ nxt_memzero(&vldt, sizeof(nxt_conf_validation_t));
+
+ conf = nxt_conf_json_parse_str(mp, &input);
+ if (conf == NULL) {
+ goto failed;
+ }
+
+ nxt_conf_json_length(conf, NULL);
+ nxt_conf_json_length(conf, &pretty);
+
+ vldt.pool = nxt_mp_create(1024, 128, 256, 32);
+ if (vldt.pool == NULL) {
+ goto failed;
+ }
+
+ vldt.conf = conf;
+ vldt.conf_pool = mp;
+ vldt.ver = NXT_VERNUM;
+
+ nxt_conf_validate(&vldt);
+ nxt_mp_destroy(vldt.pool);
+
+failed:
+
+ nxt_mp_destroy(mp);
+
+ return 0;
+}
diff --git a/fuzzing/oss-fuzz.sh b/fuzzing/oss-fuzz.sh
new file mode 100644
index 00000000..1fe5ecda
--- /dev/null
+++ b/fuzzing/oss-fuzz.sh
@@ -0,0 +1,29 @@
+#!/bin/bash -eu
+
+# Build unit
+./configure --no-regex --no-pcre2 --fuzz="$LIB_FUZZING_ENGINE"
+make fuzz -j"$(nproc)"
+
+# Copy all fuzzers.
+cp build/fuzz_* $OUT/
+
+# cd into fuzzing dir
+pushd fuzzing/
+cp fuzz_http.dict $OUT/fuzz_http_controller.dict
+cp fuzz_http.dict $OUT/fuzz_http_h1p.dict
+cp fuzz_http.dict $OUT/fuzz_http_h1p_peer.dict
+
+# Create temporary directories.
+cp -r fuzz_http_seed_corpus/ fuzz_http_controller_seed_corpus/
+cp -r fuzz_http_seed_corpus/ fuzz_http_h1p_seed_corpus/
+cp -r fuzz_http_seed_corpus/ fuzz_http_h1p_peer_seed_corpus/
+
+zip -r $OUT/fuzz_basic_seed_corpus.zip fuzz_basic_seed_corpus/
+zip -r $OUT/fuzz_http_controller_seed_corpus.zip fuzz_http_controller_seed_corpus/
+zip -r $OUT/fuzz_http_h1p_seed_corpus.zip fuzz_http_h1p_seed_corpus/
+zip -r $OUT/fuzz_http_h1p_peer_seed_corpus.zip fuzz_http_h1p_peer_seed_corpus/
+zip -r $OUT/fuzz_json_seed_corpus.zip fuzz_json_seed_corpus/
+
+# Delete temporary directories.
+rm -r fuzz_http_controller_seed_corpus/ fuzz_http_h1p_seed_corpus/ fuzz_http_h1p_peer_seed_corpus/
+popd