Skip to content

Commit 0d6565d

Browse files
committed
fuzzer for bcmath
1 parent cd58662 commit 0d6565d

File tree

10 files changed

+152
-1
lines changed

10 files changed

+152
-1
lines changed

sapi/fuzzer/Makefile.frag

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,3 +31,6 @@ $(SAPI_FUZZER_PATH)/php-fuzz-mbstring: $(PHP_GLOBAL_OBJS) $(PHP_SAPI_OBJS) $(PHP
3131

3232
$(SAPI_FUZZER_PATH)/php-fuzz-mbregex: $(PHP_GLOBAL_OBJS) $(PHP_SAPI_OBJS) $(PHP_FUZZER_MBREGEX_OBJS)
3333
$(FUZZER_BUILD) $(PHP_FUZZER_MBREGEX_OBJS) -o $@
34+
35+
$(SAPI_FUZZER_PATH)/php-fuzz-bcmath: $(PHP_GLOBAL_OBJS) $(PHP_SAPI_OBJS) $(PHP_FUZZER_BCMATH_OBJS)
36+
$(FUZZER_BUILD) $(PHP_FUZZER_BCMATH_OBJS) -o $@

sapi/fuzzer/README.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,8 @@ CC=clang CXX=clang++ \
1212
--enable-debug-assertions \
1313
--enable-address-sanitizer \
1414
--enable-exif \
15-
--enable-mbstring
15+
--enable-mbstring \
16+
--enable-bcmath
1617
```
1718

1819
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.
@@ -33,6 +34,7 @@ When running `make` it creates these binaries in `sapi/fuzzer/`:
3334
* `php-fuzz-execute`: Fuzzing the executor
3435
* `php-fuzz-function-jit`: Fuzzing the function JIT (requires --enable-opcache)
3536
* `php-fuzz-tracing-jit`: Fuzzing the tracing JIT (requires --enable-opcache)
37+
* `php-fuzz-bcmath`: Fuzzing division (requires --enable-bcmath)
3638

3739
Some fuzzers have a seed corpus in `sapi/fuzzer/corpus`. You can use it as follows:
3840

sapi/fuzzer/config.m4

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ if test "$PHP_FUZZER" != "no"; then
6363
PHP_FUZZER_TARGET([unserialize], [PHP_FUZZER_UNSERIALIZE_OBJS])
6464
PHP_FUZZER_TARGET([unserializehash], [PHP_FUZZER_UNSERIALIZEHASH_OBJS])
6565
PHP_FUZZER_TARGET([json], [PHP_FUZZER_JSON_OBJS])
66+
PHP_FUZZER_TARGET([bcmath], [PHP_FUZZER_BCMATH_OBJS])
6667

6768
if test -n "$enable_exif" && test "$enable_exif" != "no"; then
6869
PHP_FUZZER_TARGET([exif], [PHP_FUZZER_EXIF_OBJS])

sapi/fuzzer/corpus/bcmath/1

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
15,7,0

sapi/fuzzer/corpus/bcmath/2

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
14.14,9,10

sapi/fuzzer/corpus/bcmath/3

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
1.23456789,0.56,10

sapi/fuzzer/corpus/bcmath/4

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
0.00123456789,0.001,10

sapi/fuzzer/corpus/bcmath/5

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
12345.6789,100,2

sapi/fuzzer/corpus/bcmath/6

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
12345.6,0.00001,20

sapi/fuzzer/fuzzer-bcmath.c

Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,139 @@
1+
/*
2+
+----------------------------------------------------------------------+
3+
| Copyright (c) The PHP Group |
4+
+----------------------------------------------------------------------+
5+
| This source file is subject to version 3.01 of the PHP license, |
6+
| that is bundled with this package in the file LICENSE, and is |
7+
| available through the world-wide-web at the following url: |
8+
| https://www.php.net/license/3_01.txt |
9+
| If you did not receive a copy of the PHP license and are unable to |
10+
| obtain it through the world-wide-web, please send a note to |
11+
| [email protected] so we can mail you a copy immediately. |
12+
+----------------------------------------------------------------------+
13+
| Authors: Saki Takamachi <[email protected]> |
14+
+----------------------------------------------------------------------+
15+
*/
16+
17+
18+
19+
#include "fuzzer.h"
20+
21+
#include "Zend/zend.h"
22+
#include <main/php_config.h>
23+
#include "main/php_main.h"
24+
25+
#include <stdio.h>
26+
#include <stdint.h>
27+
#include <stdlib.h>
28+
29+
#include "fuzzer-sapi.h"
30+
31+
zend_long char_to_size_t(char *c) {
32+
zend_long ret = 0;
33+
if (*c >= '0' && *c <= '9') {
34+
ret *= 10;
35+
ret += *c - '0';
36+
}
37+
return ret;
38+
}
39+
40+
int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
41+
/* num1,num2,scale */
42+
const uint8_t *Comma1 = memchr(Data, ',', Size);
43+
if (!Comma1) {
44+
return 0;
45+
}
46+
47+
size_t dividend_len = Comma1 - Data;
48+
char *dividend_str = estrndup((char *) Data, dividend_len);
49+
Data = Comma1 + 1;
50+
Size -= dividend_len + 1;
51+
52+
const uint8_t *Comma2 = memchr(Data, ',', Size);
53+
if (!Comma2) {
54+
efree(dividend_str);
55+
return 0;
56+
}
57+
58+
size_t divisor_len = Comma2 - Data;
59+
char *divisor_str = estrndup((char *) Data, divisor_len);
60+
Data = Comma2 + 1;
61+
Size -= divisor_len + 1;
62+
63+
char *scale_str = malloc(Size + 1);
64+
memcpy(scale_str, Data, Size);
65+
scale_str[Size] = '\0';
66+
67+
zend_long scale = char_to_size_t(scale_str);
68+
free(scale_str);
69+
70+
if (fuzzer_request_startup() == FAILURE) {
71+
return 0;
72+
}
73+
74+
fuzzer_setup_dummy_frame();
75+
76+
zval result;
77+
ZVAL_UNDEF(&result);
78+
79+
zval args[4];
80+
ZVAL_COPY_VALUE(&args[0], &result);
81+
ZVAL_STRINGL(&args[1], dividend_str, dividend_len);
82+
ZVAL_STRINGL(&args[2], divisor_str, divisor_len);
83+
ZVAL_LONG(&args[3], scale);
84+
85+
fuzzer_call_php_func_zval("bcdiv", 4, args);
86+
87+
zval_ptr_dtor(&result);
88+
zval_ptr_dtor(&args[1]);
89+
zval_ptr_dtor(&args[2]);
90+
efree(dividend_str);
91+
efree(divisor_str);
92+
93+
fuzzer_request_shutdown();
94+
95+
return 0;
96+
}
97+
98+
size_t LLVMFuzzerCustomMutator(uint8_t *Data, size_t Size, size_t MaxSize, unsigned int Seed) {
99+
char buf[64];
100+
size_t len = 0;
101+
102+
/* num1 integer */
103+
len += snprintf(buf + len, sizeof(buf) - len, "%ld", random());
104+
if (rand() & 1) {
105+
/* num1 fraction */
106+
buf[len] = '.';
107+
len++;
108+
len += snprintf(buf + len, sizeof(buf) - len, "%ld", random());
109+
}
110+
111+
buf[len] = ',';
112+
len++;
113+
/* num2 integer */
114+
len += snprintf(buf + len, sizeof(buf) - len, "%ld", random());
115+
if (rand() & 1) {
116+
/* num2 fraction */
117+
buf[len] = '.';
118+
len++;
119+
len += snprintf(buf + len, sizeof(buf) - len, "%ld", random());
120+
}
121+
122+
buf[len] = ',';
123+
len++;
124+
/* scale */
125+
len += snprintf(buf + len, sizeof(buf) - len, "%d", rand() % 10);
126+
127+
if (len > MaxSize) {
128+
return 0;
129+
}
130+
memcpy(Data, buf, len);
131+
return len;
132+
}
133+
134+
int LLVMFuzzerInitialize(int *argc, char ***argv) {
135+
fuzzer_init_php(NULL);
136+
137+
/* fuzzer_shutdown_php(); */
138+
return 0;
139+
}

0 commit comments

Comments
 (0)