@@ -830,7 +830,6 @@ static zend_result convert_zval_to_bc_num(zval *zv, bc_num *num)
830
830
831
831
switch (Z_TYPE_P (zv )) {
832
832
case IS_LONG :
833
- case IS_STRING :
834
833
{
835
834
zend_string * str = zval_get_string (zv );
836
835
bc_init_num (& tmp );
@@ -840,58 +839,98 @@ static zend_result convert_zval_to_bc_num(zval *zv, bc_num *num)
840
839
return FAILURE ;
841
840
}
842
841
zend_string_release (str );
842
+ * num = tmp ;
843
+ }
844
+ break ;
845
+ case IS_STRING :
846
+ {
847
+ bc_init_num (& tmp );
848
+ if (php_str2num (& tmp , Z_STRVAL_P (zv )) == FAILURE ) {
849
+ bc_free_num (& tmp );
850
+ return FAILURE ;
851
+ }
852
+ * num = tmp ;
843
853
}
844
854
break ;
845
855
case IS_OBJECT :
846
856
if (instanceof_function (Z_OBJCE_P (zv ), bc_num_ce )) {
847
- tmp = bc_num_obj_from_zval (zv )-> num ;
857
+ * num = bc_num_obj_from_zval (zv )-> num ;
848
858
} else {
849
859
zend_argument_type_error (0 , "must be of type int, string, or BcNum, %s given" , zend_zval_value_name (zv ));
850
860
return FAILURE ;
851
861
}
852
862
break ;
853
863
}
854
864
855
- * num = tmp ;
856
865
return SUCCESS ;
857
866
}
858
867
859
868
static zend_result bc_num_calculation (zval * result , zval * op1 , zval * op2 , bc_num_calculation_type type , bool is_operator )
860
869
{
861
870
bc_num num1 = NULL , num2 = NULL , result_num = NULL ;
862
871
bc_num_obj * result_obj ;
872
+ size_t scale ;
863
873
864
874
if (convert_zval_to_bc_num (op1 , & num1 ) == FAILURE || convert_zval_to_bc_num (op2 , & num2 ) == FAILURE ) {
865
875
goto cleanup ;
866
876
}
867
877
868
878
bc_init_num (& result_num );
869
879
870
- size_t scale = MAX (num1 -> n_scale , num2 -> n_scale );
871
-
872
880
switch (type ) {
873
881
case BC_NUM_ADD :
882
+ scale = MAX (num1 -> n_scale , num2 -> n_scale );
874
883
bc_add (num1 , num2 , & result_num , scale );
875
884
break ;
876
885
case BC_NUM_SUB :
886
+ scale = MAX (num1 -> n_scale , num2 -> n_scale );
877
887
bc_sub (num1 , num2 , & result_num , scale );
878
888
break ;
879
889
case BC_NUM_MUL :
890
+ scale = num1 -> n_scale + num2 -> n_scale ;
891
+ if (scale > INT_MAX ) {
892
+ scale = INT_MAX ;
893
+ }
880
894
bc_multiply (num1 , num2 , & result_num , scale );
881
895
break ;
882
896
case BC_NUM_DIV :
897
+ // TODO: How set the scale?
898
+ scale = num1 -> n_scale ;
899
+ if (!bc_divide (num1 , num2 , & result_num , scale )) {
900
+ zend_throw_exception_ex (zend_ce_division_by_zero_error , 0 , "Division by zero" );
901
+ goto cleanup ;
902
+ }
883
903
bc_divide (num1 , num2 , & result_num , scale );
884
904
break ;
885
905
case BC_NUM_MOD :
886
- bc_modulo (num1 , num2 , & result_num , scale );
906
+ scale = num1 -> n_scale ;
907
+ if (!bc_modulo (num1 , num2 , & result_num , scale )) {
908
+ zend_throw_exception_ex (zend_ce_division_by_zero_error , 0 , "Modulo by zero" );
909
+ goto cleanup ;
910
+ }
887
911
break ;
888
912
case BC_NUM_POW :
889
913
{
914
+ /* Check the exponent for scale digits and convert to a long. */
915
+ if (num2 -> n_scale != 0 ) {
916
+ zend_argument_value_error (0 , "exponent cannot have a fractional part" );
917
+ goto cleanup ;
918
+ }
890
919
long exponent = bc_num2long (num2 );
891
920
if (exponent == 0 && (num2 -> n_len > 1 || num2 -> n_value [0 ] != 0 )) {
892
921
zend_argument_value_error (is_operator ? 0 : 1 , "exponent is too large" );
893
922
goto cleanup ;
894
923
}
924
+ if (exponent >= 0 ) {
925
+ scale = num1 -> n_scale * exponent ;
926
+ if (scale > INT_MAX ) {
927
+ scale = INT_MAX ;
928
+ }
929
+ } else {
930
+ // // TODO: How set the scale?
931
+ scale = num1 -> n_scale * exponent ;
932
+ }
933
+
895
934
bc_raise (num1 , bc_num2long (num2 ), & result_num , scale );
896
935
}
897
936
break ;
@@ -905,7 +944,6 @@ static zend_result bc_num_calculation(zval *result, zval *op1, zval *op2, bc_num
905
944
bc_free_num (& num2 );
906
945
}
907
946
908
- result_num -> n_scale = scale ;
909
947
result_obj = bc_num_obj_from_obj (bc_num_create_obj (bc_num_ce ));
910
948
result_obj -> num = result_num ;
911
949
ZVAL_OBJ (result , & result_obj -> std );
@@ -927,8 +965,15 @@ static zend_result bc_num_calculation(zval *result, zval *op1, zval *op2, bc_num
927
965
/* {{{ bc_num_obj_handlers.do_operation */
928
966
static int bc_num_do_operation (uint8_t opcode , zval * result , zval * op1 , zval * op2 )
929
967
{
968
+ zval op1_copy ;
930
969
zend_result ret ;
931
970
971
+ /* For increment and decrement */
972
+ if (result == op1 ) {
973
+ ZVAL_COPY_VALUE (& op1_copy , op1 );
974
+ op1 = & op1_copy ;
975
+ }
976
+
932
977
switch (opcode ) {
933
978
case ZEND_ADD :
934
979
ret = bc_num_calculation (result , op1 , op2 , BC_NUM_ADD , true);
@@ -952,6 +997,11 @@ static int bc_num_do_operation(uint8_t opcode, zval *result, zval *op1, zval *op
952
997
return FAILURE ;
953
998
}
954
999
1000
+ /* For increment and decrement */
1001
+ if (ret == SUCCESS && op1 == & op1_copy ) {
1002
+ zval_ptr_dtor (op1 );
1003
+ }
1004
+
955
1005
return ret ;
956
1006
}
957
1007
/* }}} */
0 commit comments