Skip to content

Commit 978187e

Browse files
committed
fuzzer for bcmath
1 parent cd58662 commit 978187e

File tree

10 files changed

+177
-0
lines changed

10 files changed

+177
-0
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: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ When running `make` it creates these binaries in `sapi/fuzzer/`:
3333
* `php-fuzz-execute`: Fuzzing the executor
3434
* `php-fuzz-function-jit`: Fuzzing the function JIT (requires --enable-opcache)
3535
* `php-fuzz-tracing-jit`: Fuzzing the tracing JIT (requires --enable-opcache)
36+
* `php-fuzz-bcmath`: Fuzzing division (requires --enable-bcmath)
3637

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

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: 166 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,166 @@
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+
static inline bool rand_bool() {
99+
return rand() & 1;
100+
}
101+
102+
static inline size_t generate_random_num_fraction(char *buf) {
103+
size_t len = 0;
104+
int zeros = rand() % 10;
105+
for (int i = 0; i < zeros; i++) {
106+
buf[len] = '0';
107+
len++;
108+
}
109+
len += snprintf(buf + len, sizeof(buf) - len, "%ld", random());
110+
return len;
111+
}
112+
113+
static inline size_t generate_random_num(char *buf) {
114+
size_t len = 0;
115+
116+
if (rand_bool()) {
117+
/* num < 1 */
118+
buf[0] = '0';
119+
buf[1]= '.';
120+
len += 2;
121+
/* fraction */
122+
len += generate_random_num_fraction(buf + len);
123+
} else {
124+
/* integer */
125+
len += snprintf(buf, sizeof(buf), "%ld", random());
126+
if (rand_bool()) {
127+
/* fraction */
128+
buf[len] = '.';
129+
len++;
130+
len += generate_random_num_fraction(buf + len);
131+
}
132+
}
133+
134+
return len;
135+
}
136+
137+
size_t LLVMFuzzerCustomMutator(uint8_t *Data, size_t Size, size_t MaxSize, unsigned int Seed) {
138+
char buf[128];
139+
size_t len = 0;
140+
141+
/* num1 */
142+
len += generate_random_num(buf);
143+
buf[len] = ',';
144+
len++;
145+
146+
/* num2 */
147+
len += generate_random_num(buf + len);
148+
buf[len] = ',';
149+
len++;
150+
151+
/* scale */
152+
len += snprintf(buf + len, sizeof(buf) - len, "%d", rand() % 10);
153+
154+
if (len > MaxSize) {
155+
return 0;
156+
}
157+
memcpy(Data, buf, len);
158+
return len;
159+
}
160+
161+
int LLVMFuzzerInitialize(int *argc, char ***argv) {
162+
fuzzer_init_php(NULL);
163+
164+
/* fuzzer_shutdown_php(); */
165+
return 0;
166+
}

0 commit comments

Comments
 (0)