Skip to content

Instantly share code, notes, and snippets.

@hikari-no-yume
Last active August 29, 2015 14:02
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save hikari-no-yume/08bcb39ed197be10764d to your computer and use it in GitHub Desktop.
Save hikari-no-yume/08bcb39ed197be10764d to your computer and use it in GitHub Desktop.
Work-in-progress Zend bigint patch (zend_language_scanner.c's massive diff removed for the sake of readability)
From bdec0820b6933a64c388b0451c8ae0914e817aa4 Mon Sep 17 00:00:00 2001
From: Andrea Faulds <ajf@ajf.me>
Date: Fri, 6 Jun 2014 02:12:59 +0100
Subject: [PATCH] Working bigints with no tests and some unfixed corner cases
---
Zend/Makefile.am | 2 +-
Zend/Zend.dsp | 4 +
Zend/Zend.m4 | 24 +
Zend/ZendTS.dsp | 4 +
Zend/zend.c | 5 +
Zend/zend.h | 1 +
Zend/zend_API.c | 16 +
Zend/zend_ast.c | 8 +
Zend/zend_bigint.c | 480 ++++
Zend/zend_bigint.h | 213 ++
Zend/zend_builtin_functions.c | 2 +
Zend/zend_compile.c | 8 +-
Zend/zend_exceptions.c | 8 +
Zend/zend_execute.c | 9 +
Zend/zend_execute.h | 4 +
Zend/zend_language_scanner.c | 5659 +++++++++++++++++++------------------
Zend/zend_language_scanner.l | 26 +-
Zend/zend_language_scanner_defs.h | 2 +-
Zend/zend_multiply.h | 17 +-
Zend/zend_operators.c | 986 ++++++-
Zend/zend_operators.h | 56 +-
Zend/zend_types.h | 55 +-
Zend/zend_variables.c | 24 +-
Zend/zend_vm_def.h | 42 +
Zend/zend_vm_execute.h | 578 ++++
configure.in | 2 +-
ext/standard/type.c | 3 +
ext/standard/var.c | 6 +
win32/build/config.w32 | 2 +-
29 files changed, 5299 insertions(+), 2947 deletions(-)
create mode 100644 Zend/zend_bigint.c
create mode 100644 Zend/zend_bigint.h
diff --git a/Zend/Makefile.am b/Zend/Makefile.am
index 65c4113..75a804d 100644
--- a/Zend/Makefile.am
+++ b/Zend/Makefile.am
@@ -18,7 +18,7 @@ libZend_la_SOURCES=\
zend_default_classes.c \
zend_iterators.c zend_interfaces.c zend_exceptions.c \
zend_strtod.c zend_closures.c zend_float.c zend_string.c zend_signal.c \
- zend_generators.c zend_virtual_cwd.c zend_ast.c
+ zend_generators.c zend_virtual_cwd.c zend_ast.c zend_bigint.c
libZend_la_LDFLAGS =
libZend_la_LIBADD = @ZEND_EXTRA_LIBS@
diff --git a/Zend/Zend.dsp b/Zend/Zend.dsp
index 98d368f..74b89ea 100644
--- a/Zend/Zend.dsp
+++ b/Zend/Zend.dsp
@@ -123,6 +123,10 @@ SOURCE=.\zend_ast.c
# End Source File
# Begin Source File
+SOURCE=.\zend_bigint.c
+# End Source File
+# Begin Source File
+
SOURCE=.\zend_builtin_functions.c
# End Source File
# Begin Source File
diff --git a/Zend/Zend.m4 b/Zend/Zend.m4
index 945409e..a749b31 100644
--- a/Zend/Zend.m4
+++ b/Zend/Zend.m4
@@ -433,3 +433,27 @@ else
AC_MSG_RESULT(no)
fi
fi
+
+for i in $PHP_GMP /usr/local /usr; do
+ test -f $i/include/gmp.h && GMP_DIR=$i && break
+done
+
+if test -z "$GMP_DIR"; then
+ AC_MSG_ERROR(Unable to locate gmp.h)
+fi
+
+PHP_CHECK_LIBRARY(gmp, __gmp_randinit_lc_2exp_size,
+[],[
+ PHP_CHECK_LIBRARY(gmp, gmp_randinit_lc_2exp_size,
+ [],[
+ AC_MSG_ERROR([GNU MP Library version 4.1.2 or greater required.])
+ ],[
+ -L$GMP_DIR/$PHP_LIBDIR
+ ])
+],[
+ -L$GMP_DIR/$PHP_LIBDIR
+])
+
+PHP_ADD_LIBRARY_WITH_PATH(gmp, $GMP_DIR/$PHP_LIBDIR, GMP_SHARED_LIBADD)
+PHP_ADD_INCLUDE($GMP_DIR/include)
+AC_DEFINE(HAVE_GMP, 1, [ ])
\ No newline at end of file
diff --git a/Zend/ZendTS.dsp b/Zend/ZendTS.dsp
index 21210f1..ec70e4d 100644
--- a/Zend/ZendTS.dsp
+++ b/Zend/ZendTS.dsp
@@ -148,6 +148,10 @@ SOURCE=.\zend_API.c
# End Source File
# Begin Source File
+SOURCE=.\zend_bigint.c
+# End Source File
+# Begin Source File
+
SOURCE=.\zend_builtin_functions.c
# End Source File
# Begin Source File
diff --git a/Zend/zend.c b/Zend/zend.c
index a1ffb5f..af6ab57 100644
--- a/Zend/zend.c
+++ b/Zend/zend.c
@@ -31,6 +31,7 @@
#include "zend_vm.h"
#include "zend_dtrace.h"
#include "zend_virtual_cwd.h"
+#include "zend_bigint.h"
#ifdef ZTS
# define GLOBAL_FUNCTION_TABLE global_function_table
@@ -277,6 +278,9 @@ again:
ZVAL_EMPTY_STRING(expr_copy);
}
break;
+ case IS_BIGINT:
+ ZVAL_NEW_STR(expr_copy, zend_bigint_to_zend_string(Z_BIG_P(expr), 0));
+ break;
case IS_DOUBLE:
ZVAL_DUP(expr_copy, expr);
zend_locale_sprintf_double(expr_copy ZEND_FILE_LINE_CC);
@@ -661,6 +665,7 @@ int zend_startup(zend_utility_functions *utility_functions, char **extensions TS
#endif
zend_startup_strtod();
+ zend_startup_bigint();
zend_startup_extensions_mechanism();
/* Set up utility functions and values */
diff --git a/Zend/zend.h b/Zend/zend.h
index c346c02..1c4904a 100644
--- a/Zend/zend.h
+++ b/Zend/zend.h
@@ -301,6 +301,7 @@ void zend_error_noreturn(int type, const char *format, ...) __attribute__ ((nore
#include "zend_object_handlers.h"
#include "zend_ast.h"
+#include "zend_bigint.h"
/* overloaded elements data types */
#define OE_IS_ARRAY (1<<0)
diff --git a/Zend/zend_API.c b/Zend/zend_API.c
index 33f1fc6..014bc0b 100644
--- a/Zend/zend_API.c
+++ b/Zend/zend_API.c
@@ -27,6 +27,7 @@
#include "zend_constants.h"
#include "zend_exceptions.h"
#include "zend_closures.h"
+#include "zend_bigint.h"
#ifdef HAVE_STDARG_H
#include <stdarg.h>
@@ -205,6 +206,7 @@ ZEND_API char *zend_get_type_by_const(int type) /* {{{ */
case IS_TRUE:
return "boolean";
case IS_LONG:
+ case IS_BIGINT:
return "integer";
case IS_DOUBLE:
return "double";
@@ -408,10 +410,12 @@ static const char *zend_parse_arg_impl(int arg_num, zval *arg, va_list *va, cons
break;
}
}
+
case IS_NULL:
case IS_FALSE:
case IS_TRUE:
case IS_LONG:
+ case IS_BIGINT:
convert_to_long_ex(arg);
*p = Z_LVAL_P(arg);
break;
@@ -453,6 +457,7 @@ static const char *zend_parse_arg_impl(int arg_num, zval *arg, va_list *va, cons
case IS_TRUE:
case IS_LONG:
case IS_DOUBLE:
+ case IS_BIGINT:
convert_to_double_ex(arg);
*p = Z_DVAL_P(arg);
break;
@@ -482,6 +487,7 @@ static const char *zend_parse_arg_impl(int arg_num, zval *arg, va_list *va, cons
case IS_LONG:
case IS_DOUBLE:
+ case IS_BIGINT:
case IS_FALSE:
case IS_TRUE:
convert_to_string_ex(arg);
@@ -523,6 +529,7 @@ static const char *zend_parse_arg_impl(int arg_num, zval *arg, va_list *va, cons
case IS_LONG:
case IS_DOUBLE:
+ case IS_BIGINT:
case IS_FALSE:
case IS_TRUE:
convert_to_string_ex(arg);
@@ -563,6 +570,7 @@ static const char *zend_parse_arg_impl(int arg_num, zval *arg, va_list *va, cons
case IS_STRING:
case IS_LONG:
case IS_DOUBLE:
+ case IS_BIGINT:
case IS_FALSE:
case IS_TRUE:
convert_to_boolean_ex(arg);
@@ -1632,6 +1640,13 @@ ZEND_API int array_set_zval_key(HashTable *ht, zval *key, zval *value TSRMLS_DC)
case IS_NULL:
result = zend_symtable_update(ht, STR_EMPTY_ALLOC(), value);
break;
+ case IS_BIGINT:
+ {
+ char *temp = zend_bigint_to_string(Z_BIG_P(key));
+ zend_symtable_str_update(ht, temp, strlen(temp), value);
+ efree(temp);
+ }
+ break;
case IS_RESOURCE:
zend_error(E_STRICT, "Resource ID#%ld used as offset, casting to integer (%ld)", Z_RES_HANDLE_P(key), Z_RES_HANDLE_P(key));
result = zend_hash_index_update(ht, Z_RES_HANDLE_P(key), value);
@@ -3984,6 +3999,7 @@ static int same_zval(zval *zv1, zval *zv2) /* {{{ */
return Z_LVAL_P(zv1) == Z_LVAL_P(zv2);
case IS_DOUBLE:
return Z_LVAL_P(zv1) == Z_LVAL_P(zv2);
+ case IS_BIGINT:
case IS_STRING:
case IS_ARRAY:
case IS_OBJECT:
diff --git a/Zend/zend_ast.c b/Zend/zend_ast.c
index 7a9547b..580c8f3 100644
--- a/Zend/zend_ast.c
+++ b/Zend/zend_ast.c
@@ -22,6 +22,7 @@
#include "zend_ast.h"
#include "zend_API.h"
#include "zend_operators.h"
+#include "zend_bigint.h"
ZEND_API zend_ast *zend_ast_create_constant(zval *zv)
{
@@ -112,6 +113,13 @@ static void zend_ast_add_array_element(zval *result, zval *offset, zval *expr TS
//???
zval_dtor(offset);
break;
+ case IS_BIGINT:
+ {
+ char *temp = zend_bigint_to_string(Z_BIG_P(offset));
+ zend_symtable_str_update(Z_ARRVAL_P(result), temp, strlen(temp), expr);
+ efree(temp);
+ }
+ break;
case IS_NULL:
zend_symtable_update(Z_ARRVAL_P(result), STR_EMPTY_ALLOC(), expr);
break;
diff --git a/Zend/zend_bigint.c b/Zend/zend_bigint.c
new file mode 100644
index 0000000..684e9ae
--- /dev/null
+++ b/Zend/zend_bigint.c
@@ -0,0 +1,480 @@
+/*
+ +----------------------------------------------------------------------+
+ | Zend Big Integer Support |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 2014 The PHP Group |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 3.01 of the PHP license, |
+ | that is bundled with this package in the file LICENSE, and is |
+ | available through the world-wide-web at the following url: |
+ | http://www.php.net/license/3_01.txt |
+ | If you did not receive a copy of the PHP license and are unable to |
+ | obtain it through the world-wide-web, please send a note to |
+ | license@php.net so we can mail you a copy immediately. |
+ +----------------------------------------------------------------------+
+ | Authors: Andrea Faulds <ajf@ajf.me> |
+ +----------------------------------------------------------------------+
+*/
+
+/* $Id$ */
+
+#include <ctype.h>
+#include <limits.h>
+#include <gmp.h>
+
+#include "zend.h"
+#include "zend_types.h"
+#include "zend_bigint.h"
+#include "zend_string.h"
+
+/*** INTERNAL MACROS ***/
+
+#define WITH_TEMP_MPZ_FROM_LONG(long, temp, codeblock) { \
+ mpz_t temp; \
+ mpz_init(temp); \
+ mpz_set_si(temp, long); \
+ codeblock \
+ mpz_clear(temp); \
+}
+
+/*** INTERNAL FUNCTIONS ***/
+
+/* emalloc/realloc/free are macros, not functions, so we make them functions */
+static void* gmp_emalloc(size_t size)
+{
+ return emalloc(size);
+}
+static void* gmp_erealloc(void *ptr, size_t old_size, size_t new_size)
+{
+ return erealloc(ptr, new_size);
+}
+static void gmp_efree(void *ptr, size_t size)
+{
+ efree(ptr);
+}
+
+/* Called by zend_startup */
+void zend_startup_bigint(void)
+{
+ mp_set_memory_functions(gmp_emalloc, gmp_erealloc, gmp_efree);
+}
+
+/*** INITIALISERS ***/
+
+/* Initialises a bigint
+ * HERE BE DRAGONS: Memory allocated internally by gmp is non-persistent */
+ZEND_API void zend_bigint_init(zend_bigint *big)
+{
+ GC_REFCOUNT(big) = 1;
+ GC_TYPE_INFO(big) = IS_BIGINT;
+ mpz_init(big->mpz);
+}
+
+/* Convenience function: Allocates non-persistently and initialises a bigint
+ * HERE BE DRAGONS: Memory allocated internally by gmp is non-persistent */
+ZEND_API zend_bigint* zend_bigint_init_alloc(void)
+{
+ zend_bigint *return_value;
+ return_value = emalloc(sizeof(zend_bigint));
+ zend_bigint_init(return_value);
+ return return_value;
+}
+
+/* Initialises a bigint from a string with the specified base (in range 2-36)
+ * Returns FAILURE on failure (if the string is not entirely numeric), else SUCCESS
+ * HERE BE DRAGONS: Memory allocated internally by gmp is non-persistent */
+ZEND_API int zend_bigint_init_from_string(zend_bigint *big, const char *str, int base)
+{
+ zend_bigint_init(big);
+ if (mpz_set_str(big->mpz, str, base) < 0) {
+ mpz_clear(big);
+ return FAILURE;
+ }
+ return SUCCESS;
+}
+
+/* Intialises a bigint from a string with the specified base (in range 2-36)
+ * If base is zero, it shall be detected from the prefix (0 for octal, 0x/X for hex, 0b/B for binary)
+ * Leading whitespace is ignored, will take as many valid characters as possible
+ * Stops at first non-valid character, or end of string
+ * This behaviour is supposed to mostly match that of strtol but is not exactly the same
+ * HERE BE DRAGONS: Memory allocated internally by gmp is non-persistent */
+ZEND_API void zend_bigint_init_from_string_tolerant(zend_bigint *big, const char *str, int base)
+{
+ zend_bigint_init(big);
+ if (mpz_set_str(big->mpz, str, base) < 0) {
+ char *temp_str = estrdup(str);
+ size_t len = strlen(temp_str);
+ /* truncate string until valid */
+ /* FIXME: Do this more performantly */
+ do {
+ temp_str[--len] = '\0';
+ if (!len) {
+ break;
+ }
+ }
+ while (mpz_set_str(big->mpz, temp_str, base) < 0);
+ efree(temp_str);
+ }
+}
+
+/* Initialises a bigint from a long */
+ZEND_API void zend_bigint_init_from_long(zend_bigint *big, long value)
+{
+ zend_bigint_init(big);
+ mpz_set_si(big->mpz, value);
+}
+
+/* Initialises a bigint from a double
+ * HERE BE DRAGONS: Memory allocated internally by gmp is non-persistent */
+ZEND_API void zend_bigint_init_from_double(zend_bigint *big, double value)
+{
+ zend_bigint_init(big);
+ mpz_set_d(big->mpz, value);
+}
+
+/* Destroys a bigint */
+ZEND_API void zend_bigint_dtor(zend_bigint *big)
+{
+ mpz_clear(big->mpz);
+}
+
+/*** INFORMATION ***/
+
+/* Returns true if bigint can fit into an unsigned long without truncation */
+ZEND_API zend_bool zend_bigint_can_fit_ulong(const zend_bigint *big)
+{
+ return mpz_fits_ulong_p(big->mpz);
+}
+
+/* Returns sign of bigint (-1 for negative, 0 for zero or 1 for positive) */
+ZEND_API int zend_bigint_sign(const zend_bigint *big)
+{
+ return mpz_sgn(big->mpz);
+}
+
+/* Returns true if bigint is divisible by a bigint */
+ZEND_API zend_bool zend_bigint_divisible(const zend_bigint *num, const zend_bigint *divisor)
+{
+ return mpz_divisible_p(num->mpz, divisor->mpz) ? 1 : 0;
+}
+
+/* Returns true if bigint is divisible by a long */
+ZEND_API zend_bool zend_bigint_divisible_long(const zend_bigint *num, long divisor)
+{
+ zend_bool return_value;
+ WITH_TEMP_MPZ_FROM_LONG(divisor, divisor_mpz, {
+ return_value = mpz_divisible_p(num->mpz, divisor_mpz) ? 1 : 0;
+ })
+ return return_value;
+}
+
+/* Returns true if long is divisible by a bigint */
+ZEND_API zend_bool zend_bigint_long_divisible(long num, const zend_bigint *divisor)
+{
+ zend_bool return_value;
+ WITH_TEMP_MPZ_FROM_LONG(num, num_mpz, {
+ return_value = mpz_divisible_p(num_mpz, divisor->mpz) ? 1 : 0;
+ })
+ return return_value;
+}
+
+/*** CONVERTORS ***/
+
+/* Converts to long; this will cap at the max value of a long */
+ZEND_API long zend_bigint_to_long(const zend_bigint *big)
+{
+ if (mpz_fits_slong_p(big->mpz)) {
+ return mpz_get_si(big->mpz);
+ } else {
+ if (mpz_sgn(big->mpz) == 1) {
+ return LONG_MAX;
+ } else {
+ return LONG_MIN;
+ }
+ }
+}
+
+/* Converts to unsigned long; this will cap at the max value of an unsigned long */
+ZEND_API unsigned long zend_bigint_to_ulong(const zend_bigint *big)
+{
+ if (mpz_fits_ulong_p(big->mpz)) {
+ return mpz_get_ui(big->mpz);
+ } else {
+ if (mpz_sgn(big->mpz) == 1) {
+ return ULONG_MAX;
+ } else {
+ return 0;
+ }
+ }
+}
+
+/* Converts to bool */
+ZEND_API zend_bool zend_bigint_to_bool(const zend_bigint *big)
+{
+ return mpz_sgn(big->mpz) ? 1 : 0;
+}
+
+/* Converts to double; this will lose precision beyond a certain point */
+ZEND_API double zend_bigint_to_double(const zend_bigint *big)
+{
+ return mpz_get_d(big->mpz);
+}
+
+/* Converts to decimal C string
+ * HERE BE DRAGONS: String allocated is non-persistent */
+ZEND_API char* zend_bigint_to_string(const zend_bigint *big)
+{
+ return mpz_get_str(NULL, 10, big->mpz);
+}
+
+/* Convenience function: Converts to zend string */
+ZEND_API zend_string* zend_bigint_to_zend_string(const zend_bigint *big, int persistent)
+{
+ char *temp_string = zend_bigint_to_string(big);
+ zend_string *return_value = STR_INIT(temp_string, strlen(temp_string), persistent);
+ efree(temp_string);
+ return return_value;
+}
+
+/* Converts to C string of arbitrary base */
+ZEND_API char* zend_bigint_to_string_base(const zend_bigint *big, int base)
+{
+ return mpz_get_str(NULL, base, big->mpz);
+}
+
+/*** OPERATIONS **/
+
+/* Adds two bigints and stores result in out */
+ZEND_API void zend_bigint_add(zend_bigint *out, const zend_bigint *op1, const zend_bigint *op2)
+{
+ mpz_add(out->mpz, op1->mpz, op2->mpz);
+}
+
+/* Adds a bigint and a long and stores result in out */
+ZEND_API void zend_bigint_add_long(zend_bigint *out, const zend_bigint *op1, long op2)
+{
+ WITH_TEMP_MPZ_FROM_LONG(op2, op2_mpz, {
+ mpz_add(out->mpz, op1->mpz, op2_mpz);
+ })
+}
+
+/* Adds a long and a long and stores result in out */
+ZEND_API void zend_bigint_long_add_long(zend_bigint *out, long op1, long op2)
+{
+ WITH_TEMP_MPZ_FROM_LONG(op1, op1_mpz, WITH_TEMP_MPZ_FROM_LONG(op2, op2_mpz, {
+ mpz_add(out->mpz, op1_mpz, op2_mpz);
+ }))
+}
+
+/* Subtracts two bigints and stores result in out */
+ZEND_API void zend_bigint_subtract(zend_bigint *out, const zend_bigint *op1, const zend_bigint *op2)
+{
+ mpz_sub(out->mpz, op1->mpz, op2->mpz);
+}
+
+/* Subtracts a bigint and a long and stores result in out */
+ZEND_API void zend_bigint_subtract_long(zend_bigint *out, const zend_bigint *op1, long op2)
+{
+ WITH_TEMP_MPZ_FROM_LONG(op2, op2_mpz, {
+ mpz_sub(out->mpz, op1->mpz, op2_mpz);
+ })
+}
+
+/* Subtracts a long and a long and stores result in out */
+ZEND_API void zend_bigint_long_subtract_long(zend_bigint *out, long op1, long op2)
+{
+ WITH_TEMP_MPZ_FROM_LONG(op1, op1_mpz, WITH_TEMP_MPZ_FROM_LONG(op2, op2_mpz, {
+ mpz_sub(out->mpz, op1_mpz, op2_mpz);
+ }))
+}
+
+/* Subtracts a long and a bigint and stores result in out */
+ZEND_API void zend_bigint_long_subtract(zend_bigint *out, long op1, const zend_bigint *op2)
+{
+ WITH_TEMP_MPZ_FROM_LONG(op1, op1_mpz, {
+ mpz_sub(out->mpz, op1_mpz, op2->mpz);
+ })
+}
+
+/* Multiplies two bigints and stores result in out */
+ZEND_API void zend_bigint_multiply(zend_bigint *out, const zend_bigint *op1, const zend_bigint *op2)
+{
+ mpz_mul(out->mpz, op1->mpz, op2->mpz);
+}
+
+/* Multiplies a bigint and a long and stores result in out */
+ZEND_API void zend_bigint_multiply_long(zend_bigint *out, const zend_bigint *op1, long op2)
+{
+ WITH_TEMP_MPZ_FROM_LONG(op2, op2_mpz, {
+ mpz_mul(out->mpz, op1->mpz, op2_mpz);
+ })
+}
+
+/* Multiplies a long and a long and stores result in out */
+ZEND_API void zend_bigint_long_multiply_long(zend_bigint *out, long op1, long op2)
+{
+ WITH_TEMP_MPZ_FROM_LONG(op1, op1_mpz, WITH_TEMP_MPZ_FROM_LONG(op2, op2_mpz, {
+ mpz_mul(out->mpz, op1_mpz, op2_mpz);
+ }))
+}
+
+/* Raises a bigint base to an unsigned long power and stores result in out */
+ZEND_API void zend_bigint_pow_ulong(zend_bigint *out, const zend_bigint *base, unsigned long power)
+{
+ mpz_pow_ui(out->mpz, base->mpz, power);
+}
+
+/* Raises a long base to an unsigned long power and stores result in out */
+ZEND_API void zend_bigint_long_pow_ulong(zend_bigint *out, long base, unsigned long power)
+{
+ WITH_TEMP_MPZ_FROM_LONG(base, base_mpz, {
+ mpz_pow_ui(out->mpz, base_mpz, power);
+ })
+}
+
+/* Divides a bigint by a bigint and stores result in out */
+ZEND_API void zend_bigint_divide(zend_bigint *out, const zend_bigint *num, const zend_bigint *divisor)
+{
+ mpz_fdiv_q(out->mpz, num->mpz, divisor->mpz);
+}
+
+/* Divides a bigint by a long and stores result in out */
+ZEND_API void zend_bigint_divide_long(zend_bigint *out, const zend_bigint *num, long divisor)
+{
+ WITH_TEMP_MPZ_FROM_LONG(divisor, divisor_mpz, {
+ mpz_fdiv_q(out->mpz, num->mpz, divisor_mpz);
+ })
+}
+
+/* Divides a long by a bigint and stores result in out */
+ZEND_API void zend_bigint_long_divide(zend_bigint *out, long num, const zend_bigint *divisor)
+{
+ WITH_TEMP_MPZ_FROM_LONG(num, num_mpz, {
+ mpz_fdiv_q(out->mpz, num_mpz, divisor->mpz);
+ })
+}
+
+/* Finds the remainder of the division of a bigint by a bigint and stores result in out */
+ZEND_API void zend_bigint_modulus(zend_bigint *out, const zend_bigint *num, const zend_bigint *divisor)
+{
+ mpz_fdiv_r(out->mpz, num->mpz, divisor->mpz);
+}
+
+/* Finds the remainder of the division of a bigint by a long and stores result in out */
+ZEND_API void zend_bigint_modulus_long(zend_bigint *out, const zend_bigint *num, long divisor)
+{
+ WITH_TEMP_MPZ_FROM_LONG(divisor, divisor_mpz, {
+ mpz_fdiv_r(out->mpz, num->mpz, divisor_mpz);
+ )}
+}
+
+/* Finds the remainder of the division of a long by a bigint and stores result in out */
+ZEND_API void zend_bigint_long_modulus(zend_bigint *out, long num, const zend_bigint *divisor)
+{
+ WITH_TEMP_MPZ_FROM_LONG(num, num_mpz, {
+ mpz_fdiv_r(out->mpz, num_mpz, divisor->mpz);
+ )}
+}
+
+/* Finds the one's complement of a bigint and stores result in out */
+ZEND_API void zend_bigint_ones_complement(zend_bigint *out, const zend_bigint *op)
+{
+ mpz_com(out->mpz, op->mpz);
+}
+
+/* Finds the bitwise OR of a bigint and a bigint and stores result in out */
+ZEND_API void zend_bigint_or(zend_bigint *out, const zend_bigint *op1, const zend_bigint *op2)
+{
+ mpz_ior(out->mpz, op1->mpz, op2->mpz);
+}
+
+/* Finds the bitwise OR of a bigint and a long and stores result in out */
+ZEND_API void zend_bigint_or_long(zend_bigint *out, const zend_bigint *op1, long op2)
+{
+ WITH_TEMP_MPZ_FROM_LONG(op2, op2_mpz, {
+ mpz_ior(out->mpz, op1->mpz, op2_mpz);
+ })
+}
+
+/* Finds the bitwise OR of a long and a bigint and stores result in out */
+ZEND_API void zend_bigint_long_or(zend_bigint *out, long op1, const zend_bigint *op2)
+{
+ WITH_TEMP_MPZ_FROM_LONG(op1, op1_mpz, {
+ mpz_ior(out->mpz, op1_mpz, op2->mpz);
+ })
+}
+
+/* Finds the bitwise AND of a bigint and a bigint and stores result in out */
+ZEND_API void zend_bigint_and(zend_bigint *out, const zend_bigint *op1, const zend_bigint *op2)
+{
+ mpz_and(out->mpz, op1->mpz, op2->mpz);
+}
+
+/* Finds the bitwise AND of a bigint and a long and stores result in out */
+ZEND_API void zend_bigint_and_long(zend_bigint *out, const zend_bigint *op1, long op2)
+{
+ WITH_TEMP_MPZ_FROM_LONG(op2, op2_mpz, {
+ mpz_and(out->mpz, op1->mpz, op2_mpz);
+ })
+}
+
+/* Finds the bitwise AND of a long and a bigint and stores result in out */
+ZEND_API void zend_bigint_long_and(zend_bigint *out, long op1, const zend_bigint *op2)
+{
+ WITH_TEMP_MPZ_FROM_LONG(op1, op1_mpz, {
+ mpz_and(out->mpz, op1_mpz, op2->mpz);
+ })
+}
+
+/* Finds the bitwise XOR of a bigint and a bigint and stores result in out */
+ZEND_API void zend_bigint_xor(zend_bigint *out, const zend_bigint *op1, const zend_bigint *op2)
+{
+ mpz_xor(out->mpz, op1->mpz, op2->mpz);
+}
+
+/* Finds the bitwise XOR of a bigint and a long and stores result in out */
+ZEND_API void zend_bigint_xor_long(zend_bigint *out, const zend_bigint *op1, long op2)
+{
+ WITH_TEMP_MPZ_FROM_LONG(op2, op2_mpz, {
+ mpz_xor(out->mpz, op1->mpz, op2_mpz);
+ })
+}
+
+/* Finds the bitwise XOR of a long and a bigint and stores result in out */
+ZEND_API void zend_bigint_long_xor(zend_bigint *out, long op1, const zend_bigint *op2)
+{
+ WITH_TEMP_MPZ_FROM_LONG(op1, op1_mpz, {
+ mpz_xor(out->mpz, op1_mpz, op2->mpz);
+ })
+}
+
+/* Shifts a bigint left by an unsigned long and stores result in out */
+ZEND_API void zend_bigint_shift_left_ulong(zend_bigint *out, const zend_bigint *num, unsigned long shift)
+{
+ mpz_mul_2exp(out->mpz, num->mpz, shift);
+}
+
+/* Shifts a bigint right by an unsigned long and stores result in out */
+ZEND_API void zend_bigint_shift_right_ulong(zend_bigint *out, const zend_bigint *num, unsigned long shift)
+{
+ mpz_fdiv_q_2exp(out->mpz, num->mpz, shift);
+}
+
+/* Compares a bigint and a bigint and returns result (negative if op1 > op2, zero if op1 == op2, positive if op1 < op2) */
+ZEND_API int zend_bigint_cmp(const zend_bigint *op1, const zend_bigint *op2)
+{
+ return mpz_cmp(op1->mpz, op2->mpz);
+}
+
+/* Compares a bigint and a long and returns result (negative if op1 > op2, zero if op1 == op2, positive if op1 < op2) */
+ZEND_API int zend_bigint_cmp_long(const zend_bigint *op1, long op2)
+{
+ return mpz_cmp_si(op1->mpz, op2);
+}
+
+/* Compares a bigint and a double and returns result (negative if op1 > op2, zero if op1 == op2, positive if op1 < op2) */
+ZEND_API int zend_bigint_cmp_double(const zend_bigint *op1, double op2)
+{
+ return mpz_cmp_d(op1->mpz, op2);
+}
\ No newline at end of file
diff --git a/Zend/zend_bigint.h b/Zend/zend_bigint.h
new file mode 100644
index 0000000..2eec8fa
--- /dev/null
+++ b/Zend/zend_bigint.h
@@ -0,0 +1,213 @@
+/*
+ +----------------------------------------------------------------------+
+ | Zend Big Integer Support |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 2014 The PHP Group |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 3.01 of the PHP license, |
+ | that is bundled with this package in the file LICENSE, and is |
+ | available through the world-wide-web at the following url: |
+ | http://www.php.net/license/3_01.txt |
+ | If you did not receive a copy of the PHP license and are unable to |
+ | obtain it through the world-wide-web, please send a note to |
+ | license@php.net so we can mail you a copy immediately. |
+ +----------------------------------------------------------------------+
+ | Authors: Andrea Faulds <ajf@ajf.me> |
+ +----------------------------------------------------------------------+
+*/
+
+/* $Id$ */
+
+#ifndef ZEND_BIGINT_H
+#define ZEND_BIGINT_H
+
+#include <gmp.h>
+
+#include "zend.h"
+#include "zend_types.h"
+
+/*** INTERNAL FUNCTIONS ***/
+
+/* Called by zend_startup */
+void zend_startup_bigint(void);
+
+/*** INITIALISERS ***/
+
+/* Initialises a bigint
+ * HERE BE DRAGONS: Memory allocated internally by gmp is non-persistent */
+ZEND_API void zend_bigint_init(zend_bigint *big);
+
+/* Convenience function: Allocates non-persistently and initialises a bigint
+ * HERE BE DRAGONS: Memory allocated internally by gmp is non-persistent */
+ZEND_API zend_bigint* zend_bigint_init_alloc(void);
+
+/* Initialises a bigint from a string with the specified base (in range 2-36)
+ * Returns FAILURE on failure, else SUCCESS
+ * HERE BE DRAGONS: Memory allocated internally by gmp is non-persistent */
+ZEND_API int zend_bigint_init_from_string(zend_bigint *big, const char *str, int base);
+
+/* Intialises a bigint from a string with the specified base (in range 2-36)
+ * If base is zero, it shall be detected from the prefix (0 for octal, 0x/X for hex, 0b/B for binary)
+ * Leading whitespace is ignored, will take as many valid characters as possible
+ * Stops at first non-valid character, or end of string
+ * This behaviour is supposed to mostly match that of strtol but is not exactly the same
+ * HERE BE DRAGONS: Memory allocated internally by gmp is non-persistent */
+ZEND_API void zend_bigint_init_from_string_tolerant(zend_bigint *big, const char *str, int base);
+
+/* Initialises a bigint from a long
+ * HERE BE DRAGONS: Memory allocated internally by gmp is non-persistent */
+ZEND_API void zend_bigint_init_from_long(zend_bigint *big, long value);
+
+/* Initialises a bigint from a double
+ * HERE BE DRAGONS: Memory allocated internally by gmp is non-persistent */
+ZEND_API void zend_bigint_init_from_double(zend_bigint *big, double value);
+
+/* Destroys a bigint */
+ZEND_API void zend_bigint_dtor(zend_bigint *big);
+
+/*** INFORMATION ***/
+
+/* Returns true if bigint can fit into an unsigned long without truncation */
+ZEND_API zend_bool zend_bigint_can_fit_ulong(const zend_bigint *big);
+
+/* Returns sign of bigint (-1 for negative, 0 for zero or 1 for positive) */
+ZEND_API int zend_bigint_sign(const zend_bigint *big);
+
+/* Returns true if bigint is divisible by a bigint */
+ZEND_API zend_bool zend_bigint_divisible(const zend_bigint *num, const zend_bigint *divisor);
+
+/* Returns true if bigint is divisible by a long */
+ZEND_API zend_bool zend_bigint_divisible_long(const zend_bigint *num, long divisor);
+
+/* Returns true if long is divisible by a bigint */
+ZEND_API zend_bool zend_bigint_long_divisible(long num, const zend_bigint *divisor);
+
+/*** CONVERTORS ***/
+
+/* Converts to long; this will cap at the max value of a long */
+ZEND_API long zend_bigint_to_long(const zend_bigint *big);
+
+/* Converts to unsigned long; this will cap at the max value of an unsigned long */
+ZEND_API unsigned long zend_bigint_to_ulong(const zend_bigint *big);
+
+/* Converts to bool */
+ZEND_API zend_bool zend_bigint_to_bool(const zend_bigint *big);
+
+/* Converts to double; this will lose precision beyond a certain point */
+ZEND_API double zend_bigint_to_double(const zend_bigint *big);
+
+/* Converts to decimal C string
+ * HERE BE DRAGONS: String allocated is non-persistent */
+ZEND_API char* zend_bigint_to_string(const zend_bigint *big);
+
+/* Convenience function: Converts to zend string */
+ZEND_API zend_string* zend_bigint_to_zend_string(const zend_bigint *big, int persistent);
+
+/* Converts to C string of arbitrary base */
+ZEND_API char* zend_bigint_to_string_base(const zend_bigint *big, int base);
+
+/*** OPERATIONS **/
+
+/* Adds two bigints and stores result in out */
+ZEND_API void zend_bigint_add(zend_bigint *out, const zend_bigint *op1, const zend_bigint *op2);
+
+/* Adds a bigint and a long and stores result in out */
+ZEND_API void zend_bigint_add_long(zend_bigint *out, const zend_bigint *op1, long op2);
+
+/* Adds a long and a long and stores result in out */
+ZEND_API void zend_bigint_long_add_long(zend_bigint *out, long op1, long op2);
+
+/* Subtracts two bigints and stores result in out */
+ZEND_API void zend_bigint_subtract(zend_bigint *out, const zend_bigint *op1, const zend_bigint *op2);
+
+/* Subtracts a bigint and a long and stores result in out */
+ZEND_API void zend_bigint_subtract_long(zend_bigint *out, const zend_bigint *op1, long op2);
+
+/* Subtracts a long and a long and stores result in out */
+ZEND_API void zend_long_subtract_long(zend_bigint *out, long op1, long op2);
+
+/* Subtracts a long and a bigint and stores result in out */
+ZEND_API void zend_bigint_long_subtract(zend_bigint *out, long op1, const zend_bigint *op2);
+
+/* Subtracts a long and a long and stores result in out */
+ZEND_API void zend_bigint_long_subtract_long(zend_bigint *out, long op1, long op2);
+
+/* Multiplies two bigints and stores result in out */
+ZEND_API void zend_bigint_multiply(zend_bigint *out, const zend_bigint *op1, const zend_bigint *op2);
+
+/* Multiplies a bigint and a long and stores result in out */
+ZEND_API void zend_bigint_multiply_long(zend_bigint *out, const zend_bigint *op1, long op2);
+
+/* Multiplies a long and a long and stores result in out */
+ZEND_API void zend_bigint_long_multiply_long(zend_bigint *out, long op1, long op2);
+
+/* Raises a bigint base to an unsigned long power and stores result in out */
+ZEND_API void zend_bigint_pow_ulong(zend_bigint *out, const zend_bigint *base, unsigned long power);
+
+/* Raises a long base to an unsigned long power and stores result in out */
+ZEND_API void zend_bigint_long_pow_ulong(zend_bigint *out, long base, unsigned long power);
+
+/* Divides a bigint by a bigint and stores result in out */
+ZEND_API void zend_bigint_divide(zend_bigint *out, const zend_bigint *big, const zend_bigint *divisor);
+
+/* Divides a bigint by a long and stores result in out */
+ZEND_API void zend_bigint_divide_long(zend_bigint *out, const zend_bigint *big, long divisor);
+
+/* Divides a long by a bigint and stores result in out */
+ZEND_API void zend_bigint_long_divide(zend_bigint *out, long big, const zend_bigint *divisor);
+
+/* Finds the remainder of the division of a bigint by a bigint and stores result in out */
+ZEND_API void zend_bigint_modulus(zend_bigint *out, const zend_bigint *num, const zend_bigint *divisor);
+
+/* Finds the remainder of the division of a bigint by a long and stores result in out */
+ZEND_API void zend_bigint_modulus_long(zend_bigint *out, const zend_bigint *num, long divisor);
+
+/* Finds the remainder of the division of a long by a bigint and stores result in out */
+ZEND_API void zend_bigint_long_modulus(zend_bigint *out, long num, const zend_bigint *divisor);
+
+/* Finds the one's complement of a bigint and stores result in out */
+ZEND_API void zend_bigint_ones_complement(zend_bigint *out, const zend_bigint *op);
+
+/* Finds the bitwise OR of a bigint and a bigint and stores result in out */
+ZEND_API void zend_bigint_or(zend_bigint *out, const zend_bigint *op1, const zend_bigint *op2);
+
+/* Finds the bitwise OR of a bigint and a long and stores result in out */
+ZEND_API void zend_bigint_or_long(zend_bigint *out, const zend_bigint *op1, long op2);
+
+/* Finds the bitwise OR of a long and a bigint and stores result in out */
+ZEND_API void zend_bigint_long_or(zend_bigint *out, long op1, const zend_bigint *op2);
+
+/* Finds the bitwise AND of a bigint and a bigint and stores result in out */
+ZEND_API void zend_bigint_and(zend_bigint *out, const zend_bigint *op1, const zend_bigint *op2);
+
+/* Finds the bitwise AND of a bigint and a long and stores result in out */
+ZEND_API void zend_bigint_and_long(zend_bigint *out, const zend_bigint *op1, long op2);
+
+/* Finds the bitwise AND of a long and a bigint and stores result in out */
+ZEND_API void zend_bigint_long_and(zend_bigint *out, long op1, const zend_bigint *op2);
+
+/* Finds the bitwise XOR of a bigint and a bigint and stores result in out */
+ZEND_API void zend_bigint_xor(zend_bigint *out, const zend_bigint *op1, const zend_bigint *op2);
+
+/* Finds the bitwise XOR of a bigint and a long and stores result in out */
+ZEND_API void zend_bigint_xor_long(zend_bigint *out, const zend_bigint *op1, long op2);
+
+/* Finds the bitwise XOR of a long and a bigint and stores result in out */
+ZEND_API void zend_bigint_long_xor(zend_bigint *out, long op1, const zend_bigint *op2);
+
+/* Shifts a bigint left by an unsigned long and stores result in out */
+ZEND_API void zend_bigint_shift_left_ulong(zend_bigint *out, const zend_bigint *num, unsigned long shift);
+
+/* Shifts a bigint right by an unsigned long and stores result in out */
+ZEND_API void zend_bigint_shift_right_ulong(zend_bigint *out, const zend_bigint *num, unsigned long shift);
+
+/* Compares a bigint and a bigint and returns result (negative if op1 > op2, zero if op1 == op2, positive if op1 < op2) */
+ZEND_API int zend_bigint_cmp(const zend_bigint *op1, const zend_bigint *op2);
+
+/* Compares a bigint and a long and returns result (negative if op1 > op2, zero if op1 == op2, positive if op1 < op2) */
+ZEND_API int zend_bigint_cmp_long(const zend_bigint *op1, long op2);
+
+/* Compares a bigint and a double and returns result (negative if op1 > op2, zero if op1 == op2, positive if op1 < op2) */
+ZEND_API int zend_bigint_cmp_double(const zend_bigint *op1, double op2);
+
+#endif
\ No newline at end of file
diff --git a/Zend/zend_builtin_functions.c b/Zend/zend_builtin_functions.c
index f8f6a43..57f257a 100644
--- a/Zend/zend_builtin_functions.c
+++ b/Zend/zend_builtin_functions.c
@@ -27,6 +27,7 @@
#include "zend_exceptions.h"
#include "zend_extensions.h"
#include "zend_closures.h"
+#include "zend_bigint.h"
#undef ZEND_TEST_EXCEPTIONS
@@ -690,6 +691,7 @@ repeat:
switch (Z_TYPE_P(val)) {
case IS_LONG:
case IS_DOUBLE:
+ case IS_BIGINT:
case IS_STRING:
case IS_FALSE:
case IS_TRUE:
diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c
index c84937b..7d9676c 100644
--- a/Zend/zend_compile.c
+++ b/Zend/zend_compile.c
@@ -29,6 +29,8 @@
#include "zend_virtual_cwd.h"
#include "zend_multibyte.h"
#include "zend_language_scanner.h"
+#include "zend_string.h"
+#include "zend_bigint.h"
#define CONSTANT_EX(op_array, op) \
(op_array)->literals[op]
@@ -4968,7 +4970,8 @@ void zend_do_brk_cont(zend_uchar op, znode *expr TSRMLS_DC) /* {{{ */
if (expr) {
if (expr->op_type != IS_CONST) {
zend_error_noreturn(E_COMPILE_ERROR, "'%s' operator with non-constant operand is no longer supported", op == ZEND_BRK ? "break" : "continue");
- } else if (Z_TYPE(expr->u.constant) != IS_LONG || Z_LVAL(expr->u.constant) < 1) {
+ } else if (!((Z_TYPE(expr->u.constant) == IS_LONG && Z_LVAL(expr->u.constant) > 1)
+ || (Z_TYPE(expr->u.constant) == IS_BIGINT && zend_bigint_sign(Z_BIG(expr->u.constant)) == 1))) {
zend_error_noreturn(E_COMPILE_ERROR, "'%s' operator accepts only positive numbers", op == ZEND_BRK ? "break" : "continue");
}
SET_NODE(opline->op2, expr);
@@ -5985,6 +5988,9 @@ str_index:
case IS_DOUBLE:
num = zend_dval_to_lval(Z_DVAL(CONSTANT(opline->op2.constant)));
goto num_index;
+ case IS_BIGINT:
+ constant_array = 0;
+ break;
case IS_FALSE:
num = 0;
goto num_index;
diff --git a/Zend/zend_exceptions.c b/Zend/zend_exceptions.c
index a8e57c9..9da0954 100644
--- a/Zend/zend_exceptions.c
+++ b/Zend/zend_exceptions.c
@@ -28,6 +28,7 @@
#include "zend_exceptions.h"
#include "zend_vm.h"
#include "zend_dtrace.h"
+#include "zend_bigint.h"
static zend_class_entry *default_exception_ce;
static zend_class_entry *error_exception_ce;
@@ -493,6 +494,13 @@ static void _build_trace_args(zval *arg, zend_string **str_ptr TSRMLS_DC) /* {{{
TRACE_APPEND_STR(", ");
break;
}
+ case IS_BIGINT: {
+ char *s_tmp = zend_bigint_to_string(Z_BIG_P(arg));
+ TRACE_APPEND_STRL(s_tmp, strlen(s_tmp));
+ efree(s_tmp);
+ TRACE_APPEND_STR(", ");
+ break;
+ }
case IS_ARRAY:
TRACE_APPEND_STR("Array, ");
break;
diff --git a/Zend/zend_execute.c b/Zend/zend_execute.c
index 95028ff..a99def9 100644
--- a/Zend/zend_execute.c
+++ b/Zend/zend_execute.c
@@ -985,6 +985,7 @@ static zend_always_inline zval *zend_fetch_dimension_address_inner(HashTable *ht
zval *retval;
zend_string *offset_key;
ulong hval;
+ zend_bool key_needs_release = 0;
if (EXPECTED(Z_TYPE_P(dim) == IS_LONG)) {
hval = Z_LVAL_P(dim);
@@ -1055,6 +1056,10 @@ str_index:
break;
}
}
+ if (key_needs_release)
+ {
+ STR_RELEASE(offset_key);
+ }
} else {
switch (Z_TYPE_P(dim)) {
case IS_NULL:
@@ -1063,6 +1068,10 @@ str_index:
case IS_DOUBLE:
hval = zend_dval_to_lval(Z_DVAL_P(dim));
goto num_index;
+ case IS_BIGINT:
+ offset_key = zend_bigint_to_zend_string(Z_BIG_P(dim), 0);
+ key_needs_release = 1;
+ goto str_index;
case IS_RESOURCE:
zend_error(E_STRICT, "Resource ID#%ld used as offset, casting to integer (%ld)", Z_RES_HANDLE_P(dim), Z_RES_HANDLE_P(dim));
hval = Z_RES_HANDLE_P(dim);
diff --git a/Zend/zend_execute.h b/Zend/zend_execute.h
index 623d3a8..9605e4c 100644
--- a/Zend/zend_execute.h
+++ b/Zend/zend_execute.h
@@ -26,6 +26,7 @@
#include "zend_hash.h"
#include "zend_operators.h"
#include "zend_variables.h"
+#include "zend_bigint.h"
BEGIN_EXTERN_C()
struct _zend_fcall_info;
@@ -95,6 +96,9 @@ again:
case IS_DOUBLE:
result = (Z_DVAL_P(op) ? 1 : 0);
break;
+ case IS_BIGINT:
+ result = zend_bigint_to_bool(Z_BIG_P(op));
+ break;
case IS_STRING:
if (Z_STRLEN_P(op) == 0
|| (Z_STRLEN_P(op)==1 && Z_STRVAL_P(op)[0]=='0')) {
diff --git a/Zend/zend_language_scanner.l b/Zend/zend_language_scanner.l
index b510086..ca0ad6c 100644
--- a/Zend/zend_language_scanner.l
+++ b/Zend/zend_language_scanner.l
@@ -48,6 +48,7 @@
#include "zend_strtod.h"
#include "zend_exceptions.h"
#include "zend_virtual_cwd.h"
+#include "zend_bigint.h"
#include "tsrm_config_common.h"
#define YYCTYPE unsigned char
@@ -1527,11 +1528,13 @@ NEWLINE ("\r"|"\n"|"\r\n")
} else {
ZVAL_LONG(zendlval, strtol(bin, NULL, 2));
}
- return T_LNUMBER;
} else {
- ZVAL_DOUBLE(zendlval, zend_bin_strtod(bin, NULL));
- return T_DNUMBER;
+ char *temp_str = estrndup(bin, len);
+ ZVAL_NEW_BIGINT(zendlval);
+ zend_bigint_init_from_string(Z_BIG_P(zendlval), temp_str, 2);
+ efree(temp_str);
}
+ return T_LNUMBER;
}
<ST_IN_SCRIPTING>{LNUM} {
@@ -1541,12 +1544,15 @@ NEWLINE ("\r"|"\n"|"\r\n")
errno = 0;
ZVAL_LONG(zendlval, strtol(yytext, NULL, 0));
if (errno == ERANGE) { /* Overflow */
+ char *temp_str = estrndup(yytext, yyleng);
if (yytext[0] == '0') { /* octal overflow */
- ZVAL_DOUBLE(zendlval, zend_oct_strtod(yytext, NULL));
+ ZVAL_NEW_BIGINT(zendlval);
+ zend_bigint_init_from_string(Z_BIG_P(zendlval), temp_str, 8);
} else {
- ZVAL_DOUBLE(zendlval, zend_strtod(yytext, NULL));
+ ZVAL_NEW_BIGINT(zendlval);
+ zend_bigint_init_from_string(Z_BIG_P(zendlval), temp_str, 10);
}
- return T_DNUMBER;
+ efree(temp_str);
}
}
return T_LNUMBER;
@@ -1568,11 +1574,13 @@ NEWLINE ("\r"|"\n"|"\r\n")
} else {
ZVAL_LONG(zendlval, strtol(hex, NULL, 16));
}
- return T_LNUMBER;
} else {
- ZVAL_DOUBLE(zendlval, zend_hex_strtod(hex, NULL));
- return T_DNUMBER;
+ char *temp_str = estrndup(hex, len);
+ ZVAL_NEW_BIGINT(zendlval);
+ zend_bigint_init_from_string(Z_BIG_P(zendlval), temp_str, 16);
+ efree(temp_str);
}
+ return T_DNUMBER;
}
<ST_VAR_OFFSET>[0]|([1-9][0-9]*) { /* Offset could be treated as a long */
diff --git a/Zend/zend_language_scanner_defs.h b/Zend/zend_language_scanner_defs.h
index 5926e3c..1118239 100644
--- a/Zend/zend_language_scanner_defs.h
+++ b/Zend/zend_language_scanner_defs.h
@@ -1,4 +1,4 @@
-/* Generated by re2c 0.13.5 */
+/* Generated by re2c 0.13.6 */
#line 3 "Zend/zend_language_scanner_defs.h"
enum YYCONDTYPE {
diff --git a/Zend/zend_multiply.h b/Zend/zend_multiply.h
index 74dc7d1..499359b 100644
--- a/Zend/zend_multiply.h
+++ b/Zend/zend_multiply.h
@@ -19,6 +19,11 @@
/* $Id$ */
+#include "zend_bigint.h"
+
+/* assembly commented-out as it uses the old float overflow behaviour
+* however, now longs overflow to bigints, so we can't use it */
+/*
#if defined(__i386__) && defined(__GNUC__)
#define ZEND_SIGNED_MULTIPLY_LONG(a, b, lval, dval, usedval) do { \
@@ -69,11 +74,14 @@
} while (0)
#elif SIZEOF_LONG == 4 && defined(HAVE_ZEND_LONG64)
+*/
+#if SIZEOF_LONG == 4 && defined(HAVE_ZEND_LONG64)
-#define ZEND_SIGNED_MULTIPLY_LONG(a, b, lval, dval, usedval) do { \
+#define ZEND_SIGNED_MULTIPLY_LONG(a, b, lval, big, usedval) do { \
zend_long64 __result = (zend_long64) (a) * (zend_long64) (b); \
if (__result > LONG_MAX || __result < LONG_MIN) { \
- (dval) = (double) __result; \
+ (big) = zend_bigint_init_alloc(); \
+ zend_bigint_long_multiply_long(big, a, b); \
(usedval) = 1; \
} else { \
(lval) = (long) __result; \
@@ -83,12 +91,13 @@
#else
-#define ZEND_SIGNED_MULTIPLY_LONG(a, b, lval, dval, usedval) do { \
+#define ZEND_SIGNED_MULTIPLY_LONG(a, b, lval, big, usedval) do { \
long __lres = (a) * (b); \
long double __dres = (long double)(a) * (long double)(b); \
long double __delta = (long double) __lres - __dres; \
if ( ((usedval) = (( __dres + __delta ) != __dres))) { \
- (dval) = __dres; \
+ (big) = zend_bigint_init_alloc(); \
+ zend_bigint_long_multiply_long(big, a, b); \
} else { \
(lval) = __lres; \
} \
diff --git a/Zend/zend_operators.c b/Zend/zend_operators.c
index caf5e78..d57f243 100644
--- a/Zend/zend_operators.c
+++ b/Zend/zend_operators.c
@@ -30,6 +30,7 @@
#include "zend_strtod.h"
#include "zend_exceptions.h"
#include "zend_closures.h"
+#include "zend_bigint.h"
#if ZEND_USE_TOLOWER_L
#include <locale.h>
@@ -279,6 +280,9 @@ try_again:
case IS_TRUE: \
ZVAL_LONG(&(holder), 1); \
break; \
+ case IS_BIGINT: \
+ ZVAL_LONG(&holder, zend_bigint_to_long(Z_BIG_P(op)));\
+ break; \
case IS_DOUBLE: \
ZVAL_LONG(&holder, zend_dval_to_lval(Z_DVAL_P(op)));\
break; \
@@ -305,6 +309,99 @@ try_again:
/* }}} */
+/* {{{ zendi_convert_to_bigint */
+#define zendi_convert_to_bigint(op, holder, result) \
+ if (op == result) { \
+ convert_to_bigint(op); \
+ } else if (Z_TYPE_P(op) != IS_BIGINT) { \
+ switch (Z_TYPE_P(op)) { \
+ case IS_NULL: \
+ case IS_FALSE: \
+ ZVAL_NEW_BIGINT(&holder); \
+ zend_bigint_init_from_long(Z_BIG(holder), 0); \
+ break; \
+ case IS_TRUE: \
+ ZVAL_NEW_BIGINT(&holder); \
+ zend_bigint_init_from_long(Z_BIG(holder), 1); \
+ break; \
+ case IS_LONG: \
+ ZVAL_NEW_BIGINT(&holder); \
+ zend_bigint_init_from_long(Z_BIG(holder), Z_LVAL(op));\
+ break; \
+ case IS_DOUBLE: \
+ ZVAL_NEW_BIGINT(&holder); \
+ zend_bigint_init_from_double(Z_BIG(holder), Z_DVAL(op));\
+ break; \
+ case IS_STRING: \
+ ZVAL_NEW_BIGINT(&holder); \
+ zend_bigint_init_from_string_tolerant(Z_BIG(holder), Z_STRVAL(op), 10);\
+ break; \
+ case IS_ARRAY: \
+ ZVAL_NEW_BIGINT(&holder); \
+ zend_bigint_init_from_long(Z_BIG(holder), zend_hash_num_elements(Z_ARRVAL_P(op))?1:0);\
+ break; \
+ case IS_OBJECT: \
+ ZVAL_DUP(&(holder), (op)); \
+ convert_to_bigint_base(&(holder), 10); \
+ break; \
+ case IS_RESOURCE: \
+ ZVAL_NEW_BIGINT(&holder); \
+ zend_bigint_init_from_long(Z_BIG(holder), Z_RES_HANDLE_P(op);\
+ break; \
+ default: \
+ zend_error(E_WARNING, "Cannot convert to ordinal value"); \
+ ZVAL_LONG(&holder, 0); \
+ break; \
+ } \
+ (op) = &(holder); \
+ }
+
+/* }}} */
+
+/* {{{ zendi_convert_to_bigint_or_long */
+#define zendi_convert_to_bigint_or_long(op, holder, result) \
+ if (op == result) { \
+ convert_to_bigint(op); \
+ } else if (!(Z_TYPE_P(op) == IS_LONG || Z_TYPE_P(op) == IS_BIGINT)) {\
+ switch (Z_TYPE_P(op)) { \
+ case IS_NULL: \
+ case IS_FALSE: \
+ ZVAL_LONG(&holder, 0); \
+ break; \
+ case IS_TRUE: \
+ ZVAL_LONG(&holder, 1); \
+ break; \
+ case IS_DOUBLE: \
+ ZVAL_NEW_BIGINT(&holder); \
+ zend_bigint_init_from_double(Z_BIG(holder), Z_DVAL_P(op));\
+ break; \
+ case IS_STRING: \
+ ZVAL_LONG(&holder, strtol(Z_STRVAL_P(op), NULL, 10));\
+ if (errno == ERANGE) { /* Overflow */ \
+ ZVAL_NEW_BIGINT(&holder); \
+ zend_bigint_init_from_string_tolerant(Z_BIG(holder), Z_STRVAL_P(op), 10);\
+ } \
+ break; \
+ case IS_ARRAY: \
+ ZVAL_LONG(&holder, zend_hash_num_elements(Z_ARRVAL_P(op))?1:0); \
+ break; \
+ case IS_OBJECT: \
+ ZVAL_DUP(&(holder), (op)); \
+ convert_to_bigint_or_long_base(&(holder), 10); \
+ break; \
+ case IS_RESOURCE: \
+ ZVAL_LONG(&holder, Z_RES_HANDLE_P(op)); \
+ break; \
+ default: \
+ zend_error(E_WARNING, "Cannot convert to ordinal value"); \
+ ZVAL_LONG(&holder, 0); \
+ break; \
+ } \
+ (op) = &(holder); \
+ }
+
+/* }}} */
+
/* {{{ zendi_convert_to_boolean */
#define zendi_convert_to_boolean(op, holder, result) \
if (op==result) { \
@@ -324,6 +421,9 @@ try_again:
case IS_DOUBLE: \
ZVAL_BOOL(&holder, Z_DVAL_P(op) ? 1 : 0); \
break; \
+ case IS_BIGINT: \
+ ZVAL_BOOL(&holder, zend_bigint_to_bool(Z_BIG_P(op)));\
+ break; \
case IS_STRING: \
if (Z_STRLEN_P(op) == 0 \
|| (Z_STRLEN_P(op)==1 && Z_STRVAL_P(op)[0]=='0')) { \
@@ -376,6 +476,22 @@ ZEND_API void convert_to_long(zval *op) /* {{{ */
}
/* }}} */
+ZEND_API void convert_to_bigint(zval *op) /* {{{ */
+{
+ if (Z_TYPE_P(op) != IS_BIGINT) {
+ convert_to_bigint_base(op, 10);
+ }
+}
+/* }}} */
+
+ZEND_API void convert_to_bigint_or_long(zval *op) /* {{{ */
+{
+ if (Z_TYPE_P(op) != IS_BIGINT && Z_TYPE_P(op) != IS_LONG) {
+ convert_to_bigint_or_long_base(op, 10);
+ }
+}
+/* }}} */
+
ZEND_API void convert_to_long_base(zval *op, int base) /* {{{ */
{
long tmp;
@@ -401,6 +517,13 @@ ZEND_API void convert_to_long_base(zval *op, int base) /* {{{ */
case IS_DOUBLE:
ZVAL_LONG(op, zend_dval_to_lval(Z_DVAL_P(op)));
break;
+ case IS_BIGINT:
+ {
+ long l = zend_bigint_to_long(Z_BIG_P(op));
+ zval_dtor(op);
+ ZVAL_LONG(op, l);
+ }
+ break;
case IS_STRING:
{
zend_string *str = Z_STR_P(op);
@@ -436,6 +559,151 @@ ZEND_API void convert_to_long_base(zval *op, int base) /* {{{ */
}
/* }}} */
+ZEND_API void convert_to_bigint_base(zval *op, int base) /* {{{ */
+{
+ long tmp;
+
+ switch (Z_TYPE_P(op)) {
+ case IS_NULL:
+ case IS_FALSE:
+ ZVAL_NEW_BIGINT(op);
+ zend_bigint_init_from_long(Z_BIG_P(op), 0);
+ break;
+ case IS_TRUE:
+ ZVAL_NEW_BIGINT(op);
+ zend_bigint_init_from_long(Z_BIG_P(op), 1);
+ break;
+ case IS_RESOURCE:
+ {
+ long l = Z_RES_HANDLE_P(op);
+ zval_ptr_dtor(op);
+ ZVAL_NEW_BIGINT(op);
+ zend_bigint_init_from_long(Z_BIG_P(op), l);
+ }
+ break;
+ case IS_LONG:
+ {
+ long l = Z_LVAL_P(op);
+ ZVAL_NEW_BIGINT(op);
+ zend_bigint_init_from_long(Z_BIG_P(op), l);
+ }
+ break;
+ case IS_DOUBLE:
+ {
+ double d = Z_DVAL_P(op);
+ ZVAL_NEW_BIGINT(op);
+ zend_bigint_init_from_double(Z_BIG_P(op), d);
+ }
+ break;
+ case IS_BIGINT:
+ break;
+ case IS_STRING:
+ {
+ zend_string *str = Z_STR_P(op);
+ ZVAL_NEW_BIGINT(op);
+ zend_bigint_init_from_string_tolerant(Z_BIG_P(op), str->val, base);
+ STR_RELEASE(str);
+ }
+ break;
+ case IS_ARRAY:
+ tmp = (zend_hash_num_elements(Z_ARRVAL_P(op))?1:0);
+ zval_dtor(op);
+ ZVAL_NEW_BIGINT(op);
+ zend_bigint_init_from_long(Z_BIG_P(op), tmp);
+ break;
+ case IS_OBJECT:
+ {
+ zval dst;
+ TSRMLS_FETCH();
+
+ convert_object_to_type(op, &dst, IS_BIGINT, convert_to_bigint);
+ zval_dtor(op);
+
+ if (Z_TYPE(dst) == IS_BIGINT) {
+ ZVAL_COPY_VALUE(op, &dst);
+ } else {
+ zend_error(E_NOTICE, "Object of class %s could not be converted to int", Z_OBJCE_P(op)->name->val);
+
+ ZVAL_NEW_BIGINT(op);
+ zend_bigint_init_from_long(Z_BIG_P(op), 1);
+ }
+ return;
+ }
+ EMPTY_SWITCH_DEFAULT_CASE()
+ }
+}
+/* }}} */
+
+ZEND_API void convert_to_bigint_or_long_base(zval *op, int base) /* {{{ */
+{
+ long tmp;
+
+ switch (Z_TYPE_P(op)) {
+ case IS_NULL:
+ case IS_FALSE:
+ ZVAL_LONG(op, 0);
+ break;
+ case IS_TRUE:
+ ZVAL_LONG(op, 1);
+ break;
+ case IS_RESOURCE: {
+ long l = Z_RES_HANDLE_P(op);
+ zval_ptr_dtor(op);
+ ZVAL_LONG(op, l);
+ }
+ /* break missing intentionally */
+ Z_TYPE_INFO_P(op) = IS_LONG;
+ break;
+ case IS_LONG:
+ break;
+ case IS_DOUBLE:
+ {
+ double d = Z_DVAL_P(op);
+ ZVAL_NEW_BIGINT(op);
+ zend_bigint_init_from_double(Z_BIG_P(op), d);
+ }
+ break;
+ case IS_BIGINT:
+ break;
+ case IS_STRING:
+ {
+ zend_string *str = Z_STR_P(op);
+ ZVAL_LONG(op, strtol(str->val, NULL, 10));
+ if (errno == ERANGE) { /* Overflow */
+ ZVAL_NEW_BIGINT(op);
+ zend_bigint_init_from_string_tolerant(Z_BIG_P(op), str->val, base);
+ }
+ STR_RELEASE(str);
+ }
+ break;
+ case IS_ARRAY:
+ tmp = (zend_hash_num_elements(Z_ARRVAL_P(op))?1:0);
+ zval_dtor(op);
+ ZVAL_LONG(op, tmp);
+ break;
+ case IS_OBJECT:
+ {
+ zval dst;
+ TSRMLS_FETCH();
+
+ convert_object_to_type(op, &dst, IS_BIGINT, convert_to_bigint_or_long);
+ zval_dtor(op);
+
+ if (Z_TYPE(dst) == IS_BIGINT) {
+ ZVAL_COPY_VALUE(op, &dst);
+ } else {
+ zend_error(E_NOTICE, "Object of class %s could not be converted to int", Z_OBJCE_P(op)->name->val);
+
+ ZVAL_NEW_BIGINT(op);
+ ZVAL_LONG(op, 1);
+ }
+ return;
+ }
+ EMPTY_SWITCH_DEFAULT_CASE()
+ }
+}
+/* }}} */
+
ZEND_API void convert_to_double(zval *op) /* {{{ */
{
double tmp;
@@ -459,6 +727,13 @@ ZEND_API void convert_to_double(zval *op) /* {{{ */
break;
case IS_DOUBLE:
break;
+ case IS_BIGINT:
+ {
+ double d = zend_bigint_to_double(Z_BIG_P(op));
+ zval_dtor(op);
+ ZVAL_DOUBLE(op, d);
+ }
+ break;
case IS_STRING:
{
zend_string *str = Z_STR_P(op);
@@ -539,6 +814,13 @@ ZEND_API void convert_to_boolean(zval *op) /* {{{ */
case IS_DOUBLE:
ZVAL_BOOL(op, Z_DVAL_P(op) ? 1 : 0);
break;
+ case IS_BIGINT:
+ {
+ zend_bool b = zend_bigint_to_bool(Z_BIG_P(op));
+ zval_dtor(op);
+ ZVAL_BOOL(op, b);
+ }
+ break;
case IS_STRING:
{
zend_string *str = Z_STR_P(op);
@@ -617,6 +899,10 @@ ZEND_API void _convert_to_string(zval *op ZEND_FILE_LINE_DC) /* {{{ */
ZVAL_NEW_STR(op, str);
break;
}
+ case IS_BIGINT: {
+ ZVAL_NEW_STR(op, zend_bigint_to_zend_string(Z_BIG_P(op), 0));
+ break;
+ }
case IS_ARRAY:
zend_error(E_NOTICE, "Array to string conversion");
zval_dtor(op);
@@ -798,6 +1084,8 @@ try_again:
return Z_LVAL_P(op);
case IS_DOUBLE:
return zend_dval_to_lval(Z_DVAL_P(op));
+ case IS_BIGINT:
+ return zend_bigint_to_long(Z_BIG_P(op));
case IS_STRING:
return strtol(Z_STRVAL_P(op), NULL, 10);
case IS_ARRAY:
@@ -836,6 +1124,8 @@ try_again:
return (double) Z_LVAL_P(op);
case IS_DOUBLE:
return Z_DVAL_P(op);
+ case IS_BIGINT:
+ return zend_bigint_to_double(Z_BIG_P(op));
case IS_STRING:
return zend_strtod(Z_STRVAL_P(op), NULL);
case IS_ARRAY:
@@ -885,6 +1175,9 @@ try_again:
case IS_DOUBLE: {
return zend_strpprintf(0, "%.*G", (int) EG(precision), Z_DVAL_P(op));
}
+ case IS_BIGINT: {
+ return zend_bigint_to_zend_string(Z_BIG_P(op), 0);
+ }
case IS_ARRAY:
zend_error(E_NOTICE, "Array to string conversion");
return STR_INIT("Array", sizeof("Array")-1, 0);
@@ -947,6 +1240,54 @@ ZEND_API int add_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{{ *
ZVAL_DOUBLE(result, Z_DVAL_P(op1) + Z_DVAL_P(op2));
return SUCCESS;
+ case TYPE_PAIR(IS_BIGINT, IS_BIGINT):
+ {
+ zend_bigint *out = zend_bigint_init_alloc();
+ zend_bigint_add(out, Z_BIG_P(op1), Z_BIG_P(op2));
+ if (op1 == result) {
+ zval_dtor(op1);
+ }
+ ZVAL_BIGINT(result, out);
+ }
+ return SUCCESS;
+
+ case TYPE_PAIR(IS_BIGINT, IS_LONG):
+ {
+ zend_bigint *out = zend_bigint_init_alloc();
+ zend_bigint_add_long(out, Z_BIG_P(op1), Z_LVAL_P(op2));
+ if (op1 == result) {
+ zval_dtor(op1);
+ }
+ ZVAL_BIGINT(result, out);
+ }
+ return SUCCESS;
+
+ case TYPE_PAIR(IS_LONG, IS_BIGINT):
+ {
+ zend_bigint *out = zend_bigint_init_alloc();
+ zend_bigint_add_long(out, Z_BIG_P(op2), Z_LVAL_P(op1));
+ /* unary plus does this */
+ if (op2 == result) {
+ zval_dtor(op2);
+ }
+ ZVAL_BIGINT(result, out);
+ }
+ return SUCCESS;
+
+ case TYPE_PAIR(IS_BIGINT, IS_DOUBLE):
+ {
+ double out = zend_bigint_to_double(Z_BIG_P(op1)) + Z_DVAL_P(op2);
+ if (op1 == result) {
+ zval_dtor(op1);
+ }
+ ZVAL_DOUBLE(result, out);
+ }
+ return SUCCESS;
+
+ case TYPE_PAIR(IS_DOUBLE, IS_BIGINT):
+ ZVAL_DOUBLE(result, Z_DVAL_P(op1) + zend_bigint_to_double(Z_BIG_P(op2)));
+ return SUCCESS;
+
case TYPE_PAIR(IS_ARRAY, IS_ARRAY):
if ((result == op1) && (result == op2)) {
/* $a += $a */
@@ -1011,6 +1352,54 @@ ZEND_API int sub_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{{ *
ZVAL_DOUBLE(result, Z_DVAL_P(op1) - Z_DVAL_P(op2));
return SUCCESS;
+ case TYPE_PAIR(IS_BIGINT, IS_BIGINT):
+ {
+ zend_bigint *out = zend_bigint_init_alloc();
+ zend_bigint_subtract(out, Z_BIG_P(op1), Z_BIG_P(op2));
+ if (op1 == result) {
+ zval_dtor(op1);
+ }
+ ZVAL_BIGINT(result, out);
+ }
+ return SUCCESS;
+
+ case TYPE_PAIR(IS_BIGINT, IS_LONG):
+ {
+ zend_bigint *out = zend_bigint_init_alloc();
+ zend_bigint_subtract_long(out, Z_BIG_P(op1), Z_LVAL_P(op2));
+ if (op1 == result) {
+ zval_dtor(op1);
+ }
+ ZVAL_BIGINT(result, out);
+ }
+ return SUCCESS;
+
+ case TYPE_PAIR(IS_LONG, IS_BIGINT):
+ {
+ zend_bigint *out = zend_bigint_init_alloc();
+ zend_bigint_long_subtract(out, Z_LVAL_P(op1), Z_BIG_P(op2));
+ /* unary minus does this */
+ if (op2 == result) {
+ zval_dtor(op2);
+ }
+ ZVAL_BIGINT(result, out);
+ }
+ return SUCCESS;
+
+ case TYPE_PAIR(IS_BIGINT, IS_DOUBLE):
+ {
+ double out = zend_bigint_to_double(Z_BIG_P(op1)) - Z_DVAL_P(op2);
+ if (op1 == result) {
+ zval_dtor(op1);
+ }
+ ZVAL_DOUBLE(result, out);
+ }
+ return SUCCESS;
+
+ case TYPE_PAIR(IS_DOUBLE, IS_BIGINT):
+ ZVAL_DOUBLE(result, Z_DVAL_P(op1) - zend_bigint_to_double(Z_BIG_P(op2)));
+ return SUCCESS;
+
default:
if (Z_ISREF_P(op1)) {
op1 = Z_REFVAL_P(op1);
@@ -1041,8 +1430,8 @@ ZEND_API int mul_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{{ *
case TYPE_PAIR(IS_LONG, IS_LONG): {
long overflow;
- ZEND_SIGNED_MULTIPLY_LONG(Z_LVAL_P(op1),Z_LVAL_P(op2), Z_LVAL_P(result),Z_DVAL_P(result),overflow);
- Z_TYPE_INFO_P(result) = overflow ? IS_DOUBLE : IS_LONG;
+ ZEND_SIGNED_MULTIPLY_LONG(Z_LVAL_P(op1),Z_LVAL_P(op2), Z_LVAL_P(result),Z_BIG_P(result),overflow);
+ Z_TYPE_INFO_P(result) = overflow ? IS_BIGINT_EX : IS_LONG;
return SUCCESS;
}
@@ -1058,6 +1447,47 @@ ZEND_API int mul_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{{ *
ZVAL_DOUBLE(result, Z_DVAL_P(op1) * Z_DVAL_P(op2));
return SUCCESS;
+ case TYPE_PAIR(IS_BIGINT, IS_BIGINT):
+ {
+ zend_bigint *out = zend_bigint_init_alloc();
+ zend_bigint_multiply(out, Z_BIG_P(op1), Z_BIG_P(op2));
+ if (op1 == result) {
+ zval_dtor(op1);
+ }
+ ZVAL_BIGINT(result, out);
+ }
+ return SUCCESS;
+
+ case TYPE_PAIR(IS_BIGINT, IS_LONG):
+ {
+ zend_bigint *out = zend_bigint_init_alloc();
+ zend_bigint_multiply_long(out, Z_BIG_P(op1), Z_LVAL_P(op2));
+ if (op1 == result) {
+ zval_dtor(op1);
+ }
+ ZVAL_BIGINT(result, out);
+ }
+ return SUCCESS;
+
+ case TYPE_PAIR(IS_LONG, IS_BIGINT):
+ ZVAL_BIGINT(result, zend_bigint_init_alloc());
+ zend_bigint_multiply_long(Z_BIG_P(result), Z_BIG_P(op2), Z_LVAL_P(op1));
+ return SUCCESS;
+
+ case TYPE_PAIR(IS_BIGINT, IS_DOUBLE):
+ {
+ double out = zend_bigint_to_double(Z_BIG_P(op1)) * Z_DVAL_P(op2);
+ if (op1 == result) {
+ zval_dtor(op1);
+ }
+ ZVAL_DOUBLE(result, out);
+ }
+ return SUCCESS;
+
+ case TYPE_PAIR(IS_DOUBLE, IS_BIGINT):
+ ZVAL_DOUBLE(result, Z_DVAL_P(op1) * zend_bigint_to_double(Z_BIG_P(op2)));
+ return SUCCESS;
+
default:
if (Z_ISREF_P(op1)) {
op1 = Z_REFVAL_P(op1);
@@ -1099,20 +1529,28 @@ ZEND_API int pow_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{{ *
while (i >= 1) {
long overflow;
- double dval = 0.0;
+ zend_bigint *big;
if (i % 2) {
--i;
- ZEND_SIGNED_MULTIPLY_LONG(l1, l2, l1, dval, overflow);
+ ZEND_SIGNED_MULTIPLY_LONG(l1, l2, l1, big, overflow);
if (overflow) {
- ZVAL_DOUBLE(result, dval * pow(l2, i));
+ zend_bigint *big2;
+ big2 = zend_bigint_init_alloc();
+ zend_bigint_long_pow_ulong(big2, l2, i);
+ zend_bigint_multiply(big, big, big2);
+ zend_bigint_dtor(big2);
+ efree(big2);
+ ZVAL_BIGINT(result, big);
return SUCCESS;
}
} else {
i /= 2;
- ZEND_SIGNED_MULTIPLY_LONG(l2, l2, l2, dval, overflow);
+ ZEND_SIGNED_MULTIPLY_LONG(l2, l2, l2, big, overflow);
if (overflow) {
- ZVAL_DOUBLE(result, (double)l1 * pow(dval, i));
+ zend_bigint_pow_ulong(big, big, i);
+ zend_bigint_multiply_long(big, big, l1);
+ ZVAL_BIGINT(result, big);
return SUCCESS;
}
}
@@ -1136,6 +1574,73 @@ ZEND_API int pow_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{{ *
ZVAL_DOUBLE(result, pow(Z_DVAL_P(op1), Z_DVAL_P(op2)));
return SUCCESS;
+ case TYPE_PAIR(IS_BIGINT, IS_BIGINT):
+ if (zend_bigint_sign(Z_BIG_P(op2)) < 0) {
+ double out = pow(zend_bigint_to_double(Z_BIG_P(op1)), zend_bigint_to_double(Z_BIG_P(op2)));
+ if (op1 == result) {
+ zval_dtor(op1);
+ }
+ ZVAL_DOUBLE(result, out);
+ return SUCCESS;
+ }
+ if (zend_bigint_can_fit_ulong(Z_BIG_P(op2))) {
+ unsigned long ulval = zend_bigint_to_ulong(Z_BIG_P(op2));
+ zend_bigint *out = zend_bigint_init_alloc();
+ zend_bigint_pow_ulong(out, Z_BIG_P(op1), ulval);
+ if (op1 == result) {
+ zval_dtor(op1);
+ }
+ ZVAL_BIGINT(result, out);
+ return SUCCESS;
+ } else {
+ zend_error(E_WARNING, "Exponent too large");
+ if (op1 == result) {
+ zval_dtor(op1);
+ }
+ ZVAL_BOOL(result, 0);
+ return FAILURE;
+ }
+
+ case TYPE_PAIR(IS_BIGINT, IS_LONG):
+ if (Z_LVAL_P(op2) >= 0) {
+ unsigned long ulval = Z_LVAL_P(op2);
+ ZVAL_BIGINT(result, zend_bigint_init_alloc());
+ zend_bigint_pow_ulong(Z_BIG_P(result), Z_BIG_P(op1), ulval);
+ } else {
+ ZVAL_DOUBLE(result, pow(zend_bigint_to_double(Z_BIG_P(op1)), (double)Z_LVAL_P(op2)));
+ }
+ return SUCCESS;
+
+ case TYPE_PAIR(IS_LONG, IS_BIGINT):
+ if (zend_bigint_sign(Z_BIG_P(op2)) <= 0) {
+ ZVAL_DOUBLE(result, pow(zend_bigint_to_double(Z_BIG_P(op1)), zend_bigint_to_double(Z_BIG_P(op2))));
+ return SUCCESS;
+ }
+ if (zend_bigint_can_fit_ulong(Z_BIG_P(op2))) {
+ unsigned long ulval = zend_bigint_to_ulong(Z_BIG_P(op2));
+ ZVAL_BIGINT(result, zend_bigint_init_alloc());
+ zend_bigint_long_pow_ulong(Z_BIG_P(result), Z_LVAL_P(op1), ulval);
+ return SUCCESS;
+ } else {
+ zend_error(E_WARNING, "Exponent too large");
+ ZVAL_BOOL(result, 0);
+ return FAILURE;
+ }
+
+ case TYPE_PAIR(IS_BIGINT, IS_DOUBLE):
+ {
+ double out = pow(zend_bigint_to_double(Z_BIG_P(op1)), Z_DVAL_P(op2));
+ if (op1 == result) {
+ zval_dtor(op1);
+ }
+ ZVAL_DOUBLE(result, out);
+ }
+ return SUCCESS;
+
+ case TYPE_PAIR(IS_DOUBLE, IS_BIGINT):
+ ZVAL_DOUBLE(result, pow(Z_DVAL_P(op1), zend_bigint_to_double(Z_BIG_P(op2))));
+ return SUCCESS;
+
default:
if (Z_ISREF_P(op1)) {
op1 = Z_REFVAL_P(op1);
@@ -1217,6 +1722,98 @@ ZEND_API int div_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{{ *
ZVAL_DOUBLE(result, Z_DVAL_P(op1) / Z_DVAL_P(op2));
return SUCCESS;
+ case TYPE_PAIR(IS_BIGINT, IS_BIGINT):
+ if (zend_bigint_sign(Z_BIG_P(op2)) == 0) {
+ zend_error(E_WARNING, "Division by zero");
+ if (op1 == result) {
+ zval_dtor(op1);
+ }
+ ZVAL_BOOL(result, 0);
+ return FAILURE; /* division by zero */
+ }
+ if (zend_bigint_divisible(Z_BIG_P(op1), Z_BIG_P(op2))) {
+ zend_bigint *out = zend_bigint_init_alloc();
+ zend_bigint_divide(out, Z_BIG_P(op1), Z_BIG_P(op2));
+ if (op1 == result) {
+ zval_dtor(op1);
+ }
+ ZVAL_BIGINT(result, out);
+ } else {
+ double out = zend_bigint_to_double(Z_BIG_P(op1)) / zend_bigint_to_double(Z_BIG_P(op2));
+ if (op1 == result) {
+ zval_dtor(op1);
+ }
+ ZVAL_DOUBLE(result, out);
+ }
+ return SUCCESS;
+
+ case TYPE_PAIR(IS_BIGINT, IS_LONG):
+ if (Z_LVAL_P(op2) == 0) {
+ zend_error(E_WARNING, "Division by zero");
+ if (op1 == result) {
+ zval_dtor(op1);
+ }
+ ZVAL_BOOL(result, 0);
+ return FAILURE; /* division by zero */
+ }
+ if (zend_bigint_divisible_long(Z_BIG_P(op1), Z_LVAL_P(op2))) {
+ zend_bigint *out = zend_bigint_init_alloc();
+ zend_bigint_divide_long(out, Z_BIG_P(op1), Z_LVAL_P(op2));
+ if (op1 == result) {
+ zval_dtor(op1);
+ }
+ ZVAL_BIGINT(result, out);
+ } else {
+ double out = zend_bigint_to_double(Z_BIG_P(op1)) / (double)Z_LVAL_P(op2);
+ if (op1 == result) {
+ zval_dtor(op1);
+ }
+ ZVAL_DOUBLE(result, out);
+ }
+ return SUCCESS;
+
+ case TYPE_PAIR(IS_LONG, IS_BIGINT):
+ if (zend_bigint_sign(Z_BIG_P(op2)) == 0) {
+ zend_error(E_WARNING, "Division by zero");
+ ZVAL_BOOL(result, 0);
+ return FAILURE; /* division by zero */
+ }
+ if (zend_bigint_long_divisible(Z_LVAL_P(op1), Z_BIG_P(op2))) {
+ ZVAL_BIGINT(result, zend_bigint_init_alloc());
+ zend_bigint_long_divide(Z_BIG_P(result), Z_LVAL_P(op1), Z_BIG_P(op2));
+ } else {
+ ZVAL_DOUBLE(result, (double)Z_LVAL_P(op1) / zend_bigint_to_double(Z_BIG_P(op2)));
+ }
+ return SUCCESS;
+
+ case TYPE_PAIR(IS_BIGINT, IS_DOUBLE):
+ {
+ double out;
+ if (Z_DVAL_P(op2) == 0) {
+ zend_error(E_WARNING, "Division by zero");
+ if (op1 == result) {
+ zval_dtor(op1);
+ }
+ ZVAL_BOOL(result, 0);
+ return FAILURE; /* division by zero */
+ }
+ out = zend_bigint_to_double(Z_BIG_P(op1)) / Z_DVAL_P(op2);
+ if (op1 == result) {
+ zval_dtor(op1);
+ }
+ ZVAL_DOUBLE(result, out);
+ }
+ return SUCCESS;
+
+ case TYPE_PAIR(IS_DOUBLE, IS_BIGINT):
+ if (zend_bigint_sign(Z_BIG_P(op2)) == 0) {
+ zend_error(E_WARNING, "Division by zero");
+ ZVAL_BOOL(result, 0);
+ return FAILURE; /* division by zero */
+ }
+ ZVAL_DOUBLE(result, Z_DVAL_P(op1) / zend_bigint_to_double(Z_BIG_P(op2)));
+ return SUCCESS;
+
default:
if (Z_ISREF_P(op1)) {
op1 = Z_REFVAL_P(op1);
@@ -1240,32 +1837,89 @@ ZEND_API int div_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{{ *
ZEND_API int mod_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{{ */
{
zval op1_copy, op2_copy;
- long op1_lval;
- if (Z_TYPE_P(op1) != IS_LONG || Z_TYPE_P(op2) != IS_LONG) {
+ if (!(Z_TYPE_P(op1) == IS_LONG || Z_TYPE_P(op1) == IS_BIGINT)
+ || !(Z_TYPE_P(op2) == IS_LONG || Z_TYPE_P(op2) == IS_BIGINT)) {
ZEND_TRY_BINARY_OBJECT_OPERATION(ZEND_MOD);
- zendi_convert_to_long(op1, op1_copy, result);
- op1_lval = Z_LVAL_P(op1);
- zendi_convert_to_long(op2, op2_copy, result);
- } else {
- op1_lval = Z_LVAL_P(op1);
+ zendi_convert_to_bigint_or_long(op1, op1_copy, result);
+ zendi_convert_to_bigint_or_long(op2, op2_copy, result);
}
- if (Z_LVAL_P(op2) == 0) {
- zend_error(E_WARNING, "Division by zero");
- ZVAL_BOOL(result, 0);
- return FAILURE; /* modulus by zero */
- }
-
- if (Z_LVAL_P(op2) == -1) {
- /* Prevent overflow error/crash if op1==LONG_MIN */
- ZVAL_LONG(result, 0);
- return SUCCESS;
+ switch (TYPE_PAIR(Z_TYPE_P(op1), Z_TYPE_P(op2))) {
+ case TYPE_PAIR(IS_LONG, IS_LONG):
+ if (Z_LVAL_P(op2) == 0) {
+ zend_error(E_WARNING, "Division by zero");
+ ZVAL_BOOL(result, 0);
+ return FAILURE; /* modulus by zero */
+ }
+ if (Z_LVAL_P(op2) == -1) {
+ /* Prevent overflow error/crash if op1==LONG_MIN */
+ ZVAL_LONG(result, 0);
+ return SUCCESS;
+ }
+ ZVAL_LONG(result, Z_LVAL_P(op1) % Z_LVAL_P(op2));
+ return SUCCESS;
+ case TYPE_PAIR(IS_BIGINT, IS_BIGINT):
+ {
+ zend_bigint *out;
+ if (zend_bigint_sign(Z_BIG_P(op2)) == 0) {
+ zend_error(E_WARNING, "Division by zero");
+ if (op1 == result) {
+ zval_dtor(op1);
+ }
+ ZVAL_BOOL(result, 0);
+ return FAILURE; /* modulus by zero */
+ }
+ out = zend_bigint_init_alloc();
+ zend_bigint_modulus(out, Z_BIG_P(op1), Z_BIG_P(op2));
+ if (op1 == result) {
+ zval_dtor(op1);
+ }
+ ZVAL_BIGINT(result, out);
+ if (op1 == &op1_copy) {
+ zval_dtor(&op1_copy);
+ }
+ if (op2 == &op2_copy) {
+ zval_dtor(&op2_copy);
+ }
+ }
+ return SUCCESS;
+ case TYPE_PAIR(IS_BIGINT, IS_LONG):
+ {
+ zend_bigint *out;
+ if (Z_LVAL_P(op2) == 0) {
+ zend_error(E_WARNING, "Division by zero");
+ if (op1 == result) {
+ zval_dtor(op1);
+ }
+ ZVAL_BOOL(result, 0);
+ return FAILURE; /* modulus by zero */
+ }
+ out = zend_bigint_init_alloc();
+ zend_bigint_modulus_long(out, Z_BIG_P(op1), Z_LVAL_P(op2));
+ if (op1 == result) {
+ zval_dtor(op1);
+ }
+ ZVAL_BIGINT(result, out);
+ if (op1 == &op1_copy) {
+ zval_dtor(&op1_copy);
+ }
+ }
+ return SUCCESS;
+ case TYPE_PAIR(IS_LONG, IS_BIGINT):
+ if (zend_bigint_sign(Z_BIG_P(op2)) == 0) {
+ zend_error(E_WARNING, "Division by zero");
+ ZVAL_BOOL(result, 0);
+ return FAILURE; /* modulus by zero */
+ }
+ ZVAL_BIGINT(result, zend_bigint_init_alloc());
+ zend_bigint_long_modulus(Z_BIG_P(result), Z_LVAL_P(op1), Z_BIG_P(op2));
+ if (op2 == &op2_copy) {
+ zval_dtor(&op2_copy);
+ }
+ return SUCCESS;
}
-
- ZVAL_LONG(result, op1_lval % Z_LVAL_P(op2));
- return SUCCESS;
}
/* }}} */
@@ -1319,6 +1973,16 @@ ZEND_API int bitwise_not_function(zval *result, zval *op1 TSRMLS_DC) /* {{{ */
case IS_DOUBLE:
ZVAL_LONG(result, ~zend_dval_to_lval(Z_DVAL_P(op1)));
return SUCCESS;
+ case IS_BIGINT:
+ {
+ zend_bigint *out = zend_bigint_init_alloc();
+ zend_bigint_ones_complement(out, Z_BIG_P(op1));
+ if (op1 == result) {
+ zval_dtor(op1);
+ }
+ ZVAL_BIGINT(result, out);
+ }
+ return SUCCESS;
case IS_STRING: {
int i;
zval op1_copy = *op1;
@@ -1342,7 +2006,6 @@ ZEND_API int bitwise_not_function(zval *result, zval *op1 TSRMLS_DC) /* {{{ */
ZEND_API int bitwise_or_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{{ */
{
zval op1_copy, op2_copy;
- long op1_lval;
if (Z_TYPE_P(op1) == IS_STRING && Z_TYPE_P(op2) == IS_STRING) {
zval *longer, *shorter;
@@ -1369,25 +2032,61 @@ ZEND_API int bitwise_or_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /
return SUCCESS;
}
- if (Z_TYPE_P(op1) != IS_LONG || Z_TYPE_P(op2) != IS_LONG) {
+ if (!(Z_TYPE_P(op1) == IS_LONG || Z_TYPE_P(op1) == IS_BIGINT)
+ || !(Z_TYPE_P(op2) == IS_LONG || Z_TYPE_P(op2) == IS_BIGINT)) {
ZEND_TRY_BINARY_OBJECT_OPERATION(ZEND_BW_OR);
- zendi_convert_to_long(op1, op1_copy, result);
- op1_lval = Z_LVAL_P(op1);
- zendi_convert_to_long(op2, op2_copy, result);
- } else {
- op1_lval = Z_LVAL_P(op1);
+ zendi_convert_to_bigint_or_long(op1, op1_copy, result);
+ zendi_convert_to_bigint_or_long(op2, op2_copy, result);
}
- ZVAL_LONG(result, op1_lval | Z_LVAL_P(op2));
- return SUCCESS;
+ switch (TYPE_PAIR(Z_TYPE_P(op1), Z_TYPE_P(op2))) {
+ case TYPE_PAIR(IS_LONG, IS_LONG):
+ ZVAL_LONG(result, Z_LVAL_P(op1) | Z_LVAL_P(op2));
+ return SUCCESS;
+ case TYPE_PAIR(IS_BIGINT, IS_BIGINT):
+ {
+ zend_bigint *out = zend_bigint_init_alloc();
+ zend_bigint_or(out, Z_BIG_P(op1), Z_BIG_P(op2));
+ if (op1 == result) {
+ zval_dtor(op1);
+ }
+ ZVAL_BIGINT(result, out);
+ if (op1 == &op1_copy) {
+ zval_dtor(&op1_copy);
+ }
+ if (op2 == &op2_copy) {
+ zval_dtor(&op2_copy);
+ }
+ }
+ return SUCCESS;
+ case TYPE_PAIR(IS_BIGINT, IS_LONG):
+ {
+ zend_bigint *out = zend_bigint_init_alloc();
+ zend_bigint_or_long(Z_BIG_P(result), Z_BIG_P(op1), Z_LVAL_P(op2));
+ if (op1 == result) {
+ zval_dtor(op1);
+ }
+ ZVAL_BIGINT(result, out);
+ if (op1 == &op1_copy) {
+ zval_dtor(&op1_copy);
+ }
+ }
+ return SUCCESS;
+ case TYPE_PAIR(IS_LONG, IS_BIGINT):
+ ZVAL_BIGINT(result, zend_bigint_init_alloc());
+ zend_bigint_long_or(Z_BIG_P(result), Z_LVAL_P(op1), Z_BIG_P(op2));
+ if (op2 == &op2_copy) {
+ zval_dtor(&op2_copy);
+ }
+ return SUCCESS;
+ }
}
/* }}} */
ZEND_API int bitwise_and_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{{ */
{
zval op1_copy, op2_copy;
- long op1_lval;
if (Z_TYPE_P(op1) == IS_STRING && Z_TYPE_P(op2) == IS_STRING) {
zval *longer, *shorter;
@@ -1414,25 +2113,61 @@ ZEND_API int bitwise_and_function(zval *result, zval *op1, zval *op2 TSRMLS_DC)
return SUCCESS;
}
- if (Z_TYPE_P(op1) != IS_LONG || Z_TYPE_P(op2) != IS_LONG) {
+ if (!(Z_TYPE_P(op1) == IS_LONG || Z_TYPE_P(op1) == IS_BIGINT)
+ || !(Z_TYPE_P(op2) == IS_LONG || Z_TYPE_P(op2) == IS_BIGINT)) {
ZEND_TRY_BINARY_OBJECT_OPERATION(ZEND_BW_AND);
- zendi_convert_to_long(op1, op1_copy, result);
- op1_lval = Z_LVAL_P(op1);
- zendi_convert_to_long(op2, op2_copy, result);
- } else {
- op1_lval = Z_LVAL_P(op1);
+ zendi_convert_to_bigint_or_long(op1, op1_copy, result);
+ zendi_convert_to_bigint_or_long(op2, op2_copy, result);
}
- ZVAL_LONG(result, op1_lval & Z_LVAL_P(op2));
- return SUCCESS;
+ switch (TYPE_PAIR(Z_TYPE_P(op1), Z_TYPE_P(op2))) {
+ case TYPE_PAIR(IS_LONG, IS_LONG):
+ ZVAL_LONG(result, Z_LVAL_P(op1) & Z_LVAL_P(op2));
+ return SUCCESS;
+ case TYPE_PAIR(IS_BIGINT, IS_BIGINT):
+ {
+ zend_bigint *out = zend_bigint_init_alloc();
+ zend_bigint_and(out, Z_BIG_P(op1), Z_BIG_P(op2));
+ if (op1 == result) {
+ zval_dtor(op1);
+ }
+ ZVAL_BIGINT(result, out);
+ if (op1 == &op1_copy) {
+ zval_dtor(&op1_copy);
+ }
+ if (op2 == &op2_copy) {
+ zval_dtor(&op2_copy);
+ }
+ }
+ return SUCCESS;
+ case TYPE_PAIR(IS_BIGINT, IS_LONG):
+ {
+ zend_bigint *out = zend_bigint_init_alloc();
+ zend_bigint_and_long(out, Z_BIG_P(op1), Z_LVAL_P(op2));
+ if (op1 == result) {
+ zval_dtor(op1);
+ }
+ ZVAL_BIGINT(result, out);
+ if (op1 == &op1_copy) {
+ zval_dtor(&op1_copy);
+ }
+ }
+ return SUCCESS;
+ case TYPE_PAIR(IS_LONG, IS_BIGINT):
+ ZVAL_BIGINT(result, zend_bigint_init_alloc());
+ zend_bigint_long_and(Z_BIG_P(result), Z_LVAL_P(op1), Z_BIG_P(op2));
+ if (op2 == &op2_copy) {
+ zval_dtor(&op2_copy);
+ }
+ return SUCCESS;
+ }
}
/* }}} */
ZEND_API int bitwise_xor_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{{ */
{
zval op1_copy, op2_copy;
- long op1_lval;
if (Z_TYPE_P(op1) == IS_STRING && Z_TYPE_P(op2) == IS_STRING) {
zval *longer, *shorter;
@@ -1459,58 +2194,121 @@ ZEND_API int bitwise_xor_function(zval *result, zval *op1, zval *op2 TSRMLS_DC)
return SUCCESS;
}
- if (Z_TYPE_P(op1) != IS_LONG || Z_TYPE_P(op2) != IS_LONG) {
+ if (!(Z_TYPE_P(op1) == IS_LONG || Z_TYPE_P(op1) == IS_BIGINT)
+ || !(Z_TYPE_P(op2) == IS_LONG || Z_TYPE_P(op2) == IS_BIGINT)) {
ZEND_TRY_BINARY_OBJECT_OPERATION(ZEND_BW_XOR);
- zendi_convert_to_long(op1, op1_copy, result);
- op1_lval = Z_LVAL_P(op1);
- zendi_convert_to_long(op2, op2_copy, result);
- } else {
- op1_lval = Z_LVAL_P(op1);
+ zendi_convert_to_bigint_or_long(op1, op1_copy, result);
+ zendi_convert_to_bigint_or_long(op2, op2_copy, result);
}
- ZVAL_LONG(result, op1_lval ^ Z_LVAL_P(op2));
- return SUCCESS;
+ switch (TYPE_PAIR(Z_TYPE_P(op1), Z_TYPE_P(op2))) {
+ case TYPE_PAIR(IS_LONG, IS_LONG):
+ ZVAL_LONG(result, Z_LVAL_P(op1) ^ Z_LVAL_P(op2));
+ return SUCCESS;
+ case TYPE_PAIR(IS_BIGINT, IS_BIGINT):
+ {
+ zend_bigint *out = zend_bigint_init_alloc();
+ zend_bigint_xor(out, Z_BIG_P(op1), Z_BIG_P(op2));
+ if (op1 == result) {
+ zval_dtor(op1);
+ }
+ ZVAL_BIGINT(result, out);
+ if (op1 == &op1_copy) {
+ zval_dtor(&op1_copy);
+ }
+ if (op2 == &op2_copy) {
+ zval_dtor(&op2_copy);
+ }
+ }
+ return SUCCESS;
+ case TYPE_PAIR(IS_BIGINT, IS_LONG):
+ {
+ zend_bigint *out = zend_bigint_init_alloc();
+ zend_bigint_xor_long(out, Z_BIG_P(op1), Z_LVAL_P(op2));
+ if (op1 == result) {
+ zval_dtor(op1);
+ }
+ ZVAL_BIGINT(result, out);
+ if (op1 == &op1_copy) {
+ zval_dtor(&op1_copy);
+ }
+ }
+ return SUCCESS;
+ case TYPE_PAIR(IS_LONG, IS_BIGINT):
+ ZVAL_BIGINT(result, zend_bigint_init_alloc());
+ zend_bigint_long_xor(Z_BIG_P(result), Z_LVAL_P(op1), Z_BIG_P(op2));
+ if (op2 == &op2_copy) {
+ zval_dtor(&op2_copy);
+ }
+ return SUCCESS;
+ }
}
/* }}} */
ZEND_API int shift_left_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{{ */
{
zval op1_copy, op2_copy;
- long op1_lval;
- if (Z_TYPE_P(op1) != IS_LONG || Z_TYPE_P(op2) != IS_LONG) {
+ if (!(Z_TYPE_P(op1) == IS_LONG || Z_TYPE_P(op1) == IS_BIGINT)
+ || Z_TYPE_P(op2) != IS_LONG) {
ZEND_TRY_BINARY_OBJECT_OPERATION(ZEND_SL);
- zendi_convert_to_long(op1, op1_copy, result);
- op1_lval = Z_LVAL_P(op1);
+ zendi_convert_to_bigint_or_long(op1, op1_copy, result);
zendi_convert_to_long(op2, op2_copy, result);
- } else {
- op1_lval = Z_LVAL_P(op1);
}
- ZVAL_LONG(result, op1_lval << Z_LVAL_P(op2));
- return SUCCESS;
+ switch (TYPE_PAIR(Z_TYPE_P(op1), Z_TYPE_P(op2))) {
+ case TYPE_PAIR(IS_LONG, IS_LONG):
+ ZVAL_LONG(result, Z_LVAL_P(op1) << Z_LVAL_P(op2));
+ return SUCCESS;
+ case TYPE_PAIR(IS_BIGINT, IS_LONG):
+ {
+ zend_bigint *out = zend_bigint_init_alloc();
+ zend_bigint_shift_left_ulong(out, Z_BIG_P(op1), Z_LVAL_P(op2));
+ if (op1 == result) {
+ zval_dtor(op1);
+ }
+ ZVAL_BIGINT(result, out);
+ if (op1 == &op1_copy) {
+ zval_dtor(&op1_copy);
+ }
+ }
+ return SUCCESS;
+ }
}
/* }}} */
ZEND_API int shift_right_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{{ */
{
zval op1_copy, op2_copy;
- long op1_lval;
- if (Z_TYPE_P(op1) != IS_LONG || Z_TYPE_P(op2) != IS_LONG) {
+ if (!(Z_TYPE_P(op1) == IS_LONG || Z_TYPE_P(op1) == IS_BIGINT)
+ || Z_TYPE_P(op2) != IS_LONG) {
ZEND_TRY_BINARY_OBJECT_OPERATION(ZEND_SR);
- zendi_convert_to_long(op1, op1_copy, result);
- op1_lval = Z_LVAL_P(op1);
+ zendi_convert_to_bigint_or_long(op1, op1_copy, result);
zendi_convert_to_long(op2, op2_copy, result);
- } else {
- op1_lval = Z_LVAL_P(op1);
}
- ZVAL_LONG(result, op1_lval >> Z_LVAL_P(op2));
- return SUCCESS;
+ switch (TYPE_PAIR(Z_TYPE_P(op1), Z_TYPE_P(op2))) {
+ case TYPE_PAIR(IS_LONG, IS_LONG):
+ ZVAL_LONG(result, Z_LVAL_P(op1) >> Z_LVAL_P(op2));
+ return SUCCESS;
+ case TYPE_PAIR(IS_BIGINT, IS_LONG):
+ {
+ zend_bigint *out = zend_bigint_init_alloc();
+ zend_bigint_shift_right_ulong(out, Z_BIG_P(op1), Z_LVAL_P(op2));
+ if (op1 == result) {
+ zval_dtor(op1);
+ }
+ ZVAL_BIGINT(result, out);
+ if (op1 == &op1_copy) {
+ zval_dtor(&op1_copy);
+ }
+ }
+ return SUCCESS;
+ }
}
/* }}} */
@@ -1703,6 +2501,31 @@ ZEND_API int compare_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {
}
return SUCCESS;
+ case TYPE_PAIR(IS_BIGINT, IS_BIGINT):
+ ZVAL_LONG(result, zend_bigint_cmp(Z_BIG_P(op1), Z_BIG_P(op2)));
+ ZVAL_LONG(result, ZEND_NORMALIZE_BOOL(Z_LVAL_P(result)));
+ return SUCCESS;
+
+ case TYPE_PAIR(IS_BIGINT, IS_LONG):
+ ZVAL_LONG(result, zend_bigint_cmp_long(Z_BIG_P(op1), Z_LVAL_P(op2)));
+ ZVAL_LONG(result, ZEND_NORMALIZE_BOOL(Z_LVAL_P(result)));
+ return SUCCESS;
+
+ case TYPE_PAIR(IS_LONG, IS_BIGINT):
+ ZVAL_LONG(result, zend_bigint_cmp_long(Z_BIG_P(op2), Z_LVAL_P(op1)));
+ ZVAL_LONG(result, -ZEND_NORMALIZE_BOOL(Z_LVAL_P(result)));
+ return SUCCESS;
+
+ case TYPE_PAIR(IS_BIGINT, IS_DOUBLE):
+ ZVAL_LONG(result, zend_bigint_cmp_double(Z_BIG_P(op1), Z_DVAL_P(op2)));
+ ZVAL_LONG(result, ZEND_NORMALIZE_BOOL(Z_LVAL_P(result)));
+ return SUCCESS;
+
+ case TYPE_PAIR(IS_DOUBLE, IS_BIGINT):
+ ZVAL_LONG(result, zend_bigint_cmp_double(Z_BIG_P(op2), Z_DVAL_P(op1)));
+ ZVAL_LONG(result, -ZEND_NORMALIZE_BOOL(Z_LVAL_P(result)));
+ return SUCCESS;
+
case TYPE_PAIR(IS_ARRAY, IS_ARRAY):
zend_compare_arrays(result, op1, op2 TSRMLS_CC);
return SUCCESS;
@@ -1887,6 +2710,13 @@ ZEND_API int is_identical_function(zval *result, zval *op1, zval *op2 TSRMLS_DC)
case IS_LONG:
ZVAL_BOOL(result, Z_LVAL_P(op1) == Z_LVAL_P(op2));
break;
+ case IS_BIGINT:
+ if (Z_BIG_P(op1) == Z_BIG_P(op2)) {
+ ZVAL_BOOL(result, 1);
+ } else {
+ ZVAL_BOOL(result, !zend_bigint_cmp(Z_BIG_P(op1), Z_BIG_P(op2)));
+ }
+ break;
case IS_RESOURCE:
ZVAL_BOOL(result, Z_RES_P(op1) == Z_RES_P(op2));
break;
@@ -2105,6 +2935,14 @@ try_again:
case IS_DOUBLE:
Z_DVAL_P(op1) = Z_DVAL_P(op1) + 1;
break;
+ case IS_BIGINT:
+ {
+ zend_bigint *new = zend_bigint_init_alloc();
+ zend_bigint_add_long(new, Z_BIG_P(op1), 1);
+ zval_dtor(op1);
+ Z_BIG_P(op1) = new;
+ }
+ break;
case IS_NULL:
ZVAL_LONG(op1, 1);
break;
@@ -2175,6 +3013,14 @@ try_again:
case IS_DOUBLE:
Z_DVAL_P(op1) = Z_DVAL_P(op1) - 1;
break;
+ case IS_BIGINT:
+ {
+ zend_bigint *new = zend_bigint_init_alloc();
+ zend_bigint_subtract_long(new, Z_BIG_P(op1), 1);
+ zval_dtor(op1);
+ Z_BIG_P(op1) = new;
+ }
+ break;
case IS_STRING: /* Like perl we only support string increment */
if (Z_STRLEN_P(op1) == 0) { /* consider as 0 */
STR_RELEASE(Z_STR_P(op1));
diff --git a/Zend/zend_operators.h b/Zend/zend_operators.h
index b952b98..5c33c5a 100644
--- a/Zend/zend_operators.h
+++ b/Zend/zend_operators.h
@@ -36,6 +36,7 @@
#include "zend_strtod.h"
#include "zend_multiply.h"
+#include "zend_bigint.h"
#if 0&&HAVE_BCMATH
#include "ext/bcmath/libbcmath/src/bcmath.h"
@@ -330,6 +331,10 @@ ZEND_API void _convert_to_string(zval *op ZEND_FILE_LINE_DC);
ZEND_API void convert_to_long(zval *op);
ZEND_API void convert_to_double(zval *op);
ZEND_API void convert_to_long_base(zval *op, int base);
+ZEND_API void convert_to_bigint(zval *op);
+ZEND_API void convert_to_bigint_base(zval *op, int base);
+ZEND_API void convert_to_bigint_or_long(zval *op);
+ZEND_API void convert_to_bigint_or_long_base(zval *op, int base);
ZEND_API void convert_to_null(zval *op);
ZEND_API void convert_to_boolean(zval *op);
ZEND_API void convert_to_array(zval *op);
@@ -417,6 +422,9 @@ END_EXTERN_C()
case IS_DOUBLE: \
convert_to_double(pzv); \
break; \
+ case IS_BIGINT_OR_LONG: \
+ convert_to_bigint_or_long(pzv); \
+ break; \
case _IS_BOOL: \
convert_to_boolean(pzv); \
break; \
@@ -441,13 +449,15 @@ END_EXTERN_C()
convert_to_explicit_type(pzv, str_type); \
}
-#define convert_to_boolean_ex(pzv) convert_to_ex_master(pzv, boolean, _IS_BOOL)
-#define convert_to_long_ex(pzv) convert_to_ex_master(pzv, long, IS_LONG)
-#define convert_to_double_ex(pzv) convert_to_ex_master(pzv, double, IS_DOUBLE)
-#define convert_to_string_ex(pzv) convert_to_ex_master(pzv, string, IS_STRING)
-#define convert_to_array_ex(pzv) convert_to_ex_master(pzv, array, IS_ARRAY)
-#define convert_to_object_ex(pzv) convert_to_ex_master(pzv, object, IS_OBJECT)
-#define convert_to_null_ex(pzv) convert_to_ex_master(pzv, null, IS_NULL)
+#define convert_to_boolean_ex(pzv) convert_to_ex_master(pzv, boolean, _IS_BOOL)
+#define convert_to_long_ex(pzv) convert_to_ex_master(pzv, long, IS_LONG)
+#define convert_to_double_ex(pzv) convert_to_ex_master(pzv, double, IS_DOUBLE)
+#define convert_to_bigint_ex(pzv) convert_to_ex_master(pzv, bigint, IS_LONG)
+#define convert_to_bigint_or_long_ex(pzv) convert_to_ex_master(pzv, bigint_or_long, IS_BIGINT_OR_LONG)
+#define convert_to_string_ex(pzv) convert_to_ex_master(pzv, string, IS_STRING)
+#define convert_to_array_ex(pzv) convert_to_ex_master(pzv, array, IS_ARRAY)
+#define convert_to_object_ex(pzv) convert_to_ex_master(pzv, object, IS_OBJECT)
+#define convert_to_null_ex(pzv) convert_to_ex_master(pzv, null, IS_NULL)
#define convert_scalar_to_number_ex(pzv) \
if (Z_TYPE_P(pzv)!=IS_LONG && Z_TYPE_P(pzv)!=IS_DOUBLE) { \
@@ -560,7 +570,9 @@ static zend_always_inline int fast_add_function(zval *result, zval *op1, zval *o
{
if (EXPECTED(Z_TYPE_P(op1) == IS_LONG)) {
if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) {
-#if defined(__GNUC__) && defined(__i386__)
+/* assembly commented-out as it uses the old float overflow behaviour
+ * however, now longs overflow to bigints, so we can't use it */
+/*#if defined(__GNUC__) && defined(__i386__)
__asm__(
"movl (%1), %%eax\n\t"
"addl (%2), %%eax\n\t"
@@ -606,7 +618,7 @@ static zend_always_inline int fast_add_function(zval *result, zval *op1, zval *o
"n"(IS_DOUBLE),
"n"(ZVAL_OFFSETOF_TYPE)
: "rax","cc");
-#else
+#else*/
/*
* 'result' may alias with op1 or op2, so we need to
* ensure that 'result' is not updated until after we
@@ -615,11 +627,13 @@ static zend_always_inline int fast_add_function(zval *result, zval *op1, zval *o
if (UNEXPECTED((Z_LVAL_P(op1) & LONG_SIGN_MASK) == (Z_LVAL_P(op2) & LONG_SIGN_MASK)
&& (Z_LVAL_P(op1) & LONG_SIGN_MASK) != ((Z_LVAL_P(op1) + Z_LVAL_P(op2)) & LONG_SIGN_MASK))) {
- ZVAL_DOUBLE(result, (double) Z_LVAL_P(op1) + (double) Z_LVAL_P(op2));
+ zend_bigint *out = zend_bigint_init_alloc();
+ zend_bigint_long_add_long(out, Z_LVAL_P(op1), Z_LVAL_P(op2));
+ ZVAL_BIGINT(result, out);
} else {
ZVAL_LONG(result, Z_LVAL_P(op1) + Z_LVAL_P(op2));
}
-#endif
+/*#endif*/
return SUCCESS;
} else if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) {
ZVAL_DOUBLE(result, ((double)Z_LVAL_P(op1)) + Z_DVAL_P(op2));
@@ -641,7 +655,9 @@ static zend_always_inline int fast_sub_function(zval *result, zval *op1, zval *o
{
if (EXPECTED(Z_TYPE_P(op1) == IS_LONG)) {
if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) {
-#if defined(__GNUC__) && defined(__i386__)
+/* assembly commented-out as it uses the old float overflow behaviour
+* however, now longs overflow to bigints, so we can't use it */
+/*#if defined(__GNUC__) && defined(__i386__)
__asm__(
"movl (%1), %%eax\n\t"
"subl (%2), %%eax\n\t"
@@ -654,7 +670,7 @@ static zend_always_inline int fast_sub_function(zval *result, zval *op1, zval *o
"fildl (%1)\n\t"
#if defined(__clang__) && (__clang_major__ < 2 || (__clang_major__ == 2 && __clang_minor__ < 10))
"fsubp %%st(1), %%st\n\t" /* LLVM bug #9164 */
-#else
+/*#else
"fsubp %%st, %%st(1)\n\t"
#endif
"movl %4, %c5(%0)\n\t"
@@ -681,7 +697,7 @@ static zend_always_inline int fast_sub_function(zval *result, zval *op1, zval *o
"fildq (%1)\n\t"
#if defined(__clang__) && (__clang_major__ < 2 || (__clang_major__ == 2 && __clang_minor__ < 10))
"fsubp %%st(1), %%st\n\t" /* LLVM bug #9164 */
-#else
+/*#else
"fsubp %%st, %%st(1)\n\t"
#endif
"movl %4, %c5(%0)\n\t"
@@ -695,14 +711,16 @@ static zend_always_inline int fast_sub_function(zval *result, zval *op1, zval *o
"n"(IS_DOUBLE),
"n"(ZVAL_OFFSETOF_TYPE)
: "rax","cc");
-#else
+#else*/
ZVAL_LONG(result, Z_LVAL_P(op1) - Z_LVAL_P(op2));
if (UNEXPECTED((Z_LVAL_P(op1) & LONG_SIGN_MASK) != (Z_LVAL_P(op2) & LONG_SIGN_MASK)
&& (Z_LVAL_P(op1) & LONG_SIGN_MASK) != (Z_LVAL_P(result) & LONG_SIGN_MASK))) {
- ZVAL_DOUBLE(result, (double) Z_LVAL_P(op1) - (double) Z_LVAL_P(op2));
+ zend_bigint *out = zend_bigint_init_alloc();
+ zend_bigint_long_subtract_long(out, Z_LVAL_P(op1), Z_LVAL_P(op2));
+ ZVAL_BIGINT(result, out);
}
-#endif
+/*#endif*/
return SUCCESS;
} else if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) {
ZVAL_DOUBLE(result, ((double)Z_LVAL_P(op1)) - Z_DVAL_P(op2));
@@ -726,8 +744,8 @@ static zend_always_inline int fast_mul_function(zval *result, zval *op1, zval *o
if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) {
long overflow;
- ZEND_SIGNED_MULTIPLY_LONG(Z_LVAL_P(op1), Z_LVAL_P(op2), Z_LVAL_P(result), Z_DVAL_P(result), overflow);
- Z_TYPE_INFO_P(result) = overflow ? IS_DOUBLE : IS_LONG;
+ ZEND_SIGNED_MULTIPLY_LONG(Z_LVAL_P(op1), Z_LVAL_P(op2), Z_LVAL_P(result), Z_BIG_P(result), overflow);
+ Z_TYPE_INFO_P(result) = overflow ? IS_BIGINT_EX : IS_LONG;
return SUCCESS;
} else if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) {
ZVAL_DOUBLE(result, ((double)Z_LVAL_P(op1)) * Z_DVAL_P(op2));
diff --git a/Zend/zend_types.h b/Zend/zend_types.h
index 232fcba..c773f21 100644
--- a/Zend/zend_types.h
+++ b/Zend/zend_types.h
@@ -22,6 +22,9 @@
#ifndef ZEND_TYPES_H
#define ZEND_TYPES_H
+/* For defining zend_bigint */
+#include <gmp.h>
+
#ifdef WORDS_BIGENDIAN
# define ZEND_ENDIAN_LOHI(lo, hi) hi; lo;
# define ZEND_ENDIAN_LOHI_3(lo, mi, hi) hi; mi; lo;
@@ -73,6 +76,7 @@ typedef union _zend_function zend_function;
typedef struct _zval_struct zval;
typedef struct _zend_refcounted zend_refcounted;
+typedef struct _zend_bigint zend_bigint;
typedef struct _zend_string zend_string;
typedef struct _zend_array zend_array;
typedef struct _zend_object zend_object;
@@ -89,6 +93,7 @@ typedef void (*copy_ctor_func_t)(zval *pElement);
typedef union _zend_value {
long lval; /* long value */
double dval; /* double value */
+ zend_bigint *big;
zend_refcounted *counted;
zend_string *str;
zend_array *arr;
@@ -135,6 +140,11 @@ struct _zend_refcounted {
} u;
};
+struct _zend_bigint {
+ zend_refcounted gc;
+ mpz_t mpz;
+};
+
struct _zend_string {
zend_refcounted gc;
zend_ulong h; /* hash value */
@@ -208,24 +218,26 @@ struct _zend_ast_ref {
#define IS_TRUE 3
#define IS_LONG 4
#define IS_DOUBLE 5
-#define IS_STRING 6
-#define IS_ARRAY 7
-#define IS_OBJECT 8
-#define IS_RESOURCE 9
-#define IS_REFERENCE 10
+#define IS_STRING 7
+#define IS_BIGINT 8
+#define IS_ARRAY 9
+#define IS_OBJECT 10
+#define IS_RESOURCE 11
+#define IS_REFERENCE 12
/* constant expressions */
-#define IS_CONSTANT 11
-#define IS_CONSTANT_AST 12
+#define IS_CONSTANT 13
+#define IS_CONSTANT_AST 14
/* fake types */
-#define _IS_BOOL 13
-#define IS_CALLABLE 14
+#define _IS_BOOL 15
+#define IS_CALLABLE 16
+#define IS_BIGINT_OR_LONG 17
/* internal types */
-#define IS_INDIRECT 15
-#define IS_STR_OFFSET 16
-#define IS_PTR 17
+#define IS_INDIRECT 18
+#define IS_STR_OFFSET 19
+#define IS_PTR 20
static inline zend_uchar zval_get_type(const zval* pz) {
return pz->u1.v.type;
@@ -289,6 +301,7 @@ static inline zend_uchar zval_get_type(const zval* pz) {
#define IS_STRING_EX (IS_STRING | (( IS_TYPE_REFCOUNTED | IS_TYPE_COPYABLE) << Z_TYPE_FLAGS_SHIFT))
#define IS_ARRAY_EX (IS_ARRAY | (( IS_TYPE_REFCOUNTED | IS_TYPE_COLLECTABLE | IS_TYPE_COPYABLE) << Z_TYPE_FLAGS_SHIFT))
+#define IS_BIGINT_EX (IS_BIGINT | (( IS_TYPE_REFCOUNTED ) << Z_TYPE_FLAGS_SHIFT))
#define IS_OBJECT_EX (IS_OBJECT | (( IS_TYPE_REFCOUNTED | IS_TYPE_COLLECTABLE ) << Z_TYPE_FLAGS_SHIFT))
#define IS_RESOURCE_EX (IS_RESOURCE | (( IS_TYPE_REFCOUNTED ) << Z_TYPE_FLAGS_SHIFT))
#define IS_REFERENCE_EX (IS_REFERENCE | (( IS_TYPE_REFCOUNTED ) << Z_TYPE_FLAGS_SHIFT))
@@ -387,6 +400,9 @@ static inline zend_uchar zval_get_type(const zval* pz) {
#define Z_DVAL(zval) (zval).value.dval
#define Z_DVAL_P(zval_p) Z_DVAL(*(zval_p))
+#define Z_BIG(zval) (zval).value.big
+#define Z_BIG_P(zval_p) Z_BIG(*(zval_p))
+
#define Z_STR(zval) (zval).value.str
#define Z_STR_P(zval_p) Z_STR(*(zval_p))
@@ -495,6 +511,21 @@ static inline zend_uchar zval_get_type(const zval* pz) {
Z_TYPE_INFO_P(__z) = IS_DOUBLE; \
}
+#define ZVAL_BIGINT(z, b) { \
+ zval *__z = (z); \
+ Z_BIG_P(__z) = b; \
+ Z_TYPE_INFO_P(__z) = IS_BIGINT_EX; \
+ }
+
+#define ZVAL_NEW_BIGINT(z) do { \
+ zval *__z = (z); \
+ zend_bigint *_big = emalloc(sizeof(zend_bigint)); \
+ GC_REFCOUNT(_big) = 1; \
+ GC_TYPE_INFO(_big) = IS_BIGINT; \
+ Z_BIG_P(__z) = _big; \
+ Z_TYPE_INFO_P(__z) = IS_BIGINT_EX; \
+ } while (0)
+
#define ZVAL_STR(z, s) do { \
zval *__z = (z); \
zend_string *__s = (s); \
diff --git a/Zend/zend_variables.c b/Zend/zend_variables.c
index 2031b01..07210df 100644
--- a/Zend/zend_variables.c
+++ b/Zend/zend_variables.c
@@ -26,6 +26,7 @@
#include "zend_globals.h"
#include "zend_constants.h"
#include "zend_list.h"
+#include "zend_bigint.h"
ZEND_API void _zval_dtor_func(zend_refcounted *p ZEND_FILE_LINE_DC)
{
@@ -50,6 +51,15 @@ ZEND_API void _zval_dtor_func(zend_refcounted *p ZEND_FILE_LINE_DC)
}
break;
}
+ case IS_BIGINT: {
+ zend_bigint *big = (zend_bigint*)p;
+
+ if (--GC_REFCOUNT(big) <= 0) {
+ zend_bigint_dtor(big);
+ efree(big);
+ }
+ break;
+ }
case IS_CONSTANT_AST: {
zend_ast_ref *ast = (zend_ast_ref*)p;
@@ -110,6 +120,13 @@ ZEND_API void _zval_dtor_func_for_ptr(zend_refcounted *p ZEND_FILE_LINE_DC)
}
break;
}
+ case IS_BIGINT: {
+ zend_bigint *big = (zend_bigint*)p;
+
+ zend_bigint_dtor(big);
+ efree(big);
+ break;
+ }
case IS_CONSTANT_AST: {
zend_ast_ref *ast = (zend_ast_ref*)p;
@@ -153,10 +170,11 @@ ZEND_API void _zval_internal_dtor(zval *zvalue ZEND_FILE_LINE_DC)
STR_RELEASE(Z_STR_P(zvalue));
break;
case IS_ARRAY:
+ case IS_BIGINT:
case IS_CONSTANT_AST:
case IS_OBJECT:
case IS_RESOURCE:
- zend_error(E_CORE_ERROR, "Internal zval's can't be arrays, objects or resources");
+ zend_error(E_CORE_ERROR, "Internal zval's can't be arrays, bigints, constant ASTs, objects or resources");
break;
case IS_REFERENCE: {
zend_reference *ref = (zend_reference*)Z_REF_P(zvalue);
@@ -184,10 +202,11 @@ ZEND_API void _zval_internal_dtor_for_ptr(zval *zvalue ZEND_FILE_LINE_DC)
STR_FREE(Z_STR_P(zvalue));
break;
case IS_ARRAY:
+ case IS_BIGINT:
case IS_CONSTANT_AST:
case IS_OBJECT:
case IS_RESOURCE:
- zend_error(E_CORE_ERROR, "Internal zval's can't be arrays, objects or resources");
+ zend_error(E_CORE_ERROR, "Internal zval's can't be arrays, bigints, constant ASTs, objects or resources");
break;
case IS_REFERENCE: {
zend_reference *ref = (zend_reference*)Z_REF_P(zvalue);
@@ -257,6 +276,7 @@ ZEND_API void _zval_copy_ctor_func(zval *zvalue ZEND_FILE_LINE_DC)
Z_AST_P(zvalue) = ast;
}
break;
+ case IS_BIGINT:
case IS_OBJECT:
case IS_RESOURCE:
case IS_REFERENCE:
diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h
index 8aa60ce..7f66b7c 100644
--- a/Zend/zend_vm_def.h
+++ b/Zend/zend_vm_def.h
@@ -3763,6 +3763,17 @@ ZEND_VM_C_LABEL(num_index):
ZEND_VM_C_LABEL(str_index):
zend_hash_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), str, expr_ptr);
break;
+ case IS_BIGINT:
+ {
+ char *temp_str = zend_bigint_to_string(Z_BIG_P(offset));
+ if (ZEND_HANDLE_NUMERIC_STR(temp_str, strlen(temp_str), hval)) {
+ zend_hash_index_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), hval, expr_ptr);
+ } else {
+ zend_hash_str_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), temp_str, strlen(temp_str), expr_ptr);
+ }
+ efree(temp_str);
+ }
+ break;
case IS_NULL:
str = STR_EMPTY_ALLOC();
ZEND_VM_C_GOTO(str_index);
@@ -4174,6 +4185,21 @@ ZEND_VM_C_LABEL(num_index_dim):
zval_ptr_dtor(offset);
}
break;
+ case IS_BIGINT:
+ {
+ zend_string *temp_str = zend_bigint_to_zend_string(Z_BIG_P(offset), 0);
+ if (ZEND_HANDLE_NUMERIC(temp_str, hval)) {
+ zend_hash_index_del(ht, hval);
+ } else {
+ if (ht == &EG(symbol_table).ht) {
+ zend_delete_global_variable(temp_str TSRMLS_CC);
+ } else {
+ zend_hash_del(ht, temp_str);
+ }
+ }
+ STR_RELEASE(temp_str);
+ }
+ break;
ZEND_VM_C_LABEL(numeric_index_dim):
zend_hash_index_del(ht, hval);
if (OP2_TYPE == IS_CV || OP2_TYPE == IS_VAR) {
@@ -4701,6 +4727,17 @@ ZEND_VM_C_LABEL(num_index_prop):
case IS_DOUBLE:
hval = zend_dval_to_lval(Z_DVAL_P(offset));
ZEND_VM_C_GOTO(num_index_prop);
+ case IS_BIGINT:
+ {
+ char *temp_str = zend_bigint_to_string(Z_BIG_P(offset));
+ if (ZEND_HANDLE_NUMERIC_STR(temp_str, strlen(temp_str), hval)) {
+ value = zend_hash_index_find(ht, hval);
+ } else {
+ value = zend_hash_str_find_ind(ht, temp_str, strlen(temp_str));
+ }
+ efree(temp_str);
+ }
+ break;
case IS_NULL:
str = STR_EMPTY_ALLOC();
ZEND_VM_C_GOTO(str_index_prop);
@@ -4750,6 +4787,9 @@ ZEND_VM_C_LABEL(num_index_prop):
ZVAL_DUP(&tmp, offset);
convert_to_long(&tmp);
offset = &tmp;
+ } else if (Z_TYPE_P(offset) == IS_BIGINT) {
+ ZVAL_LONG(&tmp, zend_bigint_to_long(Z_BIG_P(offset)));
+ offset = &tmp;
}
}
if (Z_TYPE_P(offset) == IS_LONG) {
@@ -4819,6 +4859,8 @@ ZEND_VM_HANDLER(79, ZEND_EXIT, CONST|TMP|VAR|UNUSED|CV, ANY)
if (Z_TYPE_P(ptr) == IS_LONG) {
EG(exit_status) = Z_LVAL_P(ptr);
+ } else if (Z_TYPE_P(ptr) == IS_BIGINT) {
+ EG(exit_status) = zend_bigint_to_long(Z_BIG_P(ptr));
} else {
zend_print_variable(ptr TSRMLS_CC);
}
diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h
index 1babe85..c83ec5d 100644
--- a/Zend/zend_vm_execute.h
+++ b/Zend/zend_vm_execute.h
@@ -3220,6 +3220,8 @@ static int ZEND_FASTCALL ZEND_EXIT_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
if (Z_TYPE_P(ptr) == IS_LONG) {
EG(exit_status) = Z_LVAL_P(ptr);
+ } else if (Z_TYPE_P(ptr) == IS_BIGINT) {
+ EG(exit_status) = zend_bigint_to_long(Z_BIG_P(ptr));
} else {
zend_print_variable(ptr TSRMLS_CC);
}
@@ -4071,6 +4073,17 @@ num_index:
str_index:
zend_hash_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), str, expr_ptr);
break;
+ case IS_BIGINT:
+ {
+ char *temp_str = zend_bigint_to_string(Z_BIG_P(offset));
+ if (ZEND_HANDLE_NUMERIC_STR(temp_str, strlen(temp_str), hval)) {
+ zend_hash_index_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), hval, expr_ptr);
+ } else {
+ zend_hash_str_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), temp_str, strlen(temp_str), expr_ptr);
+ }
+ efree(temp_str);
+ }
+ break;
case IS_NULL:
str = STR_EMPTY_ALLOC();
goto str_index;
@@ -4941,6 +4954,17 @@ num_index:
str_index:
zend_hash_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), str, expr_ptr);
break;
+ case IS_BIGINT:
+ {
+ char *temp_str = zend_bigint_to_string(Z_BIG_P(offset));
+ if (ZEND_HANDLE_NUMERIC_STR(temp_str, strlen(temp_str), hval)) {
+ zend_hash_index_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), hval, expr_ptr);
+ } else {
+ zend_hash_str_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), temp_str, strlen(temp_str), expr_ptr);
+ }
+ efree(temp_str);
+ }
+ break;
case IS_NULL:
str = STR_EMPTY_ALLOC();
goto str_index;
@@ -5775,6 +5799,17 @@ num_index:
str_index:
zend_hash_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), str, expr_ptr);
break;
+ case IS_BIGINT:
+ {
+ char *temp_str = zend_bigint_to_string(Z_BIG_P(offset));
+ if (ZEND_HANDLE_NUMERIC_STR(temp_str, strlen(temp_str), hval)) {
+ zend_hash_index_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), hval, expr_ptr);
+ } else {
+ zend_hash_str_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), temp_str, strlen(temp_str), expr_ptr);
+ }
+ efree(temp_str);
+ }
+ break;
case IS_NULL:
str = STR_EMPTY_ALLOC();
goto str_index;
@@ -6452,6 +6487,17 @@ num_index:
str_index:
zend_hash_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), str, expr_ptr);
break;
+ case IS_BIGINT:
+ {
+ char *temp_str = zend_bigint_to_string(Z_BIG_P(offset));
+ if (ZEND_HANDLE_NUMERIC_STR(temp_str, strlen(temp_str), hval)) {
+ zend_hash_index_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), hval, expr_ptr);
+ } else {
+ zend_hash_str_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), temp_str, strlen(temp_str), expr_ptr);
+ }
+ efree(temp_str);
+ }
+ break;
case IS_NULL:
str = STR_EMPTY_ALLOC();
goto str_index;
@@ -7344,6 +7390,17 @@ num_index:
str_index:
zend_hash_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), str, expr_ptr);
break;
+ case IS_BIGINT:
+ {
+ char *temp_str = zend_bigint_to_string(Z_BIG_P(offset));
+ if (ZEND_HANDLE_NUMERIC_STR(temp_str, strlen(temp_str), hval)) {
+ zend_hash_index_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), hval, expr_ptr);
+ } else {
+ zend_hash_str_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), temp_str, strlen(temp_str), expr_ptr);
+ }
+ efree(temp_str);
+ }
+ break;
case IS_NULL:
str = STR_EMPTY_ALLOC();
goto str_index;
@@ -8410,6 +8467,8 @@ static int ZEND_FASTCALL ZEND_EXIT_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
if (Z_TYPE_P(ptr) == IS_LONG) {
EG(exit_status) = Z_LVAL_P(ptr);
+ } else if (Z_TYPE_P(ptr) == IS_BIGINT) {
+ EG(exit_status) = zend_bigint_to_long(Z_BIG_P(ptr));
} else {
zend_print_variable(ptr TSRMLS_CC);
}
@@ -9205,6 +9264,17 @@ num_index:
str_index:
zend_hash_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), str, expr_ptr);
break;
+ case IS_BIGINT:
+ {
+ char *temp_str = zend_bigint_to_string(Z_BIG_P(offset));
+ if (ZEND_HANDLE_NUMERIC_STR(temp_str, strlen(temp_str), hval)) {
+ zend_hash_index_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), hval, expr_ptr);
+ } else {
+ zend_hash_str_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), temp_str, strlen(temp_str), expr_ptr);
+ }
+ efree(temp_str);
+ }
+ break;
case IS_NULL:
str = STR_EMPTY_ALLOC();
goto str_index;
@@ -10042,6 +10112,17 @@ num_index:
str_index:
zend_hash_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), str, expr_ptr);
break;
+ case IS_BIGINT:
+ {
+ char *temp_str = zend_bigint_to_string(Z_BIG_P(offset));
+ if (ZEND_HANDLE_NUMERIC_STR(temp_str, strlen(temp_str), hval)) {
+ zend_hash_index_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), hval, expr_ptr);
+ } else {
+ zend_hash_str_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), temp_str, strlen(temp_str), expr_ptr);
+ }
+ efree(temp_str);
+ }
+ break;
case IS_NULL:
str = STR_EMPTY_ALLOC();
goto str_index;
@@ -10876,6 +10957,17 @@ num_index:
str_index:
zend_hash_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), str, expr_ptr);
break;
+ case IS_BIGINT:
+ {
+ char *temp_str = zend_bigint_to_string(Z_BIG_P(offset));
+ if (ZEND_HANDLE_NUMERIC_STR(temp_str, strlen(temp_str), hval)) {
+ zend_hash_index_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), hval, expr_ptr);
+ } else {
+ zend_hash_str_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), temp_str, strlen(temp_str), expr_ptr);
+ }
+ efree(temp_str);
+ }
+ break;
case IS_NULL:
str = STR_EMPTY_ALLOC();
goto str_index;
@@ -11439,6 +11531,17 @@ num_index:
str_index:
zend_hash_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), str, expr_ptr);
break;
+ case IS_BIGINT:
+ {
+ char *temp_str = zend_bigint_to_string(Z_BIG_P(offset));
+ if (ZEND_HANDLE_NUMERIC_STR(temp_str, strlen(temp_str), hval)) {
+ zend_hash_index_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), hval, expr_ptr);
+ } else {
+ zend_hash_str_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), temp_str, strlen(temp_str), expr_ptr);
+ }
+ efree(temp_str);
+ }
+ break;
case IS_NULL:
str = STR_EMPTY_ALLOC();
goto str_index;
@@ -12258,6 +12361,17 @@ num_index:
str_index:
zend_hash_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), str, expr_ptr);
break;
+ case IS_BIGINT:
+ {
+ char *temp_str = zend_bigint_to_string(Z_BIG_P(offset));
+ if (ZEND_HANDLE_NUMERIC_STR(temp_str, strlen(temp_str), hval)) {
+ zend_hash_index_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), hval, expr_ptr);
+ } else {
+ zend_hash_str_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), temp_str, strlen(temp_str), expr_ptr);
+ }
+ efree(temp_str);
+ }
+ break;
case IS_NULL:
str = STR_EMPTY_ALLOC();
goto str_index;
@@ -13810,6 +13924,8 @@ static int ZEND_FASTCALL ZEND_EXIT_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
if (Z_TYPE_P(ptr) == IS_LONG) {
EG(exit_status) = Z_LVAL_P(ptr);
+ } else if (Z_TYPE_P(ptr) == IS_BIGINT) {
+ EG(exit_status) = zend_bigint_to_long(Z_BIG_P(ptr));
} else {
zend_print_variable(ptr TSRMLS_CC);
}
@@ -15680,6 +15796,17 @@ num_index:
str_index:
zend_hash_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), str, expr_ptr);
break;
+ case IS_BIGINT:
+ {
+ char *temp_str = zend_bigint_to_string(Z_BIG_P(offset));
+ if (ZEND_HANDLE_NUMERIC_STR(temp_str, strlen(temp_str), hval)) {
+ zend_hash_index_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), hval, expr_ptr);
+ } else {
+ zend_hash_str_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), temp_str, strlen(temp_str), expr_ptr);
+ }
+ efree(temp_str);
+ }
+ break;
case IS_NULL:
str = STR_EMPTY_ALLOC();
goto str_index;
@@ -15858,6 +15985,21 @@ num_index_dim:
zval_ptr_dtor(offset);
}
break;
+ case IS_BIGINT:
+ {
+ zend_string *temp_str = zend_bigint_to_zend_string(Z_BIG_P(offset), 0);
+ if (ZEND_HANDLE_NUMERIC(temp_str, hval)) {
+ zend_hash_index_del(ht, hval);
+ } else {
+ if (ht == &EG(symbol_table).ht) {
+ zend_delete_global_variable(temp_str TSRMLS_CC);
+ } else {
+ zend_hash_del(ht, temp_str);
+ }
+ }
+ STR_RELEASE(temp_str);
+ }
+ break;
numeric_index_dim:
zend_hash_index_del(ht, hval);
if (IS_CONST == IS_CV || IS_CONST == IS_VAR) {
@@ -16058,6 +16200,17 @@ num_index_prop:
case IS_DOUBLE:
hval = zend_dval_to_lval(Z_DVAL_P(offset));
goto num_index_prop;
+ case IS_BIGINT:
+ {
+ char *temp_str = zend_bigint_to_string(Z_BIG_P(offset));
+ if (ZEND_HANDLE_NUMERIC_STR(temp_str, strlen(temp_str), hval)) {
+ value = zend_hash_index_find(ht, hval);
+ } else {
+ value = zend_hash_str_find_ind(ht, temp_str, strlen(temp_str));
+ }
+ efree(temp_str);
+ }
+ break;
case IS_NULL:
str = STR_EMPTY_ALLOC();
goto str_index_prop;
@@ -16107,6 +16260,9 @@ num_index_prop:
ZVAL_DUP(&tmp, offset);
convert_to_long(&tmp);
offset = &tmp;
+ } else if (Z_TYPE_P(offset) == IS_BIGINT) {
+ ZVAL_LONG(&tmp, zend_bigint_to_long(Z_BIG_P(offset)));
+ offset = &tmp;
}
}
if (Z_TYPE_P(offset) == IS_LONG) {
@@ -17821,6 +17977,17 @@ num_index:
str_index:
zend_hash_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), str, expr_ptr);
break;
+ case IS_BIGINT:
+ {
+ char *temp_str = zend_bigint_to_string(Z_BIG_P(offset));
+ if (ZEND_HANDLE_NUMERIC_STR(temp_str, strlen(temp_str), hval)) {
+ zend_hash_index_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), hval, expr_ptr);
+ } else {
+ zend_hash_str_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), temp_str, strlen(temp_str), expr_ptr);
+ }
+ efree(temp_str);
+ }
+ break;
case IS_NULL:
str = STR_EMPTY_ALLOC();
goto str_index;
@@ -17927,6 +18094,21 @@ num_index_dim:
zval_ptr_dtor(offset);
}
break;
+ case IS_BIGINT:
+ {
+ zend_string *temp_str = zend_bigint_to_zend_string(Z_BIG_P(offset), 0);
+ if (ZEND_HANDLE_NUMERIC(temp_str, hval)) {
+ zend_hash_index_del(ht, hval);
+ } else {
+ if (ht == &EG(symbol_table).ht) {
+ zend_delete_global_variable(temp_str TSRMLS_CC);
+ } else {
+ zend_hash_del(ht, temp_str);
+ }
+ }
+ STR_RELEASE(temp_str);
+ }
+ break;
numeric_index_dim:
zend_hash_index_del(ht, hval);
if (IS_TMP_VAR == IS_CV || IS_TMP_VAR == IS_VAR) {
@@ -18048,6 +18230,17 @@ num_index_prop:
case IS_DOUBLE:
hval = zend_dval_to_lval(Z_DVAL_P(offset));
goto num_index_prop;
+ case IS_BIGINT:
+ {
+ char *temp_str = zend_bigint_to_string(Z_BIG_P(offset));
+ if (ZEND_HANDLE_NUMERIC_STR(temp_str, strlen(temp_str), hval)) {
+ value = zend_hash_index_find(ht, hval);
+ } else {
+ value = zend_hash_str_find_ind(ht, temp_str, strlen(temp_str));
+ }
+ efree(temp_str);
+ }
+ break;
case IS_NULL:
str = STR_EMPTY_ALLOC();
goto str_index_prop;
@@ -18097,6 +18290,9 @@ num_index_prop:
ZVAL_DUP(&tmp, offset);
convert_to_long(&tmp);
offset = &tmp;
+ } else if (Z_TYPE_P(offset) == IS_BIGINT) {
+ ZVAL_LONG(&tmp, zend_bigint_to_long(Z_BIG_P(offset)));
+ offset = &tmp;
}
}
if (Z_TYPE_P(offset) == IS_LONG) {
@@ -20025,6 +20221,17 @@ num_index:
str_index:
zend_hash_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), str, expr_ptr);
break;
+ case IS_BIGINT:
+ {
+ char *temp_str = zend_bigint_to_string(Z_BIG_P(offset));
+ if (ZEND_HANDLE_NUMERIC_STR(temp_str, strlen(temp_str), hval)) {
+ zend_hash_index_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), hval, expr_ptr);
+ } else {
+ zend_hash_str_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), temp_str, strlen(temp_str), expr_ptr);
+ }
+ efree(temp_str);
+ }
+ break;
case IS_NULL:
str = STR_EMPTY_ALLOC();
goto str_index;
@@ -20203,6 +20410,21 @@ num_index_dim:
zval_ptr_dtor(offset);
}
break;
+ case IS_BIGINT:
+ {
+ zend_string *temp_str = zend_bigint_to_zend_string(Z_BIG_P(offset), 0);
+ if (ZEND_HANDLE_NUMERIC(temp_str, hval)) {
+ zend_hash_index_del(ht, hval);
+ } else {
+ if (ht == &EG(symbol_table).ht) {
+ zend_delete_global_variable(temp_str TSRMLS_CC);
+ } else {
+ zend_hash_del(ht, temp_str);
+ }
+ }
+ STR_RELEASE(temp_str);
+ }
+ break;
numeric_index_dim:
zend_hash_index_del(ht, hval);
if (IS_VAR == IS_CV || IS_VAR == IS_VAR) {
@@ -20403,6 +20625,17 @@ num_index_prop:
case IS_DOUBLE:
hval = zend_dval_to_lval(Z_DVAL_P(offset));
goto num_index_prop;
+ case IS_BIGINT:
+ {
+ char *temp_str = zend_bigint_to_string(Z_BIG_P(offset));
+ if (ZEND_HANDLE_NUMERIC_STR(temp_str, strlen(temp_str), hval)) {
+ value = zend_hash_index_find(ht, hval);
+ } else {
+ value = zend_hash_str_find_ind(ht, temp_str, strlen(temp_str));
+ }
+ efree(temp_str);
+ }
+ break;
case IS_NULL:
str = STR_EMPTY_ALLOC();
goto str_index_prop;
@@ -20452,6 +20685,9 @@ num_index_prop:
ZVAL_DUP(&tmp, offset);
convert_to_long(&tmp);
offset = &tmp;
+ } else if (Z_TYPE_P(offset) == IS_BIGINT) {
+ ZVAL_LONG(&tmp, zend_bigint_to_long(Z_BIG_P(offset)));
+ offset = &tmp;
}
}
if (Z_TYPE_P(offset) == IS_LONG) {
@@ -21483,6 +21719,17 @@ num_index:
str_index:
zend_hash_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), str, expr_ptr);
break;
+ case IS_BIGINT:
+ {
+ char *temp_str = zend_bigint_to_string(Z_BIG_P(offset));
+ if (ZEND_HANDLE_NUMERIC_STR(temp_str, strlen(temp_str), hval)) {
+ zend_hash_index_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), hval, expr_ptr);
+ } else {
+ zend_hash_str_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), temp_str, strlen(temp_str), expr_ptr);
+ }
+ efree(temp_str);
+ }
+ break;
case IS_NULL:
str = STR_EMPTY_ALLOC();
goto str_index;
@@ -23408,6 +23655,17 @@ num_index:
str_index:
zend_hash_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), str, expr_ptr);
break;
+ case IS_BIGINT:
+ {
+ char *temp_str = zend_bigint_to_string(Z_BIG_P(offset));
+ if (ZEND_HANDLE_NUMERIC_STR(temp_str, strlen(temp_str), hval)) {
+ zend_hash_index_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), hval, expr_ptr);
+ } else {
+ zend_hash_str_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), temp_str, strlen(temp_str), expr_ptr);
+ }
+ efree(temp_str);
+ }
+ break;
case IS_NULL:
str = STR_EMPTY_ALLOC();
goto str_index;
@@ -23514,6 +23772,21 @@ num_index_dim:
zval_ptr_dtor(offset);
}
break;
+ case IS_BIGINT:
+ {
+ zend_string *temp_str = zend_bigint_to_zend_string(Z_BIG_P(offset), 0);
+ if (ZEND_HANDLE_NUMERIC(temp_str, hval)) {
+ zend_hash_index_del(ht, hval);
+ } else {
+ if (ht == &EG(symbol_table).ht) {
+ zend_delete_global_variable(temp_str TSRMLS_CC);
+ } else {
+ zend_hash_del(ht, temp_str);
+ }
+ }
+ STR_RELEASE(temp_str);
+ }
+ break;
numeric_index_dim:
zend_hash_index_del(ht, hval);
if (IS_CV == IS_CV || IS_CV == IS_VAR) {
@@ -23635,6 +23908,17 @@ num_index_prop:
case IS_DOUBLE:
hval = zend_dval_to_lval(Z_DVAL_P(offset));
goto num_index_prop;
+ case IS_BIGINT:
+ {
+ char *temp_str = zend_bigint_to_string(Z_BIG_P(offset));
+ if (ZEND_HANDLE_NUMERIC_STR(temp_str, strlen(temp_str), hval)) {
+ value = zend_hash_index_find(ht, hval);
+ } else {
+ value = zend_hash_str_find_ind(ht, temp_str, strlen(temp_str));
+ }
+ efree(temp_str);
+ }
+ break;
case IS_NULL:
str = STR_EMPTY_ALLOC();
goto str_index_prop;
@@ -23684,6 +23968,9 @@ num_index_prop:
ZVAL_DUP(&tmp, offset);
convert_to_long(&tmp);
offset = &tmp;
+ } else if (Z_TYPE_P(offset) == IS_BIGINT) {
+ ZVAL_LONG(&tmp, zend_bigint_to_long(Z_BIG_P(offset)));
+ offset = &tmp;
}
}
if (Z_TYPE_P(offset) == IS_LONG) {
@@ -23960,6 +24247,8 @@ static int ZEND_FASTCALL ZEND_EXIT_SPEC_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS
if (Z_TYPE_P(ptr) == IS_LONG) {
EG(exit_status) = Z_LVAL_P(ptr);
+ } else if (Z_TYPE_P(ptr) == IS_BIGINT) {
+ EG(exit_status) = zend_bigint_to_long(Z_BIG_P(ptr));
} else {
zend_print_variable(ptr TSRMLS_CC);
}
@@ -24982,6 +25271,21 @@ num_index_dim:
zval_ptr_dtor(offset);
}
break;
+ case IS_BIGINT:
+ {
+ zend_string *temp_str = zend_bigint_to_zend_string(Z_BIG_P(offset), 0);
+ if (ZEND_HANDLE_NUMERIC(temp_str, hval)) {
+ zend_hash_index_del(ht, hval);
+ } else {
+ if (ht == &EG(symbol_table).ht) {
+ zend_delete_global_variable(temp_str TSRMLS_CC);
+ } else {
+ zend_hash_del(ht, temp_str);
+ }
+ }
+ STR_RELEASE(temp_str);
+ }
+ break;
numeric_index_dim:
zend_hash_index_del(ht, hval);
if (IS_CONST == IS_CV || IS_CONST == IS_VAR) {
@@ -25103,6 +25407,17 @@ num_index_prop:
case IS_DOUBLE:
hval = zend_dval_to_lval(Z_DVAL_P(offset));
goto num_index_prop;
+ case IS_BIGINT:
+ {
+ char *temp_str = zend_bigint_to_string(Z_BIG_P(offset));
+ if (ZEND_HANDLE_NUMERIC_STR(temp_str, strlen(temp_str), hval)) {
+ value = zend_hash_index_find(ht, hval);
+ } else {
+ value = zend_hash_str_find_ind(ht, temp_str, strlen(temp_str));
+ }
+ efree(temp_str);
+ }
+ break;
case IS_NULL:
str = STR_EMPTY_ALLOC();
goto str_index_prop;
@@ -25152,6 +25467,9 @@ num_index_prop:
ZVAL_DUP(&tmp, offset);
convert_to_long(&tmp);
offset = &tmp;
+ } else if (Z_TYPE_P(offset) == IS_BIGINT) {
+ ZVAL_LONG(&tmp, zend_bigint_to_long(Z_BIG_P(offset)));
+ offset = &tmp;
}
}
if (Z_TYPE_P(offset) == IS_LONG) {
@@ -26267,6 +26585,21 @@ num_index_dim:
zval_ptr_dtor(offset);
}
break;
+ case IS_BIGINT:
+ {
+ zend_string *temp_str = zend_bigint_to_zend_string(Z_BIG_P(offset), 0);
+ if (ZEND_HANDLE_NUMERIC(temp_str, hval)) {
+ zend_hash_index_del(ht, hval);
+ } else {
+ if (ht == &EG(symbol_table).ht) {
+ zend_delete_global_variable(temp_str TSRMLS_CC);
+ } else {
+ zend_hash_del(ht, temp_str);
+ }
+ }
+ STR_RELEASE(temp_str);
+ }
+ break;
numeric_index_dim:
zend_hash_index_del(ht, hval);
if (IS_TMP_VAR == IS_CV || IS_TMP_VAR == IS_VAR) {
@@ -26388,6 +26721,17 @@ num_index_prop:
case IS_DOUBLE:
hval = zend_dval_to_lval(Z_DVAL_P(offset));
goto num_index_prop;
+ case IS_BIGINT:
+ {
+ char *temp_str = zend_bigint_to_string(Z_BIG_P(offset));
+ if (ZEND_HANDLE_NUMERIC_STR(temp_str, strlen(temp_str), hval)) {
+ value = zend_hash_index_find(ht, hval);
+ } else {
+ value = zend_hash_str_find_ind(ht, temp_str, strlen(temp_str));
+ }
+ efree(temp_str);
+ }
+ break;
case IS_NULL:
str = STR_EMPTY_ALLOC();
goto str_index_prop;
@@ -26437,6 +26781,9 @@ num_index_prop:
ZVAL_DUP(&tmp, offset);
convert_to_long(&tmp);
offset = &tmp;
+ } else if (Z_TYPE_P(offset) == IS_BIGINT) {
+ ZVAL_LONG(&tmp, zend_bigint_to_long(Z_BIG_P(offset)));
+ offset = &tmp;
}
}
if (Z_TYPE_P(offset) == IS_LONG) {
@@ -27554,6 +27901,21 @@ num_index_dim:
zval_ptr_dtor(offset);
}
break;
+ case IS_BIGINT:
+ {
+ zend_string *temp_str = zend_bigint_to_zend_string(Z_BIG_P(offset), 0);
+ if (ZEND_HANDLE_NUMERIC(temp_str, hval)) {
+ zend_hash_index_del(ht, hval);
+ } else {
+ if (ht == &EG(symbol_table).ht) {
+ zend_delete_global_variable(temp_str TSRMLS_CC);
+ } else {
+ zend_hash_del(ht, temp_str);
+ }
+ }
+ STR_RELEASE(temp_str);
+ }
+ break;
numeric_index_dim:
zend_hash_index_del(ht, hval);
if (IS_VAR == IS_CV || IS_VAR == IS_VAR) {
@@ -27675,6 +28037,17 @@ num_index_prop:
case IS_DOUBLE:
hval = zend_dval_to_lval(Z_DVAL_P(offset));
goto num_index_prop;
+ case IS_BIGINT:
+ {
+ char *temp_str = zend_bigint_to_string(Z_BIG_P(offset));
+ if (ZEND_HANDLE_NUMERIC_STR(temp_str, strlen(temp_str), hval)) {
+ value = zend_hash_index_find(ht, hval);
+ } else {
+ value = zend_hash_str_find_ind(ht, temp_str, strlen(temp_str));
+ }
+ efree(temp_str);
+ }
+ break;
case IS_NULL:
str = STR_EMPTY_ALLOC();
goto str_index_prop;
@@ -27724,6 +28097,9 @@ num_index_prop:
ZVAL_DUP(&tmp, offset);
convert_to_long(&tmp);
offset = &tmp;
+ } else if (Z_TYPE_P(offset) == IS_BIGINT) {
+ ZVAL_LONG(&tmp, zend_bigint_to_long(Z_BIG_P(offset)));
+ offset = &tmp;
}
}
if (Z_TYPE_P(offset) == IS_LONG) {
@@ -29356,6 +29732,21 @@ num_index_dim:
zval_ptr_dtor(offset);
}
break;
+ case IS_BIGINT:
+ {
+ zend_string *temp_str = zend_bigint_to_zend_string(Z_BIG_P(offset), 0);
+ if (ZEND_HANDLE_NUMERIC(temp_str, hval)) {
+ zend_hash_index_del(ht, hval);
+ } else {
+ if (ht == &EG(symbol_table).ht) {
+ zend_delete_global_variable(temp_str TSRMLS_CC);
+ } else {
+ zend_hash_del(ht, temp_str);
+ }
+ }
+ STR_RELEASE(temp_str);
+ }
+ break;
numeric_index_dim:
zend_hash_index_del(ht, hval);
if (IS_CV == IS_CV || IS_CV == IS_VAR) {
@@ -29477,6 +29868,17 @@ num_index_prop:
case IS_DOUBLE:
hval = zend_dval_to_lval(Z_DVAL_P(offset));
goto num_index_prop;
+ case IS_BIGINT:
+ {
+ char *temp_str = zend_bigint_to_string(Z_BIG_P(offset));
+ if (ZEND_HANDLE_NUMERIC_STR(temp_str, strlen(temp_str), hval)) {
+ value = zend_hash_index_find(ht, hval);
+ } else {
+ value = zend_hash_str_find_ind(ht, temp_str, strlen(temp_str));
+ }
+ efree(temp_str);
+ }
+ break;
case IS_NULL:
str = STR_EMPTY_ALLOC();
goto str_index_prop;
@@ -29526,6 +29928,9 @@ num_index_prop:
ZVAL_DUP(&tmp, offset);
convert_to_long(&tmp);
offset = &tmp;
+ } else if (Z_TYPE_P(offset) == IS_BIGINT) {
+ ZVAL_LONG(&tmp, zend_bigint_to_long(Z_BIG_P(offset)));
+ offset = &tmp;
}
}
if (Z_TYPE_P(offset) == IS_LONG) {
@@ -30883,6 +31288,8 @@ static int ZEND_FASTCALL ZEND_EXIT_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
if (Z_TYPE_P(ptr) == IS_LONG) {
EG(exit_status) = Z_LVAL_P(ptr);
+ } else if (Z_TYPE_P(ptr) == IS_BIGINT) {
+ EG(exit_status) = zend_bigint_to_long(Z_BIG_P(ptr));
} else {
zend_print_variable(ptr TSRMLS_CC);
}
@@ -32536,6 +32943,17 @@ num_index:
str_index:
zend_hash_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), str, expr_ptr);
break;
+ case IS_BIGINT:
+ {
+ char *temp_str = zend_bigint_to_string(Z_BIG_P(offset));
+ if (ZEND_HANDLE_NUMERIC_STR(temp_str, strlen(temp_str), hval)) {
+ zend_hash_index_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), hval, expr_ptr);
+ } else {
+ zend_hash_str_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), temp_str, strlen(temp_str), expr_ptr);
+ }
+ efree(temp_str);
+ }
+ break;
case IS_NULL:
str = STR_EMPTY_ALLOC();
goto str_index;
@@ -32714,6 +33132,21 @@ num_index_dim:
zval_ptr_dtor(offset);
}
break;
+ case IS_BIGINT:
+ {
+ zend_string *temp_str = zend_bigint_to_zend_string(Z_BIG_P(offset), 0);
+ if (ZEND_HANDLE_NUMERIC(temp_str, hval)) {
+ zend_hash_index_del(ht, hval);
+ } else {
+ if (ht == &EG(symbol_table).ht) {
+ zend_delete_global_variable(temp_str TSRMLS_CC);
+ } else {
+ zend_hash_del(ht, temp_str);
+ }
+ }
+ STR_RELEASE(temp_str);
+ }
+ break;
numeric_index_dim:
zend_hash_index_del(ht, hval);
if (IS_CONST == IS_CV || IS_CONST == IS_VAR) {
@@ -32914,6 +33347,17 @@ num_index_prop:
case IS_DOUBLE:
hval = zend_dval_to_lval(Z_DVAL_P(offset));
goto num_index_prop;
+ case IS_BIGINT:
+ {
+ char *temp_str = zend_bigint_to_string(Z_BIG_P(offset));
+ if (ZEND_HANDLE_NUMERIC_STR(temp_str, strlen(temp_str), hval)) {
+ value = zend_hash_index_find(ht, hval);
+ } else {
+ value = zend_hash_str_find_ind(ht, temp_str, strlen(temp_str));
+ }
+ efree(temp_str);
+ }
+ break;
case IS_NULL:
str = STR_EMPTY_ALLOC();
goto str_index_prop;
@@ -32963,6 +33407,9 @@ num_index_prop:
ZVAL_DUP(&tmp, offset);
convert_to_long(&tmp);
offset = &tmp;
+ } else if (Z_TYPE_P(offset) == IS_BIGINT) {
+ ZVAL_LONG(&tmp, zend_bigint_to_long(Z_BIG_P(offset)));
+ offset = &tmp;
}
}
if (Z_TYPE_P(offset) == IS_LONG) {
@@ -34560,6 +35007,17 @@ num_index:
str_index:
zend_hash_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), str, expr_ptr);
break;
+ case IS_BIGINT:
+ {
+ char *temp_str = zend_bigint_to_string(Z_BIG_P(offset));
+ if (ZEND_HANDLE_NUMERIC_STR(temp_str, strlen(temp_str), hval)) {
+ zend_hash_index_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), hval, expr_ptr);
+ } else {
+ zend_hash_str_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), temp_str, strlen(temp_str), expr_ptr);
+ }
+ efree(temp_str);
+ }
+ break;
case IS_NULL:
str = STR_EMPTY_ALLOC();
goto str_index;
@@ -34666,6 +35124,21 @@ num_index_dim:
zval_ptr_dtor(offset);
}
break;
+ case IS_BIGINT:
+ {
+ zend_string *temp_str = zend_bigint_to_zend_string(Z_BIG_P(offset), 0);
+ if (ZEND_HANDLE_NUMERIC(temp_str, hval)) {
+ zend_hash_index_del(ht, hval);
+ } else {
+ if (ht == &EG(symbol_table).ht) {
+ zend_delete_global_variable(temp_str TSRMLS_CC);
+ } else {
+ zend_hash_del(ht, temp_str);
+ }
+ }
+ STR_RELEASE(temp_str);
+ }
+ break;
numeric_index_dim:
zend_hash_index_del(ht, hval);
if (IS_TMP_VAR == IS_CV || IS_TMP_VAR == IS_VAR) {
@@ -34787,6 +35260,17 @@ num_index_prop:
case IS_DOUBLE:
hval = zend_dval_to_lval(Z_DVAL_P(offset));
goto num_index_prop;
+ case IS_BIGINT:
+ {
+ char *temp_str = zend_bigint_to_string(Z_BIG_P(offset));
+ if (ZEND_HANDLE_NUMERIC_STR(temp_str, strlen(temp_str), hval)) {
+ value = zend_hash_index_find(ht, hval);
+ } else {
+ value = zend_hash_str_find_ind(ht, temp_str, strlen(temp_str));
+ }
+ efree(temp_str);
+ }
+ break;
case IS_NULL:
str = STR_EMPTY_ALLOC();
goto str_index_prop;
@@ -34836,6 +35320,9 @@ num_index_prop:
ZVAL_DUP(&tmp, offset);
convert_to_long(&tmp);
offset = &tmp;
+ } else if (Z_TYPE_P(offset) == IS_BIGINT) {
+ ZVAL_LONG(&tmp, zend_bigint_to_long(Z_BIG_P(offset)));
+ offset = &tmp;
}
}
if (Z_TYPE_P(offset) == IS_LONG) {
@@ -36646,6 +37133,17 @@ num_index:
str_index:
zend_hash_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), str, expr_ptr);
break;
+ case IS_BIGINT:
+ {
+ char *temp_str = zend_bigint_to_string(Z_BIG_P(offset));
+ if (ZEND_HANDLE_NUMERIC_STR(temp_str, strlen(temp_str), hval)) {
+ zend_hash_index_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), hval, expr_ptr);
+ } else {
+ zend_hash_str_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), temp_str, strlen(temp_str), expr_ptr);
+ }
+ efree(temp_str);
+ }
+ break;
case IS_NULL:
str = STR_EMPTY_ALLOC();
goto str_index;
@@ -36824,6 +37322,21 @@ num_index_dim:
zval_ptr_dtor(offset);
}
break;
+ case IS_BIGINT:
+ {
+ zend_string *temp_str = zend_bigint_to_zend_string(Z_BIG_P(offset), 0);
+ if (ZEND_HANDLE_NUMERIC(temp_str, hval)) {
+ zend_hash_index_del(ht, hval);
+ } else {
+ if (ht == &EG(symbol_table).ht) {
+ zend_delete_global_variable(temp_str TSRMLS_CC);
+ } else {
+ zend_hash_del(ht, temp_str);
+ }
+ }
+ STR_RELEASE(temp_str);
+ }
+ break;
numeric_index_dim:
zend_hash_index_del(ht, hval);
if (IS_VAR == IS_CV || IS_VAR == IS_VAR) {
@@ -37024,6 +37537,17 @@ num_index_prop:
case IS_DOUBLE:
hval = zend_dval_to_lval(Z_DVAL_P(offset));
goto num_index_prop;
+ case IS_BIGINT:
+ {
+ char *temp_str = zend_bigint_to_string(Z_BIG_P(offset));
+ if (ZEND_HANDLE_NUMERIC_STR(temp_str, strlen(temp_str), hval)) {
+ value = zend_hash_index_find(ht, hval);
+ } else {
+ value = zend_hash_str_find_ind(ht, temp_str, strlen(temp_str));
+ }
+ efree(temp_str);
+ }
+ break;
case IS_NULL:
str = STR_EMPTY_ALLOC();
goto str_index_prop;
@@ -37073,6 +37597,9 @@ num_index_prop:
ZVAL_DUP(&tmp, offset);
convert_to_long(&tmp);
offset = &tmp;
+ } else if (Z_TYPE_P(offset) == IS_BIGINT) {
+ ZVAL_LONG(&tmp, zend_bigint_to_long(Z_BIG_P(offset)));
+ offset = &tmp;
}
}
if (Z_TYPE_P(offset) == IS_LONG) {
@@ -37988,6 +38515,17 @@ num_index:
str_index:
zend_hash_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), str, expr_ptr);
break;
+ case IS_BIGINT:
+ {
+ char *temp_str = zend_bigint_to_string(Z_BIG_P(offset));
+ if (ZEND_HANDLE_NUMERIC_STR(temp_str, strlen(temp_str), hval)) {
+ zend_hash_index_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), hval, expr_ptr);
+ } else {
+ zend_hash_str_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), temp_str, strlen(temp_str), expr_ptr);
+ }
+ efree(temp_str);
+ }
+ break;
case IS_NULL:
str = STR_EMPTY_ALLOC();
goto str_index;
@@ -39777,6 +40315,17 @@ num_index:
str_index:
zend_hash_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), str, expr_ptr);
break;
+ case IS_BIGINT:
+ {
+ char *temp_str = zend_bigint_to_string(Z_BIG_P(offset));
+ if (ZEND_HANDLE_NUMERIC_STR(temp_str, strlen(temp_str), hval)) {
+ zend_hash_index_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), hval, expr_ptr);
+ } else {
+ zend_hash_str_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), temp_str, strlen(temp_str), expr_ptr);
+ }
+ efree(temp_str);
+ }
+ break;
case IS_NULL:
str = STR_EMPTY_ALLOC();
goto str_index;
@@ -39883,6 +40432,21 @@ num_index_dim:
zval_ptr_dtor(offset);
}
break;
+ case IS_BIGINT:
+ {
+ zend_string *temp_str = zend_bigint_to_zend_string(Z_BIG_P(offset), 0);
+ if (ZEND_HANDLE_NUMERIC(temp_str, hval)) {
+ zend_hash_index_del(ht, hval);
+ } else {
+ if (ht == &EG(symbol_table).ht) {
+ zend_delete_global_variable(temp_str TSRMLS_CC);
+ } else {
+ zend_hash_del(ht, temp_str);
+ }
+ }
+ STR_RELEASE(temp_str);
+ }
+ break;
numeric_index_dim:
zend_hash_index_del(ht, hval);
if (IS_CV == IS_CV || IS_CV == IS_VAR) {
@@ -40004,6 +40568,17 @@ num_index_prop:
case IS_DOUBLE:
hval = zend_dval_to_lval(Z_DVAL_P(offset));
goto num_index_prop;
+ case IS_BIGINT:
+ {
+ char *temp_str = zend_bigint_to_string(Z_BIG_P(offset));
+ if (ZEND_HANDLE_NUMERIC_STR(temp_str, strlen(temp_str), hval)) {
+ value = zend_hash_index_find(ht, hval);
+ } else {
+ value = zend_hash_str_find_ind(ht, temp_str, strlen(temp_str));
+ }
+ efree(temp_str);
+ }
+ break;
case IS_NULL:
str = STR_EMPTY_ALLOC();
goto str_index_prop;
@@ -40053,6 +40628,9 @@ num_index_prop:
ZVAL_DUP(&tmp, offset);
convert_to_long(&tmp);
offset = &tmp;
+ } else if (Z_TYPE_P(offset) == IS_BIGINT) {
+ ZVAL_LONG(&tmp, zend_bigint_to_long(Z_BIG_P(offset)));
+ offset = &tmp;
}
}
if (Z_TYPE_P(offset) == IS_LONG) {
diff --git a/configure.in b/configure.in
index 8781cbc..ccbc2cb 100644
--- a/configure.in
+++ b/configure.in
@@ -1476,7 +1476,7 @@ PHP_ADD_SOURCES(Zend, \
zend_ini.c zend_qsort.c zend_multibyte.c zend_ts_hash.c zend_stream.c \
zend_iterators.c zend_interfaces.c zend_exceptions.c zend_strtod.c zend_gc.c \
zend_closures.c zend_float.c zend_string.c zend_signal.c zend_generators.c \
- zend_virtual_cwd.c zend_ast.c)
+ zend_virtual_cwd.c zend_ast.c zend_bigint.c)
if test -r "$abs_srcdir/Zend/zend_objects.c"; then
PHP_ADD_SOURCES(Zend, zend_objects.c zend_object_handlers.c zend_objects_API.c zend_default_classes.c)
diff --git a/ext/standard/type.c b/ext/standard/type.c
index a42dd0b..99c6a6e 100644
--- a/ext/standard/type.c
+++ b/ext/standard/type.c
@@ -42,6 +42,7 @@ PHP_FUNCTION(gettype)
break;
case IS_LONG:
+ case IS_BIGINT:
RETVAL_STRING("integer");
break;
@@ -324,6 +325,7 @@ PHP_FUNCTION(is_numeric)
switch (Z_TYPE_P(arg)) {
case IS_LONG:
case IS_DOUBLE:
+ case IS_BIGINT:
RETURN_TRUE;
break;
@@ -357,6 +359,7 @@ PHP_FUNCTION(is_scalar)
case IS_TRUE:
case IS_DOUBLE:
case IS_LONG:
+ case IS_BIGINT:
case IS_STRING:
RETURN_TRUE;
break;
diff --git a/ext/standard/var.c b/ext/standard/var.c
index 1a6a165..9df93ca 100644
--- a/ext/standard/var.c
+++ b/ext/standard/var.c
@@ -103,6 +103,7 @@ PHPAPI void php_var_dump(zval *struc, int level TSRMLS_DC) /* {{{ */
ulong num;
zend_string *key;
zval *val;
+ char *temp_str;
if (level > 1) {
php_printf("%*c", level - 1, ' ');
@@ -122,6 +123,11 @@ again:
case IS_LONG:
php_printf("%sint(%ld)\n", COMMON, Z_LVAL_P(struc));
break;
+ case IS_BIGINT:
+ temp_str = zend_bigint_to_string(Z_BIG_P(struc));
+ php_printf("%sint(%s)\n", COMMON, temp_str);
+ efree(temp_str);
+ break;
case IS_DOUBLE:
php_printf("%sfloat(%.*G)\n", COMMON, (int) EG(precision), Z_DVAL_P(struc));
break;
diff --git a/win32/build/config.w32 b/win32/build/config.w32
index 3fe8469..16f8248 100644
--- a/win32/build/config.w32
+++ b/win32/build/config.w32
@@ -362,7 +362,7 @@ ADD_SOURCES("Zend", "zend_language_parser.c zend_language_scanner.c \
zend_stream.c zend_iterators.c zend_interfaces.c zend_objects.c \
zend_object_handlers.c zend_objects_API.c \
zend_default_classes.c zend_execute.c zend_strtod.c zend_gc.c zend_closures.c \
- zend_float.c zend_string.c zend_generators.c zend_virtual_cwd.c zend_ast.c");
+ zend_float.c zend_string.c zend_generators.c zend_virtual_cwd.c zend_ast.c zend_bigint.c");
if (VCVERS == 1200) {
AC_DEFINE('ZEND_DVAL_TO_LVAL_CAST_OK', 1);
--
1.8.5.2 (Apple Git-48)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment