-
Notifications
You must be signed in to change notification settings - Fork 7.9k
Fix GH-16411: gmp_export() can cause overflow #16418
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
We need not only to avoid the signed overflow while calculating `bits_per_word` (reported issue), but also the unsigned overflow when calculating `count`. While the former has a fixed threshold, the latter does not, since it also depends on the size in base 2. Thus we use a somewhat unconventional error message.
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.
Seems reasonable, but I don't exactly understand what this function does.
ext/gmp/tests/gh16411.phpt
Outdated
gmp | ||
--FILE-- | ||
<?php | ||
gmp_export(-9223372036854775808, 9223372036854775807, -9223372036854775808); |
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.
Seems like we don't validate the $option
argument properly?
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, we're only checking for the relevant flags:
Lines 929 to 958 in 79c71c9
switch (options & (GMP_LSW_FIRST | GMP_MSW_FIRST)) { | |
case GMP_LSW_FIRST: | |
*order = -1; | |
break; | |
case GMP_MSW_FIRST: | |
case 0: /* default */ | |
*order = 1; | |
break; | |
default: | |
/* options argument is in third position */ | |
zend_argument_value_error(3, "cannot use multiple word order options"); | |
return false; | |
} | |
switch (options & (GMP_LITTLE_ENDIAN | GMP_BIG_ENDIAN | GMP_NATIVE_ENDIAN)) { | |
case GMP_LITTLE_ENDIAN: | |
*endian = -1; | |
break; | |
case GMP_BIG_ENDIAN: | |
*endian = 1; | |
break; | |
case GMP_NATIVE_ENDIAN: | |
case 0: /* default */ | |
*endian = 0; | |
break; | |
default: | |
/* options argument is in third position */ | |
zend_argument_value_error(3, "cannot use multiple endian options"); | |
return false; | |
} |
So basically $options % 32
. I think this okay (wouldn't want to touch it for a stable release), but could be improved for master (reject >= 32).
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.
Yeah, improving this for master is what I had in mind, I was just surprised that large int wasn't caught by the option checking.
Also, is this not an issue for |
Do you mean
No, since there are no calculations, and from what I can tell, we're not calling Anyway, as CI tells me, I need to cater to 32bit. |
I meant
OK
Indeed. |
The documentation is pretty clear about It's actually an elaborate
Need to check what's going on there. |
PS: all good. For
Only for
|
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.
LGTM
--FILE-- | ||
<?php | ||
gmp_export("-9223372036854775808", PHP_INT_MAX, PHP_INT_MIN); | ||
?> | ||
--EXPECTF-- | ||
Fatal error: Uncaught ValueError: gmp_export(): Argument #2 ($word_size) is too large for argument #1 ($num) in %s:%d | ||
%A |
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.
You could try/catch the ValueError and have the output just be an EXPECT section, but that is minor nit.
We need not only to avoid the signed overflow while calculating
bits_per_word
(reported issue), but also the unsigned overflow when calculatingcount
. While the former has a fixed threshold, the latter does not, since it also depends on the size in base 2. Thus we use a somewhat unconventional error message.