diff --git a/sapi/fuzzer/.gitignore b/sapi/fuzzer/.gitignore new file mode 100644 index 0000000000000..8e655e0fc9b1b --- /dev/null +++ b/sapi/fuzzer/.gitignore @@ -0,0 +1 @@ +php-fuzz-* diff --git a/sapi/fuzzer/Makefile.frag b/sapi/fuzzer/Makefile.frag index 9608e29d48910..d6cabedde7015 100644 --- a/sapi/fuzzer/Makefile.frag +++ b/sapi/fuzzer/Makefile.frag @@ -31,3 +31,6 @@ $(SAPI_FUZZER_PATH)/php-fuzz-mbstring: $(PHP_GLOBAL_OBJS) $(PHP_SAPI_OBJS) $(PHP $(SAPI_FUZZER_PATH)/php-fuzz-mbregex: $(PHP_GLOBAL_OBJS) $(PHP_SAPI_OBJS) $(PHP_FUZZER_MBREGEX_OBJS) $(FUZZER_BUILD) $(PHP_FUZZER_MBREGEX_OBJS) -o $@ + +$(SAPI_FUZZER_PATH)/php-fuzz-bcmath: $(PHP_GLOBAL_OBJS) $(PHP_SAPI_OBJS) $(PHP_FUZZER_BCMATH_OBJS) + $(FUZZER_BUILD) $(PHP_FUZZER_BCMATH_OBJS) -o $@ diff --git a/sapi/fuzzer/README.md b/sapi/fuzzer/README.md index b4bb2bbe4573f..6a5fbe19ff13e 100644 --- a/sapi/fuzzer/README.md +++ b/sapi/fuzzer/README.md @@ -33,6 +33,7 @@ When running `make` it creates these binaries in `sapi/fuzzer/`: * `php-fuzz-execute`: Fuzzing the executor * `php-fuzz-function-jit`: Fuzzing the function JIT (requires --enable-opcache) * `php-fuzz-tracing-jit`: Fuzzing the tracing JIT (requires --enable-opcache) +* `php-fuzz-bcmath`: Fuzzing bcadd, bcsub, bcmul, bcdiv, bcmod and bcpow (requires --enable-bcmath) Some fuzzers have a seed corpus in `sapi/fuzzer/corpus`. You can use it as follows: diff --git a/sapi/fuzzer/config.m4 b/sapi/fuzzer/config.m4 index 21a44cd6d886e..5da5ea5e71a8a 100644 --- a/sapi/fuzzer/config.m4 +++ b/sapi/fuzzer/config.m4 @@ -63,6 +63,7 @@ if test "$PHP_FUZZER" != "no"; then PHP_FUZZER_TARGET([unserialize], [PHP_FUZZER_UNSERIALIZE_OBJS]) PHP_FUZZER_TARGET([unserializehash], [PHP_FUZZER_UNSERIALIZEHASH_OBJS]) PHP_FUZZER_TARGET([json], [PHP_FUZZER_JSON_OBJS]) + PHP_FUZZER_TARGET([bcmath], [PHP_FUZZER_BCMATH_OBJS]) if test -n "$enable_exif" && test "$enable_exif" != "no"; then PHP_FUZZER_TARGET([exif], [PHP_FUZZER_EXIF_OBJS]) diff --git a/sapi/fuzzer/corpus/bcmath/1 b/sapi/fuzzer/corpus/bcmath/1 new file mode 100644 index 0000000000000..87e56bbe3c16a --- /dev/null +++ b/sapi/fuzzer/corpus/bcmath/1 @@ -0,0 +1 @@ +15,7,0 diff --git a/sapi/fuzzer/corpus/bcmath/2 b/sapi/fuzzer/corpus/bcmath/2 new file mode 100644 index 0000000000000..d476337baa9cc --- /dev/null +++ b/sapi/fuzzer/corpus/bcmath/2 @@ -0,0 +1 @@ +14.14,-9,10 diff --git a/sapi/fuzzer/corpus/bcmath/3 b/sapi/fuzzer/corpus/bcmath/3 new file mode 100644 index 0000000000000..0b218cc599193 --- /dev/null +++ b/sapi/fuzzer/corpus/bcmath/3 @@ -0,0 +1 @@ +1.23456789,0.56,10 diff --git a/sapi/fuzzer/corpus/bcmath/4 b/sapi/fuzzer/corpus/bcmath/4 new file mode 100644 index 0000000000000..e44b29bd6715e --- /dev/null +++ b/sapi/fuzzer/corpus/bcmath/4 @@ -0,0 +1 @@ +0.00123456789,0.001,10 diff --git a/sapi/fuzzer/corpus/bcmath/5 b/sapi/fuzzer/corpus/bcmath/5 new file mode 100644 index 0000000000000..a1bb0eceb04e3 --- /dev/null +++ b/sapi/fuzzer/corpus/bcmath/5 @@ -0,0 +1 @@ +-12345.6789,100,2 diff --git a/sapi/fuzzer/corpus/bcmath/6 b/sapi/fuzzer/corpus/bcmath/6 new file mode 100644 index 0000000000000..ba59d52f5047b --- /dev/null +++ b/sapi/fuzzer/corpus/bcmath/6 @@ -0,0 +1 @@ +12345.6,0.00001,20 diff --git a/sapi/fuzzer/dict/bcmath b/sapi/fuzzer/dict/bcmath new file mode 100644 index 0000000000000..583f5220fed59 --- /dev/null +++ b/sapi/fuzzer/dict/bcmath @@ -0,0 +1,9 @@ +"," +"1234567890" +"-9876543" +"0.12345678" +"-0.002468" +"9999999999999999" +"0.00000000000000000000001" +"10" +"-29" diff --git a/sapi/fuzzer/fuzzer-bcmath.c b/sapi/fuzzer/fuzzer-bcmath.c new file mode 100644 index 0000000000000..fb658ab9220b5 --- /dev/null +++ b/sapi/fuzzer/fuzzer-bcmath.c @@ -0,0 +1,119 @@ +/* + +----------------------------------------------------------------------+ + | 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: | + | https://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: Saki Takamachi | + +----------------------------------------------------------------------+ + */ + + + +#include "fuzzer.h" + +#include "Zend/zend.h" +#include
+#include "main/php_main.h" + +#include +#include +#include + +#include "fuzzer-sapi.h" + +bool char_to_zend_long(const char *c, size_t scale_len, zend_long *ret) { + *ret = 0; + zend_long old_ret = 0; + for (size_t i = 0; i < scale_len; i++) { + if (*c >= '0' && *c <= '9') { + *ret *= 10; + *ret += *c - '0'; + } + if (*ret > old_ret) { + old_ret = *ret; + } else { + return false; + } + } + return true; +} + +int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { + /* num1,num2,scale */ + const char *n1ptr = (char *) Data; + const char *comma1 = memchr(n1ptr, ',', Size); + if (!comma1) { + return 0; + } + size_t n1len = comma1 - n1ptr; + Size -= n1len + 1; + + const char *n2ptr = comma1 + 1; + const char *comma2 = memchr(n2ptr, ',', Size); + if (!comma2) { + return 0; + } + size_t n2len = comma2 - n2ptr; + Size -= n2len + 1; + + zend_long scale = 0; + if (!char_to_zend_long((char *) comma2 + 1, Size, &scale)) { + return 0; + } + + if (fuzzer_request_startup() == FAILURE) { + return 0; + } + + char func_name[6]; + switch (rand() % 6) { + case 0: + sprintf(func_name, "%s", "bcadd"); + break; + case 1: + sprintf(func_name, "%s", "bcsub"); + break; + case 2: + sprintf(func_name, "%s", "bcmul"); + break; + case 3: + sprintf(func_name, "%s", "bcdiv"); + break; + case 4: + sprintf(func_name, "%s", "bcmod"); + break; + case 5: + sprintf(func_name, "%s", "bcpow"); + break; + } + + fuzzer_setup_dummy_frame(); + + zval args[3]; + ZVAL_STRINGL(&args[0], n1ptr, n1len); + ZVAL_STRINGL(&args[1], n2ptr, n2len); + ZVAL_LONG(&args[2], scale); + + fuzzer_call_php_func_zval(func_name, 3, args); + + zval_ptr_dtor(&args[0]); + zval_ptr_dtor(&args[1]); + + fuzzer_request_shutdown(); + + return 0; +} + +int LLVMFuzzerInitialize(int *argc, char ***argv) { + fuzzer_init_php(NULL); + + /* fuzzer_shutdown_php(); */ + return 0; +}