Skip to content

ext/bcmath: Added fuzzer for divide #18045

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 11 commits into
base: PHP-8.4
Choose a base branch
from
1 change: 1 addition & 0 deletions sapi/fuzzer/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
php-fuzz-*
3 changes: 3 additions & 0 deletions sapi/fuzzer/Makefile.frag
Original file line number Diff line number Diff line change
Expand Up @@ -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 $@
1 change: 1 addition & 0 deletions sapi/fuzzer/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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:

Expand Down
1 change: 1 addition & 0 deletions sapi/fuzzer/config.m4
Original file line number Diff line number Diff line change
Expand Up @@ -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])
Expand Down
1 change: 1 addition & 0 deletions sapi/fuzzer/corpus/bcmath/1
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
15,7,0
1 change: 1 addition & 0 deletions sapi/fuzzer/corpus/bcmath/2
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
14.14,-9,10
1 change: 1 addition & 0 deletions sapi/fuzzer/corpus/bcmath/3
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
1.23456789,0.56,10
1 change: 1 addition & 0 deletions sapi/fuzzer/corpus/bcmath/4
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
0.00123456789,0.001,10
1 change: 1 addition & 0 deletions sapi/fuzzer/corpus/bcmath/5
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
-12345.6789,100,2
1 change: 1 addition & 0 deletions sapi/fuzzer/corpus/bcmath/6
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
12345.6,0.00001,20
9 changes: 9 additions & 0 deletions sapi/fuzzer/dict/bcmath
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
","
"1234567890"
"-9876543"
"0.12345678"
"-0.002468"
"9999999999999999"
"0.00000000000000000000001"
"10"
"-29"
119 changes: 119 additions & 0 deletions sapi/fuzzer/fuzzer-bcmath.c
Original file line number Diff line number Diff line change
@@ -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 |
| [email protected] so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
| Authors: Saki Takamachi <[email protected]> |
+----------------------------------------------------------------------+
*/



#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"

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) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should happen earlier to not leak memory.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed unnecessary memory allocations and relocated code.
How about the code now?
e1fa2fa

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");
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When the exponent is large, the processing is too slow. It may be better to set a limit such as "when num2 is less than 1000"...

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;
}
Loading