Skip to content

Commit f5a8027

Browse files
committed
Use Error exceptions instead of warning in some place in string stdlib
1 parent b78347b commit f5a8027

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
@@ -295,6 +295,10 @@ static void php_spn_common_handler(INTERNAL_FUNCTION_PARAMETERS, int behavior) /
295295
start = 0;
296296
}
297297
} else if ((size_t)start > ZSTR_LEN(s11)) {
298+
/* Convert to Exception ?
299+
zend_throw_exception(zend_ce_error_exception, "Offset not contained in string", E_ERROR);
300+
return;
301+
*/
298302
RETURN_FALSE;
299303
}
300304

@@ -328,15 +332,15 @@ static void php_spn_common_handler(INTERNAL_FUNCTION_PARAMETERS, int behavior) /
328332
}
329333
/* }}} */
330334

331-
/* {{{ proto int|false strspn(string str, string mask [, int start [, int len]])
335+
/* {{{ proto int strspn(string str, string mask [, int start [, int len]])
332336
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) */
333337
PHP_FUNCTION(strspn)
334338
{
335339
php_spn_common_handler(INTERNAL_FUNCTION_PARAM_PASSTHRU, STR_STRSPN);
336340
}
337341
/* }}} */
338342

339-
/* {{{ proto int|false strcspn(string str, string mask [, int start [, int len]])
343+
/* {{{ proto int strcspn(string str, string mask [, int start [, int len]])
340344
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) */
341345
PHP_FUNCTION(strcspn)
342346
{
@@ -686,6 +690,9 @@ PHP_FUNCTION(nl_langinfo)
686690
#endif
687691
break;
688692
default:
693+
/* TODO Convert to ErrorException
694+
* zend_throw_exception(zend_ce_error_exception, "", E_ERROR);
695+
*/
689696
php_error_docref(NULL, E_WARNING, "Item '" ZEND_LONG_FMT "' is not valid", item);
690697
RETURN_FALSE;
691698
}
@@ -722,6 +729,7 @@ PHP_FUNCTION(strcoll)
722729
* it needs to be incrementing.
723730
* Returns: FAILURE/SUCCESS whether the input was correct (i.e. no range errors)
724731
*/
732+
/* TODO (maybe) convert docref errors into ErrorException? */
725733
static inline int php_charmask(const unsigned char *input, size_t len, char *mask)
726734
{
727735
const unsigned char *end;
@@ -911,7 +919,7 @@ PHP_FUNCTION(ltrim)
911919
}
912920
/* }}} */
913921

914-
/* {{{ proto string|false wordwrap(string str [, int width [, string break [, bool cut]]])
922+
/* {{{ proto string wordwrap(string str [, int width [, string break [, bool cut]]])
915923
Wraps buffer to selected number of characters using string break char */
916924
PHP_FUNCTION(wordwrap)
917925
{
@@ -937,13 +945,13 @@ PHP_FUNCTION(wordwrap)
937945
}
938946

939947
if (breakchar_len == 0) {
940-
php_error_docref(NULL, E_WARNING, "Break string cannot be empty");
941-
RETURN_FALSE;
948+
zend_throw_exception(zend_ce_error_exception, "Break string cannot be empty", E_ERROR);
949+
return;
942950
}
943951

944952
if (linelength == 0 && docut) {
945-
php_error_docref(NULL, E_WARNING, "Can't force cut when width is zero");
946-
RETURN_FALSE;
953+
zend_throw_exception(zend_ce_error_exception, "Can't force cut when width is zero", E_ERROR);
954+
return;
947955
}
948956

949957
/* Special case for a single-character break as it needs no
@@ -1133,7 +1141,7 @@ PHPAPI void php_explode_negative_limit(const zend_string *delim, zend_string *st
11331141
}
11341142
/* }}} */
11351143

1136-
/* {{{ proto array|false explode(string separator, string str [, int limit])
1144+
/* {{{ proto array explode(string separator, string str [, int limit])
11371145
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. */
11381146
PHP_FUNCTION(explode)
11391147
{
@@ -1149,8 +1157,8 @@ PHP_FUNCTION(explode)
11491157
ZEND_PARSE_PARAMETERS_END();
11501158

11511159
if (ZSTR_LEN(delim) == 0) {
1152-
php_error_docref(NULL, E_WARNING, "Empty delimiter");
1153-
RETURN_FALSE;
1160+
zend_throw_exception(zend_ce_error_exception, "Empty delimiter", E_ERROR);
1161+
return;
11541162
}
11551163

11561164
array_init(return_value);
@@ -1623,7 +1631,7 @@ PHPAPI size_t php_dirname(char *path, size_t len)
16231631
}
16241632
/* }}} */
16251633

1626-
/* {{{ proto string|null dirname(string path[, int levels])
1634+
/* {{{ proto string dirname(string path[, int levels])
16271635
Returns the directory name component of the path */
16281636
PHP_FUNCTION(dirname)
16291637
{
@@ -1648,7 +1656,7 @@ PHP_FUNCTION(dirname)
16481656
ZSTR_LEN(ret) = zend_dirname(ZSTR_VAL(ret), str_len);
16491657
#endif
16501658
} else if (levels < 1) {
1651-
php_error_docref(NULL, E_WARNING, "Invalid argument, levels must be >= 1");
1659+
zend_throw_exception(zend_ce_error_exception, "Invalid argument, levels must be >= 1", E_ERROR);
16521660
zend_string_efree(ret);
16531661
return;
16541662
} else {
@@ -1817,8 +1825,8 @@ PHP_FUNCTION(stristr)
18171825
ZEND_PARSE_PARAMETERS_END();
18181826

18191827
if (!ZSTR_LEN(needle)) {
1820-
php_error_docref(NULL, E_WARNING, "Empty needle");
1821-
RETURN_FALSE;
1828+
zend_throw_exception(zend_ce_error_exception, "Empty needle", E_ERROR);
1829+
return;
18221830
}
18231831

18241832
haystack_dup = estrndup(ZSTR_VAL(haystack), ZSTR_LEN(haystack));
@@ -1858,8 +1866,8 @@ PHP_FUNCTION(strstr)
18581866
ZEND_PARSE_PARAMETERS_END();
18591867

18601868
if (!ZSTR_LEN(needle)) {
1861-
php_error_docref(NULL, E_WARNING, "Empty needle");
1862-
RETURN_FALSE;
1869+
zend_throw_exception(zend_ce_error_exception, "Empty needle", E_ERROR);
1870+
return;
18631871
}
18641872

18651873
found = php_memnstr(ZSTR_VAL(haystack), ZSTR_VAL(needle), ZSTR_LEN(needle), ZSTR_VAL(haystack) + ZSTR_LEN(haystack));
@@ -1904,8 +1912,8 @@ PHP_FUNCTION(strpos)
19041912
}
19051913

19061914
if (!ZSTR_LEN(needle)) {
1907-
php_error_docref(NULL, E_WARNING, "Empty needle");
1908-
RETURN_FALSE;
1915+
zend_throw_exception(zend_ce_error_exception, "Empty needle", E_ERROR);
1916+
return;
19091917
}
19101918

19111919
found = (char*)php_memnstr(ZSTR_VAL(haystack) + offset,
@@ -2198,8 +2206,8 @@ PHP_FUNCTION(chunk_split)
21982206
ZEND_PARSE_PARAMETERS_END();
21992207

22002208
if (chunklen <= 0) {
2201-
php_error_docref(NULL, E_WARNING, "Chunk length should be greater than zero");
2202-
RETURN_FALSE;
2209+
zend_throw_exception(zend_ce_error_exception, "Chunk length should be greater than zero", E_ERROR);
2210+
return;
22032211
}
22042212

22052213
if ((size_t)chunklen > ZSTR_LEN(str)) {
@@ -2354,11 +2362,13 @@ PHP_FUNCTION(substr_replace)
23542362
(argc == 3 && Z_TYPE_P(from) == IS_ARRAY) ||
23552363
(argc == 4 && Z_TYPE_P(from) != Z_TYPE_P(len))
23562364
) {
2365+
/* TODO can convert to TypeError ? */
23572366
php_error_docref(NULL, E_WARNING, "'start' and 'length' should be of same type - numerical or array ");
23582367
RETURN_STR_COPY(Z_STR_P(str));
23592368
}
23602369
if (argc == 4 && Z_TYPE_P(from) == IS_ARRAY) {
23612370
if (zend_hash_num_elements(Z_ARRVAL_P(from)) != zend_hash_num_elements(Z_ARRVAL_P(len))) {
2371+
/* TODO can convert to Exception ? */
23622372
php_error_docref(NULL, E_WARNING, "'start' and 'length' should have the same number of elements");
23632373
RETURN_STR_COPY(Z_STR_P(str));
23642374
}
@@ -2428,6 +2438,7 @@ PHP_FUNCTION(substr_replace)
24282438
zend_tmp_string_release(tmp_repl_str);
24292439
RETURN_NEW_STR(result);
24302440
} else {
2441+
/* TODO can convert to Exception ? */
24312442
php_error_docref(NULL, E_WARNING, "Functionality of 'start' and 'length' as arrays is not implemented");
24322443
RETURN_STR_COPY(Z_STR_P(str));
24332444
}
@@ -3296,7 +3307,7 @@ PHPAPI zend_string *php_str_to_str(const char *haystack, size_t length, const ch
32963307
}
32973308
/* }}} */
32983309

3299-
/* {{{ proto string|false strtr(string str, string from[, string to])
3310+
/* {{{ proto string strtr(string str, string from[, string to])
33003311
Translates characters in str using given translation tables */
33013312
PHP_FUNCTION(strtr)
33023313
{
@@ -3314,8 +3325,8 @@ PHP_FUNCTION(strtr)
33143325
ZEND_PARSE_PARAMETERS_END();
33153326

33163327
if (ac == 2 && Z_TYPE_P(from) != IS_ARRAY) {
3317-
php_error_docref(NULL, E_WARNING, "The second argument is not an array");
3318-
RETURN_FALSE;
3328+
zend_type_error("The second argument is not an array");
3329+
return;
33193330
}
33203331

33213332
/* shortcut for empty string */
@@ -3363,6 +3374,7 @@ PHP_FUNCTION(strtr)
33633374
}
33643375
} else {
33653376
if (!try_convert_to_string(from)) {
3377+
zend_type_error("Cannot convert 'from' into string.");
33663378
return;
33673379
}
33683380

@@ -5367,7 +5379,7 @@ PHP_FUNCTION(str_repeat)
53675379
ZEND_PARSE_PARAMETERS_END();
53685380

53695381
if (mult < 0) {
5370-
php_error_docref(NULL, E_WARNING, "Second argument has to be greater than or equal to 0");
5382+
zend_throw_exception(zend_ce_error_exception, "Second argument has to be greater than or equal to 0", E_ERROR);
53715383
return;
53725384
}
53735385

@@ -5405,7 +5417,7 @@ PHP_FUNCTION(str_repeat)
54055417
}
54065418
/* }}} */
54075419

5408-
/* {{{ proto array|string|false count_chars(string input [, int mode])
5420+
/* {{{ proto array|string count_chars(string input [, int mode])
54095421
Returns info about what characters are used in input */
54105422
PHP_FUNCTION(count_chars)
54115423
{
@@ -5425,8 +5437,8 @@ PHP_FUNCTION(count_chars)
54255437
ZEND_PARSE_PARAMETERS_END();
54265438

54275439
if (mymode < 0 || mymode > 4) {
5428-
php_error_docref(NULL, E_WARNING, "Unknown mode");
5429-
RETURN_FALSE;
5440+
zend_throw_exception(zend_ce_error_exception, "Unknown mode", E_ERROR);
5441+
return;
54305442
}
54315443

54325444
buf = (const unsigned char *) ZSTR_VAL(input);
@@ -5614,8 +5626,8 @@ PHP_FUNCTION(substr_count)
56145626
ZEND_PARSE_PARAMETERS_END();
56155627

56165628
if (needle_len == 0) {
5617-
php_error_docref(NULL, E_WARNING, "Empty substring");
5618-
RETURN_FALSE;
5629+
zend_throw_exception(zend_ce_error_exception, "Empty substring", E_ERROR);
5630+
return;
56195631
}
56205632

56215633
p = haystack;
@@ -5636,6 +5648,7 @@ PHP_FUNCTION(substr_count)
56365648
length += (haystack_len - offset);
56375649
}
56385650
if (length < 0 || ((size_t)length > (haystack_len - offset))) {
5651+
/* Convert to Exception ? */
56395652
php_error_docref(NULL, E_WARNING, "Invalid length value");
56405653
RETURN_FALSE;
56415654
}
@@ -5691,18 +5704,19 @@ PHP_FUNCTION(str_pad)
56915704
}
56925705

56935706
if (pad_str_len == 0) {
5694-
php_error_docref(NULL, E_WARNING, "Padding string cannot be empty");
5707+
zend_throw_exception(zend_ce_error_exception, "Padding string cannot be empty", E_ERROR);
56955708
return;
56965709
}
56975710

56985711
if (pad_type_val < STR_PAD_LEFT || pad_type_val > STR_PAD_BOTH) {
5699-
php_error_docref(NULL, E_WARNING, "Padding type has to be STR_PAD_LEFT, STR_PAD_RIGHT, or STR_PAD_BOTH");
5712+
zend_throw_exception(zend_ce_error_exception,
5713+
"Padding type has to be STR_PAD_LEFT, STR_PAD_RIGHT, or STR_PAD_BOTH", E_ERROR);
57005714
return;
57015715
}
57025716

57035717
num_pad_chars = pad_length - ZSTR_LEN(input);
57045718
if (num_pad_chars >= INT_MAX) {
5705-
php_error_docref(NULL, E_WARNING, "Padding length is too long");
5719+
zend_throw_exception(zend_ce_error_exception, "Padding length is too long", E_ERROR);
57065720
return;
57075721
}
57085722

@@ -5920,7 +5934,7 @@ PHP_FUNCTION(str_shuffle)
59205934
}
59215935
/* }}} */
59225936

5923-
/* {{{ proto mixed str_word_count(string str, [int format [, string charlist]])
5937+
/* {{{ proto array|int|null|false str_word_count(string str, [int format [, string charlist]])
59245938
Counts the number of words inside a string. If format of 1 is specified,
59255939
then the function will return an array containing all the words
59265940
found inside the string. If format of 2 is specified, then the function
@@ -5961,6 +5975,10 @@ PHP_FUNCTION(str_word_count)
59615975
/* nothing to be done */
59625976
break;
59635977
default:
5978+
/* Not sure how to proceed here
5979+
zend_throw_exception(zend_ce_error_exception, "Padding string cannot be empty", E_ERROR);
5980+
return;
5981+
*/
59645982
php_error_docref(NULL, E_WARNING, "Invalid format value " ZEND_LONG_FMT, type);
59655983
RETURN_FALSE;
59665984
}
@@ -6062,7 +6080,7 @@ PHP_FUNCTION(money_format)
60626080
/* }}} */
60636081
#endif
60646082

6065-
/* {{{ proto array|false str_split(string str [, int split_length])
6083+
/* {{{ proto array str_split(string str [, int split_length])
60666084
Convert a string to an array. If split_length is specified, break the string down into chunks each split_length characters long. */
60676085
PHP_FUNCTION(str_split)
60686086
{
@@ -6078,8 +6096,8 @@ PHP_FUNCTION(str_split)
60786096
ZEND_PARSE_PARAMETERS_END();
60796097

60806098
if (split_length <= 0) {
6081-
php_error_docref(NULL, E_WARNING, "The length of each segment must be greater than zero");
6082-
RETURN_FALSE;
6099+
zend_throw_exception(zend_ce_error_exception, "The length of each segment must be greater than zero", E_ERROR);
6100+
return;
60836101
}
60846102

60856103

@@ -6118,8 +6136,8 @@ PHP_FUNCTION(strpbrk)
61186136
ZEND_PARSE_PARAMETERS_END_EX(RETURN_FALSE);
61196137

61206138
if (!ZSTR_LEN(char_list)) {
6121-
php_error_docref(NULL, E_WARNING, "The character list cannot be empty");
6122-
RETURN_FALSE;
6139+
zend_throw_exception(zend_ce_error_exception, "The character list cannot be empty", E_ERROR);
6140+
return;
61236141
}
61246142

61256143
for (haystack_ptr = ZSTR_VAL(haystack); haystack_ptr < (ZSTR_VAL(haystack) + ZSTR_LEN(haystack)); ++haystack_ptr) {
@@ -6157,8 +6175,8 @@ PHP_FUNCTION(substr_compare)
61576175
if (len == 0) {
61586176
RETURN_LONG(0L);
61596177
} else {
6160-
php_error_docref(NULL, E_WARNING, "The length must be greater than or equal to zero");
6161-
RETURN_FALSE;
6178+
zend_throw_exception(zend_ce_error_exception, "The length must be greater than or equal to zero", E_ERROR);
6179+
return;
61626180
}
61636181
}
61646182

@@ -6168,6 +6186,7 @@ PHP_FUNCTION(substr_compare)
61686186
}
61696187

61706188
if ((size_t)offset > ZSTR_LEN(s1)) {
6189+
/* Candidate to convert to Exception ? */
61716190
php_error_docref(NULL, E_WARNING, "The start position cannot exceed initial string length");
61726191
RETURN_FALSE;
61736192
}

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)