@@ -33,7 +33,7 @@ void bc_round(bc_num num, zend_long precision, zend_long mode, bc_num *result)
33
33
* - If the fractional part ends with zeros, the zeros are omitted and the number of digits in num is reduced.
34
34
* Meaning we might end up in the previous case.
35
35
*/
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 ) {
37
37
* result = bc_copy_num (BCG (_zero_ ));
38
38
return ;
39
39
}
@@ -42,15 +42,24 @@ void bc_round(bc_num num, zend_long precision, zend_long mode, bc_num *result)
42
42
return ;
43
43
}
44
44
45
- /* Initialize result */
46
- * result = bc_new_num (num -> n_len , precision > 0 ? precision : 0 );
47
- (* result )-> n_sign = num -> n_sign ;
48
45
/*
49
46
* If the calculation result is a negative value, there is an early return,
50
47
* so no underflow will occur.
51
48
*/
52
49
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 ;
54
63
55
64
const char * nptr = num -> n_value + rounded_len ;
56
65
@@ -126,13 +135,13 @@ void bc_round(bc_num num, zend_long precision, zend_long mode, bc_num *result)
126
135
return ;
127
136
128
137
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 ) {
130
139
return ;
131
140
}
132
141
break ;
133
142
134
143
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 ) {
136
145
return ;
137
146
}
138
147
break ;
@@ -142,8 +151,14 @@ void bc_round(bc_num num, zend_long precision, zend_long mode, bc_num *result)
142
151
143
152
up :
144
153
{
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
+ }
147
162
148
163
bc_num tmp = _bc_do_add (* result , scaled_one , (* result )-> n_scale );
149
164
tmp -> n_sign = (* result )-> n_sign ;
0 commit comments