Skip to content

Commit

Permalink
Fix for bugs #10133 and #15454.
Browse files Browse the repository at this point in the history
Bug #15454 results from a bug in GMP.  If you pass in a string '0xABCD' and
specify a base of 0, GMP figures out that it is hex and skips over the 0x
characters.  If you specify base 16, then it doesn't skip those chars.
This was confirmed with the following test program:

#include <stdio.h>
#include <gmp.h>

int main()
{
        char *str_one, *str_two;
        mpz_t num_one, num_two;

	mpz_init_set_str (num_one, "0x45", 0);
	str_one = mpz_get_str(NULL, 10, num_one);

	mpz_init_set_str (num_two, "0x45", 16);
	str_two = mpz_get_str(NULL, 10, num_two);

	printf("%s / %s\n", str_one, str_two);

	mpz_clear (num_one);
	mpz_clear (num_two);

	return 0;
}

We now take anything that starts with 0[xX] as hexidecimal and anything
that starts 0[bB] as binary (this is what GMP does internally).  We also
no longer force the base to 10 or 16, but instead let GMP decide what the
best base is, be it hex, dec, or octal.
  • Loading branch information
Sean Bright committed Feb 10, 2002
1 parent 150d339 commit cc065b3
Showing 1 changed file with 35 additions and 12 deletions.
47 changes: 35 additions & 12 deletions ext/gmp/gmp.c
Original file line number Diff line number Diff line change
Expand Up @@ -86,15 +86,15 @@ function_entry gmp_functions[] = {
/* {{{ gmp_module_entry
*/
zend_module_entry gmp_module_entry = {
STANDARD_MODULE_HEADER,
STANDARD_MODULE_HEADER,
"gmp",
gmp_functions,
ZEND_MODULE_STARTUP_N(gmp),
ZEND_MODULE_SHUTDOWN_N(gmp),
NULL, /* Replace with NULL if there's nothing to do at request start */
NULL, /* Replace with NULL if there's nothing to do at request end */
NULL,
NULL,
ZEND_MODULE_INFO_N(gmp),
NO_VERSION_YET,
NO_VERSION_YET,
STANDARD_MODULE_PROPERTIES
};
/* }}} */
Expand Down Expand Up @@ -193,6 +193,7 @@ if(Z_TYPE_PP(zval) == IS_RESOURCE) { \
static int convert_to_gmp(mpz_t * *gmpnumber, zval **val, int base)
{
int ret = 0;
int skip_lead = 0;

*gmpnumber = emalloc(sizeof(mpz_t));
switch(Z_TYPE_PP(val)) {
Expand All @@ -207,23 +208,33 @@ static int convert_to_gmp(mpz_t * *gmpnumber, zval **val, int base)
case IS_STRING:
{
char *numstr = Z_STRVAL_PP(val);
if (base==0) {
if(numstr[0] == '0' && (numstr[1] == 'x' || numstr[1] == 'X')) {
base=16;
} else {
base=10;

if (Z_STRLEN_PP(val) > 2) {
if (numstr[0] == '0') {
if (numstr[1] == 'x' || numstr[1] == 'X') {
base = 16;
skip_lead = 1;
} else if (numstr[1] == 'b' || numstr[1] == 'B') {
base = 2;
skip_lead = 1;
}
}
}
ret = mpz_init_set_str(**gmpnumber, numstr, base);
ret = mpz_init_set_str(**gmpnumber, (skip_lead ? &numstr[2] : numstr), base);
}
break;
default:
zend_error(E_WARNING,"Unable to convert variable to GMP - wrong type");
efree(*gmpnumber);
return FAILURE;
}

if (ret) {
FREE_GMP_NUM(*gmpnumber);
return FAILURE;
}

return ret?FAILURE:SUCCESS;
return SUCCESS;
}
/* }}} */

Expand Down Expand Up @@ -530,7 +541,19 @@ ZEND_FUNCTION(gmp_strval)
num_len++;
}
mpz_get_str(out_string, base, *gmpnum);
out_string[num_len] = '\0';

/*
From GMP documentation for mpz_sizeinbase():
The returned value will be exact or 1 too big. If base is a power of
2, the returned value will always be exact.
So let's check to see if we already have a \0 byte...
*/

if (out_string[num_len-1] == '\0')
num_len--;
else
out_string[num_len] = '\0';

RETVAL_STRINGL(out_string, num_len, 0);
}
Expand Down

0 comments on commit cc065b3

Please sign in to comment.