Skip to content

Commit cba3760

Browse files
committed
wip
1 parent ce8374b commit cba3760

File tree

1 file changed

+57
-7
lines changed

1 file changed

+57
-7
lines changed

ext/bcmath/bcmath.c

Lines changed: 57 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -823,7 +823,6 @@ static zend_result convert_zval_to_bc_num(zval *zv, bc_num *num)
823823

824824
switch (Z_TYPE_P(zv)) {
825825
case IS_LONG:
826-
case IS_STRING:
827826
{
828827
zend_string *str = zval_get_string(zv);
829828
bc_init_num(&tmp);
@@ -833,58 +832,98 @@ static zend_result convert_zval_to_bc_num(zval *zv, bc_num *num)
833832
return FAILURE;
834833
}
835834
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;
836846
}
837847
break;
838848
case IS_OBJECT:
839849
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;
841851
} else {
842852
zend_argument_type_error(0, "must be of type int, string, or BcNum, %s given", zend_zval_value_name(zv));
843853
return FAILURE;
844854
}
845855
break;
846856
}
847857

848-
*num = tmp;
849858
return SUCCESS;
850859
}
851860

852861
static zend_result bc_num_calculation(zval *result, zval *op1, zval *op2, bc_num_calculation_type type, bool is_operator)
853862
{
854863
bc_num num1 = NULL, num2 = NULL, result_num = NULL;
855864
bc_num_obj *result_obj;
865+
size_t scale;
856866

857867
if (convert_zval_to_bc_num(op1, &num1) == FAILURE || convert_zval_to_bc_num(op2, &num2) == FAILURE) {
858868
goto cleanup;
859869
}
860870

861871
bc_init_num(&result_num);
862872

863-
size_t scale = MAX(num1->n_scale, num2->n_scale);
864-
865873
switch (type) {
866874
case BC_NUM_ADD:
875+
scale = MAX(num1->n_scale, num2->n_scale);
867876
bc_add(num1, num2, &result_num, scale);
868877
break;
869878
case BC_NUM_SUB:
879+
scale = MAX(num1->n_scale, num2->n_scale);
870880
bc_sub(num1, num2, &result_num, scale);
871881
break;
872882
case BC_NUM_MUL:
883+
scale = num1->n_scale + num2->n_scale;
884+
if (scale > INT_MAX) {
885+
scale = INT_MAX;
886+
}
873887
bc_multiply(num1, num2, &result_num, scale);
874888
break;
875889
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+
}
876896
bc_divide(num1, num2, &result_num, scale);
877897
break;
878898
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+
}
880904
break;
881905
case BC_NUM_POW:
882906
{
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+
}
883912
long exponent = bc_num2long(num2);
884913
if (exponent == 0 && (num2->n_len > 1 || num2->n_value[0] != 0)) {
885914
zend_argument_value_error(is_operator ? 0 : 1, "exponent is too large");
886915
goto cleanup;
887916
}
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+
888927
bc_raise(num1, bc_num2long(num2), &result_num, scale);
889928
}
890929
break;
@@ -898,7 +937,6 @@ static zend_result bc_num_calculation(zval *result, zval *op1, zval *op2, bc_num
898937
bc_free_num(&num2);
899938
}
900939

901-
result_num->n_scale = scale;
902940
result_obj = bc_num_obj_from_obj(bc_num_create_obj(bc_num_ce));
903941
result_obj->num = result_num;
904942
ZVAL_OBJ(result, &result_obj->std);
@@ -920,8 +958,15 @@ static zend_result bc_num_calculation(zval *result, zval *op1, zval *op2, bc_num
920958
/* {{{ bc_num_obj_handlers.do_operation */
921959
static int bc_num_do_operation(uint8_t opcode, zval *result, zval *op1, zval *op2)
922960
{
961+
zval op1_copy;
923962
zend_result ret;
924963

964+
/* For increment and decrement */
965+
if (result == op1) {
966+
ZVAL_COPY_VALUE(&op1_copy, op1);
967+
op1 = &op1_copy;
968+
}
969+
925970
switch (opcode) {
926971
case ZEND_ADD:
927972
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
945990
return FAILURE;
946991
}
947992

993+
/* For increment and decrement */
994+
if (ret == SUCCESS && op1 == &op1_copy) {
995+
zval_ptr_dtor(op1);
996+
}
997+
948998
return ret;
949999
}
9501000
/* }}} */

0 commit comments

Comments
 (0)