@@ -803,6 +803,7 @@ static int bcmath_number_compare(zval *op1, zval *op2);
803
803
#else
804
804
# define CHECK_RET_SCALE_OVERFLOW (scale , origin_scale ) (scale > INT_MAX || scale < origin_scale)
805
805
#endif
806
+ #define CHECK_SCALE_OVERFLOW (scale ) (scale > INT_MAX)
806
807
807
808
static zend_always_inline bcmath_number_obj_t * get_bcmath_number_from_obj (const zend_object * obj )
808
809
{
@@ -1185,6 +1186,11 @@ static zend_result bcmath_number_do_operation(uint8_t opcode, zval *ret_val, zva
1185
1186
goto fail ;
1186
1187
}
1187
1188
1189
+ if (UNEXPECTED (CHECK_SCALE_OVERFLOW (n1_full_scale ) || CHECK_SCALE_OVERFLOW (n2_full_scale ))) {
1190
+ zend_value_error ("Number has too large scale" );
1191
+ goto fail ;
1192
+ }
1193
+
1188
1194
bc_num ret = NULL ;
1189
1195
size_t scale ;
1190
1196
switch (opcode ) {
@@ -1265,8 +1271,15 @@ static int bcmath_number_compare(zval *op1, zval *op2)
1265
1271
goto fallback ;
1266
1272
}
1267
1273
1268
- if (UNEXPECTED (bc_num_from_obj_or_str_or_long (& n1 , NULL , obj1 , str1 , lval1 ) == FAILURE ||
1269
- bc_num_from_obj_or_str_or_long (& n2 , NULL , obj2 , str2 , lval2 ) == FAILURE )) {
1274
+ size_t n1_full_scale ;
1275
+ size_t n2_full_scale ;
1276
+ if (UNEXPECTED (bc_num_from_obj_or_str_or_long (& n1 , & n1_full_scale , obj1 , str1 , lval1 ) == FAILURE ||
1277
+ bc_num_from_obj_or_str_or_long (& n2 , & n2_full_scale , obj2 , str2 , lval2 ) == FAILURE )) {
1278
+ goto fallback ;
1279
+ }
1280
+
1281
+ if (UNEXPECTED (CHECK_SCALE_OVERFLOW (n1_full_scale ) || CHECK_SCALE_OVERFLOW (n2_full_scale ))) {
1282
+ zend_value_error ("Number has too large scale" );
1270
1283
goto fallback ;
1271
1284
}
1272
1285
@@ -1298,10 +1311,18 @@ static int bcmath_number_compare(zval *op1, zval *op2)
1298
1311
static zend_always_inline zend_result bc_num_from_obj_or_str_or_long_with_err (
1299
1312
bc_num * num , size_t * scale , zend_object * obj , zend_string * str , zend_long lval , uint32_t arg_num )
1300
1313
{
1301
- if (UNEXPECTED (bc_num_from_obj_or_str_or_long (num , scale , obj , str , lval ) == FAILURE )) {
1314
+ size_t full_scale = 0 ;
1315
+ if (UNEXPECTED (bc_num_from_obj_or_str_or_long (num , & full_scale , obj , str , lval ) == FAILURE )) {
1302
1316
zend_argument_value_error (arg_num , "is not well-formed" );
1303
1317
return FAILURE ;
1304
1318
}
1319
+ if (UNEXPECTED (CHECK_SCALE_OVERFLOW (full_scale ))) {
1320
+ zend_argument_value_error (arg_num , "has too large scale" );
1321
+ return FAILURE ;
1322
+ }
1323
+ if (scale != NULL ) {
1324
+ * scale = full_scale ;
1325
+ }
1305
1326
return SUCCESS ;
1306
1327
}
1307
1328
@@ -1330,7 +1351,7 @@ PHP_METHOD(BcMath_Number, __construct)
1330
1351
}
1331
1352
1332
1353
bc_num num = NULL ;
1333
- size_t scale ;
1354
+ size_t scale = 0 ;
1334
1355
if (bc_num_from_obj_or_str_or_long_with_err (& num , & scale , NULL , str , lval , 1 ) == FAILURE ) {
1335
1356
bc_free_num (& num );
1336
1357
RETURN_THROWS ();
@@ -1355,7 +1376,7 @@ static void bcmath_number_calc_method(INTERNAL_FUNCTION_PARAMETERS, uint8_t opco
1355
1376
ZEND_PARSE_PARAMETERS_END ();
1356
1377
1357
1378
bc_num num = NULL ;
1358
- size_t num_full_scale ;
1379
+ size_t num_full_scale = 0 ;
1359
1380
if (bc_num_from_obj_or_str_or_long_with_err (& num , & num_full_scale , num_obj , num_str , num_lval , 1 ) == FAILURE ) {
1360
1381
goto fail ;
1361
1382
}
@@ -1580,7 +1601,7 @@ PHP_METHOD(BcMath_Number, compare)
1580
1601
ZEND_PARSE_PARAMETERS_END ();
1581
1602
1582
1603
bc_num num = NULL ;
1583
- size_t num_full_scale ;
1604
+ size_t num_full_scale = 0 ;
1584
1605
if (bc_num_from_obj_or_str_or_long_with_err (& num , & num_full_scale , num_obj , num_str , num_lval , 1 ) == FAILURE ) {
1585
1606
goto fail ;
1586
1607
}
@@ -1714,8 +1735,8 @@ PHP_METHOD(BcMath_Number, __unserialize)
1714
1735
}
1715
1736
1716
1737
bc_num num = NULL ;
1717
- size_t scale ;
1718
- if (php_str2num_ex (& num , Z_STR_P (zv ), & scale ) == FAILURE ) {
1738
+ size_t scale = 0 ;
1739
+ if (php_str2num_ex (& num , Z_STR_P (zv ), & scale ) == FAILURE || CHECK_SCALE_OVERFLOW ( scale ) ) {
1719
1740
bc_free_num (& num );
1720
1741
goto fail ;
1721
1742
}
0 commit comments