-
Notifications
You must be signed in to change notification settings - Fork 7.9k
BCmath fix for validation arguments #4092
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
Conversation
It seems to me that a regex would be overkill, since ext/bcmath/bcmath.c | 16 ++++++++++++----
ext/bcmath/libbcmath/src/bcmath.h | 2 +-
ext/bcmath/libbcmath/src/str2num.c | 6 ++++--
3 files changed, 17 insertions(+), 7 deletions(-)
diff --git a/ext/bcmath/bcmath.c b/ext/bcmath/bcmath.c
index cc9d901fdf..84735b5e5d 100644
--- a/ext/bcmath/bcmath.c
+++ b/ext/bcmath/bcmath.c
@@ -198,11 +198,15 @@ static void php_str2num(bc_num *num, char *str)
char *p;
if (!(p = strchr(str, '.'))) {
- bc_str2num(num, str, 0);
+ if (bc_str2num(num, str, 0)) {
+ php_error_docref(NULL, E_WARNING, "bcmath function argument is not well formatted");
+ }
return;
}
- bc_str2num(num, str, strlen(p+1));
+ if (bc_str2num(num, str, strlen(p+1))) {
+ php_error_docref(NULL, E_WARNING, "bcmath function argument is not well formatted");
+ }
}
/* }}} */
@@ -527,8 +531,12 @@ PHP_FUNCTION(bccomp)
bc_init_num(&first);
bc_init_num(&second);
- bc_str2num(&first, ZSTR_VAL(left), scale);
- bc_str2num(&second, ZSTR_VAL(right), scale);
+ if (bc_str2num(&first, ZSTR_VAL(left), scale)) {
+ php_error_docref(NULL, E_WARNING, "bcmath function argument is not well formatted");
+ }
+ if (bc_str2num(&second, ZSTR_VAL(right), scale)) {
+ php_error_docref(NULL, E_WARNING, "bcmath function argument is not well formatted");
+ }
RETVAL_LONG(bc_compare(first, second));
bc_free_num(&first);
diff --git a/ext/bcmath/libbcmath/src/bcmath.h b/ext/bcmath/libbcmath/src/bcmath.h
index 78868edcb3..1297a3279c 100644
--- a/ext/bcmath/libbcmath/src/bcmath.h
+++ b/ext/bcmath/libbcmath/src/bcmath.h
@@ -108,7 +108,7 @@ _PROTOTYPE(bc_num bc_copy_num, (bc_num num));
_PROTOTYPE(void bc_init_num, (bc_num *num));
-_PROTOTYPE(void bc_str2num, (bc_num *num, char *str, int scale));
+_PROTOTYPE(int bc_str2num, (bc_num *num, char *str, int scale));
_PROTOTYPE(zend_string *bc_num2str_ex, (bc_num num, int scale));
diff --git a/ext/bcmath/libbcmath/src/str2num.c b/ext/bcmath/libbcmath/src/str2num.c
index f38d341570..6cca4a0760 100644
--- a/ext/bcmath/libbcmath/src/str2num.c
+++ b/ext/bcmath/libbcmath/src/str2num.c
@@ -40,7 +40,7 @@
/* Convert strings to bc numbers. Base 10 only.*/
-void
+int
bc_str2num (bc_num *num, char *str, int scale)
{
int digits, strscale;
@@ -63,7 +63,7 @@ bc_str2num (bc_num *num, char *str, int scale)
if ((*ptr != '\0') || (digits+strscale == 0))
{
*num = bc_copy_num (BCG(_zero_));
- return;
+ return str[0] != '0' || str[1] != '\0';
}
/* Adjust numbers and allocate storage and initialize fields. */
@@ -108,4 +108,6 @@ bc_str2num (bc_num *num, char *str, int scale)
if (bc_is_zero (*num))
(*num)->n_sign = PLUS;
+
+ return 0;
} Note that this would allow strings like |
@cmb69 yeah, works well! |
I've found that I've failed some tests somehow.
those 2 are from
I've tested the |
@vladyslavstartsev Can you paste the contents of ext/opcache/tests/opt/sccp_010.diff (and maybe other .diff files) somewhere? |
@nikic is that good enough? |
@vladyslavstartsev It's not clear to me what is causing those test failures. My best guess is that an incorrect opcache.so gets loaded. In any case they are unrelated to your changes here. |
@nikic done all the things! |
ext/bcmath/libbcmath/src/str2num.c
Outdated
@@ -62,7 +62,7 @@ bc_str2num (bc_num *num, char *str, int scale) | |||
if ((*ptr != '\0') || (digits+strscale == 0)) | |||
{ | |||
*num = bc_copy_num (BCG(_zero_)); | |||
return; | |||
return str[0] == '0' || str[1] == '\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.
Shouldn't the ||
here be a &&
? And then it will not handle leading whitespace right. I think the right thing to do here might be return *ptr == '\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.
I agree that we shouldn't throw a warning if there is leading whitespace (although the proposed regexp would not allow leading whitespace).
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.
@nikic somehow the return *ptr == '\0'
does not work, I'm still getting warnings on echo bcadd(" 0", "2"), "\n";
and echo bccomp(" 0", "2"), "\n";
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.
Ah! As it is (and was), bc_tr2num()
doesn't accept leading whitespace at all. We could change this like so:
ext/bcmath/libbcmath/src/str2num.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/ext/bcmath/libbcmath/src/str2num.c b/ext/bcmath/libbcmath/src/str2num.c
index 7fdccd15d6..8e20c6ec36 100644
--- a/ext/bcmath/libbcmath/src/str2num.c
+++ b/ext/bcmath/libbcmath/src/str2num.c
@@ -54,6 +54,7 @@ bc_str2num (bc_num *num, char *str, int scale)
digits = 0;
strscale = 0;
zero_int = FALSE;
+ while (*ptr == ' ' || *ptr == '\t' || *ptr == '\n' || *ptr == '\r' || *ptr == '\v' || *ptr == '\f') ptr++; /* Skip leading whitespace. */
if ( (*ptr == '+') || (*ptr == '-')) ptr++; /* Sign */
while (*ptr == '0') ptr++; /* Skip leading zeros. */
while (isdigit((int)*ptr)) ptr++, digits++; /* digits */
@@ -76,6 +77,7 @@ bc_str2num (bc_num *num, char *str, int scale)
/* Build the whole number. */
ptr = str;
+ while (*ptr == ' ' || *ptr == '\t' || *ptr == '\n' || *ptr == '\r' || *ptr == '\v' || *ptr == '\f') ptr++; /* Skip leading whitespace. */
if (*ptr == '-')
{
(*num)->n_sign = MINUS;
Anyhow, the test has to be fixed to work on other systems as well; currently, it expects hard-coded absolute path names. See how that's solved in bcpow_errror1.phpt and the documentation of the EXPECTF section.
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.
@cmb69 fixed tests and leading white space char.
Seams to be done with all the things
ok, |
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.
Thanks! LGTM.
Sorry about the confusion with the whitespace, I incorrectly assumed it was supported. I'm not totally sure if we really should add support for it if it's not there already, especially given the discussion in https://externals.io/message/104594. Instead of testing |
@nikic yeah, might be better to be conservative here. |
Co-Authored-By: Nikita Popov <[email protected]> Co-Authored-By: Christoph M. Becker <[email protected]>
@nikic I've updated the code to throw warnings on |
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.
Thanks!
Merged as a07d422 into 7.4. Thanks! |
I've added only todo for it here since I'm not C dev.
my concept looks like this, but some why it doesn't work as expected.
I think this should be easy for people who know how to do C right way.
Here are threads from internals mailing list to get what I want to implement
https://externals.io/message/104295#104295
https://externals.io/message/104374#105461