Skip to content

Commit 24003b5

Browse files
committed
fuzzer for bcmath
1 parent 5885b94 commit 24003b5

File tree

10 files changed

+176
-0
lines changed

10 files changed

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

0 commit comments

Comments
 (0)