Skip to content

Commit b750a97

Browse files
committed
wip
1 parent 052f8fe commit b750a97

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
@@ -830,7 +830,6 @@ static zend_result convert_zval_to_bc_num(zval *zv, bc_num *num)
830830

831831
switch (Z_TYPE_P(zv)) {
832832
case IS_LONG:
833-
case IS_STRING:
834833
{
835834
zend_string *str = zval_get_string(zv);
836835
bc_init_num(&tmp);
@@ -840,58 +839,98 @@ static zend_result convert_zval_to_bc_num(zval *zv, bc_num *num)
840839
return FAILURE;
841840
}
842841
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;
843853
}
844854
break;
845855
case IS_OBJECT:
846856
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;
848858
} else {
849859
zend_argument_type_error(0, "must be of type int, string, or BcNum, %s given", zend_zval_value_name(zv));
850860
return FAILURE;
851861
}
852862
break;
853863
}
854864

855-
*num = tmp;
856865
return SUCCESS;
857866
}
858867

859868
static zend_result bc_num_calculation(zval *result, zval *op1, zval *op2, bc_num_calculation_type type, bool is_operator)
860869
{
861870
bc_num num1 = NULL, num2 = NULL, result_num = NULL;
862871
bc_num_obj *result_obj;
872+
size_t scale;
863873

864874
if (convert_zval_to_bc_num(op1, &num1) == FAILURE || convert_zval_to_bc_num(op2, &num2) == FAILURE) {
865875
goto cleanup;
866876
}
867877

868878
bc_init_num(&result_num);
869879

870-
size_t scale = MAX(num1->n_scale, num2->n_scale);
871-
872880
switch (type) {
873881
case BC_NUM_ADD:
882+
scale = MAX(num1->n_scale, num2->n_scale);
874883
bc_add(num1, num2, &result_num, scale);
875884
break;
876885
case BC_NUM_SUB:
886+
scale = MAX(num1->n_scale, num2->n_scale);
877887
bc_sub(num1, num2, &result_num, scale);
878888
break;
879889
case BC_NUM_MUL:
890+
scale = num1->n_scale + num2->n_scale;
891+
if (scale > INT_MAX) {
892+
scale = INT_MAX;
893+
}
880894
bc_multiply(num1, num2, &result_num, scale);
881895
break;
882896
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+
}
883903
bc_divide(num1, num2, &result_num, scale);
884904
break;
885905
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+
}
887911
break;
888912
case BC_NUM_POW:
889913
{
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+
}
890919
long exponent = bc_num2long(num2);
891920
if (exponent == 0 && (num2->n_len > 1 || num2->n_value[0] != 0)) {
892921
zend_argument_value_error(is_operator ? 0 : 1, "exponent is too large");
893922
goto cleanup;
894923
}
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+
895934
bc_raise(num1, bc_num2long(num2), &result_num, scale);
896935
}
897936
break;
@@ -905,7 +944,6 @@ static zend_result bc_num_calculation(zval *result, zval *op1, zval *op2, bc_num
905944
bc_free_num(&num2);
906945
}
907946

908-
result_num->n_scale = scale;
909947
result_obj = bc_num_obj_from_obj(bc_num_create_obj(bc_num_ce));
910948
result_obj->num = result_num;
911949
ZVAL_OBJ(result, &result_obj->std);
@@ -927,8 +965,15 @@ static zend_result bc_num_calculation(zval *result, zval *op1, zval *op2, bc_num
927965
/* {{{ bc_num_obj_handlers.do_operation */
928966
static int bc_num_do_operation(uint8_t opcode, zval *result, zval *op1, zval *op2)
929967
{
968+
zval op1_copy;
930969
zend_result ret;
931970

971+
/* For increment and decrement */
972+
if (result == op1) {
973+
ZVAL_COPY_VALUE(&op1_copy, op1);
974+
op1 = &op1_copy;
975+
}
976+
932977
switch (opcode) {
933978
case ZEND_ADD:
934979
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
952997
return FAILURE;
953998
}
954999

1000+
/* For increment and decrement */
1001+
if (ret == SUCCESS && op1 == &op1_copy) {
1002+
zval_ptr_dtor(op1);
1003+
}
1004+
9551005
return ret;
9561006
}
9571007
/* }}} */

0 commit comments

Comments
 (0)