Skip to content

Commit 1257d42

Browse files
committed
Use Error exceptions instead of warning in some place in string stdlib
1 parent f50c460 commit 1257d42

28 files changed

+443
-256
lines changed

ext/standard/string.c

Lines changed: 59 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -291,6 +291,10 @@ static void php_spn_common_handler(INTERNAL_FUNCTION_PARAMETERS, int behavior) /
291291
start = 0;
292292
}
293293
} else if ((size_t)start > ZSTR_LEN(s11)) {
294+
/* Convert to Exception ?
295+
zend_throw_exception(zend_ce_error_exception, "Offset not contained in string", E_ERROR);
296+
return;
297+
*/
294298
RETURN_FALSE;
295299
}
296300

@@ -324,15 +328,15 @@ static void php_spn_common_handler(INTERNAL_FUNCTION_PARAMETERS, int behavior) /
324328
}
325329
/* }}} */
326330

327-
/* {{{ proto int|false strspn(string str, string mask [, int start [, int len]])
331+
/* {{{ proto int strspn(string str, string mask [, int start [, int len]])
328332
Finds length of initial segment consisting entirely of characters found in mask. If start or/and length is provided works like strspn(substr($s,$start,$len),$good_chars) */
329333
PHP_FUNCTION(strspn)
330334
{
331335
php_spn_common_handler(INTERNAL_FUNCTION_PARAM_PASSTHRU, STR_STRSPN);
332336
}
333337
/* }}} */
334338

335-
/* {{{ proto int|false strcspn(string str, string mask [, int start [, int len]])
339+
/* {{{ proto int strcspn(string str, string mask [, int start [, int len]])
336340
Finds length of initial segment consisting entirely of characters not found in mask. If start or/and length is provide works like strcspn(substr($s,$start,$len),$bad_chars) */
337341
PHP_FUNCTION(strcspn)
338342
{
@@ -682,6 +686,9 @@ PHP_FUNCTION(nl_langinfo)
682686
#endif
683687
break;
684688
default:
689+
/* TODO Convert to ErrorException
690+
* zend_throw_exception(zend_ce_error_exception, "", E_ERROR);
691+
*/
685692
php_error_docref(NULL, E_WARNING, "Item '" ZEND_LONG_FMT "' is not valid", item);
686693
RETURN_FALSE;
687694
}
@@ -718,6 +725,7 @@ PHP_FUNCTION(strcoll)
718725
* it needs to be incrementing.
719726
* Returns: FAILURE/SUCCESS whether the input was correct (i.e. no range errors)
720727
*/
728+
/* TODO (maybe) convert docref errors into ErrorException? */
721729
static inline int php_charmask(const unsigned char *input, size_t len, char *mask)
722730
{
723731
const unsigned char *end;
@@ -907,7 +915,7 @@ PHP_FUNCTION(ltrim)
907915
}
908916
/* }}} */
909917

910-
/* {{{ proto string|false wordwrap(string str [, int width [, string break [, bool cut]]])
918+
/* {{{ proto string wordwrap(string str [, int width [, string break [, bool cut]]])
911919
Wraps buffer to selected number of characters using string break char */
912920
PHP_FUNCTION(wordwrap)
913921
{
@@ -933,13 +941,13 @@ PHP_FUNCTION(wordwrap)
933941
}
934942

935943
if (breakchar_len == 0) {
936-
php_error_docref(NULL, E_WARNING, "Break string cannot be empty");
937-
RETURN_FALSE;
944+
zend_throw_exception(zend_ce_error_exception, "Break string cannot be empty", E_ERROR);
945+
return;
938946
}
939947

940948
if (linelength == 0 && docut) {
941-
php_error_docref(NULL, E_WARNING, "Can't force cut when width is zero");
942-
RETURN_FALSE;
949+
zend_throw_exception(zend_ce_error_exception, "Can't force cut when width is zero", E_ERROR);
950+
return;
943951
}
944952

945953
/* Special case for a single-character break as it needs no
@@ -1129,7 +1137,7 @@ PHPAPI void php_explode_negative_limit(const zend_string *delim, zend_string *st
11291137
}
11301138
/* }}} */
11311139

1132-
/* {{{ proto array|false explode(string separator, string str [, int limit])
1140+
/* {{{ proto array explode(string separator, string str [, int limit])
11331141
Splits a string on string separator and return array of components. If limit is positive only limit number of components is returned. If limit is negative all components except the last abs(limit) are returned. */
11341142
PHP_FUNCTION(explode)
11351143
{
@@ -1145,8 +1153,8 @@ PHP_FUNCTION(explode)
11451153
ZEND_PARSE_PARAMETERS_END();
11461154

11471155
if (ZSTR_LEN(delim) == 0) {
1148-
php_error_docref(NULL, E_WARNING, "Empty delimiter");
1149-
RETURN_FALSE;
1156+
zend_throw_exception(zend_ce_error_exception, "Empty delimiter", E_ERROR);
1157+
return;
11501158
}
11511159

11521160
array_init(return_value);
@@ -1619,7 +1627,7 @@ PHPAPI size_t php_dirname(char *path, size_t len)
16191627
}
16201628
/* }}} */
16211629

1622-
/* {{{ proto string|null dirname(string path[, int levels])
1630+
/* {{{ proto string dirname(string path[, int levels])
16231631
Returns the directory name component of the path */
16241632
PHP_FUNCTION(dirname)
16251633
{
@@ -1644,7 +1652,7 @@ PHP_FUNCTION(dirname)
16441652
ZSTR_LEN(ret) = zend_dirname(ZSTR_VAL(ret), str_len);
16451653
#endif
16461654
} else if (levels < 1) {
1647-
php_error_docref(NULL, E_WARNING, "Invalid argument, levels must be >= 1");
1655+
zend_throw_exception(zend_ce_error_exception, "Invalid argument, levels must be >= 1", E_ERROR);
16481656
zend_string_efree(ret);
16491657
return;
16501658
} else {
@@ -1813,8 +1821,8 @@ PHP_FUNCTION(stristr)
18131821
ZEND_PARSE_PARAMETERS_END();
18141822

18151823
if (!ZSTR_LEN(needle)) {
1816-
php_error_docref(NULL, E_WARNING, "Empty needle");
1817-
RETURN_FALSE;
1824+
zend_throw_exception(zend_ce_error_exception, "Empty needle", E_ERROR);
1825+
return;
18181826
}
18191827

18201828
haystack_dup = estrndup(ZSTR_VAL(haystack), ZSTR_LEN(haystack));
@@ -1854,8 +1862,8 @@ PHP_FUNCTION(strstr)
18541862
ZEND_PARSE_PARAMETERS_END();
18551863

18561864
if (!ZSTR_LEN(needle)) {
1857-
php_error_docref(NULL, E_WARNING, "Empty needle");
1858-
RETURN_FALSE;
1865+
zend_throw_exception(zend_ce_error_exception, "Empty needle", E_ERROR);
1866+
return;
18591867
}
18601868

18611869
found = php_memnstr(ZSTR_VAL(haystack), ZSTR_VAL(needle), ZSTR_LEN(needle), ZSTR_VAL(haystack) + ZSTR_LEN(haystack));
@@ -1900,8 +1908,8 @@ PHP_FUNCTION(strpos)
19001908
}
19011909

19021910
if (!ZSTR_LEN(needle)) {
1903-
php_error_docref(NULL, E_WARNING, "Empty needle");
1904-
RETURN_FALSE;
1911+
zend_throw_exception(zend_ce_error_exception, "Empty needle", E_ERROR);
1912+
return;
19051913
}
19061914

19071915
found = (char*)php_memnstr(ZSTR_VAL(haystack) + offset,
@@ -2194,8 +2202,8 @@ PHP_FUNCTION(chunk_split)
21942202
ZEND_PARSE_PARAMETERS_END();
21952203

21962204
if (chunklen <= 0) {
2197-
php_error_docref(NULL, E_WARNING, "Chunk length should be greater than zero");
2198-
RETURN_FALSE;
2205+
zend_throw_exception(zend_ce_error_exception, "Chunk length should be greater than zero", E_ERROR);
2206+
return;
21992207
}
22002208

22012209
if ((size_t)chunklen > ZSTR_LEN(str)) {
@@ -2350,11 +2358,13 @@ PHP_FUNCTION(substr_replace)
23502358
(argc == 3 && Z_TYPE_P(from) == IS_ARRAY) ||
23512359
(argc == 4 && Z_TYPE_P(from) != Z_TYPE_P(len))
23522360
) {
2361+
/* TODO can convert to TypeError ? */
23532362
php_error_docref(NULL, E_WARNING, "'start' and 'length' should be of same type - numerical or array ");
23542363
RETURN_STR_COPY(Z_STR_P(str));
23552364
}
23562365
if (argc == 4 && Z_TYPE_P(from) == IS_ARRAY) {
23572366
if (zend_hash_num_elements(Z_ARRVAL_P(from)) != zend_hash_num_elements(Z_ARRVAL_P(len))) {
2367+
/* TODO can convert to Exception ? */
23582368
php_error_docref(NULL, E_WARNING, "'start' and 'length' should have the same number of elements");
23592369
RETURN_STR_COPY(Z_STR_P(str));
23602370
}
@@ -2424,6 +2434,7 @@ PHP_FUNCTION(substr_replace)
24242434
zend_tmp_string_release(tmp_repl_str);
24252435
RETURN_NEW_STR(result);
24262436
} else {
2437+
/* TODO can convert to Exception ? */
24272438
php_error_docref(NULL, E_WARNING, "Functionality of 'start' and 'length' as arrays is not implemented");
24282439
RETURN_STR_COPY(Z_STR_P(str));
24292440
}
@@ -3292,7 +3303,7 @@ PHPAPI zend_string *php_str_to_str(const char *haystack, size_t length, const ch
32923303
}
32933304
/* }}} */
32943305

3295-
/* {{{ proto string|false strtr(string str, string from[, string to])
3306+
/* {{{ proto string strtr(string str, string from[, string to])
32963307
Translates characters in str using given translation tables */
32973308
PHP_FUNCTION(strtr)
32983309
{
@@ -3310,8 +3321,8 @@ PHP_FUNCTION(strtr)
33103321
ZEND_PARSE_PARAMETERS_END();
33113322

33123323
if (ac == 2 && Z_TYPE_P(from) != IS_ARRAY) {
3313-
php_error_docref(NULL, E_WARNING, "The second argument is not an array");
3314-
RETURN_FALSE;
3324+
zend_type_error("The second argument is not an array");
3325+
return;
33153326
}
33163327

33173328
/* shortcut for empty string */
@@ -3359,6 +3370,7 @@ PHP_FUNCTION(strtr)
33593370
}
33603371
} else {
33613372
if (!try_convert_to_string(from)) {
3373+
zend_type_error("Cannot convert 'from' into string.");
33623374
return;
33633375
}
33643376

@@ -5363,7 +5375,7 @@ PHP_FUNCTION(str_repeat)
53635375
ZEND_PARSE_PARAMETERS_END();
53645376

53655377
if (mult < 0) {
5366-
php_error_docref(NULL, E_WARNING, "Second argument has to be greater than or equal to 0");
5378+
zend_throw_exception(zend_ce_error_exception, "Second argument has to be greater than or equal to 0", E_ERROR);
53675379
return;
53685380
}
53695381

@@ -5401,7 +5413,7 @@ PHP_FUNCTION(str_repeat)
54015413
}
54025414
/* }}} */
54035415

5404-
/* {{{ proto array|string|false count_chars(string input [, int mode])
5416+
/* {{{ proto array|string count_chars(string input [, int mode])
54055417
Returns info about what characters are used in input */
54065418
PHP_FUNCTION(count_chars)
54075419
{
@@ -5421,8 +5433,8 @@ PHP_FUNCTION(count_chars)
54215433
ZEND_PARSE_PARAMETERS_END();
54225434

54235435
if (mymode < 0 || mymode > 4) {
5424-
php_error_docref(NULL, E_WARNING, "Unknown mode");
5425-
RETURN_FALSE;
5436+
zend_throw_exception(zend_ce_error_exception, "Unknown mode", E_ERROR);
5437+
return;
54265438
}
54275439

54285440
buf = (const unsigned char *) ZSTR_VAL(input);
@@ -5610,8 +5622,8 @@ PHP_FUNCTION(substr_count)
56105622
ZEND_PARSE_PARAMETERS_END();
56115623

56125624
if (needle_len == 0) {
5613-
php_error_docref(NULL, E_WARNING, "Empty substring");
5614-
RETURN_FALSE;
5625+
zend_throw_exception(zend_ce_error_exception, "Empty substring", E_ERROR);
5626+
return;
56155627
}
56165628

56175629
p = haystack;
@@ -5632,6 +5644,7 @@ PHP_FUNCTION(substr_count)
56325644
length += (haystack_len - offset);
56335645
}
56345646
if (length < 0 || ((size_t)length > (haystack_len - offset))) {
5647+
/* Convert to Exception ? */
56355648
php_error_docref(NULL, E_WARNING, "Invalid length value");
56365649
RETURN_FALSE;
56375650
}
@@ -5687,18 +5700,19 @@ PHP_FUNCTION(str_pad)
56875700
}
56885701

56895702
if (pad_str_len == 0) {
5690-
php_error_docref(NULL, E_WARNING, "Padding string cannot be empty");
5703+
zend_throw_exception(zend_ce_error_exception, "Padding string cannot be empty", E_ERROR);
56915704
return;
56925705
}
56935706

56945707
if (pad_type_val < STR_PAD_LEFT || pad_type_val > STR_PAD_BOTH) {
5695-
php_error_docref(NULL, E_WARNING, "Padding type has to be STR_PAD_LEFT, STR_PAD_RIGHT, or STR_PAD_BOTH");
5708+
zend_throw_exception(zend_ce_error_exception,
5709+
"Padding type has to be STR_PAD_LEFT, STR_PAD_RIGHT, or STR_PAD_BOTH", E_ERROR);
56965710
return;
56975711
}
56985712

56995713
num_pad_chars = pad_length - ZSTR_LEN(input);
57005714
if (num_pad_chars >= INT_MAX) {
5701-
php_error_docref(NULL, E_WARNING, "Padding length is too long");
5715+
zend_throw_exception(zend_ce_error_exception, "Padding length is too long", E_ERROR);
57025716
return;
57035717
}
57045718

@@ -5916,7 +5930,7 @@ PHP_FUNCTION(str_shuffle)
59165930
}
59175931
/* }}} */
59185932

5919-
/* {{{ proto mixed str_word_count(string str, [int format [, string charlist]])
5933+
/* {{{ proto array|int|null|false str_word_count(string str, [int format [, string charlist]])
59205934
Counts the number of words inside a string. If format of 1 is specified,
59215935
then the function will return an array containing all the words
59225936
found inside the string. If format of 2 is specified, then the function
@@ -5957,6 +5971,10 @@ PHP_FUNCTION(str_word_count)
59575971
/* nothing to be done */
59585972
break;
59595973
default:
5974+
/* Not sure how to proceed here
5975+
zend_throw_exception(zend_ce_error_exception, "Padding string cannot be empty", E_ERROR);
5976+
return;
5977+
*/
59605978
php_error_docref(NULL, E_WARNING, "Invalid format value " ZEND_LONG_FMT, type);
59615979
RETURN_FALSE;
59625980
}
@@ -6058,7 +6076,7 @@ PHP_FUNCTION(money_format)
60586076
/* }}} */
60596077
#endif
60606078

6061-
/* {{{ proto array|false str_split(string str [, int split_length])
6079+
/* {{{ proto array str_split(string str [, int split_length])
60626080
Convert a string to an array. If split_length is specified, break the string down into chunks each split_length characters long. */
60636081
PHP_FUNCTION(str_split)
60646082
{
@@ -6074,8 +6092,8 @@ PHP_FUNCTION(str_split)
60746092
ZEND_PARSE_PARAMETERS_END();
60756093

60766094
if (split_length <= 0) {
6077-
php_error_docref(NULL, E_WARNING, "The length of each segment must be greater than zero");
6078-
RETURN_FALSE;
6095+
zend_throw_exception(zend_ce_error_exception, "The length of each segment must be greater than zero", E_ERROR);
6096+
return;
60796097
}
60806098

60816099

@@ -6114,8 +6132,8 @@ PHP_FUNCTION(strpbrk)
61146132
ZEND_PARSE_PARAMETERS_END_EX(RETURN_FALSE);
61156133

61166134
if (!ZSTR_LEN(char_list)) {
6117-
php_error_docref(NULL, E_WARNING, "The character list cannot be empty");
6118-
RETURN_FALSE;
6135+
zend_throw_exception(zend_ce_error_exception, "The character list cannot be empty", E_ERROR);
6136+
return;
61196137
}
61206138

61216139
for (haystack_ptr = ZSTR_VAL(haystack); haystack_ptr < (ZSTR_VAL(haystack) + ZSTR_LEN(haystack)); ++haystack_ptr) {
@@ -6153,8 +6171,8 @@ PHP_FUNCTION(substr_compare)
61536171
if (len == 0) {
61546172
RETURN_LONG(0L);
61556173
} else {
6156-
php_error_docref(NULL, E_WARNING, "The length must be greater than or equal to zero");
6157-
RETURN_FALSE;
6174+
zend_throw_exception(zend_ce_error_exception, "The length must be greater than or equal to zero", E_ERROR);
6175+
return;
61586176
}
61596177
}
61606178

@@ -6164,6 +6182,7 @@ PHP_FUNCTION(substr_compare)
61646182
}
61656183

61666184
if ((size_t)offset > ZSTR_LEN(s1)) {
6185+
/* Candidate to convert to Exception ? */
61676186
php_error_docref(NULL, E_WARNING, "The start position cannot exceed initial string length");
61686187
RETURN_FALSE;
61696188
}

ext/standard/tests/strings/bug33605.phpt

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,12 @@
22
Bug #33605 (substr_compare crashes)
33
--FILE--
44
<?php
5-
$res = substr_compare("aa", "a", -99999999, -1, 0);
6-
var_dump($res);
5+
try {
6+
substr_compare("aa", "a", -99999999, -1, 0);
7+
} catch (\ErrorException $e) {
8+
echo $e->getMessage();
9+
}
710

811
?>
912
--EXPECTF--
10-
Warning: substr_compare(): The length must be greater than or equal to zero in %s on line %d
11-
bool(false)
13+
The length must be greater than or equal to zero

ext/standard/tests/strings/bug63943.phpt

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,11 @@
22
Bug #63943 (Bad warning text from strpos() on empty needle)
33
--FILE--
44
<?php
5-
strpos("lllllll", '');
5+
try {
6+
strpos("lllllll", '');
7+
} catch (\ErrorException $e) {
8+
echo $e->getMessage();
9+
}
610
?>
711
--EXPECTF--
8-
Warning: strpos(): Empty needle in %sbug63943.php on line %d
12+
Empty needle
Binary file not shown.

0 commit comments

Comments
 (0)