mirror of
https://github.com/php/php-src.git
synced 2026-03-24 00:02:20 +01:00
BCMath: Avoid using the heap for temporary objects by using arena allocations (#14170)
* BCMath: Avoid using the heap for temporary objects by using arena allocations * Fix alignment * Improve size computation
This commit is contained in:
@@ -29,6 +29,16 @@
|
||||
#include "php_bcmath.h"
|
||||
#include "libbcmath/src/bcmath.h"
|
||||
|
||||
/* Always pair SETUP with TEARDOWN, and do so in the outer scope!
|
||||
* Should not be used when data can escape the function. */
|
||||
#define BC_ARENA_SETUP \
|
||||
char bc_arena[BC_ARENA_SIZE]; \
|
||||
BCG(arena) = bc_arena;
|
||||
|
||||
#define BC_ARENA_TEARDOWN \
|
||||
BCG(arena) = NULL; \
|
||||
BCG(arena_offset) = 0;
|
||||
|
||||
ZEND_DECLARE_MODULE_GLOBALS(bcmath)
|
||||
static PHP_GINIT_FUNCTION(bcmath);
|
||||
static PHP_GSHUTDOWN_FUNCTION(bcmath);
|
||||
@@ -89,6 +99,8 @@ static PHP_GINIT_FUNCTION(bcmath)
|
||||
ZEND_TSRMLS_CACHE_UPDATE();
|
||||
#endif
|
||||
bcmath_globals->bc_precision = 0;
|
||||
bcmath_globals->arena = NULL;
|
||||
bcmath_globals->arena_offset = 0;
|
||||
bc_init_numbers();
|
||||
}
|
||||
/* }}} */
|
||||
@@ -99,6 +111,8 @@ static PHP_GSHUTDOWN_FUNCTION(bcmath)
|
||||
_bc_free_num_ex(&bcmath_globals->_zero_, 1);
|
||||
_bc_free_num_ex(&bcmath_globals->_one_, 1);
|
||||
_bc_free_num_ex(&bcmath_globals->_two_, 1);
|
||||
bcmath_globals->arena = NULL;
|
||||
bcmath_globals->arena_offset = 0;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
@@ -167,6 +181,8 @@ PHP_FUNCTION(bcadd)
|
||||
scale = (int) scale_param;
|
||||
}
|
||||
|
||||
BC_ARENA_SETUP;
|
||||
|
||||
if (php_str2num(&first, left) == FAILURE) {
|
||||
zend_argument_value_error(1, "is not well-formed");
|
||||
goto cleanup;
|
||||
@@ -185,6 +201,7 @@ PHP_FUNCTION(bcadd)
|
||||
bc_free_num(&first);
|
||||
bc_free_num(&second);
|
||||
bc_free_num(&result);
|
||||
BC_ARENA_TEARDOWN;
|
||||
};
|
||||
}
|
||||
/* }}} */
|
||||
@@ -214,6 +231,8 @@ PHP_FUNCTION(bcsub)
|
||||
scale = (int) scale_param;
|
||||
}
|
||||
|
||||
BC_ARENA_SETUP;
|
||||
|
||||
if (php_str2num(&first, left) == FAILURE) {
|
||||
zend_argument_value_error(1, "is not well-formed");
|
||||
goto cleanup;
|
||||
@@ -232,6 +251,7 @@ PHP_FUNCTION(bcsub)
|
||||
bc_free_num(&first);
|
||||
bc_free_num(&second);
|
||||
bc_free_num(&result);
|
||||
BC_ARENA_TEARDOWN;
|
||||
};
|
||||
}
|
||||
/* }}} */
|
||||
@@ -261,6 +281,8 @@ PHP_FUNCTION(bcmul)
|
||||
scale = (int) scale_param;
|
||||
}
|
||||
|
||||
BC_ARENA_SETUP;
|
||||
|
||||
if (php_str2num(&first, left) == FAILURE) {
|
||||
zend_argument_value_error(1, "is not well-formed");
|
||||
goto cleanup;
|
||||
@@ -279,6 +301,7 @@ PHP_FUNCTION(bcmul)
|
||||
bc_free_num(&first);
|
||||
bc_free_num(&second);
|
||||
bc_free_num(&result);
|
||||
BC_ARENA_TEARDOWN;
|
||||
};
|
||||
}
|
||||
/* }}} */
|
||||
@@ -308,6 +331,8 @@ PHP_FUNCTION(bcdiv)
|
||||
scale = (int) scale_param;
|
||||
}
|
||||
|
||||
BC_ARENA_SETUP;
|
||||
|
||||
bc_init_num(&result);
|
||||
|
||||
if (php_str2num(&first, left) == FAILURE) {
|
||||
@@ -331,6 +356,7 @@ PHP_FUNCTION(bcdiv)
|
||||
bc_free_num(&first);
|
||||
bc_free_num(&second);
|
||||
bc_free_num(&result);
|
||||
BC_ARENA_TEARDOWN;
|
||||
};
|
||||
}
|
||||
/* }}} */
|
||||
@@ -360,6 +386,8 @@ PHP_FUNCTION(bcmod)
|
||||
scale = (int) scale_param;
|
||||
}
|
||||
|
||||
BC_ARENA_SETUP;
|
||||
|
||||
bc_init_num(&result);
|
||||
|
||||
if (php_str2num(&first, left) == FAILURE) {
|
||||
@@ -383,6 +411,7 @@ PHP_FUNCTION(bcmod)
|
||||
bc_free_num(&first);
|
||||
bc_free_num(&second);
|
||||
bc_free_num(&result);
|
||||
BC_ARENA_TEARDOWN;
|
||||
};
|
||||
}
|
||||
/* }}} */
|
||||
@@ -413,6 +442,8 @@ PHP_FUNCTION(bcpowmod)
|
||||
scale = (int) scale_param;
|
||||
}
|
||||
|
||||
BC_ARENA_SETUP;
|
||||
|
||||
bc_init_num(&result);
|
||||
|
||||
if (php_str2num(&bc_base, base_str) == FAILURE) {
|
||||
@@ -458,6 +489,7 @@ PHP_FUNCTION(bcpowmod)
|
||||
bc_free_num(&bc_expo);
|
||||
bc_free_num(&bc_modulus);
|
||||
bc_free_num(&result);
|
||||
BC_ARENA_TEARDOWN;
|
||||
};
|
||||
}
|
||||
/* }}} */
|
||||
@@ -487,6 +519,8 @@ PHP_FUNCTION(bcpow)
|
||||
scale = (int) scale_param;
|
||||
}
|
||||
|
||||
BC_ARENA_SETUP;
|
||||
|
||||
bc_init_num(&result);
|
||||
|
||||
if (php_str2num(&first, base_str) == FAILURE) {
|
||||
@@ -518,6 +552,7 @@ PHP_FUNCTION(bcpow)
|
||||
bc_free_num(&first);
|
||||
bc_free_num(&bc_exponent);
|
||||
bc_free_num(&result);
|
||||
BC_ARENA_TEARDOWN;
|
||||
};
|
||||
}
|
||||
/* }}} */
|
||||
@@ -546,6 +581,8 @@ PHP_FUNCTION(bcsqrt)
|
||||
scale = (int) scale_param;
|
||||
}
|
||||
|
||||
BC_ARENA_SETUP;
|
||||
|
||||
if (php_str2num(&result, left) == FAILURE) {
|
||||
zend_argument_value_error(1, "is not well-formed");
|
||||
goto cleanup;
|
||||
@@ -559,6 +596,7 @@ PHP_FUNCTION(bcsqrt)
|
||||
|
||||
cleanup: {
|
||||
bc_free_num(&result);
|
||||
BC_ARENA_TEARDOWN;
|
||||
};
|
||||
}
|
||||
/* }}} */
|
||||
@@ -588,6 +626,8 @@ PHP_FUNCTION(bccomp)
|
||||
scale = (int) scale_param;
|
||||
}
|
||||
|
||||
BC_ARENA_SETUP;
|
||||
|
||||
if (!bc_str2num(&first, ZSTR_VAL(left), ZSTR_VAL(left) + ZSTR_LEN(left), scale, false)) {
|
||||
zend_argument_value_error(1, "is not well-formed");
|
||||
goto cleanup;
|
||||
@@ -603,6 +643,7 @@ PHP_FUNCTION(bccomp)
|
||||
cleanup: {
|
||||
bc_free_num(&first);
|
||||
bc_free_num(&second);
|
||||
BC_ARENA_TEARDOWN;
|
||||
};
|
||||
}
|
||||
/* }}} */
|
||||
@@ -617,6 +658,8 @@ static void bcfloor_or_bcceil(INTERNAL_FUNCTION_PARAMETERS, bool is_floor)
|
||||
Z_PARAM_STR(numstr)
|
||||
ZEND_PARSE_PARAMETERS_END();
|
||||
|
||||
BC_ARENA_SETUP;
|
||||
|
||||
if (php_str2num(&num, numstr) == FAILURE) {
|
||||
zend_argument_value_error(1, "is not well-formed");
|
||||
goto cleanup;
|
||||
@@ -628,6 +671,7 @@ static void bcfloor_or_bcceil(INTERNAL_FUNCTION_PARAMETERS, bool is_floor)
|
||||
cleanup: {
|
||||
bc_free_num(&num);
|
||||
bc_free_num(&result);
|
||||
BC_ARENA_TEARDOWN;
|
||||
};
|
||||
}
|
||||
/* }}} */
|
||||
@@ -676,6 +720,8 @@ PHP_FUNCTION(bcround)
|
||||
return;
|
||||
}
|
||||
|
||||
BC_ARENA_SETUP;
|
||||
|
||||
bc_init_num(&result);
|
||||
|
||||
if (php_str2num(&num, numstr) == FAILURE) {
|
||||
@@ -689,6 +735,7 @@ PHP_FUNCTION(bcround)
|
||||
cleanup: {
|
||||
bc_free_num(&num);
|
||||
bc_free_num(&result);
|
||||
BC_ARENA_TEARDOWN;
|
||||
};
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
@@ -35,14 +35,25 @@
|
||||
#include <string.h>
|
||||
#include "zend_alloc.h"
|
||||
|
||||
static zend_always_inline bc_num _bc_new_num_nonzeroed_ex_internal(size_t length, size_t scale, bool persistent)
|
||||
static bc_num _bc_new_num_nonzeroed_ex_internal(size_t length, size_t scale, bool persistent)
|
||||
{
|
||||
/* PHP Change: malloc() -> pemalloc(), removed free_list code, merged n_ptr and n_value */
|
||||
bc_num temp = safe_pemalloc(1, sizeof(bc_struct) + length, scale, persistent);
|
||||
size_t required_size = zend_safe_address_guarded(1, sizeof(bc_struct) + (ZEND_MM_ALIGNMENT - 1) + length, scale);
|
||||
required_size &= -ZEND_MM_ALIGNMENT;
|
||||
bc_num temp;
|
||||
|
||||
if (!persistent && BCG(arena) && required_size <= BC_ARENA_SIZE - BCG(arena_offset)) {
|
||||
temp = (bc_num) (BCG(arena) + BCG(arena_offset));
|
||||
BCG(arena_offset) += required_size;
|
||||
temp->n_refs = 2; /* prevent freeing */
|
||||
} else {
|
||||
/* PHP Change: malloc() -> pemalloc(), removed free_list code, merged n_ptr and n_value */
|
||||
temp = pemalloc(required_size, persistent);
|
||||
temp->n_refs = 1;
|
||||
}
|
||||
|
||||
temp->n_sign = PLUS;
|
||||
temp->n_len = length;
|
||||
temp->n_scale = scale;
|
||||
temp->n_refs = 1;
|
||||
temp->n_value = (char *) temp + sizeof(bc_struct);
|
||||
return temp;
|
||||
}
|
||||
|
||||
@@ -27,11 +27,15 @@ extern zend_module_entry bcmath_module_entry;
|
||||
#include "php_version.h"
|
||||
#define PHP_BCMATH_VERSION PHP_VERSION
|
||||
|
||||
#define BC_ARENA_SIZE 256
|
||||
|
||||
ZEND_BEGIN_MODULE_GLOBALS(bcmath)
|
||||
bc_num _zero_;
|
||||
bc_num _one_;
|
||||
bc_num _two_;
|
||||
int bc_precision;
|
||||
char *arena;
|
||||
size_t arena_offset;
|
||||
ZEND_END_MODULE_GLOBALS(bcmath)
|
||||
|
||||
#if defined(ZTS) && defined(COMPILE_DL_BCMATH)
|
||||
|
||||
Reference in New Issue
Block a user