cvs: php4 /ext/gmp gmp.c

From: Date: Sun, 10 Feb 2002 23:12:57 +0000
Subject: cvs: php4 /ext/gmp gmp.c
Groups: php.cvs 
Request: Send a blank email to php-cvs+get-9342@lists.php.net to get a copy of this message
elixer Sun Feb 10 18:12:57 2002 EDT Modified files: /php4/ext/gmp gmp.c Log: Fix for bugs #10133 and #15454. 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. Index: php4/ext/gmp/gmp.c diff -u php4/ext/gmp/gmp.c:1.23 php4/ext/gmp/gmp.c:1.24 --- php4/ext/gmp/gmp.c:1.23 Sat Dec 15 09:22:29 2001 +++ php4/ext/gmp/gmp.c Sun Feb 10 18:12:57 2002 @@ -86,15 +86,15 @@ /* {{{ 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 }; /* }}} */ @@ -193,6 +193,7 @@ 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)) { @@ -207,14 +208,19 @@ 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: @@ -222,8 +228,13 @@ efree(*gmpnumber); return FAILURE; } + + if (ret) { + FREE_GMP_NUM(*gmpnumber); + return FAILURE; + } - return ret?FAILURE:SUCCESS; + return SUCCESS; } /* }}} */ @@ -530,7 +541,19 @@ 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); }

« previous php.cvs (#9342) next »