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