From 77406d131e49d28c323ee0dfc2b8322a3fdd2602 Mon Sep 17 00:00:00 2001 From: Michael Wallner Date: Tue, 14 Dec 2021 12:33:53 +0100 Subject: [PATCH] properly check whether an ion int/decimal fits a zend_long --- ion.c | 26 +++++++++++++++++++++++++- ion_private.h | 23 ++++++++++++++++++++++- 2 files changed, 47 insertions(+), 2 deletions(-) diff --git a/ion.c b/ion.c index 5ec89a1..3e8ba01 100644 --- a/ion.c +++ b/ion.c @@ -30,6 +30,10 @@ #define DECNUMDIGITS 34 /* DECQUAD_Pmax */ #include "ionc/ion.h" +static decContext g_dec_ctx; +static ION_INT *g_ion_int_zend_max, *g_ion_int_zend_min; +static ION_DECIMAL g_ion_dec_zend_max, g_ion_dec_zend_min; + #include "php_ion.h" #define ZEND_ARG_VARIADIC_OBJ_TYPE_MASK(pass_by_ref, name, classname, type_mask, default_value) \ { #name, ZEND_TYPE_INIT_CLASS_CONST_MASK(#classname, type_mask | _ZEND_ARG_INFO_FLAGS(pass_by_ref, 1, 0)), default_value }, @@ -1447,6 +1451,18 @@ PHP_RSHUTDOWN_FUNCTION(ion) PHP_MINIT_FUNCTION(ion) { + if (!g_ion_int_zend_max) { + decContextDefault(&g_dec_ctx, DEC_INIT_DECIMAL64); + + ion_int_alloc(NULL, &g_ion_int_zend_max); + ion_int_from_long(g_ion_int_zend_max, ZEND_LONG_MAX); + ion_decimal_from_ion_int(&g_ion_dec_zend_max, &g_dec_ctx, g_ion_int_zend_max); + + ion_int_alloc(NULL, &g_ion_int_zend_min); + ion_int_from_long(g_ion_int_zend_min, ZEND_LONG_MIN); + ion_decimal_from_ion_int(&g_ion_dec_zend_min, &g_dec_ctx, g_ion_int_zend_min); + } + ce_Annotation = register_class_ion_Annotation(); php_ion_register(type, Type); @@ -1494,6 +1510,14 @@ PHP_MINIT_FUNCTION(ion) return SUCCESS; } +PHP_MSHUTDOWN_FUNCTION(ion) +{ + if (g_ion_int_zend_max) { + ion_int_free(g_ion_int_zend_max); + ion_int_free(g_ion_int_zend_min); + } + return SUCCESS; +} PHP_MINFO_FUNCTION(ion) { php_info_print_table_start(); @@ -1521,7 +1545,7 @@ zend_module_entry ion_module_entry = { "ion", /* Extension name */ ext_functions, /* zend_function_entry */ PHP_MINIT(ion), /* PHP_MINIT - Module initialization */ - NULL, /* PHP_MSHUTDOWN - Module shutdown */ + PHP_MSHUTDOWN(ion), /* PHP_MSHUTDOWN - Module shutdown */ PHP_RINIT(ion), /* PHP_RINIT - Request initialization */ PHP_RSHUTDOWN(ion), /* PHP_RSHUTDOWN - Request shutdown */ PHP_MINFO(ion), /* PHP_MINFO - Module info */ diff --git a/ion_private.h b/ion_private.h index 8c0ec60..2a51126 100644 --- a/ion_private.h +++ b/ion_private.h @@ -442,6 +442,27 @@ static inline void php_ion_decimal_to_int(ION_DECIMAL *dec, decContext *ctx, zen ion_int_free(ii); } +static inline bool php_ion_decimal_fits_zend_long(php_ion_decimal *obj) +{ + int32_t result; + + if (!ion_decimal_is_integer(&obj->dec)) { + return false; + } + + result = 1; + ion_decimal_compare(&obj->dec, &g_ion_dec_zend_max, &g_dec_ctx, &result); + if (result == 1) { + return false; + } + result = -1; + ion_decimal_compare(&obj->dec, &g_ion_dec_zend_min, &g_dec_ctx, &result); + if (result == -1) { + return false; + } + return true; +} + static inline void php_ion_decimal_ctor(php_ion_decimal *obj) { if (!obj->ctx) { @@ -453,7 +474,7 @@ static inline void php_ion_decimal_ctor(php_ion_decimal *obj) } update_property_obj(&obj->std, ZEND_STRL("context"), obj->ctx); - if (ion_decimal_is_integer(&obj->dec)) { + if (php_ion_decimal_fits_zend_long(obj)) { zend_long l; php_ion_decimal_to_int(&obj->dec, &php_ion_obj(decimal_ctx, obj->ctx)->ctx, &l); zend_update_property_long(obj->std.ce, &obj->std, ZEND_STRL("number"), l); -- 2.30.2