-
Notifications
You must be signed in to change notification settings - Fork 7.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
ext/bcmath: Added fuzzer for divide #18045
base: PHP-8.4
Are you sure you want to change the base?
Changes from 1 commit
24003b5
5341ef7
1fb2cd1
82ed67d
bd630e3
a2c3f56
13319aa
e1fa2fa
3d52e01
39cca77
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
15,7,0 |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
14.14,9,10 |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
1.23456789,0.56,10 |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
0.00123456789,0.001,10 |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
12345.6789,100,2 |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
12345.6,0.00001,20 |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,165 @@ | ||
/* | ||
+----------------------------------------------------------------------+ | ||
| Copyright (c) The PHP Group | | ||
+----------------------------------------------------------------------+ | ||
| This source file is subject to version 3.01 of the PHP license, | | ||
| that is bundled with this package in the file LICENSE, and is | | ||
| available through the world-wide-web at the following url: | | ||
| https://www.php.net/license/3_01.txt | | ||
| If you did not receive a copy of the PHP license and are unable to | | ||
| obtain it through the world-wide-web, please send a note to | | ||
| [email protected] so we can mail you a copy immediately. | | ||
+----------------------------------------------------------------------+ | ||
| Authors: Saki Takamachi <[email protected]> | | ||
+----------------------------------------------------------------------+ | ||
*/ | ||
|
||
|
||
|
||
#include "fuzzer.h" | ||
|
||
#include "Zend/zend.h" | ||
#include <main/php_config.h> | ||
#include "main/php_main.h" | ||
|
||
#include <stdio.h> | ||
#include <stdint.h> | ||
#include <stdlib.h> | ||
|
||
#include "fuzzer-sapi.h" | ||
|
||
zend_long char_to_size_t(char *c) { | ||
zend_long ret = 0; | ||
if (*c >= '0' && *c <= '9') { | ||
ret *= 10; | ||
ret += *c - '0'; | ||
} | ||
return ret; | ||
} | ||
|
||
int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { | ||
/* num1,num2,scale */ | ||
const uint8_t *Comma1 = memchr(Data, ',', Size); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please just use snake_case instead of CamelCase for variables There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Fixed in 1fb2cd1 |
||
if (!Comma1) { | ||
return 0; | ||
} | ||
|
||
size_t dividend_len = Comma1 - Data; | ||
char *dividend_str = estrndup((char *) Data, dividend_len); | ||
Data = Comma1 + 1; | ||
Size -= dividend_len + 1; | ||
|
||
const uint8_t *Comma2 = memchr(Data, ',', Size); | ||
if (!Comma2) { | ||
efree(dividend_str); | ||
return 0; | ||
} | ||
|
||
size_t divisor_len = Comma2 - Data; | ||
char *divisor_str = estrndup((char *) Data, divisor_len); | ||
Data = Comma2 + 1; | ||
Size -= divisor_len + 1; | ||
|
||
char *scale_str = malloc(Size + 1); | ||
memcpy(scale_str, Data, Size); | ||
scale_str[Size] = '\0'; | ||
|
||
zend_long scale = char_to_size_t(scale_str); | ||
free(scale_str); | ||
|
||
if (fuzzer_request_startup() == FAILURE) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This should happen earlier to not leak memory. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Removed unnecessary memory allocations and relocated code. |
||
return 0; | ||
} | ||
|
||
fuzzer_setup_dummy_frame(); | ||
|
||
zval result; | ||
ZVAL_UNDEF(&result); | ||
|
||
zval args[4]; | ||
ZVAL_COPY_VALUE(&args[0], &result); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Very confused by this line, There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Fixed in 5341ef7 |
||
ZVAL_STRINGL(&args[1], dividend_str, dividend_len); | ||
ZVAL_STRINGL(&args[2], divisor_str, divisor_len); | ||
ZVAL_LONG(&args[3], scale); | ||
|
||
fuzzer_call_php_func_zval("bcdiv", 4, args); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It would be great to extend the fuzzer to pick one of a few bc function at random (e.g. bcadd, bcsub, ...) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Changed in bd630e3 |
||
|
||
zval_ptr_dtor(&result); | ||
zval_ptr_dtor(&args[1]); | ||
zval_ptr_dtor(&args[2]); | ||
efree(dividend_str); | ||
efree(divisor_str); | ||
|
||
fuzzer_request_shutdown(); | ||
|
||
return 0; | ||
} | ||
|
||
#define BUF_SIZE 128 | ||
|
||
static inline bool rand_bool() { | ||
return rand() & 1; | ||
} | ||
|
||
static inline size_t generate_random_num_fraction(char *buf, size_t len) { | ||
int zeros = rand() % 10; | ||
for (int i = 0; i < zeros; i++) { | ||
buf[len] = '0'; | ||
len++; | ||
} | ||
len += snprintf(buf + len, BUF_SIZE - len, "%ld", random()); | ||
return len; | ||
} | ||
|
||
static inline size_t generate_random_num(char *buf, size_t len) { | ||
if (rand_bool()) { | ||
/* num < 1 */ | ||
buf[len] = '0'; | ||
buf[len + 1]= '.'; | ||
len += 2; | ||
/* fraction */ | ||
len = generate_random_num_fraction(buf, len); | ||
} else { | ||
/* integer */ | ||
len += snprintf(buf + len, BUF_SIZE - len, "%ld", random()); | ||
if (rand_bool()) { | ||
/* fraction */ | ||
buf[len] = '.'; | ||
len++; | ||
len = generate_random_num_fraction(buf, len); | ||
} | ||
} | ||
|
||
return len; | ||
} | ||
|
||
size_t LLVMFuzzerCustomMutator(uint8_t *Data, size_t Size, size_t MaxSize, unsigned int Seed) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm not so sure a custom mutator is the best approach. You're also not really mutating the buffer here. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Wouldn't it be better to let the fuzzer mutate the input but just choose to interpret the raw bytes as numbers? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Thanks, does that mean accepting the mutated input as is? Or does it mean, for example, taking it, chopping it into 64-bit chunks, interpreting them as integers, converting them to numeric characters, and concatenating them? I had trouble creating numeric data with no decimal points or just one, so I used a custom mutator. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
char buf[BUF_SIZE]; | ||
size_t len = 0; | ||
|
||
/* num1 */ | ||
len = generate_random_num(buf, len); | ||
buf[len] = ','; | ||
len++; | ||
|
||
/* num2 */ | ||
len = generate_random_num(buf, len); | ||
buf[len] = ','; | ||
len++; | ||
|
||
/* scale */ | ||
len += snprintf(buf + len, BUF_SIZE - len, "%d", rand() % 10); | ||
|
||
if (len > MaxSize) { | ||
return 0; | ||
} | ||
memcpy(Data, buf, len); | ||
return len; | ||
} | ||
|
||
int LLVMFuzzerInitialize(int *argc, char ***argv) { | ||
fuzzer_init_php(NULL); | ||
|
||
/* fuzzer_shutdown_php(); */ | ||
return 0; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This could also cause overflow
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed in 82ed67d
Parsing scale was left unfinished code...