Skip to content

Commit 9c7fcdb

Browse files
committed
fuzzer for bcmath
1 parent d17ed34 commit 9c7fcdb

File tree

4 files changed

+199
-0
lines changed

4 files changed

+199
-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/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/fuzzer-bcmath.c

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
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+
const uint8_t *Comma1 = memchr(Data, ',', Size);
42+
if (!Comma1) {
43+
return 0;
44+
}
45+
46+
size_t dividend_len = Comma1 - Data;
47+
char *dividend_str = estrndup((char *) Data, dividend_len);
48+
Data = Comma1 + 1;
49+
Size -= dividend_len + 1;
50+
51+
const uint8_t *Comma2 = memchr(Data, ',', Size);
52+
if (!Comma2) {
53+
efree(dividend_str);
54+
return 0;
55+
}
56+
57+
size_t divisor_len = Comma2 - Data;
58+
char *divisor_str = estrndup((char *) Data, divisor_len);
59+
Data = Comma2 + 1;
60+
Size -= divisor_len + 1;
61+
62+
char *scale_str = malloc(Size + 1);
63+
memcpy(scale_str, Data, Size);
64+
scale_str[Size] = '\0';
65+
66+
zend_long scale = char_to_size_t(scale_str);
67+
free(scale_str);
68+
69+
if (fuzzer_request_startup() == FAILURE) {
70+
return 0;
71+
}
72+
73+
fuzzer_setup_dummy_frame();
74+
75+
zval result;
76+
ZVAL_UNDEF(&result);
77+
78+
zval args[4];
79+
ZVAL_COPY_VALUE(&args[0], &result);
80+
ZVAL_STRINGL(&args[1], dividend_str, dividend_len);
81+
ZVAL_STRINGL(&args[2], divisor_str, divisor_len);
82+
ZVAL_LONG(&args[3], scale);
83+
84+
fuzzer_call_php_func_zval("bcdiv", 4, args);
85+
86+
zval_ptr_dtor(&result);
87+
zval_ptr_dtor(&args[1]);
88+
zval_ptr_dtor(&args[2]);
89+
efree(dividend_str);
90+
efree(divisor_str);
91+
92+
fuzzer_request_shutdown();
93+
94+
return 0;
95+
}
96+
97+
int LLVMFuzzerInitialize(int *argc, char ***argv) {
98+
fuzzer_init_php(NULL);
99+
100+
/* fuzzer_shutdown_php(); */
101+
return 0;
102+
}

sapi/fuzzer/generate_bcmath_dict.php

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
<?php
2+
3+
if (!extension_loaded('bcmath')) {
4+
echo "Skipping bcmath dictionary generation\n";
5+
return;
6+
}
7+
8+
define('BCMATH_GEN_DICT_LOOP', 300);
9+
10+
function genRandomNumberString(): string
11+
{
12+
return match (rand(0, 2)) {
13+
0 => (string) rand(0, 1000000),
14+
1 => rand(0, 1000000) . rand(0, 1000000),
15+
2 => rand(0, 1000000) . rand(0, 1000000) . rand(0, 1000000),
16+
};
17+
}
18+
19+
function genRandomNumber(bool $integerIsZero, bool $hasFraction): string
20+
{
21+
$sign = rand(0, 1) ? '' : '-';
22+
$integer = $integerIsZero ? '0' : genRandomNumberString();
23+
$fraction = $hasFraction ? '.' . genRandomNumberString() : '';
24+
return $sign . $integer . $fraction;
25+
}
26+
27+
function writeDict(array $dicts): void
28+
{
29+
$dict = implode("\n", $dicts) . "\n";
30+
file_put_contents(__DIR__ . "/dict/bcmath", $dict, FILE_APPEND);
31+
}
32+
33+
$total = 0;
34+
35+
for ($loop = 0; $loop < BCMATH_GEN_DICT_LOOP; $loop++) {
36+
$case1 = [true, true];
37+
$case2 = [false, true];
38+
$case3 = [false, false];
39+
40+
foreach ([
41+
[
42+
$case1,
43+
$case1,
44+
],
45+
[
46+
$case1,
47+
$case2,
48+
],
49+
[
50+
$case1,
51+
$case3,
52+
],
53+
[
54+
$case2,
55+
$case1,
56+
],
57+
[
58+
$case2,
59+
$case2,
60+
],
61+
[
62+
$case2,
63+
$case3,
64+
],
65+
[
66+
$case3,
67+
$case1,
68+
],
69+
[
70+
$case3,
71+
$case2,
72+
],
73+
[
74+
$case3,
75+
$case3,
76+
],
77+
] as [
78+
[$integerIsZero, $hasFraction],
79+
[$integerIsZero2, $hasFraction2],
80+
]) {
81+
//$dicts = [];
82+
for ($i = 0; $i < 100; $i++) {
83+
$dividend = genRandomNumber($integerIsZero, $hasFraction);
84+
$divisor = genRandomNumber($integerIsZero2, $hasFraction2);
85+
$scale = rand(0, 100);
86+
//$dicts[] = '"' . implode(',', [$dividend, $divisor, $scale]) . '"';
87+
$dict = '"' . implode(',', [$dividend, $divisor, $scale]) . '"' . "\n";
88+
file_put_contents(__DIR__ . "/corpus/bcmath/{$total}", $dict);
89+
$total++;
90+
}
91+
//writeDict($dicts);
92+
}
93+
}

0 commit comments

Comments
 (0)