From: Nikita Popov Date: Tue, 2 Sep 2014 12:28:07 +0000 (+0200) Subject: Merge branch 'PHP-5.6' X-Git-Tag: PRE_PHP7_REMOVALS~152 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=8e7cd7a0f9b4fdbae4516dca865de2ce58a48c49;p=php Merge branch 'PHP-5.6' Conflicts: ext/gmp/gmp.c --- 8e7cd7a0f9b4fdbae4516dca865de2ce58a48c49 diff --cc ext/gmp/gmp.c index fc7f4fbe56,399749d397..86188e25f7 --- a/ext/gmp/gmp.c +++ b/ext/gmp/gmp.c @@@ -1037,6 -1096,118 +1063,118 @@@ ZEND_FUNCTION(gmp_init } /* }}} */ -int gmp_import_export_validate(long size, long options, int *order, int *endian TSRMLS_DC) ++int gmp_import_export_validate(zend_long size, zend_long options, int *order, int *endian TSRMLS_DC) + { + if (size < 1) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, + "Word size must be positive, %ld given", size); + return FAILURE; + } + + 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: + php_error_docref(NULL TSRMLS_CC, E_WARNING, + "Invalid options: Conflicting word orders"); + return FAILURE; + } + + 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: + php_error_docref(NULL TSRMLS_CC, E_WARNING, + "Invalid options: Conflicting word endianness"); + return FAILURE; + } + + return SUCCESS; + } + + /* {{{ proto GMP gmp_import(string data [, int word_size = 1, int options = GMP_MSW_FIRST | GMP_NATIVE_ENDIAN]) + Imports a GMP number from a binary string */ + ZEND_FUNCTION(gmp_import) + { + char *data; - int data_len; - long size = 1; - long options = GMP_MSW_FIRST | GMP_NATIVE_ENDIAN;; ++ size_t data_len; ++ zend_long size = 1; ++ zend_long options = GMP_MSW_FIRST | GMP_NATIVE_ENDIAN;; + int order, endian; + mpz_ptr gmpnumber; + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|ll", &data, &data_len, &size, &options) == FAILURE) { + return; + } + + if (gmp_import_export_validate(size, options, &order, &endian TSRMLS_CC) == FAILURE) { + RETURN_FALSE; + } + + if ((data_len % size) != 0) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, + "Input length must be a multiple of word size"); + RETURN_FALSE; + } + + INIT_GMP_RETVAL(gmpnumber); + + mpz_import(gmpnumber, data_len / size, order, size, endian, 0, data); + } + /* }}} */ + + /* {{{ proto string gmp_export(GMP gmpnumber [, int word_size = 1, int options = GMP_MSW_FIRST | GMP_NATIVE_ENDIAN]) + Exports a GMP number to a binary string */ + ZEND_FUNCTION(gmp_export) + { + zval *gmpnumber_arg; - long size = 1; - long options = GMP_MSW_FIRST | GMP_NATIVE_ENDIAN;; ++ zend_long size = 1; ++ zend_long options = GMP_MSW_FIRST | GMP_NATIVE_ENDIAN;; + int order, endian; + mpz_ptr gmpnumber; + gmp_temp_t temp_a; + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z|ll", &gmpnumber_arg, &size, &options) == FAILURE) { + return; + } + + if (gmp_import_export_validate(size, options, &order, &endian TSRMLS_CC) == FAILURE) { + RETURN_FALSE; + } + + FETCH_GMP_ZVAL(gmpnumber, gmpnumber_arg, temp_a); + + if (mpz_sgn(gmpnumber) == 0) { - ZVAL_STRING(return_value, "", 1); ++ RETURN_EMPTY_STRING(); + } else { + size_t bits_per_word = size * 8; + size_t count = (mpz_sizeinbase(gmpnumber, 2) + bits_per_word - 1) / bits_per_word; + size_t out_len = count * size; + - char *out_string = emalloc(out_len + 1); - mpz_export(out_string, NULL, order, size, endian, 0, gmpnumber); - out_string[out_len] = '\0'; ++ zend_string *out_string = zend_string_alloc(out_len, 0); ++ mpz_export(out_string->val, NULL, order, size, endian, 0, gmpnumber); ++ out_string->val[out_len] = '\0'; + - ZVAL_STRINGL(return_value, out_string, out_len, 0); ++ RETURN_STR(out_string); + } + + FREE_GMP_TEMP(temp_a); + } + /* }}} */ + /* {{{ proto int gmp_intval(mixed gmpnumber) Gets signed long value of GMP number */ ZEND_FUNCTION(gmp_intval)