Skip to content

Commit 7c69945

Browse files
committed
fuzzer for bcmath
1 parent cd58662 commit 7c69945

File tree

10 files changed

+194
-0
lines changed

10 files changed

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

0 commit comments

Comments
 (0)