Skip to content

Commit 98ea4a0

Browse files
committed
Fixed round.c
The comparison conditions for determining early returns were incorrect and have been corrected. Added processing when the rounding result is carried forward or becomes 0.
1 parent d227a94 commit 98ea4a0

File tree

1 file changed

+24
-9
lines changed

1 file changed

+24
-9
lines changed

ext/bcmath/libbcmath/src/round.c

Lines changed: 24 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ void bc_round(bc_num num, zend_long precision, zend_long mode, bc_num *result)
3333
* - If the fractional part ends with zeros, the zeros are omitted and the number of digits in num is reduced.
3434
* Meaning we might end up in the previous case.
3535
*/
36-
if (precision < 0 && num->n_len <= (size_t) (-(precision + Z_L(1))) + 1) {
36+
if (precision < 0 && num->n_len < (size_t) (-(precision + Z_L(1))) + 1) {
3737
*result = bc_copy_num(BCG(_zero_));
3838
return;
3939
}
@@ -42,15 +42,24 @@ void bc_round(bc_num num, zend_long precision, zend_long mode, bc_num *result)
4242
return;
4343
}
4444

45-
/* Initialize result */
46-
*result = bc_new_num(num->n_len, precision > 0 ? precision : 0);
47-
(*result)->n_sign = num->n_sign;
4845
/*
4946
* If the calculation result is a negative value, there is an early return,
5047
* so no underflow will occur.
5148
*/
5249
size_t rounded_len = num->n_len + precision;
53-
memcpy((*result)->n_value, num->n_value, rounded_len);
50+
51+
/*
52+
* Initialize result
53+
* For example, if rounded_len is 0, it means trying to round 50 to 100 or 0.
54+
* If the result of rounding is carried over, it will be added later, so first set it to 0 here.
55+
*/
56+
if (rounded_len == 0) {
57+
*result = bc_copy_num(BCG(_zero_));
58+
} else {
59+
*result = bc_new_num(num->n_len, precision > 0 ? precision : 0);
60+
memcpy((*result)->n_value, num->n_value, rounded_len);
61+
}
62+
(*result)->n_sign = num->n_sign;
5463

5564
const char *nptr = num->n_value + rounded_len;
5665

@@ -126,13 +135,13 @@ void bc_round(bc_num num, zend_long precision, zend_long mode, bc_num *result)
126135
return;
127136

128137
case PHP_ROUND_HALF_EVEN:
129-
if (num->n_value[rounded_len - 1] % 2 == 0) {
138+
if (rounded_len == 0 || num->n_value[rounded_len - 1] % 2 == 0) {
130139
return;
131140
}
132141
break;
133142

134143
case PHP_ROUND_HALF_ODD:
135-
if (num->n_value[rounded_len - 1] % 2 == 1) {
144+
if (rounded_len != 0 && num->n_value[rounded_len - 1] % 2 == 1) {
136145
return;
137146
}
138147
break;
@@ -142,8 +151,14 @@ void bc_round(bc_num num, zend_long precision, zend_long mode, bc_num *result)
142151

143152
up:
144153
{
145-
bc_num scaled_one = bc_new_num((*result)->n_len, (*result)->n_scale);
146-
scaled_one->n_value[rounded_len - 1] = 1;
154+
bc_num scaled_one;
155+
if (rounded_len == 0) {
156+
scaled_one = bc_new_num(num->n_len + 1, 0);
157+
scaled_one->n_value[0] = 1;
158+
} else {
159+
scaled_one = bc_new_num((*result)->n_len, (*result)->n_scale);
160+
scaled_one->n_value[rounded_len - 1] = 1;
161+
}
147162

148163
bc_num tmp = _bc_do_add(*result, scaled_one, (*result)->n_scale);
149164
tmp->n_sign = (*result)->n_sign;

0 commit comments

Comments
 (0)