@@ -802,6 +802,7 @@ static int bcmath_number_compare(zval *op1, zval *op2);
802
802
#else
803
803
# define CHECK_RET_SCALE_OVERFLOW (scale , origin_scale ) (scale > INT_MAX || scale < origin_scale)
804
804
#endif
805
+ #define CHECK_SCALE_OVERFLOW (scale ) (scale > INT_MAX)
805
806
806
807
static zend_always_inline bcmath_number_obj_t * get_bcmath_number_from_obj (const zend_object * obj )
807
808
{
@@ -1184,6 +1185,11 @@ static zend_result bcmath_number_do_operation(uint8_t opcode, zval *ret_val, zva
1184
1185
goto fail ;
1185
1186
}
1186
1187
1188
+ if (UNEXPECTED (CHECK_SCALE_OVERFLOW (n1_full_scale ) || CHECK_SCALE_OVERFLOW (n2_full_scale ))) {
1189
+ zend_value_error ("scale must be between 0 and %d" , INT_MAX );
1190
+ goto fail ;
1191
+ }
1192
+
1187
1193
bc_num ret = NULL ;
1188
1194
size_t scale ;
1189
1195
switch (opcode ) {
@@ -1264,8 +1270,15 @@ static int bcmath_number_compare(zval *op1, zval *op2)
1264
1270
goto fallback ;
1265
1271
}
1266
1272
1267
- if (UNEXPECTED (bc_num_from_obj_or_str_or_long (& n1 , NULL , obj1 , str1 , lval1 ) == FAILURE ||
1268
- bc_num_from_obj_or_str_or_long (& n2 , NULL , obj2 , str2 , lval2 ) == FAILURE )) {
1273
+ size_t n1_full_scale ;
1274
+ size_t n2_full_scale ;
1275
+ if (UNEXPECTED (bc_num_from_obj_or_str_or_long (& n1 , & n1_full_scale , obj1 , str1 , lval1 ) == FAILURE ||
1276
+ bc_num_from_obj_or_str_or_long (& n2 , & n2_full_scale , obj2 , str2 , lval2 ) == FAILURE )) {
1277
+ goto fallback ;
1278
+ }
1279
+
1280
+ if (UNEXPECTED (CHECK_SCALE_OVERFLOW (n1_full_scale ) || CHECK_SCALE_OVERFLOW (n2_full_scale ))) {
1281
+ zend_value_error ("scale must be between 0 and %d" , INT_MAX );
1269
1282
goto fallback ;
1270
1283
}
1271
1284
@@ -1297,10 +1310,18 @@ static int bcmath_number_compare(zval *op1, zval *op2)
1297
1310
static zend_always_inline zend_result bc_num_from_obj_or_str_or_long_with_err (
1298
1311
bc_num * num , size_t * scale , zend_object * obj , zend_string * str , zend_long lval , uint32_t arg_num )
1299
1312
{
1300
- if (UNEXPECTED (bc_num_from_obj_or_str_or_long (num , scale , obj , str , lval ) == FAILURE )) {
1313
+ size_t full_scale = 0 ;
1314
+ if (UNEXPECTED (bc_num_from_obj_or_str_or_long (num , & full_scale , obj , str , lval ) == FAILURE )) {
1301
1315
zend_argument_value_error (arg_num , "is not well-formed" );
1302
1316
return FAILURE ;
1303
1317
}
1318
+ if (UNEXPECTED (CHECK_SCALE_OVERFLOW (full_scale ))) {
1319
+ zend_argument_value_error (arg_num , "must be between 0 and %d" , INT_MAX );
1320
+ return FAILURE ;
1321
+ }
1322
+ if (scale != NULL ) {
1323
+ * scale = full_scale ;
1324
+ }
1304
1325
return SUCCESS ;
1305
1326
}
1306
1327
@@ -1320,7 +1341,7 @@ PHP_METHOD(BcMath_Number, __construct)
1320
1341
}
1321
1342
1322
1343
bc_num num = NULL ;
1323
- size_t scale ;
1344
+ size_t scale = 0 ;
1324
1345
if (bc_num_from_obj_or_str_or_long_with_err (& num , & scale , NULL , str , lval , 1 ) == FAILURE ) {
1325
1346
bc_free_num (& num );
1326
1347
RETURN_THROWS ();
@@ -1345,7 +1366,7 @@ static void bcmath_number_calc_method(INTERNAL_FUNCTION_PARAMETERS, uint8_t opco
1345
1366
ZEND_PARSE_PARAMETERS_END ();
1346
1367
1347
1368
bc_num num = NULL ;
1348
- size_t num_full_scale ;
1369
+ size_t num_full_scale = 0 ;
1349
1370
if (bc_num_from_obj_or_str_or_long_with_err (& num , & num_full_scale , num_obj , num_str , num_lval , 1 ) == FAILURE ) {
1350
1371
goto fail ;
1351
1372
}
@@ -1570,7 +1591,7 @@ PHP_METHOD(BcMath_Number, compare)
1570
1591
ZEND_PARSE_PARAMETERS_END ();
1571
1592
1572
1593
bc_num num = NULL ;
1573
- size_t num_full_scale ;
1594
+ size_t num_full_scale = 0 ;
1574
1595
if (bc_num_from_obj_or_str_or_long_with_err (& num , & num_full_scale , num_obj , num_str , num_lval , 1 ) == FAILURE ) {
1575
1596
goto fail ;
1576
1597
}
@@ -1704,8 +1725,8 @@ PHP_METHOD(BcMath_Number, __unserialize)
1704
1725
}
1705
1726
1706
1727
bc_num num = NULL ;
1707
- size_t scale ;
1708
- if (php_str2num_ex (& num , Z_STR_P (zv ), & scale ) == FAILURE ) {
1728
+ size_t scale = 0 ;
1729
+ if (php_str2num_ex (& num , Z_STR_P (zv ), & scale ) == FAILURE || CHECK_SCALE_OVERFLOW ( scale ) ) {
1709
1730
bc_free_num (& num );
1710
1731
goto fail ;
1711
1732
}
0 commit comments