Skip to content

Commit 94a151a

Browse files
jensdeniesnikic
authored andcommitted
Fixed bug #80545
This converts the remaining "non well-formed" warnings in bcmath to ValueErrors, in line with the other warning promotions that have been performed in this extension. Closes GH-80545.
1 parent 95a13ca commit 94a151a

File tree

4 files changed

+248
-84
lines changed

4 files changed

+248
-84
lines changed

NEWS

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,10 @@ PHP NEWS
77
. Fixed bug #80384 (filter buffers entire read until file closed). (Adam
88
Seitz, cmb)
99

10+
- BCMath:
11+
. Fixed bug #80545 (bcadd('a', 'a') doesn't throw an exception).
12+
(Jens de Nies)
13+
1014
- Date:
1115
. Fixed bug #80376 (last day of the month causes runway cpu usage). (Derick)
1216

ext/bcmath/bcmath.c

Lines changed: 144 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -129,20 +129,23 @@ PHP_MINFO_FUNCTION(bcmath)
129129

130130
/* {{{ php_str2num
131131
Convert to bc_num detecting scale */
132-
static void php_str2num(bc_num *num, char *str)
132+
static zend_result php_str2num(bc_num *num, char *str)
133133
{
134134
char *p;
135135

136136
if (!(p = strchr(str, '.'))) {
137137
if (!bc_str2num(num, str, 0)) {
138-
php_error_docref(NULL, E_WARNING, "bcmath function argument is not well-formed");
138+
return FAILURE;
139139
}
140-
return;
140+
141+
return SUCCESS;
141142
}
142143

143144
if (!bc_str2num(num, str, strlen(p+1))) {
144-
php_error_docref(NULL, E_WARNING, "bcmath function argument is not well-formed");
145+
return FAILURE;
145146
}
147+
148+
return SUCCESS;
146149
}
147150
/* }}} */
148151

@@ -174,15 +177,26 @@ PHP_FUNCTION(bcadd)
174177
bc_init_num(&first);
175178
bc_init_num(&second);
176179
bc_init_num(&result);
177-
php_str2num(&first, ZSTR_VAL(left));
178-
php_str2num(&second, ZSTR_VAL(right));
180+
181+
if (php_str2num(&first, ZSTR_VAL(left)) == FAILURE) {
182+
zend_argument_value_error(1, "is not well-formed");
183+
goto cleanup;
184+
}
185+
186+
if (php_str2num(&second, ZSTR_VAL(right)) == FAILURE) {
187+
zend_argument_value_error(2, "is not well-formed");
188+
goto cleanup;
189+
}
190+
179191
bc_add (first, second, &result, scale);
180192

181193
RETVAL_STR(bc_num2str_ex(result, scale));
182-
bc_free_num(&first);
183-
bc_free_num(&second);
184-
bc_free_num(&result);
185-
return;
194+
195+
cleanup: {
196+
bc_free_num(&first);
197+
bc_free_num(&second);
198+
bc_free_num(&result);
199+
};
186200
}
187201
/* }}} */
188202

@@ -214,15 +228,26 @@ PHP_FUNCTION(bcsub)
214228
bc_init_num(&first);
215229
bc_init_num(&second);
216230
bc_init_num(&result);
217-
php_str2num(&first, ZSTR_VAL(left));
218-
php_str2num(&second, ZSTR_VAL(right));
231+
232+
if (php_str2num(&first, ZSTR_VAL(left)) == FAILURE) {
233+
zend_argument_value_error(1, "is not well-formed");
234+
goto cleanup;
235+
}
236+
237+
if (php_str2num(&second, ZSTR_VAL(right)) == FAILURE) {
238+
zend_argument_value_error(2, "is not well-formed");
239+
goto cleanup;
240+
}
241+
219242
bc_sub (first, second, &result, scale);
220243

221244
RETVAL_STR(bc_num2str_ex(result, scale));
222-
bc_free_num(&first);
223-
bc_free_num(&second);
224-
bc_free_num(&result);
225-
return;
245+
246+
cleanup: {
247+
bc_free_num(&first);
248+
bc_free_num(&second);
249+
bc_free_num(&result);
250+
};
226251
}
227252
/* }}} */
228253

@@ -254,15 +279,26 @@ PHP_FUNCTION(bcmul)
254279
bc_init_num(&first);
255280
bc_init_num(&second);
256281
bc_init_num(&result);
257-
php_str2num(&first, ZSTR_VAL(left));
258-
php_str2num(&second, ZSTR_VAL(right));
282+
283+
if (php_str2num(&first, ZSTR_VAL(left)) == FAILURE) {
284+
zend_argument_value_error(1, "is not well-formed");
285+
goto cleanup;
286+
}
287+
288+
if (php_str2num(&second, ZSTR_VAL(right)) == FAILURE) {
289+
zend_argument_value_error(2, "is not well-formed");
290+
goto cleanup;
291+
}
292+
259293
bc_multiply (first, second, &result, scale);
260294

261295
RETVAL_STR(bc_num2str_ex(result, scale));
262-
bc_free_num(&first);
263-
bc_free_num(&second);
264-
bc_free_num(&result);
265-
return;
296+
297+
cleanup: {
298+
bc_free_num(&first);
299+
bc_free_num(&second);
300+
bc_free_num(&result);
301+
};
266302
}
267303
/* }}} */
268304

@@ -294,8 +330,16 @@ PHP_FUNCTION(bcdiv)
294330
bc_init_num(&first);
295331
bc_init_num(&second);
296332
bc_init_num(&result);
297-
php_str2num(&first, ZSTR_VAL(left));
298-
php_str2num(&second, ZSTR_VAL(right));
333+
334+
if (php_str2num(&first, ZSTR_VAL(left)) == FAILURE) {
335+
zend_argument_value_error(1, "is not well-formed");
336+
goto cleanup;
337+
}
338+
339+
if (php_str2num(&second, ZSTR_VAL(right)) == FAILURE) {
340+
zend_argument_value_error(2, "is not well-formed");
341+
goto cleanup;
342+
}
299343

300344
switch (bc_divide(first, second, &result, scale)) {
301345
case 0: /* OK */
@@ -306,10 +350,11 @@ PHP_FUNCTION(bcdiv)
306350
break;
307351
}
308352

309-
bc_free_num(&first);
310-
bc_free_num(&second);
311-
bc_free_num(&result);
312-
return;
353+
cleanup: {
354+
bc_free_num(&first);
355+
bc_free_num(&second);
356+
bc_free_num(&result);
357+
};
313358
}
314359
/* }}} */
315360

@@ -341,8 +386,16 @@ PHP_FUNCTION(bcmod)
341386
bc_init_num(&first);
342387
bc_init_num(&second);
343388
bc_init_num(&result);
344-
php_str2num(&first, ZSTR_VAL(left));
345-
php_str2num(&second, ZSTR_VAL(right));
389+
390+
if (php_str2num(&first, ZSTR_VAL(left)) == FAILURE) {
391+
zend_argument_value_error(1, "is not well-formed");
392+
goto cleanup;
393+
}
394+
395+
if (php_str2num(&second, ZSTR_VAL(right)) == FAILURE) {
396+
zend_argument_value_error(2, "is not well-formed");
397+
goto cleanup;
398+
}
346399

347400
switch (bc_modulo(first, second, &result, scale)) {
348401
case 0:
@@ -353,9 +406,11 @@ PHP_FUNCTION(bcmod)
353406
break;
354407
}
355408

356-
bc_free_num(&first);
357-
bc_free_num(&second);
358-
bc_free_num(&result);
409+
cleanup: {
410+
bc_free_num(&first);
411+
bc_free_num(&second);
412+
bc_free_num(&result);
413+
};
359414
}
360415
/* }}} */
361416

@@ -389,18 +444,32 @@ PHP_FUNCTION(bcpowmod)
389444
bc_init_num(&second);
390445
bc_init_num(&mod);
391446
bc_init_num(&result);
392-
php_str2num(&first, ZSTR_VAL(left));
393-
php_str2num(&second, ZSTR_VAL(right));
394-
php_str2num(&mod, ZSTR_VAL(modulus));
447+
448+
if (php_str2num(&first, ZSTR_VAL(left)) == FAILURE) {
449+
zend_argument_value_error(1, "is not well-formed");
450+
goto cleanup;
451+
}
452+
453+
if (php_str2num(&second, ZSTR_VAL(right)) == FAILURE) {
454+
zend_argument_value_error(2, "is not well-formed");
455+
goto cleanup;
456+
}
457+
458+
if (php_str2num(&mod, ZSTR_VAL(modulus)) == FAILURE) {
459+
zend_argument_value_error(3, "is not well-formed");
460+
goto cleanup;
461+
}
395462

396463
if (bc_raisemod(first, second, mod, &result, scale) == SUCCESS) {
397464
RETVAL_STR(bc_num2str_ex(result, scale));
398465
}
399466

400-
bc_free_num(&first);
401-
bc_free_num(&second);
402-
bc_free_num(&mod);
403-
bc_free_num(&result);
467+
cleanup: {
468+
bc_free_num(&first);
469+
bc_free_num(&second);
470+
bc_free_num(&mod);
471+
bc_free_num(&result);
472+
};
404473
}
405474
/* }}} */
406475

@@ -432,14 +501,26 @@ PHP_FUNCTION(bcpow)
432501
bc_init_num(&first);
433502
bc_init_num(&second);
434503
bc_init_num(&result);
435-
php_str2num(&first, ZSTR_VAL(left));
436-
php_str2num(&second, ZSTR_VAL(right));
504+
505+
if (php_str2num(&first, ZSTR_VAL(left)) == FAILURE) {
506+
zend_argument_value_error(1, "is not well-formed");
507+
goto cleanup;
508+
}
509+
510+
if (php_str2num(&second, ZSTR_VAL(right)) == FAILURE) {
511+
zend_argument_value_error(2, "is not well-formed");
512+
goto cleanup;
513+
}
514+
437515
bc_raise (first, second, &result, scale);
438516

439517
RETVAL_STR(bc_num2str_ex(result, scale));
440-
bc_free_num(&first);
441-
bc_free_num(&second);
442-
bc_free_num(&result);
518+
519+
cleanup: {
520+
bc_free_num(&first);
521+
bc_free_num(&second);
522+
bc_free_num(&result);
523+
};
443524
}
444525
/* }}} */
445526

@@ -468,16 +549,21 @@ PHP_FUNCTION(bcsqrt)
468549
}
469550

470551
bc_init_num(&result);
471-
php_str2num(&result, ZSTR_VAL(left));
552+
553+
if (php_str2num(&result, ZSTR_VAL(left)) == FAILURE) {
554+
zend_argument_value_error(1, "is not well-formed");
555+
goto cleanup;
556+
}
472557

473558
if (bc_sqrt (&result, scale) != 0) {
474559
RETVAL_STR(bc_num2str_ex(result, scale));
475560
} else {
476561
zend_argument_value_error(1, "must be greater than or equal to 0");
477562
}
478563

479-
bc_free_num(&result);
480-
return;
564+
cleanup: {
565+
bc_free_num(&result);
566+
};
481567
}
482568
/* }}} */
483569

@@ -510,16 +596,21 @@ PHP_FUNCTION(bccomp)
510596
bc_init_num(&second);
511597

512598
if (!bc_str2num(&first, ZSTR_VAL(left), scale)) {
513-
php_error_docref(NULL, E_WARNING, "bcmath function argument is not well-formed");
599+
zend_argument_value_error(1, "is not well-formed");
600+
goto cleanup;
514601
}
602+
515603
if (!bc_str2num(&second, ZSTR_VAL(right), scale)) {
516-
php_error_docref(NULL, E_WARNING, "bcmath function argument is not well-formed");
604+
zend_argument_value_error(2, "is not well-formed");
605+
goto cleanup;
517606
}
607+
518608
RETVAL_LONG(bc_compare(first, second));
519609

520-
bc_free_num(&first);
521-
bc_free_num(&second);
522-
return;
610+
cleanup: {
611+
bc_free_num(&first);
612+
bc_free_num(&second);
613+
};
523614
}
524615
/* }}} */
525616

ext/bcmath/tests/bug80545.phpt

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
--TEST--
2+
Bug #80545 (bcadd('a', 'a') and bcadd('1', 'a') doesn't throw an exception)
3+
--SKIPIF--
4+
<?php
5+
if (!extension_loaded('bcmath')) die('skip bcmath extension not available');
6+
?>
7+
--FILE--
8+
<?php
9+
10+
try {
11+
bcadd('a', 'a');
12+
} catch (\ValueError $e) {
13+
echo $e->getMessage() . PHP_EOL;
14+
}
15+
16+
try {
17+
bcadd('1', 'a');
18+
} catch (\ValueError $e) {
19+
echo $e->getMessage();
20+
}
21+
22+
?>
23+
--EXPECT--
24+
bcadd(): Argument #1 ($num1) is not well-formed
25+
bcadd(): Argument #2 ($num2) is not well-formed

0 commit comments

Comments
 (0)