summaryrefslogtreecommitdiff
path: root/sapi/fuzzer
diff options
context:
space:
mode:
Diffstat (limited to 'sapi/fuzzer')
-rw-r--r--sapi/fuzzer/Makefile.frag24
-rw-r--r--sapi/fuzzer/README.md77
-rw-r--r--sapi/fuzzer/config.m493
-rw-r--r--sapi/fuzzer/corpus/exif/bug34704.jpgbin0 -> 9976 bytes
-rw-r--r--sapi/fuzzer/corpus/exif/bug34704_2.jpgbin0 -> 9976 bytes
-rw-r--r--sapi/fuzzer/corpus/exif/bug48378.jpegbin0 -> 2566 bytes
-rw-r--r--sapi/fuzzer/corpus/exif/bug54002_1.jpegbin0 -> 87599 bytes
-rw-r--r--sapi/fuzzer/corpus/exif/bug54002_2.jpegbin0 -> 87599 bytes
-rw-r--r--sapi/fuzzer/corpus/exif/bug62523_1.jpg9
-rw-r--r--sapi/fuzzer/corpus/exif/bug62523_3.jpg12
-rw-r--r--sapi/fuzzer/corpus/exif/bug68113.jpgbin0 -> 368 bytes
-rw-r--r--sapi/fuzzer/corpus/exif/bug68113_2.jpgbin0 -> 368 bytes
-rw-r--r--sapi/fuzzer/corpus/exif/bug68799.jpgbin0 -> 735 bytes
-rw-r--r--sapi/fuzzer/corpus/exif/bug72094_1.jpgbin0 -> 140 bytes
-rw-r--r--sapi/fuzzer/corpus/exif/bug72094_2.jpgbin0 -> 140 bytes
-rw-r--r--sapi/fuzzer/corpus/exif/bug72094_3.jpgbin0 -> 112 bytes
-rw-r--r--sapi/fuzzer/corpus/exif/bug72094_4.jpgbin0 -> 32 bytes
-rw-r--r--sapi/fuzzer/corpus/exif/bug72603.jpegbin0 -> 3711 bytes
-rw-r--r--sapi/fuzzer/corpus/exif/bug72618.jpgbin0 -> 3711 bytes
-rw-r--r--sapi/fuzzer/corpus/exif/bug72627.tiffbin0 -> 1250 bytes
-rw-r--r--sapi/fuzzer/corpus/exif/bug73737.tiffbin0 -> 48 bytes
-rw-r--r--sapi/fuzzer/corpus/exif/bug76130_1.jpgbin0 -> 3396 bytes
-rw-r--r--sapi/fuzzer/corpus/exif/bug76130_2.jpgbin0 -> 1632 bytes
-rw-r--r--sapi/fuzzer/corpus/exif/bug76423.jpgbin0 -> 1537 bytes
-rw-r--r--sapi/fuzzer/corpus/exif/bug76557.jpgbin0 -> 2372 bytes
-rw-r--r--sapi/fuzzer/corpus/exif/bug77540.jpgbin0 -> 91 bytes
-rw-r--r--sapi/fuzzer/corpus/exif/bug77563.jpgbin0 -> 63 bytes
-rw-r--r--sapi/fuzzer/corpus/exif/bug77753.tiffbin0 -> 873 bytes
-rw-r--r--sapi/fuzzer/corpus/exif/bug77831.tiffbin0 -> 49 bytes
-rw-r--r--sapi/fuzzer/corpus/exif/bug77950.tiffbin0 -> 1267 bytes
-rw-r--r--sapi/fuzzer/corpus/exif/bug77988.jpgbin0 -> 1202 bytes
-rw-r--r--sapi/fuzzer/corpus/exif/duplicate_copyright_tag_leak.tiffbin0 -> 9397 bytes
-rw-r--r--sapi/fuzzer/corpus/exif/exif_encoding_crash.jpgbin0 -> 7599 bytes
-rw-r--r--sapi/fuzzer/corpus/exif/image007.jpgbin0 -> 283 bytes
-rw-r--r--sapi/fuzzer/corpus/exif/image008.jpgbin0 -> 527 bytes
-rw-r--r--sapi/fuzzer/corpus/exif/image009.jpgbin0 -> 527 bytes
-rw-r--r--sapi/fuzzer/corpus/exif/image010.jpgbin0 -> 741 bytes
-rw-r--r--sapi/fuzzer/corpus/exif/image011.jpgbin0 -> 741 bytes
-rw-r--r--sapi/fuzzer/corpus/exif/image012.jpgbin0 -> 721 bytes
-rw-r--r--sapi/fuzzer/corpus/exif/image013.jpgbin0 -> 721 bytes
-rw-r--r--sapi/fuzzer/corpus/exif/image014.jpgbin0 -> 935 bytes
-rw-r--r--sapi/fuzzer/corpus/exif/image015.jpgbin0 -> 935 bytes
-rw-r--r--sapi/fuzzer/corpus/exif/image016.tiffbin0 -> 1874 bytes
-rw-r--r--sapi/fuzzer/corpus/exif/image017.tiffbin0 -> 1874 bytes
-rw-r--r--sapi/fuzzer/corpus/exif/image018.tiffbin0 -> 2088 bytes
-rw-r--r--sapi/fuzzer/corpus/exif/image020.tiffbin0 -> 2068 bytes
-rw-r--r--sapi/fuzzer/corpus/exif/image021.tiffbin0 -> 2068 bytes
-rw-r--r--sapi/fuzzer/corpus/exif/image022.tiffbin0 -> 2282 bytes
-rw-r--r--sapi/fuzzer/corpus/exif/image023.tiffbin0 -> 2282 bytes
-rw-r--r--sapi/fuzzer/corpus/exif/image024.jpgbin0 -> 417 bytes
-rw-r--r--sapi/fuzzer/corpus/exif/image025.jpgbin0 -> 417 bytes
-rw-r--r--sapi/fuzzer/corpus/exif/image026.tiffbin0 -> 1984 bytes
-rw-r--r--sapi/fuzzer/corpus/exif/image027.tiffbin0 -> 1984 bytes
-rw-r--r--sapi/fuzzer/corpus/exif/tag_with_illegal_zero_components.jpegbin0 -> 43 bytes
-rw-r--r--sapi/fuzzer/corpus/exif/temporary_buffer_leak.jpgbin0 -> 46 bytes
-rw-r--r--sapi/fuzzer/corpus/exif/test1.jpgbin0 -> 523 bytes
-rw-r--r--sapi/fuzzer/corpus/exif/test2.jpgbin0 -> 1240 bytes
-rw-r--r--sapi/fuzzer/corpus/exif/test22.jpgbin0 -> 1240 bytes
-rw-r--r--sapi/fuzzer/corpus/exif/test3.jpgbin0 -> 1240 bytes
-rw-r--r--sapi/fuzzer/corpus/exif/test4.jpgbin0 -> 713 bytes
-rw-r--r--sapi/fuzzer/corpus/exif/test5.jpgbin0 -> 603 bytes
-rw-r--r--sapi/fuzzer/corpus/exif/test6.jpgbin0 -> 1240 bytes
-rw-r--r--sapi/fuzzer/corpus/exif/zero_length_makernote_leak.tiffbin0 -> 164 bytes
-rw-r--r--sapi/fuzzer/corpus/json/1.json1
-rw-r--r--sapi/fuzzer/corpus/json/10.json1
-rw-r--r--sapi/fuzzer/corpus/json/11.json1
-rw-r--r--sapi/fuzzer/corpus/json/12.json2
-rw-r--r--sapi/fuzzer/corpus/json/13.json1
-rw-r--r--sapi/fuzzer/corpus/json/14.json2
-rw-r--r--sapi/fuzzer/corpus/json/15.json1
-rw-r--r--sapi/fuzzer/corpus/json/16.json1
-rw-r--r--sapi/fuzzer/corpus/json/17.json1
-rw-r--r--sapi/fuzzer/corpus/json/18.json1
-rw-r--r--sapi/fuzzer/corpus/json/19.json1
-rw-r--r--sapi/fuzzer/corpus/json/2.json1
-rw-r--r--sapi/fuzzer/corpus/json/3.json1
-rw-r--r--sapi/fuzzer/corpus/json/4.json1
-rw-r--r--sapi/fuzzer/corpus/json/5.json5
-rw-r--r--sapi/fuzzer/corpus/json/6.json1
-rw-r--r--sapi/fuzzer/corpus/json/7.json2
-rw-r--r--sapi/fuzzer/corpus/json/8.json1
-rw-r--r--sapi/fuzzer/corpus/json/9.json1
-rw-r--r--sapi/fuzzer/corpus/json/fail1.json1
-rw-r--r--sapi/fuzzer/corpus/json/fail10.json1
-rw-r--r--sapi/fuzzer/corpus/json/fail11.json1
-rw-r--r--sapi/fuzzer/corpus/json/fail12.json1
-rw-r--r--sapi/fuzzer/corpus/json/fail13.json1
-rw-r--r--sapi/fuzzer/corpus/json/fail14.json1
-rw-r--r--sapi/fuzzer/corpus/json/fail15.json1
-rw-r--r--sapi/fuzzer/corpus/json/fail16.json1
-rw-r--r--sapi/fuzzer/corpus/json/fail17.json1
-rw-r--r--sapi/fuzzer/corpus/json/fail18.json1
-rw-r--r--sapi/fuzzer/corpus/json/fail19.json1
-rw-r--r--sapi/fuzzer/corpus/json/fail2.json1
-rw-r--r--sapi/fuzzer/corpus/json/fail20.json1
-rw-r--r--sapi/fuzzer/corpus/json/fail21.json1
-rw-r--r--sapi/fuzzer/corpus/json/fail22.json1
-rw-r--r--sapi/fuzzer/corpus/json/fail23.json1
-rw-r--r--sapi/fuzzer/corpus/json/fail24.json1
-rw-r--r--sapi/fuzzer/corpus/json/fail25.json1
-rw-r--r--sapi/fuzzer/corpus/json/fail26.json1
-rw-r--r--sapi/fuzzer/corpus/json/fail27.json2
-rw-r--r--sapi/fuzzer/corpus/json/fail28.json2
-rw-r--r--sapi/fuzzer/corpus/json/fail29.json1
-rw-r--r--sapi/fuzzer/corpus/json/fail3.json1
-rw-r--r--sapi/fuzzer/corpus/json/fail30.json1
-rw-r--r--sapi/fuzzer/corpus/json/fail31.json1
-rw-r--r--sapi/fuzzer/corpus/json/fail32.json1
-rw-r--r--sapi/fuzzer/corpus/json/fail33.json1
-rw-r--r--sapi/fuzzer/corpus/json/fail4.json1
-rw-r--r--sapi/fuzzer/corpus/json/fail5.json1
-rw-r--r--sapi/fuzzer/corpus/json/fail6.json1
-rw-r--r--sapi/fuzzer/corpus/json/fail7.json1
-rw-r--r--sapi/fuzzer/corpus/json/fail8.json1
-rw-r--r--sapi/fuzzer/corpus/json/fail9.json1
-rw-r--r--sapi/fuzzer/corpus/json/pass1.json58
-rw-r--r--sapi/fuzzer/corpus/json/pass2.json1
-rw-r--r--sapi/fuzzer/corpus/json/pass3.json6
-rw-r--r--sapi/fuzzer/corpus/unserialize/__serialize_0071
-rw-r--r--sapi/fuzzer/corpus/unserialize/bug71311
-rw-r--r--sapi/fuzzer/corpus/unserialize/bug713131
-rw-r--r--sapi/fuzzer/corpus/unserialize/bug73144_11
-rw-r--r--sapi/fuzzer/corpus/unserialize/bug73144_21
-rw-r--r--sapi/fuzzer/corpus/unserialize/bug738251
-rw-r--r--sapi/fuzzer/corpus/unserialize/bug741011
-rw-r--r--sapi/fuzzer/corpus/unserialize/bug741031
-rw-r--r--sapi/fuzzer/corpus/unserialize/bug741111
-rw-r--r--sapi/fuzzer/corpus/unserialize/bug746141
-rw-r--r--sapi/fuzzer/corpus/unserialize/bug750541
-rw-r--r--sapi/fuzzer/corpus/unserialize/int_min_iv1
-rw-r--r--sapi/fuzzer/corpus/unserialize/leak_176281
-rw-r--r--sapi/fuzzer/corpus/unserialize/leak_176391
-rw-r--r--sapi/fuzzer/corpus/unserialize/leak_176461
-rw-r--r--sapi/fuzzer/corpus/unserialize/oss_fuzz_276281
-rw-r--r--sapi/fuzzer/corpus/unserialize/oss_fuzz_278761
-rw-r--r--sapi/fuzzer/corpus/unserialize/oss_fuzz_279781
-rw-r--r--sapi/fuzzer/corpus/unserialize/splobjectstorage_negative_count1
-rw-r--r--sapi/fuzzer/dict/parser85
-rw-r--r--sapi/fuzzer/fuzzer-execute.c90
-rw-r--r--sapi/fuzzer/fuzzer-exif.c72
-rw-r--r--sapi/fuzzer/fuzzer-json.c62
-rw-r--r--sapi/fuzzer/fuzzer-mbstring.c78
-rw-r--r--sapi/fuzzer/fuzzer-parser.c49
-rw-r--r--sapi/fuzzer/fuzzer-sapi.c304
-rw-r--r--sapi/fuzzer/fuzzer-sapi.h25
-rw-r--r--sapi/fuzzer/fuzzer-unserialize.c67
-rw-r--r--sapi/fuzzer/fuzzer-unserializehash.c82
-rw-r--r--sapi/fuzzer/fuzzer.h18
-rw-r--r--sapi/fuzzer/generate_all.php5
-rw-r--r--sapi/fuzzer/generate_execute_corpus.php38
-rw-r--r--sapi/fuzzer/generate_parser_corpus.php24
-rw-r--r--sapi/fuzzer/generate_unserialize_dict.php9
-rw-r--r--sapi/fuzzer/generate_unserializehash_corpus.php10
-rw-r--r--sapi/fuzzer/json.dict52
154 files changed, 1430 insertions, 0 deletions
diff --git a/sapi/fuzzer/Makefile.frag b/sapi/fuzzer/Makefile.frag
new file mode 100644
index 0000000000..50feac3a9a
--- /dev/null
+++ b/sapi/fuzzer/Makefile.frag
@@ -0,0 +1,24 @@
+fuzzer: $(PHP_FUZZER_BINARIES)
+
+FUZZER_BUILD = $(LIBTOOL) --mode=link $(FUZZING_CC) -export-dynamic $(CFLAGS_CLEAN) $(EXTRA_CFLAGS) $(EXTRA_LDFLAGS_PROGRAM) $(LDFLAGS) $(PHP_RPATHS) $(PHP_GLOBAL_OBJS) $(PHP_BINARY_OBJS) $(EXTRA_LIBS) $(ZEND_EXTRA_LIBS) $(FUZZING_LIB) -rpath /ORIGIN/lib
+
+$(SAPI_FUZZER_PATH)/php-fuzz-parser: $(PHP_GLOBAL_OBJS) $(PHP_SAPI_OBJS) $(PHP_FUZZER_PARSER_OBJS)
+ $(FUZZER_BUILD) $(PHP_FUZZER_PARSER_OBJS) -o $@
+
+$(SAPI_FUZZER_PATH)/php-fuzz-execute: $(PHP_GLOBAL_OBJS) $(PHP_SAPI_OBJS) $(PHP_FUZZER_EXECUTE_OBJS)
+ $(FUZZER_BUILD) $(PHP_FUZZER_EXECUTE_OBJS) -o $@
+
+$(SAPI_FUZZER_PATH)/php-fuzz-unserialize: $(PHP_GLOBAL_OBJS) $(PHP_SAPI_OBJS) $(PHP_FUZZER_UNSERIALIZE_OBJS)
+ $(FUZZER_BUILD) $(PHP_FUZZER_UNSERIALIZE_OBJS) -o $@
+
+$(SAPI_FUZZER_PATH)/php-fuzz-unserializehash: $(PHP_GLOBAL_OBJS) $(PHP_SAPI_OBJS) $(PHP_FUZZER_UNSERIALIZEHASH_OBJS)
+ $(FUZZER_BUILD) $(PHP_FUZZER_UNSERIALIZEHASH_OBJS) -o $@
+
+$(SAPI_FUZZER_PATH)/php-fuzz-json: $(PHP_GLOBAL_OBJS) $(PHP_SAPI_OBJS) $(PHP_FUZZER_JSON_OBJS)
+ $(FUZZER_BUILD) $(PHP_FUZZER_JSON_OBJS) -o $@
+
+$(SAPI_FUZZER_PATH)/php-fuzz-exif: $(PHP_GLOBAL_OBJS) $(PHP_SAPI_OBJS) $(PHP_FUZZER_EXIF_OBJS)
+ $(FUZZER_BUILD) $(PHP_FUZZER_EXIF_OBJS) -o $@
+
+$(SAPI_FUZZER_PATH)/php-fuzz-mbstring: $(PHP_GLOBAL_OBJS) $(PHP_SAPI_OBJS) $(PHP_FUZZER_MBSTRING_OBJS)
+ $(FUZZER_BUILD) $(PHP_FUZZER_MBSTRING_OBJS) -o $@
diff --git a/sapi/fuzzer/README.md b/sapi/fuzzer/README.md
new file mode 100644
index 0000000000..f79baa6c00
--- /dev/null
+++ b/sapi/fuzzer/README.md
@@ -0,0 +1,77 @@
+Fuzzing SAPI for PHP
+--------------------
+
+The following `./configure` options can be used to enable the fuzzing SAPI, as well as all availablefuzzers. If you don't build the exif/json/mbstring extensions, fuzzers for these extensions will not be built.
+
+```sh
+CC=clang CXX=clang++ \
+./configure \
+ --disable-all \
+ --enable-fuzzer \
+ --with-pic \
+ --enable-debug-assertions \
+ --enable-exif \
+ --enable-mbstring
+```
+
+The `--with-pic` option is required to avoid a linking failure. The `--enable-debug-assertions` option can be used to enable debug assertions despite the use of a release build.
+
+You will need a recent version of clang that supports the `-fsanitize=fuzzer-no-link` option.
+
+When running `make` it creates these binaries in `sapi/fuzzer/`:
+
+* `php-fuzz-parser`: Fuzzing language parser and compiler
+* `php-fuzz-unserialize`: Fuzzing unserialize() function
+* `php-fuzz-unserializehash`: Fuzzing unserialize() for HashContext objects
+* `php-fuzz-json`: Fuzzing JSON parser (requires --enable-json)
+* `php-fuzz-exif`: Fuzzing `exif_read_data()` function (requires --enable-exif)
+* `php-fuzz-mbstring`: Fuzzing `mb_ereg[i]()` (requires --enable-mbstring)
+* `php-fuzz-execute`: Fuzzing the executor
+
+Some fuzzers have a seed corpus in `sapi/fuzzer/corpus`. You can use it as follows:
+
+```sh
+cp -r sapi/fuzzer/corpus/exif ./my-exif-corpus
+sapi/fuzzer/php-fuzz-exif ./my-exif-corpus
+```
+
+For the unserialize fuzzer, a dictionary of internal classes should be generated first:
+
+```sh
+sapi/cli/php sapi/fuzzer/generate_unserialize_dict.php
+cp -r sapi/fuzzer/corpus/unserialize ./my-unserialize-corpus
+sapi/fuzzer/php-fuzz-unserialize -dict=$PWD/sapi/fuzzer/dict/unserialize ./my-unserialize-corpus
+```
+
+For the unserializehash fuzzer, generate a corpus of initial hash serializations:
+
+```sh
+sapi/cli/php sapi/fuzzer/generate_unserializehash_corpus.php
+cp -r sapi/fuzzer/corpus/unserializehash ./my-unserialize-corpus
+sapi/fuzzer/php-fuzz-unserializehash ./my-unserialize-corpus
+```
+
+For the parser fuzzer, a corpus may be generated from Zend test files:
+
+```sh
+sapi/cli/php sapi/fuzzer/generate_parser_corpus.php
+mkdir ./my-parser-corpus
+sapi/fuzzer/php-fuzz-parser -merge=1 ./my-parser-corpus sapi/fuzzer/corpus/parser
+sapi/fuzzer/php-fuzz-parser -only_ascii=1 ./my-parser-corpus
+```
+
+For the mbstring fuzzer, you may want to build the libonig dependency with instrumentation. At this time, libonig is not clean under ubsan, so only the fuzzer and address sanitizers may be used.
+
+```sh
+git clone https://github.com/kkos/oniguruma.git
+pushd oniguruma
+autoreconf -vfi
+./configure CC=clang CFLAGS="-fsanitize=fuzzer-no-link,address -O2 -g"
+make
+popd
+
+export ONIG_CFLAGS="-I$PWD/oniguruma/src"
+export ONIG_LIBS="-L$PWD/oniguruma/src/.libs -l:libonig.a"
+```
+
+This will link an instrumented libonig statically into the PHP binary.
diff --git a/sapi/fuzzer/config.m4 b/sapi/fuzzer/config.m4
new file mode 100644
index 0000000000..92327fc1d4
--- /dev/null
+++ b/sapi/fuzzer/config.m4
@@ -0,0 +1,93 @@
+AC_MSG_CHECKING(for clang fuzzer SAPI)
+
+PHP_ARG_ENABLE([fuzzer],,
+ [AS_HELP_STRING([--enable-fuzzer],
+ [Build PHP as clang fuzzing test module (for developers)])],
+ [no],
+ [no])
+
+PHP_ARG_ENABLE([fuzzer-msan],,
+ [AS_HELP_STRING([--enable-fuzzer-msan],
+ [Enable msan instead of asan/ubsan when fuzzing])],
+ [no],
+ [no])
+
+dnl For newer clang versions see https://llvm.org/docs/LibFuzzer.html#fuzzer-usage
+dnl for relevant flags.
+
+dnl Macro to define fuzzing target
+dnl PHP_FUZZER_TARGET(name, target-var)
+dnl
+AC_DEFUN([PHP_FUZZER_TARGET], [
+ PHP_FUZZER_BINARIES="$PHP_FUZZER_BINARIES $SAPI_FUZZER_PATH/php-fuzz-$1"
+ PHP_SUBST($2)
+ PHP_ADD_SOURCES_X([sapi/fuzzer],[fuzzer-$1.c],[],$2)
+ $2="[$]$2 $FUZZER_COMMON_OBJS"
+])
+
+if test "$PHP_FUZZER" != "no"; then
+ AC_MSG_RESULT([yes])
+ dnl Don't use PHP_REQUIRE_CXX() to avoid unnecessarily pulling in -lstdc++
+ AC_PROG_CXX
+ AC_PROG_CXXCPP
+ PHP_ADD_MAKEFILE_FRAGMENT($abs_srcdir/sapi/fuzzer/Makefile.frag)
+ SAPI_FUZZER_PATH=sapi/fuzzer
+ PHP_SUBST(SAPI_FUZZER_PATH)
+ if test -z "$LIB_FUZZING_ENGINE"; then
+ FUZZING_LIB="-fsanitize=fuzzer"
+ FUZZING_CC="$CC"
+ AX_CHECK_COMPILE_FLAG([-fsanitize=fuzzer-no-link], [
+ CFLAGS="$CFLAGS -fsanitize=fuzzer-no-link"
+ CXXFLAGS="$CXXFLAGS -fsanitize=fuzzer-no-link"
+
+ if test "$PHP_FUZZER_MSAN" = "yes"; then
+ CFLAGS="$CFLAGS -fsanitize=memory -fsanitize-memory-track-origins"
+ CXXFLAGS="$CXXFLAGS -fsanitize=memory -fsanitize-memory-track-origins"
+ else
+ CFLAGS="$CFLAGS -fsanitize=address"
+ CXXFLAGS="$CXXFLAGS -fsanitize=address"
+
+ dnl Don't include -fundefined in CXXFLAGS, because that would also require linking
+ dnl with a C++ compiler.
+ dnl Disable object-size sanitizer, because it is incompatible with our zend_function
+ dnl union, and this can't be easily fixed.
+ dnl We need to specify -fno-sanitize-recover=undefined here, otherwise ubsan warnings
+ dnl will not be considered failures by the fuzzer.
+ CFLAGS="$CFLAGS -fsanitize=undefined -fno-sanitize=object-size -fno-sanitize-recover=undefined"
+ fi
+ ],[
+ AC_MSG_ERROR(Compiler doesn't support -fsanitize=fuzzer-no-link)
+ ])
+ else
+ FUZZING_LIB="$LIB_FUZZING_ENGINE"
+ FUZZING_CC="$CXX -stdlib=libc++"
+ fi
+ PHP_SUBST(FUZZING_LIB)
+ PHP_SUBST(FUZZING_CC)
+
+ dnl PHP_SELECT_SAPI(fuzzer-parser, program, $FUZZER_SOURCES, , '$(SAPI_FUZZER_PATH)')
+
+ PHP_ADD_BUILD_DIR([sapi/fuzzer])
+ PHP_FUZZER_BINARIES=""
+ PHP_BINARIES="$PHP_BINARIES fuzzer"
+ PHP_INSTALLED_SAPIS="$PHP_INSTALLED_SAPIS fuzzer"
+
+ PHP_ADD_SOURCES_X([sapi/fuzzer], [fuzzer-sapi.c], [], FUZZER_COMMON_OBJS)
+
+ PHP_FUZZER_TARGET([parser], PHP_FUZZER_PARSER_OBJS)
+ PHP_FUZZER_TARGET([execute], PHP_FUZZER_EXECUTE_OBJS)
+ PHP_FUZZER_TARGET([unserialize], PHP_FUZZER_UNSERIALIZE_OBJS)
+ PHP_FUZZER_TARGET([unserializehash], PHP_FUZZER_UNSERIALIZEHASH_OBJS)
+ PHP_FUZZER_TARGET([json], PHP_FUZZER_JSON_OBJS)
+
+ if test -n "$enable_exif" && test "$enable_exif" != "no"; then
+ PHP_FUZZER_TARGET([exif], PHP_FUZZER_EXIF_OBJS)
+ fi
+ if test -n "$enable_mbstring" && test "$enable_mbstring" != "no"; then
+ PHP_FUZZER_TARGET([mbstring], PHP_FUZZER_MBSTRING_OBJS)
+ fi
+
+ PHP_SUBST(PHP_FUZZER_BINARIES)
+fi
+
+AC_MSG_RESULT($PHP_FUZZER)
diff --git a/sapi/fuzzer/corpus/exif/bug34704.jpg b/sapi/fuzzer/corpus/exif/bug34704.jpg
new file mode 100644
index 0000000000..42b14c1908
--- /dev/null
+++ b/sapi/fuzzer/corpus/exif/bug34704.jpg
Binary files differ
diff --git a/sapi/fuzzer/corpus/exif/bug34704_2.jpg b/sapi/fuzzer/corpus/exif/bug34704_2.jpg
new file mode 100644
index 0000000000..42b14c1908
--- /dev/null
+++ b/sapi/fuzzer/corpus/exif/bug34704_2.jpg
Binary files differ
diff --git a/sapi/fuzzer/corpus/exif/bug48378.jpeg b/sapi/fuzzer/corpus/exif/bug48378.jpeg
new file mode 100644
index 0000000000..759d805709
--- /dev/null
+++ b/sapi/fuzzer/corpus/exif/bug48378.jpeg
Binary files differ
diff --git a/sapi/fuzzer/corpus/exif/bug54002_1.jpeg b/sapi/fuzzer/corpus/exif/bug54002_1.jpeg
new file mode 100644
index 0000000000..a622d6d213
--- /dev/null
+++ b/sapi/fuzzer/corpus/exif/bug54002_1.jpeg
Binary files differ
diff --git a/sapi/fuzzer/corpus/exif/bug54002_2.jpeg b/sapi/fuzzer/corpus/exif/bug54002_2.jpeg
new file mode 100644
index 0000000000..a622d6d213
--- /dev/null
+++ b/sapi/fuzzer/corpus/exif/bug54002_2.jpeg
Binary files differ
diff --git a/sapi/fuzzer/corpus/exif/bug62523_1.jpg b/sapi/fuzzer/corpus/exif/bug62523_1.jpg
new file mode 100644
index 0000000000..9a63d1e84d
--- /dev/null
+++ b/sapi/fuzzer/corpus/exif/bug62523_1.jpg
@@ -0,0 +1,9 @@
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
+<html><head>
+<title>301 Moved Permanently</title>
+</head><body>
+<h1>Moved Permanently</h1>
+<p>The document has moved <a href="http://www.getid3.org/temp/62523.jpg">here</a>.</p>
+<hr>
+<address>Apache Server at getid3.org Port 80</address>
+</body></html>
diff --git a/sapi/fuzzer/corpus/exif/bug62523_3.jpg b/sapi/fuzzer/corpus/exif/bug62523_3.jpg
new file mode 100644
index 0000000000..3ee91368ce
--- /dev/null
+++ b/sapi/fuzzer/corpus/exif/bug62523_3.jpg
@@ -0,0 +1,12 @@
+<html>
+ <head><title>Found</title></head>
+ <body>
+ <h1>Found</h1>
+ <p>The resource was found at <a href="http://dl.dropboxusercontent.com/u/7562584/Bugs/Php/bad_exif.jpeg">http://dl.dropboxusercontent.com/u/7562584/Bugs/Php/bad_exif.jpeg</a>;
+you should be redirected automatically.
+
+<!-- --></p>
+ <hr noshade>
+ <div align="right">WSGI Server</div>
+ </body>
+</html>
diff --git a/sapi/fuzzer/corpus/exif/bug68113.jpg b/sapi/fuzzer/corpus/exif/bug68113.jpg
new file mode 100644
index 0000000000..3ce7a620fb
--- /dev/null
+++ b/sapi/fuzzer/corpus/exif/bug68113.jpg
Binary files differ
diff --git a/sapi/fuzzer/corpus/exif/bug68113_2.jpg b/sapi/fuzzer/corpus/exif/bug68113_2.jpg
new file mode 100644
index 0000000000..3ce7a620fb
--- /dev/null
+++ b/sapi/fuzzer/corpus/exif/bug68113_2.jpg
Binary files differ
diff --git a/sapi/fuzzer/corpus/exif/bug68799.jpg b/sapi/fuzzer/corpus/exif/bug68799.jpg
new file mode 100644
index 0000000000..acc326dbbf
--- /dev/null
+++ b/sapi/fuzzer/corpus/exif/bug68799.jpg
Binary files differ
diff --git a/sapi/fuzzer/corpus/exif/bug72094_1.jpg b/sapi/fuzzer/corpus/exif/bug72094_1.jpg
new file mode 100644
index 0000000000..d21382b44b
--- /dev/null
+++ b/sapi/fuzzer/corpus/exif/bug72094_1.jpg
Binary files differ
diff --git a/sapi/fuzzer/corpus/exif/bug72094_2.jpg b/sapi/fuzzer/corpus/exif/bug72094_2.jpg
new file mode 100644
index 0000000000..ec414ce02b
--- /dev/null
+++ b/sapi/fuzzer/corpus/exif/bug72094_2.jpg
Binary files differ
diff --git a/sapi/fuzzer/corpus/exif/bug72094_3.jpg b/sapi/fuzzer/corpus/exif/bug72094_3.jpg
new file mode 100644
index 0000000000..8b05314b67
--- /dev/null
+++ b/sapi/fuzzer/corpus/exif/bug72094_3.jpg
Binary files differ
diff --git a/sapi/fuzzer/corpus/exif/bug72094_4.jpg b/sapi/fuzzer/corpus/exif/bug72094_4.jpg
new file mode 100644
index 0000000000..ca6d453c2c
--- /dev/null
+++ b/sapi/fuzzer/corpus/exif/bug72094_4.jpg
Binary files differ
diff --git a/sapi/fuzzer/corpus/exif/bug72603.jpeg b/sapi/fuzzer/corpus/exif/bug72603.jpeg
new file mode 100644
index 0000000000..1764c805fb
--- /dev/null
+++ b/sapi/fuzzer/corpus/exif/bug72603.jpeg
Binary files differ
diff --git a/sapi/fuzzer/corpus/exif/bug72618.jpg b/sapi/fuzzer/corpus/exif/bug72618.jpg
new file mode 100644
index 0000000000..0a61ae2e02
--- /dev/null
+++ b/sapi/fuzzer/corpus/exif/bug72618.jpg
Binary files differ
diff --git a/sapi/fuzzer/corpus/exif/bug72627.tiff b/sapi/fuzzer/corpus/exif/bug72627.tiff
new file mode 100644
index 0000000000..229190a604
--- /dev/null
+++ b/sapi/fuzzer/corpus/exif/bug72627.tiff
Binary files differ
diff --git a/sapi/fuzzer/corpus/exif/bug73737.tiff b/sapi/fuzzer/corpus/exif/bug73737.tiff
new file mode 100644
index 0000000000..2cb036fc47
--- /dev/null
+++ b/sapi/fuzzer/corpus/exif/bug73737.tiff
Binary files differ
diff --git a/sapi/fuzzer/corpus/exif/bug76130_1.jpg b/sapi/fuzzer/corpus/exif/bug76130_1.jpg
new file mode 100644
index 0000000000..e063e46d22
--- /dev/null
+++ b/sapi/fuzzer/corpus/exif/bug76130_1.jpg
Binary files differ
diff --git a/sapi/fuzzer/corpus/exif/bug76130_2.jpg b/sapi/fuzzer/corpus/exif/bug76130_2.jpg
new file mode 100644
index 0000000000..a9e79dca5c
--- /dev/null
+++ b/sapi/fuzzer/corpus/exif/bug76130_2.jpg
Binary files differ
diff --git a/sapi/fuzzer/corpus/exif/bug76423.jpg b/sapi/fuzzer/corpus/exif/bug76423.jpg
new file mode 100644
index 0000000000..08fe2bbc57
--- /dev/null
+++ b/sapi/fuzzer/corpus/exif/bug76423.jpg
Binary files differ
diff --git a/sapi/fuzzer/corpus/exif/bug76557.jpg b/sapi/fuzzer/corpus/exif/bug76557.jpg
new file mode 100644
index 0000000000..d678f07c0f
--- /dev/null
+++ b/sapi/fuzzer/corpus/exif/bug76557.jpg
Binary files differ
diff --git a/sapi/fuzzer/corpus/exif/bug77540.jpg b/sapi/fuzzer/corpus/exif/bug77540.jpg
new file mode 100644
index 0000000000..559022db0e
--- /dev/null
+++ b/sapi/fuzzer/corpus/exif/bug77540.jpg
Binary files differ
diff --git a/sapi/fuzzer/corpus/exif/bug77563.jpg b/sapi/fuzzer/corpus/exif/bug77563.jpg
new file mode 100644
index 0000000000..d6280151f0
--- /dev/null
+++ b/sapi/fuzzer/corpus/exif/bug77563.jpg
Binary files differ
diff --git a/sapi/fuzzer/corpus/exif/bug77753.tiff b/sapi/fuzzer/corpus/exif/bug77753.tiff
new file mode 100644
index 0000000000..b237f39e2b
--- /dev/null
+++ b/sapi/fuzzer/corpus/exif/bug77753.tiff
Binary files differ
diff --git a/sapi/fuzzer/corpus/exif/bug77831.tiff b/sapi/fuzzer/corpus/exif/bug77831.tiff
new file mode 100644
index 0000000000..c7e9f4472b
--- /dev/null
+++ b/sapi/fuzzer/corpus/exif/bug77831.tiff
Binary files differ
diff --git a/sapi/fuzzer/corpus/exif/bug77950.tiff b/sapi/fuzzer/corpus/exif/bug77950.tiff
new file mode 100644
index 0000000000..5c8250ab04
--- /dev/null
+++ b/sapi/fuzzer/corpus/exif/bug77950.tiff
Binary files differ
diff --git a/sapi/fuzzer/corpus/exif/bug77988.jpg b/sapi/fuzzer/corpus/exif/bug77988.jpg
new file mode 100644
index 0000000000..120ff8565a
--- /dev/null
+++ b/sapi/fuzzer/corpus/exif/bug77988.jpg
Binary files differ
diff --git a/sapi/fuzzer/corpus/exif/duplicate_copyright_tag_leak.tiff b/sapi/fuzzer/corpus/exif/duplicate_copyright_tag_leak.tiff
new file mode 100644
index 0000000000..48c7fe61ff
--- /dev/null
+++ b/sapi/fuzzer/corpus/exif/duplicate_copyright_tag_leak.tiff
Binary files differ
diff --git a/sapi/fuzzer/corpus/exif/exif_encoding_crash.jpg b/sapi/fuzzer/corpus/exif/exif_encoding_crash.jpg
new file mode 100644
index 0000000000..55138abe55
--- /dev/null
+++ b/sapi/fuzzer/corpus/exif/exif_encoding_crash.jpg
Binary files differ
diff --git a/sapi/fuzzer/corpus/exif/image007.jpg b/sapi/fuzzer/corpus/exif/image007.jpg
new file mode 100644
index 0000000000..852654075a
--- /dev/null
+++ b/sapi/fuzzer/corpus/exif/image007.jpg
Binary files differ
diff --git a/sapi/fuzzer/corpus/exif/image008.jpg b/sapi/fuzzer/corpus/exif/image008.jpg
new file mode 100644
index 0000000000..3e8bfe4512
--- /dev/null
+++ b/sapi/fuzzer/corpus/exif/image008.jpg
Binary files differ
diff --git a/sapi/fuzzer/corpus/exif/image009.jpg b/sapi/fuzzer/corpus/exif/image009.jpg
new file mode 100644
index 0000000000..8803ddccd4
--- /dev/null
+++ b/sapi/fuzzer/corpus/exif/image009.jpg
Binary files differ
diff --git a/sapi/fuzzer/corpus/exif/image010.jpg b/sapi/fuzzer/corpus/exif/image010.jpg
new file mode 100644
index 0000000000..31ed6d678d
--- /dev/null
+++ b/sapi/fuzzer/corpus/exif/image010.jpg
Binary files differ
diff --git a/sapi/fuzzer/corpus/exif/image011.jpg b/sapi/fuzzer/corpus/exif/image011.jpg
new file mode 100644
index 0000000000..fcd5783ec7
--- /dev/null
+++ b/sapi/fuzzer/corpus/exif/image011.jpg
Binary files differ
diff --git a/sapi/fuzzer/corpus/exif/image012.jpg b/sapi/fuzzer/corpus/exif/image012.jpg
new file mode 100644
index 0000000000..dd25e06181
--- /dev/null
+++ b/sapi/fuzzer/corpus/exif/image012.jpg
Binary files differ
diff --git a/sapi/fuzzer/corpus/exif/image013.jpg b/sapi/fuzzer/corpus/exif/image013.jpg
new file mode 100644
index 0000000000..93ded26667
--- /dev/null
+++ b/sapi/fuzzer/corpus/exif/image013.jpg
Binary files differ
diff --git a/sapi/fuzzer/corpus/exif/image014.jpg b/sapi/fuzzer/corpus/exif/image014.jpg
new file mode 100644
index 0000000000..7657a0a4c7
--- /dev/null
+++ b/sapi/fuzzer/corpus/exif/image014.jpg
Binary files differ
diff --git a/sapi/fuzzer/corpus/exif/image015.jpg b/sapi/fuzzer/corpus/exif/image015.jpg
new file mode 100644
index 0000000000..6f52dec4d7
--- /dev/null
+++ b/sapi/fuzzer/corpus/exif/image015.jpg
Binary files differ
diff --git a/sapi/fuzzer/corpus/exif/image016.tiff b/sapi/fuzzer/corpus/exif/image016.tiff
new file mode 100644
index 0000000000..1712113933
--- /dev/null
+++ b/sapi/fuzzer/corpus/exif/image016.tiff
Binary files differ
diff --git a/sapi/fuzzer/corpus/exif/image017.tiff b/sapi/fuzzer/corpus/exif/image017.tiff
new file mode 100644
index 0000000000..89800d8796
--- /dev/null
+++ b/sapi/fuzzer/corpus/exif/image017.tiff
Binary files differ
diff --git a/sapi/fuzzer/corpus/exif/image018.tiff b/sapi/fuzzer/corpus/exif/image018.tiff
new file mode 100644
index 0000000000..6b4492f7cd
--- /dev/null
+++ b/sapi/fuzzer/corpus/exif/image018.tiff
Binary files differ
diff --git a/sapi/fuzzer/corpus/exif/image020.tiff b/sapi/fuzzer/corpus/exif/image020.tiff
new file mode 100644
index 0000000000..87f187821a
--- /dev/null
+++ b/sapi/fuzzer/corpus/exif/image020.tiff
Binary files differ
diff --git a/sapi/fuzzer/corpus/exif/image021.tiff b/sapi/fuzzer/corpus/exif/image021.tiff
new file mode 100644
index 0000000000..190f30b93a
--- /dev/null
+++ b/sapi/fuzzer/corpus/exif/image021.tiff
Binary files differ
diff --git a/sapi/fuzzer/corpus/exif/image022.tiff b/sapi/fuzzer/corpus/exif/image022.tiff
new file mode 100644
index 0000000000..88f4373341
--- /dev/null
+++ b/sapi/fuzzer/corpus/exif/image022.tiff
Binary files differ
diff --git a/sapi/fuzzer/corpus/exif/image023.tiff b/sapi/fuzzer/corpus/exif/image023.tiff
new file mode 100644
index 0000000000..dc33f6ed90
--- /dev/null
+++ b/sapi/fuzzer/corpus/exif/image023.tiff
Binary files differ
diff --git a/sapi/fuzzer/corpus/exif/image024.jpg b/sapi/fuzzer/corpus/exif/image024.jpg
new file mode 100644
index 0000000000..0b5a42e894
--- /dev/null
+++ b/sapi/fuzzer/corpus/exif/image024.jpg
Binary files differ
diff --git a/sapi/fuzzer/corpus/exif/image025.jpg b/sapi/fuzzer/corpus/exif/image025.jpg
new file mode 100644
index 0000000000..a5c0e17c7a
--- /dev/null
+++ b/sapi/fuzzer/corpus/exif/image025.jpg
Binary files differ
diff --git a/sapi/fuzzer/corpus/exif/image026.tiff b/sapi/fuzzer/corpus/exif/image026.tiff
new file mode 100644
index 0000000000..8fdafc738f
--- /dev/null
+++ b/sapi/fuzzer/corpus/exif/image026.tiff
Binary files differ
diff --git a/sapi/fuzzer/corpus/exif/image027.tiff b/sapi/fuzzer/corpus/exif/image027.tiff
new file mode 100644
index 0000000000..7c3a37a90a
--- /dev/null
+++ b/sapi/fuzzer/corpus/exif/image027.tiff
Binary files differ
diff --git a/sapi/fuzzer/corpus/exif/tag_with_illegal_zero_components.jpeg b/sapi/fuzzer/corpus/exif/tag_with_illegal_zero_components.jpeg
new file mode 100644
index 0000000000..c000b938df
--- /dev/null
+++ b/sapi/fuzzer/corpus/exif/tag_with_illegal_zero_components.jpeg
Binary files differ
diff --git a/sapi/fuzzer/corpus/exif/temporary_buffer_leak.jpg b/sapi/fuzzer/corpus/exif/temporary_buffer_leak.jpg
new file mode 100644
index 0000000000..c9f7ce821f
--- /dev/null
+++ b/sapi/fuzzer/corpus/exif/temporary_buffer_leak.jpg
Binary files differ
diff --git a/sapi/fuzzer/corpus/exif/test1.jpg b/sapi/fuzzer/corpus/exif/test1.jpg
new file mode 100644
index 0000000000..121decb65a
--- /dev/null
+++ b/sapi/fuzzer/corpus/exif/test1.jpg
Binary files differ
diff --git a/sapi/fuzzer/corpus/exif/test2.jpg b/sapi/fuzzer/corpus/exif/test2.jpg
new file mode 100644
index 0000000000..f60ecded6f
--- /dev/null
+++ b/sapi/fuzzer/corpus/exif/test2.jpg
Binary files differ
diff --git a/sapi/fuzzer/corpus/exif/test22.jpg b/sapi/fuzzer/corpus/exif/test22.jpg
new file mode 100644
index 0000000000..f60ecded6f
--- /dev/null
+++ b/sapi/fuzzer/corpus/exif/test22.jpg
Binary files differ
diff --git a/sapi/fuzzer/corpus/exif/test3.jpg b/sapi/fuzzer/corpus/exif/test3.jpg
new file mode 100644
index 0000000000..7547a16630
--- /dev/null
+++ b/sapi/fuzzer/corpus/exif/test3.jpg
Binary files differ
diff --git a/sapi/fuzzer/corpus/exif/test4.jpg b/sapi/fuzzer/corpus/exif/test4.jpg
new file mode 100644
index 0000000000..8a23a7b658
--- /dev/null
+++ b/sapi/fuzzer/corpus/exif/test4.jpg
Binary files differ
diff --git a/sapi/fuzzer/corpus/exif/test5.jpg b/sapi/fuzzer/corpus/exif/test5.jpg
new file mode 100644
index 0000000000..d03cac18a3
--- /dev/null
+++ b/sapi/fuzzer/corpus/exif/test5.jpg
Binary files differ
diff --git a/sapi/fuzzer/corpus/exif/test6.jpg b/sapi/fuzzer/corpus/exif/test6.jpg
new file mode 100644
index 0000000000..073cefdfe0
--- /dev/null
+++ b/sapi/fuzzer/corpus/exif/test6.jpg
Binary files differ
diff --git a/sapi/fuzzer/corpus/exif/zero_length_makernote_leak.tiff b/sapi/fuzzer/corpus/exif/zero_length_makernote_leak.tiff
new file mode 100644
index 0000000000..f1541b39b6
--- /dev/null
+++ b/sapi/fuzzer/corpus/exif/zero_length_makernote_leak.tiff
Binary files differ
diff --git a/sapi/fuzzer/corpus/json/1.json b/sapi/fuzzer/corpus/json/1.json
new file mode 100644
index 0000000000..8161287aab
--- /dev/null
+++ b/sapi/fuzzer/corpus/json/1.json
@@ -0,0 +1 @@
+{"prop":{"prop":null}}
diff --git a/sapi/fuzzer/corpus/json/10.json b/sapi/fuzzer/corpus/json/10.json
new file mode 100644
index 0000000000..59483c2539
--- /dev/null
+++ b/sapi/fuzzer/corpus/json/10.json
@@ -0,0 +1 @@
+{"a":100.1,"b":"foo"}
diff --git a/sapi/fuzzer/corpus/json/11.json b/sapi/fuzzer/corpus/json/11.json
new file mode 100644
index 0000000000..e3907a414c
--- /dev/null
+++ b/sapi/fuzzer/corpus/json/11.json
@@ -0,0 +1 @@
+[100.1,"bar"]
diff --git a/sapi/fuzzer/corpus/json/12.json b/sapi/fuzzer/corpus/json/12.json
new file mode 100644
index 0000000000..222a6678f9
--- /dev/null
+++ b/sapi/fuzzer/corpus/json/12.json
@@ -0,0 +1,2 @@
+{"0":0,"\u0000ab":1,"1":"\u0000null-prefixed value"}
+
diff --git a/sapi/fuzzer/corpus/json/13.json b/sapi/fuzzer/corpus/json/13.json
new file mode 100644
index 0000000000..b9c504cdbe
--- /dev/null
+++ b/sapi/fuzzer/corpus/json/13.json
@@ -0,0 +1 @@
+{ "test": { "foo": "bar" } }
diff --git a/sapi/fuzzer/corpus/json/14.json b/sapi/fuzzer/corpus/json/14.json
new file mode 100644
index 0000000000..0014681471
--- /dev/null
+++ b/sapi/fuzzer/corpus/json/14.json
@@ -0,0 +1,2 @@
+"aa\udbff\udffdzz"
+
diff --git a/sapi/fuzzer/corpus/json/15.json b/sapi/fuzzer/corpus/json/15.json
new file mode 100644
index 0000000000..92591f81a3
--- /dev/null
+++ b/sapi/fuzzer/corpus/json/15.json
@@ -0,0 +1 @@
+"latin 1234 -\/ russian мама мыла раму specialchars \u0002 \b \n U+1D11E >𝄞<"
diff --git a/sapi/fuzzer/corpus/json/16.json b/sapi/fuzzer/corpus/json/16.json
new file mode 100644
index 0000000000..2129292029
--- /dev/null
+++ b/sapi/fuzzer/corpus/json/16.json
@@ -0,0 +1 @@
+{"test":"123343e871700"}
diff --git a/sapi/fuzzer/corpus/json/17.json b/sapi/fuzzer/corpus/json/17.json
new file mode 100644
index 0000000000..4e4676b299
--- /dev/null
+++ b/sapi/fuzzer/corpus/json/17.json
@@ -0,0 +1 @@
+[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[["Too deep"]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]
diff --git a/sapi/fuzzer/corpus/json/18.json b/sapi/fuzzer/corpus/json/18.json
new file mode 100644
index 0000000000..81873afdec
--- /dev/null
+++ b/sapi/fuzzer/corpus/json/18.json
@@ -0,0 +1 @@
+{"myInt":99,"myFloat":123.45,"myNull":null,"myBool":true,"myString":"Hello World"}
diff --git a/sapi/fuzzer/corpus/json/19.json b/sapi/fuzzer/corpus/json/19.json
new file mode 100644
index 0000000000..cc33c95a71
--- /dev/null
+++ b/sapi/fuzzer/corpus/json/19.json
@@ -0,0 +1 @@
+"\u65e5\u672c\u8a9e\u30c6\u30ad\u30b9\u30c8\u3067\u3059\u300201234\uff15\uff16\uff17\uff18\uff19\u3002"
diff --git a/sapi/fuzzer/corpus/json/2.json b/sapi/fuzzer/corpus/json/2.json
new file mode 100644
index 0000000000..3a9a9722e2
--- /dev/null
+++ b/sapi/fuzzer/corpus/json/2.json
@@ -0,0 +1 @@
+{"largenum":123456789012345678901234567890}
diff --git a/sapi/fuzzer/corpus/json/3.json b/sapi/fuzzer/corpus/json/3.json
new file mode 100644
index 0000000000..b004f2079d
--- /dev/null
+++ b/sapi/fuzzer/corpus/json/3.json
@@ -0,0 +1 @@
+["<foo>","'bar'","\"baz\"","&blong&"]
diff --git a/sapi/fuzzer/corpus/json/4.json b/sapi/fuzzer/corpus/json/4.json
new file mode 100644
index 0000000000..8e73a26dab
--- /dev/null
+++ b/sapi/fuzzer/corpus/json/4.json
@@ -0,0 +1 @@
+["\u003Cfoo\u003E","\u0027bar\u0027","\u0022baz\u0022","\u0026blong\u0026"]
diff --git a/sapi/fuzzer/corpus/json/5.json b/sapi/fuzzer/corpus/json/5.json
new file mode 100644
index 0000000000..5c7912450d
--- /dev/null
+++ b/sapi/fuzzer/corpus/json/5.json
@@ -0,0 +1,5 @@
+[
+{"":"value"},
+{"":"value", "key":"value"},
+{"key":"value", "":"value"}
+]
diff --git a/sapi/fuzzer/corpus/json/6.json b/sapi/fuzzer/corpus/json/6.json
new file mode 100644
index 0000000000..2d852843f1
--- /dev/null
+++ b/sapi/fuzzer/corpus/json/6.json
@@ -0,0 +1 @@
+[123,13452345,123.13452345]
diff --git a/sapi/fuzzer/corpus/json/7.json b/sapi/fuzzer/corpus/json/7.json
new file mode 100644
index 0000000000..6e74debaf0
--- /dev/null
+++ b/sapi/fuzzer/corpus/json/7.json
@@ -0,0 +1,2 @@
+["\ud834\udd00"]
+
diff --git a/sapi/fuzzer/corpus/json/8.json b/sapi/fuzzer/corpus/json/8.json
new file mode 100644
index 0000000000..7ea60c3af9
--- /dev/null
+++ b/sapi/fuzzer/corpus/json/8.json
@@ -0,0 +1 @@
+{"zero": 0e0}
diff --git a/sapi/fuzzer/corpus/json/9.json b/sapi/fuzzer/corpus/json/9.json
new file mode 100644
index 0000000000..49e7327986
--- /dev/null
+++ b/sapi/fuzzer/corpus/json/9.json
@@ -0,0 +1 @@
+[null,null,"abc"]
diff --git a/sapi/fuzzer/corpus/json/fail1.json b/sapi/fuzzer/corpus/json/fail1.json
new file mode 100644
index 0000000000..6216b865f1
--- /dev/null
+++ b/sapi/fuzzer/corpus/json/fail1.json
@@ -0,0 +1 @@
+"A JSON payload should be an object or array, not a string." \ No newline at end of file
diff --git a/sapi/fuzzer/corpus/json/fail10.json b/sapi/fuzzer/corpus/json/fail10.json
new file mode 100644
index 0000000000..5d8c0047bd
--- /dev/null
+++ b/sapi/fuzzer/corpus/json/fail10.json
@@ -0,0 +1 @@
+{"Extra value after close": true} "misplaced quoted value" \ No newline at end of file
diff --git a/sapi/fuzzer/corpus/json/fail11.json b/sapi/fuzzer/corpus/json/fail11.json
new file mode 100644
index 0000000000..76eb95b458
--- /dev/null
+++ b/sapi/fuzzer/corpus/json/fail11.json
@@ -0,0 +1 @@
+{"Illegal expression": 1 + 2} \ No newline at end of file
diff --git a/sapi/fuzzer/corpus/json/fail12.json b/sapi/fuzzer/corpus/json/fail12.json
new file mode 100644
index 0000000000..77580a4522
--- /dev/null
+++ b/sapi/fuzzer/corpus/json/fail12.json
@@ -0,0 +1 @@
+{"Illegal invocation": alert()} \ No newline at end of file
diff --git a/sapi/fuzzer/corpus/json/fail13.json b/sapi/fuzzer/corpus/json/fail13.json
new file mode 100644
index 0000000000..379406b59b
--- /dev/null
+++ b/sapi/fuzzer/corpus/json/fail13.json
@@ -0,0 +1 @@
+{"Numbers cannot have leading zeroes": 013} \ No newline at end of file
diff --git a/sapi/fuzzer/corpus/json/fail14.json b/sapi/fuzzer/corpus/json/fail14.json
new file mode 100644
index 0000000000..0ed366b38a
--- /dev/null
+++ b/sapi/fuzzer/corpus/json/fail14.json
@@ -0,0 +1 @@
+{"Numbers cannot be hex": 0x14} \ No newline at end of file
diff --git a/sapi/fuzzer/corpus/json/fail15.json b/sapi/fuzzer/corpus/json/fail15.json
new file mode 100644
index 0000000000..fc8376b605
--- /dev/null
+++ b/sapi/fuzzer/corpus/json/fail15.json
@@ -0,0 +1 @@
+["Illegal backslash escape: \x15"] \ No newline at end of file
diff --git a/sapi/fuzzer/corpus/json/fail16.json b/sapi/fuzzer/corpus/json/fail16.json
new file mode 100644
index 0000000000..3fe21d4b53
--- /dev/null
+++ b/sapi/fuzzer/corpus/json/fail16.json
@@ -0,0 +1 @@
+[\naked] \ No newline at end of file
diff --git a/sapi/fuzzer/corpus/json/fail17.json b/sapi/fuzzer/corpus/json/fail17.json
new file mode 100644
index 0000000000..62b9214aed
--- /dev/null
+++ b/sapi/fuzzer/corpus/json/fail17.json
@@ -0,0 +1 @@
+["Illegal backslash escape: \017"] \ No newline at end of file
diff --git a/sapi/fuzzer/corpus/json/fail18.json b/sapi/fuzzer/corpus/json/fail18.json
new file mode 100644
index 0000000000..edac92716f
--- /dev/null
+++ b/sapi/fuzzer/corpus/json/fail18.json
@@ -0,0 +1 @@
+[[[[[[[[[[[[[[[[[[[["Too deep"]]]]]]]]]]]]]]]]]]]] \ No newline at end of file
diff --git a/sapi/fuzzer/corpus/json/fail19.json b/sapi/fuzzer/corpus/json/fail19.json
new file mode 100644
index 0000000000..3b9c46fa9a
--- /dev/null
+++ b/sapi/fuzzer/corpus/json/fail19.json
@@ -0,0 +1 @@
+{"Missing colon" null} \ No newline at end of file
diff --git a/sapi/fuzzer/corpus/json/fail2.json b/sapi/fuzzer/corpus/json/fail2.json
new file mode 100644
index 0000000000..6b7c11e5a5
--- /dev/null
+++ b/sapi/fuzzer/corpus/json/fail2.json
@@ -0,0 +1 @@
+["Unclosed array" \ No newline at end of file
diff --git a/sapi/fuzzer/corpus/json/fail20.json b/sapi/fuzzer/corpus/json/fail20.json
new file mode 100644
index 0000000000..27c1af3e72
--- /dev/null
+++ b/sapi/fuzzer/corpus/json/fail20.json
@@ -0,0 +1 @@
+{"Double colon":: null} \ No newline at end of file
diff --git a/sapi/fuzzer/corpus/json/fail21.json b/sapi/fuzzer/corpus/json/fail21.json
new file mode 100644
index 0000000000..62474573b2
--- /dev/null
+++ b/sapi/fuzzer/corpus/json/fail21.json
@@ -0,0 +1 @@
+{"Comma instead of colon", null} \ No newline at end of file
diff --git a/sapi/fuzzer/corpus/json/fail22.json b/sapi/fuzzer/corpus/json/fail22.json
new file mode 100644
index 0000000000..a7752581bc
--- /dev/null
+++ b/sapi/fuzzer/corpus/json/fail22.json
@@ -0,0 +1 @@
+["Colon instead of comma": false] \ No newline at end of file
diff --git a/sapi/fuzzer/corpus/json/fail23.json b/sapi/fuzzer/corpus/json/fail23.json
new file mode 100644
index 0000000000..494add1ca1
--- /dev/null
+++ b/sapi/fuzzer/corpus/json/fail23.json
@@ -0,0 +1 @@
+["Bad value", truth] \ No newline at end of file
diff --git a/sapi/fuzzer/corpus/json/fail24.json b/sapi/fuzzer/corpus/json/fail24.json
new file mode 100644
index 0000000000..caff239bfc
--- /dev/null
+++ b/sapi/fuzzer/corpus/json/fail24.json
@@ -0,0 +1 @@
+['single quote'] \ No newline at end of file
diff --git a/sapi/fuzzer/corpus/json/fail25.json b/sapi/fuzzer/corpus/json/fail25.json
new file mode 100644
index 0000000000..8b7ad23e01
--- /dev/null
+++ b/sapi/fuzzer/corpus/json/fail25.json
@@ -0,0 +1 @@
+[" tab character in string "] \ No newline at end of file
diff --git a/sapi/fuzzer/corpus/json/fail26.json b/sapi/fuzzer/corpus/json/fail26.json
new file mode 100644
index 0000000000..845d26a6a5
--- /dev/null
+++ b/sapi/fuzzer/corpus/json/fail26.json
@@ -0,0 +1 @@
+["tab\ character\ in\ string\ "] \ No newline at end of file
diff --git a/sapi/fuzzer/corpus/json/fail27.json b/sapi/fuzzer/corpus/json/fail27.json
new file mode 100644
index 0000000000..6b01a2ca4a
--- /dev/null
+++ b/sapi/fuzzer/corpus/json/fail27.json
@@ -0,0 +1,2 @@
+["line
+break"] \ No newline at end of file
diff --git a/sapi/fuzzer/corpus/json/fail28.json b/sapi/fuzzer/corpus/json/fail28.json
new file mode 100644
index 0000000000..621a0101c6
--- /dev/null
+++ b/sapi/fuzzer/corpus/json/fail28.json
@@ -0,0 +1,2 @@
+["line\
+break"] \ No newline at end of file
diff --git a/sapi/fuzzer/corpus/json/fail29.json b/sapi/fuzzer/corpus/json/fail29.json
new file mode 100644
index 0000000000..47ec421bb6
--- /dev/null
+++ b/sapi/fuzzer/corpus/json/fail29.json
@@ -0,0 +1 @@
+[0e] \ No newline at end of file
diff --git a/sapi/fuzzer/corpus/json/fail3.json b/sapi/fuzzer/corpus/json/fail3.json
new file mode 100644
index 0000000000..168c81eb78
--- /dev/null
+++ b/sapi/fuzzer/corpus/json/fail3.json
@@ -0,0 +1 @@
+{unquoted_key: "keys must be quoted"} \ No newline at end of file
diff --git a/sapi/fuzzer/corpus/json/fail30.json b/sapi/fuzzer/corpus/json/fail30.json
new file mode 100644
index 0000000000..8ab0bc4b8b
--- /dev/null
+++ b/sapi/fuzzer/corpus/json/fail30.json
@@ -0,0 +1 @@
+[0e+] \ No newline at end of file
diff --git a/sapi/fuzzer/corpus/json/fail31.json b/sapi/fuzzer/corpus/json/fail31.json
new file mode 100644
index 0000000000..1cce602b51
--- /dev/null
+++ b/sapi/fuzzer/corpus/json/fail31.json
@@ -0,0 +1 @@
+[0e+-1] \ No newline at end of file
diff --git a/sapi/fuzzer/corpus/json/fail32.json b/sapi/fuzzer/corpus/json/fail32.json
new file mode 100644
index 0000000000..45cba7396f
--- /dev/null
+++ b/sapi/fuzzer/corpus/json/fail32.json
@@ -0,0 +1 @@
+{"Comma instead if closing brace": true, \ No newline at end of file
diff --git a/sapi/fuzzer/corpus/json/fail33.json b/sapi/fuzzer/corpus/json/fail33.json
new file mode 100644
index 0000000000..ca5eb19dc9
--- /dev/null
+++ b/sapi/fuzzer/corpus/json/fail33.json
@@ -0,0 +1 @@
+["mismatch"} \ No newline at end of file
diff --git a/sapi/fuzzer/corpus/json/fail4.json b/sapi/fuzzer/corpus/json/fail4.json
new file mode 100644
index 0000000000..9de168bf34
--- /dev/null
+++ b/sapi/fuzzer/corpus/json/fail4.json
@@ -0,0 +1 @@
+["extra comma",] \ No newline at end of file
diff --git a/sapi/fuzzer/corpus/json/fail5.json b/sapi/fuzzer/corpus/json/fail5.json
new file mode 100644
index 0000000000..ddf3ce3d24
--- /dev/null
+++ b/sapi/fuzzer/corpus/json/fail5.json
@@ -0,0 +1 @@
+["double extra comma",,] \ No newline at end of file
diff --git a/sapi/fuzzer/corpus/json/fail6.json b/sapi/fuzzer/corpus/json/fail6.json
new file mode 100644
index 0000000000..ed91580e1b
--- /dev/null
+++ b/sapi/fuzzer/corpus/json/fail6.json
@@ -0,0 +1 @@
+[ , "<-- missing value"] \ No newline at end of file
diff --git a/sapi/fuzzer/corpus/json/fail7.json b/sapi/fuzzer/corpus/json/fail7.json
new file mode 100644
index 0000000000..8a96af3e4e
--- /dev/null
+++ b/sapi/fuzzer/corpus/json/fail7.json
@@ -0,0 +1 @@
+["Comma after the close"], \ No newline at end of file
diff --git a/sapi/fuzzer/corpus/json/fail8.json b/sapi/fuzzer/corpus/json/fail8.json
new file mode 100644
index 0000000000..b28479c6ec
--- /dev/null
+++ b/sapi/fuzzer/corpus/json/fail8.json
@@ -0,0 +1 @@
+["Extra close"]] \ No newline at end of file
diff --git a/sapi/fuzzer/corpus/json/fail9.json b/sapi/fuzzer/corpus/json/fail9.json
new file mode 100644
index 0000000000..5815574f36
--- /dev/null
+++ b/sapi/fuzzer/corpus/json/fail9.json
@@ -0,0 +1 @@
+{"Extra comma": true,} \ No newline at end of file
diff --git a/sapi/fuzzer/corpus/json/pass1.json b/sapi/fuzzer/corpus/json/pass1.json
new file mode 100644
index 0000000000..70e2685436
--- /dev/null
+++ b/sapi/fuzzer/corpus/json/pass1.json
@@ -0,0 +1,58 @@
+[
+ "JSON Test Pattern pass1",
+ {"object with 1 member":["array with 1 element"]},
+ {},
+ [],
+ -42,
+ true,
+ false,
+ null,
+ {
+ "integer": 1234567890,
+ "real": -9876.543210,
+ "e": 0.123456789e-12,
+ "E": 1.234567890E+34,
+ "": 23456789012E66,
+ "zero": 0,
+ "one": 1,
+ "space": " ",
+ "quote": "\"",
+ "backslash": "\\",
+ "controls": "\b\f\n\r\t",
+ "slash": "/ & \/",
+ "alpha": "abcdefghijklmnopqrstuvwyz",
+ "ALPHA": "ABCDEFGHIJKLMNOPQRSTUVWYZ",
+ "digit": "0123456789",
+ "0123456789": "digit",
+ "special": "`1~!@#$%^&*()_+-={':[,]}|;.</>?",
+ "hex": "\u0123\u4567\u89AB\uCDEF\uabcd\uef4A",
+ "true": true,
+ "false": false,
+ "null": null,
+ "array":[ ],
+ "object":{ },
+ "address": "50 St. James Street",
+ "url": "http://www.JSON.org/",
+ "comment": "// /* <!-- --",
+ "# -- --> */": " ",
+ " s p a c e d " :[1,2 , 3
+
+,
+
+4 , 5 , 6 ,7 ],"compact":[1,2,3,4,5,6,7],
+ "jsontext": "{\"object with 1 member\":[\"array with 1 element\"]}",
+ "quotes": "&#34; \u0022 %22 0x22 034 &#x22;",
+ "\/\\\"\uCAFE\uBABE\uAB98\uFCDE\ubcda\uef4A\b\f\n\r\t`1~!@#$%^&*()_+-=[]{}|;:',./<>?"
+: "A key can be any string"
+ },
+ 0.5 ,98.6
+,
+99.44
+,
+
+1066,
+1e1,
+0.1e1,
+1e-1,
+1e00,2e+00,2e-00
+,"rosebud"] \ No newline at end of file
diff --git a/sapi/fuzzer/corpus/json/pass2.json b/sapi/fuzzer/corpus/json/pass2.json
new file mode 100644
index 0000000000..d3c63c7ad8
--- /dev/null
+++ b/sapi/fuzzer/corpus/json/pass2.json
@@ -0,0 +1 @@
+[[[[[[[[[[[[[[[[[[["Not too deep"]]]]]]]]]]]]]]]]]]] \ No newline at end of file
diff --git a/sapi/fuzzer/corpus/json/pass3.json b/sapi/fuzzer/corpus/json/pass3.json
new file mode 100644
index 0000000000..4528d51f1a
--- /dev/null
+++ b/sapi/fuzzer/corpus/json/pass3.json
@@ -0,0 +1,6 @@
+{
+ "JSON Test Pattern pass3": {
+ "The outermost value": "must be an object or array.",
+ "In this test": "It is an object."
+ }
+}
diff --git a/sapi/fuzzer/corpus/unserialize/__serialize_007 b/sapi/fuzzer/corpus/unserialize/__serialize_007
new file mode 100644
index 0000000000..6709aca303
--- /dev/null
+++ b/sapi/fuzzer/corpus/unserialize/__serialize_007
@@ -0,0 +1 @@
+O:13:"ArrayIterator":2:{i:0;i:0;s:1:"x";R:2;}
diff --git a/sapi/fuzzer/corpus/unserialize/bug7131 b/sapi/fuzzer/corpus/unserialize/bug7131
new file mode 100644
index 0000000000..1ba49d8da1
--- /dev/null
+++ b/sapi/fuzzer/corpus/unserialize/bug7131
@@ -0,0 +1 @@
+C:11:"ArrayObject":11:{x:i:0;r:3;X} \ No newline at end of file
diff --git a/sapi/fuzzer/corpus/unserialize/bug71313 b/sapi/fuzzer/corpus/unserialize/bug71313
new file mode 100644
index 0000000000..4163b0350a
--- /dev/null
+++ b/sapi/fuzzer/corpus/unserialize/bug71313
@@ -0,0 +1 @@
+C:16:"SplObjectStorage":113:{x:i:2;O:8:"stdClass":0:{},a:2:{s:4:"prev";i:2;s:4:"next";O:8:"stdClass":0:{}};r:7;,R:2;s:4:"next";;r:3;};m:a:0:{}} \ No newline at end of file
diff --git a/sapi/fuzzer/corpus/unserialize/bug73144_1 b/sapi/fuzzer/corpus/unserialize/bug73144_1
new file mode 100644
index 0000000000..0d6d600520
--- /dev/null
+++ b/sapi/fuzzer/corpus/unserialize/bug73144_1
@@ -0,0 +1 @@
+a:2:{i:0;O:1:"0":2:0s:1:"0";i:0;s:1:"0";a:1:{i:0;C:11:"ArrayObject":7:{x:i:0;r}
diff --git a/sapi/fuzzer/corpus/unserialize/bug73144_2 b/sapi/fuzzer/corpus/unserialize/bug73144_2
new file mode 100644
index 0000000000..d1145066c5
--- /dev/null
+++ b/sapi/fuzzer/corpus/unserialize/bug73144_2
@@ -0,0 +1 @@
+C:11:"ArrayObject":34:{x:i:1;O:8:"stdClass":1:{};m:a:0:{}} \ No newline at end of file
diff --git a/sapi/fuzzer/corpus/unserialize/bug73825 b/sapi/fuzzer/corpus/unserialize/bug73825
new file mode 100644
index 0000000000..dc9b0e4334
--- /dev/null
+++ b/sapi/fuzzer/corpus/unserialize/bug73825
@@ -0,0 +1 @@
+O:8:"00000000":
diff --git a/sapi/fuzzer/corpus/unserialize/bug74101 b/sapi/fuzzer/corpus/unserialize/bug74101
new file mode 100644
index 0000000000..b8d2fd2308
--- /dev/null
+++ b/sapi/fuzzer/corpus/unserialize/bug74101
@@ -0,0 +1 @@
+O:9:"Exception":799999999999999999999999999997:0i:0;a:0:{}i:2;i:0;i:0;R:2;
diff --git a/sapi/fuzzer/corpus/unserialize/bug74103 b/sapi/fuzzer/corpus/unserialize/bug74103
new file mode 100644
index 0000000000..ab2f70239c
--- /dev/null
+++ b/sapi/fuzzer/corpus/unserialize/bug74103
@@ -0,0 +1 @@
+a:7:{i:0;i:04;s:1:"a";i:2;i:9617006;i:4;s:1:"a";i:4;s:1:"a";R:5;s:1:"7";R:3;s:1:"a";R:5;;s:18;}}
diff --git a/sapi/fuzzer/corpus/unserialize/bug74111 b/sapi/fuzzer/corpus/unserialize/bug74111
new file mode 100644
index 0000000000..c1196ee7de
--- /dev/null
+++ b/sapi/fuzzer/corpus/unserialize/bug74111
@@ -0,0 +1 @@
+O:8:"stdClass":00000000
diff --git a/sapi/fuzzer/corpus/unserialize/bug74614 b/sapi/fuzzer/corpus/unserialize/bug74614
new file mode 100644
index 0000000000..c7174893fe
--- /dev/null
+++ b/sapi/fuzzer/corpus/unserialize/bug74614
@@ -0,0 +1 @@
+a:3020000000000000000000000000000001:{i:0;a:0:{}i:1;i:2;i:2;i:3;i:3;i:4;i:4;i:5;i:5;i:6;i:6;i:7;i:7;i:8;i:8;R:2;}
diff --git a/sapi/fuzzer/corpus/unserialize/bug75054 b/sapi/fuzzer/corpus/unserialize/bug75054
new file mode 100644
index 0000000000..866e5b8fca
--- /dev/null
+++ b/sapi/fuzzer/corpus/unserialize/bug75054
@@ -0,0 +1 @@
+a:9:{i:0;s:4:"0000";i:0;s:4:"0000";i:0;R:2;s:4:"5003";R:2;s:4:"0000";R:2;s:4:"0000";R:2;s:4:"000";R:2;s:4:"0000";d:0;s:4:"0000";a:9:{s:4:"0000"; \ No newline at end of file
diff --git a/sapi/fuzzer/corpus/unserialize/int_min_iv b/sapi/fuzzer/corpus/unserialize/int_min_iv
new file mode 100644
index 0000000000..6900dce088
--- /dev/null
+++ b/sapi/fuzzer/corpus/unserialize/int_min_iv
@@ -0,0 +1 @@
+i:-9223372036854775808;
diff --git a/sapi/fuzzer/corpus/unserialize/leak_17628 b/sapi/fuzzer/corpus/unserialize/leak_17628
new file mode 100644
index 0000000000..45fd8644db
--- /dev/null
+++ b/sapi/fuzzer/corpus/unserialize/leak_17628
@@ -0,0 +1 @@
+a:2:{i:0;O:19:"SplDoublyLinkedList":8:i:0;i:04;i:965556;a:6:{i:0;R:04;S:1:"a";i:2;i:961;a:8:{i:0;i:04;i:0;i:0026;i:0;a:2:{i:0;O:13:"RegexIterator":1: i:6176;a:8:{i:0;i:04;S:1:"a";i:2;i:96140012;s:1:"a";i:0;i:91755555500000016742;i:8;a:8:{i:0;i:048;i:2;d:0000800000001000000000000014000000000000000000000040400000004000000516742;i:9;a:8:{i:0;i:048;i:2;d:0000800000001000000000000000000000000000002;i:04;a:9:{i:5;R:11;s:4:"m000";O:9:"Eepictxon":85:{i:5;R:2;s:4:"m000";O:9:"Eepictxon":8:0i:-012;s:1:"a";i:0;i:96170026;i:0;i:04;S:1:"a";i:2;i:9617006;a:7:{i:6;a:7:{i:0;a:9:{i:5;R:1;s:4:"m000";O:9:"Eepictxon":86:{i:5;R:2;s:4:"m000";O:9:"Eepictxon":8:0i:-01400;a:8:{i:0;i:04;i:0;i:0026;i:0;a:2:{i:0;a:2:{i:0;O:19:"SplDoublyLinkedList":8:i:0;86:{i:5;R:2;on":8:0i:-0140012;s:1:"a";i:0;i:96170026;i:0;i:04;S:1:"a";i:2;i:9617006;a:7:{i:07006;a:7:{i:0;a:9:{i:5;R:1;s:4:"m000";O \ No newline at end of file
diff --git a/sapi/fuzzer/corpus/unserialize/leak_17639 b/sapi/fuzzer/corpus/unserialize/leak_17639
new file mode 100644
index 0000000000..fb8625a700
--- /dev/null
+++ b/sapi/fuzzer/corpus/unserialize/leak_17639
@@ -0,0 +1 @@
+a:7:{i:6;i:0;S:1:" ";i:1;i:6;a:8:{i:0;i:4;S:1:" ";i:2;i:9;R:4;S:1:" ";a:2:{i:5;O:13:"RegexIterator":1 i:7;a:8:{i:0;a:7:{i:0;R:10; \ No newline at end of file
diff --git a/sapi/fuzzer/corpus/unserialize/leak_17646 b/sapi/fuzzer/corpus/unserialize/leak_17646
new file mode 100644
index 0000000000..ac7969e683
--- /dev/null
+++ b/sapi/fuzzer/corpus/unserialize/leak_17646
@@ -0,0 +1 @@
+O:13:"RegexIter\tor":3:{S:1:"x";a:9:{i:04;R:1;i:5312;O:13:"RegexIterator":53;i:08032617006;a:7:{i:0;R:04;S:1:"a";i:2;i:5312;O:13:"RegexIterator":53;i:080326170;O:1:"0":2:1s:1:"1";i:0;i:0;O:13:"Literator":2:{i:0;a:6:{i:0;O:1:"0":2:1s:1:"1";i:0;i:1;r:9;}s:1:"1";i:0;i:11111101111110;O:1:"0":4:1s:1:"0";a:6:{i:0;a:2:{i:0;O:10:"ValueError":4:{i:0;O:10:"ValueError":2:{i:0;O:10:"ValueError":4:{i:Error":4:a:7:{s:2:"c{i:0;";a:7:{S:O: \ No newline at end of file
diff --git a/sapi/fuzzer/corpus/unserialize/oss_fuzz_27628 b/sapi/fuzzer/corpus/unserialize/oss_fuzz_27628
new file mode 100644
index 0000000000..e22d1c8888
--- /dev/null
+++ b/sapi/fuzzer/corpus/unserialize/oss_fuzz_27628
@@ -0,0 +1 @@
+O:1:"":4 S:8:" ";O:5:"ErRor":4 S:8:"previous";O:1:"":1 s:1:" ";R:3;} \ No newline at end of file
diff --git a/sapi/fuzzer/corpus/unserialize/oss_fuzz_27876 b/sapi/fuzzer/corpus/unserialize/oss_fuzz_27876
new file mode 100644
index 0000000000..98c5a5b19c
--- /dev/null
+++ b/sapi/fuzzer/corpus/unserialize/oss_fuzz_27876
@@ -0,0 +1 @@
+a:2:{i:7;O:5:"ErRor":5 S:8:"previous";a:5:{i:7;R:3; \ No newline at end of file
diff --git a/sapi/fuzzer/corpus/unserialize/oss_fuzz_27978 b/sapi/fuzzer/corpus/unserialize/oss_fuzz_27978
new file mode 100644
index 0000000000..22b45ddf87
--- /dev/null
+++ b/sapi/fuzzer/corpus/unserialize/oss_fuzz_27978
@@ -0,0 +1 @@
+O:1:"":4 S:8:" ";O:5:"ErRor":3 S:8:"previous";R:2;S:8:"previous"; \ No newline at end of file
diff --git a/sapi/fuzzer/corpus/unserialize/splobjectstorage_negative_count b/sapi/fuzzer/corpus/unserialize/splobjectstorage_negative_count
new file mode 100644
index 0000000000..29a3ac47af
--- /dev/null
+++ b/sapi/fuzzer/corpus/unserialize/splobjectstorage_negative_count
@@ -0,0 +1 @@
+C:16:"SplObjectStorage":25:{x:i:-9223372036854775808;}
diff --git a/sapi/fuzzer/dict/parser b/sapi/fuzzer/dict/parser
new file mode 100644
index 0000000000..8b382afac9
--- /dev/null
+++ b/sapi/fuzzer/dict/parser
@@ -0,0 +1,85 @@
+"exit"
+"die"
+"fn"
+"function"
+"const"
+"return"
+"yield"
+"yield from"
+"try"
+"catch"
+"finally"
+"throw"
+"if"
+"elseif"
+"endif"
+"else"
+"while"
+"endwhile"
+"do"
+"for"
+"endfor"
+"foreach"
+"endforeach"
+"declare"
+"enddeclare"
+"instanceof"
+"as"
+"switch"
+"endswitch"
+"case"
+"default"
+"break"
+"continue"
+"goto"
+"echo"
+"print"
+"class"
+"interface"
+"trait"
+"extends"
+"implements"
+"new"
+"clone"
+"var"
+"int"
+"integer"
+"float"
+"double"
+"real"
+"string"
+"binary"
+"array"
+"object"
+"bool"
+"boolean"
+"unset"
+"eval"
+"include"
+"include_once"
+"require"
+"require_once"
+"namespace"
+"use"
+"insteadof"
+"global"
+"isset"
+"empty"
+"__halt_compiler"
+"static"
+"abstract"
+"final"
+"private"
+"protected"
+"public"
+"unset"
+"list"
+"callable"
+"__class__"
+"__trait__"
+"__function__"
+"__method__"
+"__line__"
+"__file__"
+"__dir__"
+"__namespace__"
diff --git a/sapi/fuzzer/fuzzer-execute.c b/sapi/fuzzer/fuzzer-execute.c
new file mode 100644
index 0000000000..1259acb31e
--- /dev/null
+++ b/sapi/fuzzer/fuzzer-execute.c
@@ -0,0 +1,90 @@
+/*
+ +----------------------------------------------------------------------+
+ | Copyright (c) The PHP Group |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 3.01 of the PHP license, |
+ | that is bundled with this package in the file LICENSE, and is |
+ | available through the world-wide-web at the following url: |
+ | http://www.php.net/license/3_01.txt |
+ | If you did not receive a copy of the PHP license and are unable to |
+ | obtain it through the world-wide-web, please send a note to |
+ | license@php.net so we can mail you a copy immediately. |
+ +----------------------------------------------------------------------+
+ | Authors: Nikita Popov <nikic@php.net> |
+ +----------------------------------------------------------------------+
+ */
+
+#include <main/php.h>
+
+#include "fuzzer.h"
+#include "fuzzer-sapi.h"
+
+#define MAX_STEPS 1000
+#define MAX_SIZE (8 * 1024)
+static uint32_t steps_left;
+
+/* Because the fuzzer is always compiled with clang,
+ * we can assume that we don't use global registers / hybrid VM. */
+typedef int (ZEND_FASTCALL *opcode_handler_t)(zend_execute_data *);
+
+static void fuzzer_execute_ex(zend_execute_data *execute_data) {
+ while (1) {
+ int ret;
+ if (--steps_left == 0) {
+ /* Reset steps before bailing out, so code running after bailout (e.g. in
+ * destructors) will get another MAX_STEPS, rather than UINT32_MAX steps. */
+ steps_left = MAX_STEPS;
+ zend_bailout();
+ }
+
+ if ((ret = ((opcode_handler_t) EX(opline)->handler)(execute_data)) != 0) {
+ if (ret > 0) {
+ execute_data = EG(current_execute_data);
+ } else {
+ return;
+ }
+ }
+ }
+}
+
+static zend_op_array *(*orig_compile_string)(zend_string *source_string, const char *filename);
+
+static zend_op_array *fuzzer_compile_string(zend_string *str, const char *filename) {
+ if (ZSTR_LEN(str) > MAX_SIZE) {
+ /* Avoid compiling huge inputs via eval(). */
+ zend_bailout();
+ }
+
+ return orig_compile_string(str, filename);
+}
+
+int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
+ if (Size > MAX_SIZE) {
+ /* Large inputs have a large impact on fuzzer performance,
+ * but are unlikely to be necessary to reach new codepaths. */
+ return 0;
+ }
+
+ steps_left = MAX_STEPS;
+ fuzzer_do_request_from_buffer("/fuzzer.php", (const char *) Data, Size, /* execute */ 1);
+
+ return 0;
+}
+
+int LLVMFuzzerInitialize(int *argc, char ***argv) {
+ /* Compilation will often trigger fatal errors.
+ * Use tracked allocation mode to avoid leaks in that case. */
+ putenv("USE_TRACKED_ALLOC=1");
+
+ /* Just like other SAPIs, ignore SIGPIPEs. */
+ signal(SIGPIPE, SIG_IGN);
+
+ fuzzer_init_php();
+
+ zend_execute_ex = fuzzer_execute_ex;
+ orig_compile_string = zend_compile_string;
+ zend_compile_string = fuzzer_compile_string;
+
+ /* fuzzer_shutdown_php(); */
+ return 0;
+}
diff --git a/sapi/fuzzer/fuzzer-exif.c b/sapi/fuzzer/fuzzer-exif.c
new file mode 100644
index 0000000000..71f1c88b78
--- /dev/null
+++ b/sapi/fuzzer/fuzzer-exif.c
@@ -0,0 +1,72 @@
+/*
+ +----------------------------------------------------------------------+
+ | Copyright (c) The PHP Group |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 3.01 of the PHP license, |
+ | that is bundled with this package in the file LICENSE, and is |
+ | available through the world-wide-web at the following url: |
+ | http://www.php.net/license/3_01.txt |
+ | If you did not receive a copy of the PHP license and are unable to |
+ | obtain it through the world-wide-web, please send a note to |
+ | license@php.net so we can mail you a copy immediately. |
+ +----------------------------------------------------------------------+
+ | Authors: Stanislav Malyshev <stas@php.net> |
+ +----------------------------------------------------------------------+
+ */
+
+#include "fuzzer.h"
+
+#include "Zend/zend.h"
+#include "main/php_config.h"
+#include "main/php_main.h"
+#include "ext/standard/php_var.h"
+
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+#include "fuzzer-sapi.h"
+
+int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
+#if HAVE_EXIF
+ php_stream *stream;
+ zval stream_zv;
+
+ if (Size > 256 * 1024) {
+ /* Large inputs have a large impact on fuzzer performance,
+ * but are unlikely to be necessary to reach new codepaths. */
+ return 0;
+ }
+
+ if (fuzzer_request_startup() == FAILURE) {
+ return 0;
+ }
+
+ stream = php_stream_memory_create(TEMP_STREAM_DEFAULT);
+ php_stream_write(stream, (const char *) Data, Size);
+ php_stream_to_zval(stream, &stream_zv);
+
+ fuzzer_call_php_func_zval("exif_read_data", 1, &stream_zv);
+
+ zval_ptr_dtor(&stream_zv);
+
+ /* cleanup */
+ php_request_shutdown(NULL);
+
+ return 0;
+#else
+ fprintf(stderr, "\n\nERROR:\nPHP built without EXIF, recompile with --enable-exif to use this fuzzer\n");
+ exit(1);
+#endif
+}
+
+int LLVMFuzzerInitialize(int *argc, char ***argv) {
+ fuzzer_init_php();
+
+ /* fuzzer_shutdown_php(); */
+ return 0;
+}
+
diff --git a/sapi/fuzzer/fuzzer-json.c b/sapi/fuzzer/fuzzer-json.c
new file mode 100644
index 0000000000..85fa8bbc8e
--- /dev/null
+++ b/sapi/fuzzer/fuzzer-json.c
@@ -0,0 +1,62 @@
+/*
+ +----------------------------------------------------------------------+
+ | Copyright (c) The PHP Group |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 3.01 of the PHP license, |
+ | that is bundled with this package in the file LICENSE, and is |
+ | available through the world-wide-web at the following url: |
+ | http://www.php.net/license/3_01.txt |
+ | If you did not receive a copy of the PHP license and are unable to |
+ | obtain it through the world-wide-web, please send a note to |
+ | license@php.net so we can mail you a copy immediately. |
+ +----------------------------------------------------------------------+
+ | Authors: Johannes Schlüter <johanes@php.net> |
+ | Stanislav Malyshev <stas@php.net> |
+ +----------------------------------------------------------------------+
+ */
+
+
+
+#include "fuzzer.h"
+
+#include "Zend/zend.h"
+#include "main/php_config.h"
+#include "main/php_main.h"
+
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+
+#include "fuzzer-sapi.h"
+#include "ext/json/php_json_parser.h"
+
+int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
+ char *data = malloc(Size+1);
+ memcpy(data, Data, Size);
+ data[Size] = '\0';
+
+ if (fuzzer_request_startup() == FAILURE) {
+ return 0;
+ }
+
+ for (int option = 0; option <=1; ++option) {
+ zval result;
+ php_json_parser parser;
+ php_json_parser_init(&parser, &result, data, Size, option, 10);
+ if (php_json_yyparse(&parser) == SUCCESS) {
+ zval_ptr_dtor(&result);
+ }
+ }
+
+ php_request_shutdown(NULL);
+
+ free(data);
+ return 0;
+}
+
+int LLVMFuzzerInitialize(int *argc, char ***argv) {
+ fuzzer_init_php();
+
+ /* fuzzer_shutdown_php(); */
+ return 0;
+}
diff --git a/sapi/fuzzer/fuzzer-mbstring.c b/sapi/fuzzer/fuzzer-mbstring.c
new file mode 100644
index 0000000000..c8f084dbd4
--- /dev/null
+++ b/sapi/fuzzer/fuzzer-mbstring.c
@@ -0,0 +1,78 @@
+/*
+ +----------------------------------------------------------------------+
+ | Copyright (c) The PHP Group |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 3.01 of the PHP license, |
+ | that is bundled with this package in the file LICENSE, and is |
+ | available through the world-wide-web at the following url: |
+ | http://www.php.net/license/3_01.txt |
+ | If you did not receive a copy of the PHP license and are unable to |
+ | obtain it through the world-wide-web, please send a note to |
+ | license@php.net so we can mail you a copy immediately. |
+ +----------------------------------------------------------------------+
+ | Authors: Stanislav Malyshev <stas@php.net> |
+ +----------------------------------------------------------------------+
+ */
+
+
+#include "fuzzer.h"
+
+#include "Zend/zend.h"
+#include "main/php_config.h"
+#include "main/php_main.h"
+#include "oniguruma.h"
+
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+
+#include "fuzzer-sapi.h"
+
+int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
+#ifdef HAVE_MBREGEX
+ char *args[2];
+ char *data = malloc(Size+1);
+ memcpy(data, Data, Size);
+ data[Size] = '\0';
+
+ if (fuzzer_request_startup() == FAILURE) {
+ return 0;
+ }
+
+ fuzzer_setup_dummy_frame();
+
+ args[0] = data;
+ args[1] = "test123";
+ fuzzer_call_php_func("mb_ereg", 2, args);
+
+ args[0] = data;
+ args[1] = "test123";
+ fuzzer_call_php_func("mb_eregi", 2, args);
+
+ args[0] = data;
+ args[1] = data;
+ fuzzer_call_php_func("mb_ereg", 2, args);
+
+ args[0] = data;
+ args[1] = data;
+ fuzzer_call_php_func("mb_eregi", 2, args);
+
+ fuzzer_request_shutdown();
+
+ free(data);
+#else
+ fprintf(stderr, "\n\nERROR:\nPHP built without mbstring, recompile with --enable-mbstring to use this fuzzer\n");
+ exit(1);
+#endif
+ return 0;
+}
+
+int LLVMFuzzerInitialize(int *argc, char ***argv) {
+ fuzzer_init_php();
+
+ /* The default parse depth limit allows stack overflows under asan. */
+ onig_set_parse_depth_limit(512);
+
+ /* fuzzer_shutdown_php(); */
+ return 0;
+}
diff --git a/sapi/fuzzer/fuzzer-parser.c b/sapi/fuzzer/fuzzer-parser.c
new file mode 100644
index 0000000000..c81a6e1c24
--- /dev/null
+++ b/sapi/fuzzer/fuzzer-parser.c
@@ -0,0 +1,49 @@
+/*
+ +----------------------------------------------------------------------+
+ | Copyright (c) The PHP Group |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 3.01 of the PHP license, |
+ | that is bundled with this package in the file LICENSE, and is |
+ | available through the world-wide-web at the following url: |
+ | http://www.php.net/license/3_01.txt |
+ | If you did not receive a copy of the PHP license and are unable to |
+ | obtain it through the world-wide-web, please send a note to |
+ | license@php.net so we can mail you a copy immediately. |
+ +----------------------------------------------------------------------+
+ | Authors: Johannes Schlüter <johanes@php.net> |
+ | Stanislav Malyshev <stas@php.net> |
+ +----------------------------------------------------------------------+
+ */
+
+#include <main/php.h>
+#include <main/php_main.h>
+#include <main/SAPI.h>
+#include <ext/standard/info.h>
+#include <ext/standard/php_var.h>
+#include <main/php_variables.h>
+
+#include "fuzzer.h"
+#include "fuzzer-sapi.h"
+
+int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
+ if (Size > 32 * 1024) {
+ /* Large inputs have a large impact on fuzzer performance,
+ * but are unlikely to be necessary to reach new codepaths. */
+ return 0;
+ }
+
+ fuzzer_do_request_from_buffer("fuzzer.php", (const char *) Data, Size, /* execute */ 0);
+
+ return 0;
+}
+
+int LLVMFuzzerInitialize(int *argc, char ***argv) {
+ /* Compilation will often trigger fatal errors.
+ * Use tracked allocation mode to avoid leaks in that case. */
+ putenv("USE_TRACKED_ALLOC=1");
+
+ fuzzer_init_php();
+
+ /* fuzzer_shutdown_php(); */
+ return 0;
+}
diff --git a/sapi/fuzzer/fuzzer-sapi.c b/sapi/fuzzer/fuzzer-sapi.c
new file mode 100644
index 0000000000..fd429f503e
--- /dev/null
+++ b/sapi/fuzzer/fuzzer-sapi.c
@@ -0,0 +1,304 @@
+/*
+ +----------------------------------------------------------------------+
+ | Copyright (c) The PHP Group |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 3.01 of the PHP license, |
+ | that is bundled with this package in the file LICENSE, and is |
+ | available through the world-wide-web at the following url: |
+ | http://www.php.net/license/3_01.txt |
+ | If you did not receive a copy of the PHP license and are unable to |
+ | obtain it through the world-wide-web, please send a note to |
+ | license@php.net so we can mail you a copy immediately. |
+ +----------------------------------------------------------------------+
+ | Authors: Johannes Schlüter <johanes@php.net> |
+ | Stanislav Malyshev <stas@php.net> |
+ +----------------------------------------------------------------------+
+ */
+
+#include <main/php.h>
+#include <main/php_main.h>
+#include <main/SAPI.h>
+#include <ext/standard/info.h>
+#include <ext/standard/php_var.h>
+#include <main/php_variables.h>
+#include <zend_exceptions.h>
+
+#ifdef __SANITIZE_ADDRESS__
+# include "sanitizer/lsan_interface.h"
+#endif
+
+#include "fuzzer.h"
+#include "fuzzer-sapi.h"
+
+const char HARDCODED_INI[] =
+ "html_errors=0\n"
+ "implicit_flush=1\n"
+ "output_buffering=0\n"
+ "error_reporting=0\n"
+ /* Let the timeout be enforced by libfuzzer, not PHP. */
+ "max_execution_time=0\n"
+ /* Reduce oniguruma limits to speed up fuzzing */
+ "mbstring.regex_stack_limit=10000\n"
+ "mbstring.regex_retry_limit=10000\n"
+ /* For the "execute" fuzzer disable some functions that are likely to have
+ * undesirable consequences (shell execution, file system writes). */
+ "allow_url_include=0\n"
+ "allow_url_fopen=0\n"
+ "open_basedir=/tmp\n"
+ "disable_functions=dl,mail,mb_send_mail"
+ ",shell_exec,exec,system,proc_open,popen,passthru,pcntl_exec"
+ ",chgrp,chmod,chown,copy,file_put_contents,lchgrp,lchown,link,mkdir"
+ ",move_uploaded_file,rename,rmdir,symlink,tempname,touch,unlink,fopen"
+ /* Networking code likes to wait and wait. */
+ ",fsockopen,pfsockopen"
+ ",stream_socket_pair,stream_socket_client,stream_socket_server"
+ /* crypt() can be very slow. */
+ ",crypt"
+ /* openlog() has a known memory-management issue. */
+ ",openlog"
+ /* Can cause long loops that bypass the executor step limit. */
+ "\ndisable_classes=InfiniteIterator"
+;
+
+static int startup(sapi_module_struct *sapi_module)
+{
+ if (php_module_startup(sapi_module, NULL, 0)==FAILURE) {
+ return FAILURE;
+ }
+ return SUCCESS;
+}
+
+static size_t ub_write(const char *str, size_t str_length)
+{
+ /* quiet */
+ return str_length;
+}
+
+static void fuzzer_flush(void *server_context)
+{
+ /* quiet */
+}
+
+static void send_header(sapi_header_struct *sapi_header, void *server_context)
+{
+}
+
+static char* read_cookies()
+{
+ /* TODO: fuzz these! */
+ return NULL;
+}
+
+static void register_variables(zval *track_vars_array)
+{
+ php_import_environment_variables(track_vars_array);
+}
+
+static void log_message(const char *message, int level)
+{
+}
+
+
+static sapi_module_struct fuzzer_module = {
+ "fuzzer", /* name */
+ "clang fuzzer", /* pretty name */
+
+ startup, /* startup */
+ php_module_shutdown_wrapper, /* shutdown */
+
+ NULL, /* activate */
+ NULL, /* deactivate */
+
+ ub_write, /* unbuffered write */
+ fuzzer_flush, /* flush */
+ NULL, /* get uid */
+ NULL, /* getenv */
+
+ php_error, /* error handler */
+
+ NULL, /* header handler */
+ NULL, /* send headers handler */
+ send_header, /* send header handler */
+
+ NULL, /* read POST data */
+ read_cookies, /* read Cookies */
+
+ register_variables, /* register server variables */
+ log_message, /* Log message */
+ NULL, /* Get request time */
+ NULL, /* Child terminate */
+
+ STANDARD_SAPI_MODULE_PROPERTIES
+};
+
+int fuzzer_init_php()
+{
+#ifdef __SANITIZE_ADDRESS__
+ /* We're going to leak all the memory allocated during startup,
+ * so disable lsan temporarily. */
+ __lsan_disable();
+#endif
+
+ sapi_startup(&fuzzer_module);
+ fuzzer_module.phpinfo_as_text = 1;
+
+ fuzzer_module.ini_entries = malloc(sizeof(HARDCODED_INI));
+ memcpy(fuzzer_module.ini_entries, HARDCODED_INI, sizeof(HARDCODED_INI));
+
+ /*
+ * TODO: we might want to test both Zend and malloc MM, but testing with malloc
+ * is more likely to find bugs, so use that for now.
+ */
+ putenv("USE_ZEND_ALLOC=0");
+
+ if (fuzzer_module.startup(&fuzzer_module)==FAILURE) {
+ return FAILURE;
+ }
+
+#ifdef __SANITIZE_ADDRESS__
+ __lsan_enable();
+#endif
+
+ return SUCCESS;
+}
+
+int fuzzer_request_startup()
+{
+ if (php_request_startup() == FAILURE) {
+ php_module_shutdown();
+ return FAILURE;
+ }
+
+#ifdef ZEND_SIGNALS
+ /* Some signal handlers will be overridden,
+ * don't complain about them during shutdown. */
+ SIGG(check) = 0;
+#endif
+
+ return SUCCESS;
+}
+
+void fuzzer_request_shutdown()
+{
+ zend_try {
+ /* Destroy thrown exceptions. This does not happen as part of request shutdown. */
+ if (EG(exception)) {
+ zend_object_release(EG(exception));
+ EG(exception) = NULL;
+ }
+
+ /* Some fuzzers (like unserialize) may create circular structures. Make sure we free them.
+ * Two calls are performed to handle objects with destructors. */
+ zend_gc_collect_cycles();
+ zend_gc_collect_cycles();
+ } zend_end_try();
+
+ php_request_shutdown(NULL);
+}
+
+/* Set up a dummy stack frame so that exceptions may be thrown. */
+void fuzzer_setup_dummy_frame()
+{
+ static zend_execute_data execute_data;
+ static zend_function func;
+
+ memset(&execute_data, 0, sizeof(zend_execute_data));
+ memset(&func, 0, sizeof(zend_function));
+
+ func.type = ZEND_INTERNAL_FUNCTION;
+ func.common.function_name = ZSTR_EMPTY_ALLOC();
+ execute_data.func = &func;
+ EG(current_execute_data) = &execute_data;
+}
+
+void fuzzer_set_ini_file(const char *file)
+{
+ if (fuzzer_module.php_ini_path_override) {
+ free(fuzzer_module.php_ini_path_override);
+ }
+ fuzzer_module.php_ini_path_override = strdup(file);
+}
+
+
+int fuzzer_shutdown_php()
+{
+ php_module_shutdown();
+ sapi_shutdown();
+
+ free(fuzzer_module.ini_entries);
+ return SUCCESS;
+}
+
+int fuzzer_do_request_from_buffer(
+ char *filename, const char *data, size_t data_len, zend_bool execute)
+{
+ int retval = FAILURE; /* failure by default */
+
+ SG(options) |= SAPI_OPTION_NO_CHDIR;
+ SG(request_info).argc=0;
+ SG(request_info).argv=NULL;
+
+ if (fuzzer_request_startup() == FAILURE) {
+ return FAILURE;
+ }
+
+ // Commented out to avoid leaking the header callback.
+ //SG(headers_sent) = 1;
+ //SG(request_info).no_headers = 1;
+ php_register_variable("PHP_SELF", filename, NULL);
+
+ zend_first_try {
+ zend_file_handle file_handle;
+ zend_stream_init_filename(&file_handle, filename);
+ file_handle.buf = estrndup(data, data_len);
+ file_handle.len = data_len;
+
+ zend_op_array *op_array = zend_compile_file(&file_handle, ZEND_REQUIRE);
+ if (op_array) {
+ if (execute) {
+ zend_execute(op_array, NULL);
+ }
+ destroy_op_array(op_array);
+ efree(op_array);
+ }
+ } zend_end_try();
+
+ CG(compiled_filename) = NULL; /* ??? */
+ fuzzer_request_shutdown();
+
+ return (retval == SUCCESS) ? SUCCESS : FAILURE;
+}
+
+// Call named PHP function with N zval arguments
+void fuzzer_call_php_func_zval(const char *func_name, int nargs, zval *args) {
+ zval retval, func;
+
+ ZVAL_STRING(&func, func_name);
+ ZVAL_UNDEF(&retval);
+ call_user_function(CG(function_table), NULL, &func, &retval, nargs, args);
+
+ // TODO: check result?
+ /* to ensure retval is not broken */
+ php_var_dump(&retval, 0);
+
+ /* cleanup */
+ zval_ptr_dtor(&retval);
+ zval_ptr_dtor(&func);
+}
+
+// Call named PHP function with N string arguments
+void fuzzer_call_php_func(const char *func_name, int nargs, char **params) {
+ zval args[nargs];
+ int i;
+
+ for(i=0;i<nargs;i++) {
+ ZVAL_STRING(&args[i], params[i]);
+ }
+
+ fuzzer_call_php_func_zval(func_name, nargs, args);
+
+ for(i=0;i<nargs;i++) {
+ zval_ptr_dtor(&args[i]);
+ ZVAL_UNDEF(&args[i]);
+ }
+}
diff --git a/sapi/fuzzer/fuzzer-sapi.h b/sapi/fuzzer/fuzzer-sapi.h
new file mode 100644
index 0000000000..4eb050e357
--- /dev/null
+++ b/sapi/fuzzer/fuzzer-sapi.h
@@ -0,0 +1,25 @@
+/*
+ +----------------------------------------------------------------------+
+ | Copyright (c) The PHP Group |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 3.01 of the PHP license, |
+ | that is bundled with this package in the file LICENSE, and is |
+ | available through the world-wide-web at the following url: |
+ | http://www.php.net/license/3_01.txt |
+ | If you did not receive a copy of the PHP license and are unable to |
+ | obtain it through the world-wide-web, please send a note to |
+ | license@php.net so we can mail you a copy immediately. |
+ +----------------------------------------------------------------------+
+ | Authors: Johannes Schlüter <johanes@php.net> |
+ | Stanislav Malyshev <stas@php.net> |
+ +----------------------------------------------------------------------+
+ */
+
+int fuzzer_init_php(void);
+int fuzzer_request_startup(void);
+void fuzzer_request_shutdown(void);
+void fuzzer_setup_dummy_frame(void);
+void fuzzer_call_php_func(const char *func_name, int nargs, char **params);
+void fuzzer_call_php_func_zval(const char *func_name, int nargs, zval *args);
+int fuzzer_do_request_from_buffer(
+ char *filename, const char *data, size_t data_len, zend_bool execute);
diff --git a/sapi/fuzzer/fuzzer-unserialize.c b/sapi/fuzzer/fuzzer-unserialize.c
new file mode 100644
index 0000000000..ff68ee6e3e
--- /dev/null
+++ b/sapi/fuzzer/fuzzer-unserialize.c
@@ -0,0 +1,67 @@
+/*
+ +----------------------------------------------------------------------+
+ | Copyright (c) The PHP Group |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 3.01 of the PHP license, |
+ | that is bundled with this package in the file LICENSE, and is |
+ | available through the world-wide-web at the following url: |
+ | http://www.php.net/license/3_01.txt |
+ | If you did not receive a copy of the PHP license and are unable to |
+ | obtain it through the world-wide-web, please send a note to |
+ | license@php.net so we can mail you a copy immediately. |
+ +----------------------------------------------------------------------+
+ | Authors: Johannes Schlüter <johanes@php.net> |
+ +----------------------------------------------------------------------+
+ */
+
+
+#include "fuzzer.h"
+
+#include "Zend/zend.h"
+#include "main/php_config.h"
+#include "main/php_main.h"
+
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+
+#include "fuzzer-sapi.h"
+
+#include "ext/standard/php_var.h"
+
+int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
+ unsigned char *orig_data = malloc(Size+1);
+ memcpy(orig_data, Data, Size);
+ orig_data[Size] = '\0';
+
+ if (fuzzer_request_startup() == FAILURE) {
+ return 0;
+ }
+
+ fuzzer_setup_dummy_frame();
+
+ {
+ const unsigned char *data = orig_data;
+ zval result;
+ ZVAL_UNDEF(&result);
+
+ php_unserialize_data_t var_hash;
+ PHP_VAR_UNSERIALIZE_INIT(var_hash);
+ php_var_unserialize(&result, (const unsigned char **) &data, data + Size, &var_hash);
+ PHP_VAR_UNSERIALIZE_DESTROY(var_hash);
+
+ zval_ptr_dtor(&result);
+ }
+
+ free(orig_data);
+
+ fuzzer_request_shutdown();
+ return 0;
+}
+
+int LLVMFuzzerInitialize(int *argc, char ***argv) {
+ fuzzer_init_php();
+
+ /* fuzzer_shutdown_php(); */
+ return 0;
+}
diff --git a/sapi/fuzzer/fuzzer-unserializehash.c b/sapi/fuzzer/fuzzer-unserializehash.c
new file mode 100644
index 0000000000..c1231c4992
--- /dev/null
+++ b/sapi/fuzzer/fuzzer-unserializehash.c
@@ -0,0 +1,82 @@
+/*
+ +----------------------------------------------------------------------+
+ | Copyright (c) The PHP Group |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 3.01 of the PHP license, |
+ | that is bundled with this package in the file LICENSE, and is |
+ | available through the world-wide-web at the following url: |
+ | http://www.php.net/license/3_01.txt |
+ | If you did not receive a copy of the PHP license and are unable to |
+ | obtain it through the world-wide-web, please send a note to |
+ | license@php.net so we can mail you a copy immediately. |
+ +----------------------------------------------------------------------+
+ */
+
+
+#include "fuzzer.h"
+
+#include "Zend/zend.h"
+#include "main/php_config.h"
+#include "main/php_main.h"
+
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+
+#include "fuzzer-sapi.h"
+
+#include "ext/standard/php_var.h"
+
+int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t FullSize) {
+ const uint8_t *Start = memchr(Data, '|', FullSize);
+ if (!Start) {
+ return 0;
+ }
+ ++Start;
+
+ size_t Size = (Data + FullSize) - Start;
+ unsigned char *orig_data = malloc(Size+1);
+ memcpy(orig_data, Start, Size);
+ orig_data[Size] = '\0';
+
+ if (fuzzer_request_startup() == FAILURE) {
+ return 0;
+ }
+
+ fuzzer_setup_dummy_frame();
+
+ {
+ const unsigned char *data = orig_data;
+ zval result;
+ ZVAL_UNDEF(&result);
+
+ php_unserialize_data_t var_hash;
+ PHP_VAR_UNSERIALIZE_INIT(var_hash);
+ php_var_unserialize(&result, (const unsigned char **) &data, data + Size, &var_hash);
+ PHP_VAR_UNSERIALIZE_DESTROY(var_hash);
+
+ if (Z_TYPE(result) == IS_OBJECT
+ && zend_string_equals_literal(Z_OBJCE(result)->name, "HashContext")) {
+ zval args[2];
+ ZVAL_COPY_VALUE(&args[0], &result);
+ ZVAL_STRINGL(&args[1], (char *) Data, (Start - Data) - 1);
+ fuzzer_call_php_func_zval("hash_update", 2, args);
+ zval_ptr_dtor(&args[1]);
+ fuzzer_call_php_func_zval("hash_final", 1, args);
+ }
+
+ zval_ptr_dtor(&result);
+ }
+
+ free(orig_data);
+
+ fuzzer_request_shutdown();
+ return 0;
+}
+
+int LLVMFuzzerInitialize(int *argc, char ***argv) {
+ fuzzer_init_php();
+
+ /* fuzzer_shutdown_php(); */
+ return 0;
+}
diff --git a/sapi/fuzzer/fuzzer.h b/sapi/fuzzer/fuzzer.h
new file mode 100644
index 0000000000..644179f309
--- /dev/null
+++ b/sapi/fuzzer/fuzzer.h
@@ -0,0 +1,18 @@
+/*
+ +----------------------------------------------------------------------+
+ | Copyright (c) The PHP Group |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 3.01 of the PHP license, |
+ | that is bundled with this package in the file LICENSE, and is |
+ | available through the world-wide-web at the following url: |
+ | http://www.php.net/license/3_01.txt |
+ | If you did not receive a copy of the PHP license and are unable to |
+ | obtain it through the world-wide-web, please send a note to |
+ | license@php.net so we can mail you a copy immediately. |
+ +----------------------------------------------------------------------+
+ | Authors: Johannes Schlüter <johanes@php.net> |
+ +----------------------------------------------------------------------+
+ */
+
+#include "php_version.h"
+#define FUZZER_VERSION PHP_VERSION
diff --git a/sapi/fuzzer/generate_all.php b/sapi/fuzzer/generate_all.php
new file mode 100644
index 0000000000..589781b004
--- /dev/null
+++ b/sapi/fuzzer/generate_all.php
@@ -0,0 +1,5 @@
+<?php
+require __DIR__ . '/generate_unserialize_dict.php';
+require __DIR__ . '/generate_unserializehash_corpus.php';
+require __DIR__ . '/generate_parser_corpus.php';
+require __DIR__ . '/generate_execute_corpus.php';
diff --git a/sapi/fuzzer/generate_execute_corpus.php b/sapi/fuzzer/generate_execute_corpus.php
new file mode 100644
index 0000000000..dd6424127a
--- /dev/null
+++ b/sapi/fuzzer/generate_execute_corpus.php
@@ -0,0 +1,38 @@
+<?php
+
+if ($argc >= 2) {
+ $testsDir = $argv[1];
+} else {
+ $testsDir = __DIR__ . '/../../Zend/tests';
+}
+if ($argc >= 3) {
+ $corpusDir = $argv[2];
+} else {
+ $corpusDir = __DIR__ . '/corpus/execute';
+}
+if ($argc >= 4) {
+ $maxLen = (int) $argv[3];
+} else {
+ $maxLen = 8 * 1024;
+}
+
+$it = new RecursiveIteratorIterator(
+ new RecursiveDirectoryIterator($testsDir),
+ RecursiveIteratorIterator::LEAVES_ONLY
+);
+
+@mkdir($corpusDir);
+
+foreach ($it as $file) {
+ if (!preg_match('/\.phpt$/', $file)) continue;
+ $fullCode = file_get_contents($file);
+ if (!preg_match('/--FILE--\R(.*?)\R--([_A-Z]+)--/s', $fullCode, $matches)) continue;
+ $code = $matches[1];
+ if (strlen($code) > $maxLen) continue;
+
+ $outFile = str_replace($testsDir, '', $file);
+ $outFile = str_replace('/', '_', $outFile);
+ if (!preg_match('/SKIP_SLOW_TESTS|SKIP_PERF_SENSITIVE|USE_ZEND_ALLOC/', $fullCode)) {
+ file_put_contents($corpusDir . '/' . $outFile, $code);
+ }
+}
diff --git a/sapi/fuzzer/generate_parser_corpus.php b/sapi/fuzzer/generate_parser_corpus.php
new file mode 100644
index 0000000000..699c121901
--- /dev/null
+++ b/sapi/fuzzer/generate_parser_corpus.php
@@ -0,0 +1,24 @@
+<?php
+
+$testsDir = __DIR__ . '/../../Zend/tests/';
+$it = new RecursiveIteratorIterator(
+ new RecursiveDirectoryIterator($testsDir),
+ RecursiveIteratorIterator::LEAVES_ONLY
+);
+
+$corpusDir = __DIR__ . '/corpus/parser';
+@mkdir($corpusDir);
+
+$maxLen = 32 * 1024;
+foreach ($it as $file) {
+ if (!preg_match('/\.phpt$/', $file)) continue;
+ $code = file_get_contents($file);
+ if (!preg_match('/--FILE--\R(.*?)\R--([_A-Z]+)--/s', $code, $matches)) continue;
+ $code = $matches[1];
+ if (strlen($code) > $maxLen) continue;
+
+ $outFile = str_replace($testsDir, '', $file);
+ $outFile = str_replace('/', '_', $outFile);
+ $outFile = $corpusDir . '/' . $outFile;
+ file_put_contents($outFile, $code);
+}
diff --git a/sapi/fuzzer/generate_unserialize_dict.php b/sapi/fuzzer/generate_unserialize_dict.php
new file mode 100644
index 0000000000..cf270788d3
--- /dev/null
+++ b/sapi/fuzzer/generate_unserialize_dict.php
@@ -0,0 +1,9 @@
+<?php
+
+$dict = "";
+foreach (get_declared_classes() as $class) {
+ $len = strlen($class);
+ $dict .= "\"$len:\\\"$class\\\"\"\n";
+}
+
+file_put_contents(__DIR__ . "/dict/unserialize", $dict);
diff --git a/sapi/fuzzer/generate_unserializehash_corpus.php b/sapi/fuzzer/generate_unserializehash_corpus.php
new file mode 100644
index 0000000000..04c6ea1428
--- /dev/null
+++ b/sapi/fuzzer/generate_unserializehash_corpus.php
@@ -0,0 +1,10 @@
+<?php
+
+$corpusDir = __DIR__ . '/corpus/unserializehash';
+@mkdir($corpusDir);
+
+foreach (hash_algos() as $algo) {
+ $ctx = hash_init($algo);
+ $algx = preg_replace('/[^-_a-zA-Z0-9]/', '_', $algo);
+ file_put_contents($corpusDir . '/' . $algx, "x|" . serialize($ctx));
+}
diff --git a/sapi/fuzzer/json.dict b/sapi/fuzzer/json.dict
new file mode 100644
index 0000000000..e08245a219
--- /dev/null
+++ b/sapi/fuzzer/json.dict
@@ -0,0 +1,52 @@
+#
+# AFL dictionary for JSON
+# -----------------------
+#
+# Just the very basics.
+#
+# Inspired by a dictionary by Jakub Wilk <jwilk@jwilk.net>
+#
+
+"0"
+",0"
+":0"
+"0:"
+"-1.2e+3"
+
+"true"
+"false"
+"null"
+
+"\"\""
+",\"\""
+":\"\""
+"\"\":"
+
+"{}"
+",{}"
+":{}"
+"{\"\":0}"
+"{{}}"
+
+"[]"
+",[]"
+":[]"
+"[0]"
+"[[]]"
+
+"''"
+"\\"
+"\\b"
+"\\f"
+"\\n"
+"\\r"
+"\\t"
+"\\u0000"
+"\\x00"
+"\\0"
+"\\uD800\\uDC00"
+"\\uDBFF\\uDFFF"
+
+"\"\":0"
+"//"
+"/**/"