Skip to content

Use Error exceptions instead of warning in some place in string stdlib #4554

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
7 changes: 2 additions & 5 deletions ext/mbstring/tests/bug73646.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,7 @@ if (!function_exists('mb_ereg')) die('skip mbregex support not available');
?>
--FILE--
<?php

$v1=str_repeat("#", -1);
var_dump(mb_ereg_search_init($v1));
var_dump(mb_ereg_search_init(NULL));
?>
--EXPECTF--
Warning: str_repeat(): Second argument has to be greater than or equal to 0 in %sbug73646.php on line %d
--EXPECT--
bool(true)
4 changes: 3 additions & 1 deletion ext/opcache/tests/bug70207.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,9 @@ function bar() {
}
function foo() {
try { return bar(); }
finally { @str_repeat("foo", -10); }
finally {
@fopen("non-existent", 'r');
}
}

var_dump(foo());
Expand Down
87 changes: 49 additions & 38 deletions ext/standard/string.c
Original file line number Diff line number Diff line change
Expand Up @@ -324,15 +324,15 @@ static void php_spn_common_handler(INTERNAL_FUNCTION_PARAMETERS, int behavior) /
}
/* }}} */

/* {{{ proto int|false strspn(string str, string mask [, int start [, int len]])
/* {{{ proto int strspn(string str, string mask [, int start [, int len]])
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) */
PHP_FUNCTION(strspn)
{
php_spn_common_handler(INTERNAL_FUNCTION_PARAM_PASSTHRU, STR_STRSPN);
}
/* }}} */

/* {{{ proto int|false strcspn(string str, string mask [, int start [, int len]])
/* {{{ proto int strcspn(string str, string mask [, int start [, int len]])
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) */
PHP_FUNCTION(strcspn)
{
Expand Down Expand Up @@ -682,8 +682,8 @@ PHP_FUNCTION(nl_langinfo)
#endif
break;
default:
php_error_docref(NULL, E_WARNING, "Item '" ZEND_LONG_FMT "' is not valid", item);
RETURN_FALSE;
zend_throw_error(NULL, "Item '" ZEND_LONG_FMT "' is not valid", item);
return;
}
/* }}} */

Expand Down Expand Up @@ -735,21 +735,25 @@ static inline int php_charmask(const unsigned char *input, size_t len, char *mas
/* Error, try to be as helpful as possible:
(a range ending/starting with '.' won't be captured here) */
if (end-len >= input) { /* there was no 'left' char */
/* TODO Check if Candidate to convert to Exception */
php_error_docref(NULL, E_WARNING, "Invalid '..'-range, no character to the left of '..'");
result = FAILURE;
continue;
}
if (input+2 >= end) { /* there is no 'right' char */
/* TODO Check if Candidate to convert to Exception */
php_error_docref(NULL, E_WARNING, "Invalid '..'-range, no character to the right of '..'");
result = FAILURE;
continue;
}
if (input[-1] > input[2]) { /* wrong order */
/* TODO Check if Candidate to convert to Exception */
php_error_docref(NULL, E_WARNING, "Invalid '..'-range, '..'-range needs to be incrementing");
result = FAILURE;
continue;
}
/* FIXME: better error (a..b..c is the only left possibility?) */
/* TODO Check if Candidate to convert to Exception */
php_error_docref(NULL, E_WARNING, "Invalid '..'-range");
result = FAILURE;
continue;
Expand Down Expand Up @@ -907,7 +911,7 @@ PHP_FUNCTION(ltrim)
}
/* }}} */

/* {{{ proto string|false wordwrap(string str [, int width [, string break [, bool cut]]])
/* {{{ proto string wordwrap(string str [, int width [, string break [, bool cut]]])
Wraps buffer to selected number of characters using string break char */
PHP_FUNCTION(wordwrap)
{
Expand All @@ -933,13 +937,13 @@ PHP_FUNCTION(wordwrap)
}

if (breakchar_len == 0) {
php_error_docref(NULL, E_WARNING, "Break string cannot be empty");
RETURN_FALSE;
zend_throw_error(NULL, "Break string cannot be empty");
return;
}

if (linelength == 0 && docut) {
php_error_docref(NULL, E_WARNING, "Can't force cut when width is zero");
RETURN_FALSE;
zend_throw_error(NULL, "Can't force cut when width is zero");
return;
}

/* Special case for a single-character break as it needs no
Expand Down Expand Up @@ -1129,7 +1133,7 @@ PHPAPI void php_explode_negative_limit(const zend_string *delim, zend_string *st
}
/* }}} */

/* {{{ proto array|false explode(string separator, string str [, int limit])
/* {{{ proto array explode(string separator, string str [, int limit])
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. */
PHP_FUNCTION(explode)
{
Expand All @@ -1145,8 +1149,8 @@ PHP_FUNCTION(explode)
ZEND_PARSE_PARAMETERS_END();

if (ZSTR_LEN(delim) == 0) {
php_error_docref(NULL, E_WARNING, "Empty delimiter");
RETURN_FALSE;
zend_throw_error(NULL, "Empty delimiter");
return;
}

array_init(return_value);
Expand Down Expand Up @@ -1619,7 +1623,7 @@ PHPAPI size_t php_dirname(char *path, size_t len)
}
/* }}} */

/* {{{ proto string|null dirname(string path[, int levels])
/* {{{ proto string dirname(string path[, int levels])
Returns the directory name component of the path */
PHP_FUNCTION(dirname)
{
Expand All @@ -1644,7 +1648,7 @@ PHP_FUNCTION(dirname)
ZSTR_LEN(ret) = zend_dirname(ZSTR_VAL(ret), str_len);
#endif
} else if (levels < 1) {
php_error_docref(NULL, E_WARNING, "Invalid argument, levels must be >= 1");
zend_throw_error(NULL, "Invalid argument, levels must be >= 1");
zend_string_efree(ret);
return;
} else {
Expand Down Expand Up @@ -2194,8 +2198,8 @@ PHP_FUNCTION(chunk_split)
ZEND_PARSE_PARAMETERS_END();

if (chunklen <= 0) {
php_error_docref(NULL, E_WARNING, "Chunk length should be greater than zero");
RETURN_FALSE;
zend_throw_error(NULL, "Chunk length should be greater than zero");
return;
}

if ((size_t)chunklen > ZSTR_LEN(str)) {
Expand Down Expand Up @@ -2350,11 +2354,13 @@ PHP_FUNCTION(substr_replace)
(argc == 3 && Z_TYPE_P(from) == IS_ARRAY) ||
(argc == 4 && Z_TYPE_P(from) != Z_TYPE_P(len))
) {
/* TODO Check if Candidate to convert to TypeError ? */
php_error_docref(NULL, E_WARNING, "'start' and 'length' should be of same type - numerical or array ");
RETURN_STR_COPY(Z_STR_P(str));
}
if (argc == 4 && Z_TYPE_P(from) == IS_ARRAY) {
if (zend_hash_num_elements(Z_ARRVAL_P(from)) != zend_hash_num_elements(Z_ARRVAL_P(len))) {
/* TODO Check if Candidate to convert to Exception */
php_error_docref(NULL, E_WARNING, "'start' and 'length' should have the same number of elements");
RETURN_STR_COPY(Z_STR_P(str));
}
Expand Down Expand Up @@ -2424,6 +2430,7 @@ PHP_FUNCTION(substr_replace)
zend_tmp_string_release(tmp_repl_str);
RETURN_NEW_STR(result);
} else {
/* TODO Check if Candidate to convert to Exception */
php_error_docref(NULL, E_WARNING, "Functionality of 'start' and 'length' as arrays is not implemented");
RETURN_STR_COPY(Z_STR_P(str));
}
Expand Down Expand Up @@ -3292,7 +3299,7 @@ PHPAPI zend_string *php_str_to_str(const char *haystack, size_t length, const ch
}
/* }}} */

/* {{{ proto string|false strtr(string str, string from[, string to])
/* {{{ proto string strtr(string str, string from[, string to])
Translates characters in str using given translation tables */
PHP_FUNCTION(strtr)
{
Expand All @@ -3310,8 +3317,8 @@ PHP_FUNCTION(strtr)
ZEND_PARSE_PARAMETERS_END();

if (ac == 2 && Z_TYPE_P(from) != IS_ARRAY) {
php_error_docref(NULL, E_WARNING, "The second argument is not an array");
RETURN_FALSE;
zend_type_error("The second argument is not an array");
return;
}

/* shortcut for empty string */
Expand Down Expand Up @@ -3359,6 +3366,7 @@ PHP_FUNCTION(strtr)
}
} else {
if (!try_convert_to_string(from)) {
zend_type_error("Cannot convert 'from' into string.");
return;
}

Expand Down Expand Up @@ -5363,7 +5371,7 @@ PHP_FUNCTION(str_repeat)
ZEND_PARSE_PARAMETERS_END();

if (mult < 0) {
php_error_docref(NULL, E_WARNING, "Second argument has to be greater than or equal to 0");
zend_throw_error(NULL, "Second argument has to be greater than or equal to 0");
return;
}

Expand Down Expand Up @@ -5401,7 +5409,7 @@ PHP_FUNCTION(str_repeat)
}
/* }}} */

/* {{{ proto array|string|false count_chars(string input [, int mode])
/* {{{ proto array|string count_chars(string input [, int mode])
Returns info about what characters are used in input */
PHP_FUNCTION(count_chars)
{
Expand All @@ -5421,8 +5429,8 @@ PHP_FUNCTION(count_chars)
ZEND_PARSE_PARAMETERS_END();

if (mymode < 0 || mymode > 4) {
php_error_docref(NULL, E_WARNING, "Unknown mode");
RETURN_FALSE;
zend_throw_error(NULL, "Unknown mode");
return;
}

buf = (const unsigned char *) ZSTR_VAL(input);
Expand Down Expand Up @@ -5610,8 +5618,8 @@ PHP_FUNCTION(substr_count)
ZEND_PARSE_PARAMETERS_END();

if (needle_len == 0) {
php_error_docref(NULL, E_WARNING, "Empty substring");
RETURN_FALSE;
zend_throw_error(NULL, "Empty substring");
return;
}

p = haystack;
Expand All @@ -5632,6 +5640,7 @@ PHP_FUNCTION(substr_count)
length += (haystack_len - offset);
}
if (length < 0 || ((size_t)length > (haystack_len - offset))) {
/* TODO Check if Candidate to convert to Exception */
php_error_docref(NULL, E_WARNING, "Invalid length value");
RETURN_FALSE;
}
Expand Down Expand Up @@ -5687,18 +5696,19 @@ PHP_FUNCTION(str_pad)
}

if (pad_str_len == 0) {
php_error_docref(NULL, E_WARNING, "Padding string cannot be empty");
zend_throw_error(NULL, "Padding string cannot be empty");
return;
}

if (pad_type_val < STR_PAD_LEFT || pad_type_val > STR_PAD_BOTH) {
php_error_docref(NULL, E_WARNING, "Padding type has to be STR_PAD_LEFT, STR_PAD_RIGHT, or STR_PAD_BOTH");
zend_throw_error(NULL,
"Padding type has to be STR_PAD_LEFT, STR_PAD_RIGHT, or STR_PAD_BOTH");
return;
}

num_pad_chars = pad_length - ZSTR_LEN(input);
if (num_pad_chars >= INT_MAX) {
php_error_docref(NULL, E_WARNING, "Padding length is too long");
zend_throw_error(NULL, "Padding length is too long");
return;
}

Expand Down Expand Up @@ -5916,7 +5926,7 @@ PHP_FUNCTION(str_shuffle)
}
/* }}} */

/* {{{ proto mixed str_word_count(string str, [int format [, string charlist]])
/* {{{ proto array|int str_word_count(string str, [int format [, string charlist]])
Counts the number of words inside a string. If format of 1 is specified,
then the function will return an array containing all the words
found inside the string. If format of 2 is specified, then the function
Expand Down Expand Up @@ -5957,8 +5967,8 @@ PHP_FUNCTION(str_word_count)
/* nothing to be done */
break;
default:
php_error_docref(NULL, E_WARNING, "Invalid format value " ZEND_LONG_FMT, type);
RETURN_FALSE;
zend_throw_error(NULL, "Invalid format value " ZEND_LONG_FMT, type);
return;
}

if (char_list) {
Expand Down Expand Up @@ -6058,7 +6068,7 @@ PHP_FUNCTION(money_format)
/* }}} */
#endif

/* {{{ proto array|false str_split(string str [, int split_length])
/* {{{ proto array str_split(string str [, int split_length])
Convert a string to an array. If split_length is specified, break the string down into chunks each split_length characters long. */
PHP_FUNCTION(str_split)
{
Expand All @@ -6074,8 +6084,8 @@ PHP_FUNCTION(str_split)
ZEND_PARSE_PARAMETERS_END();

if (split_length <= 0) {
php_error_docref(NULL, E_WARNING, "The length of each segment must be greater than zero");
RETURN_FALSE;
zend_throw_error(NULL, "The length of each segment must be greater than zero");
return;
}


Expand Down Expand Up @@ -6114,8 +6124,8 @@ PHP_FUNCTION(strpbrk)
ZEND_PARSE_PARAMETERS_END_EX(RETURN_FALSE);

if (!ZSTR_LEN(char_list)) {
php_error_docref(NULL, E_WARNING, "The character list cannot be empty");
RETURN_FALSE;
zend_throw_error(NULL, "The character list cannot be empty");
return;
}

for (haystack_ptr = ZSTR_VAL(haystack); haystack_ptr < (ZSTR_VAL(haystack) + ZSTR_LEN(haystack)); ++haystack_ptr) {
Expand Down Expand Up @@ -6153,8 +6163,8 @@ PHP_FUNCTION(substr_compare)
if (len == 0) {
RETURN_LONG(0L);
} else {
php_error_docref(NULL, E_WARNING, "The length must be greater than or equal to zero");
RETURN_FALSE;
zend_throw_error(NULL, "The length must be greater than or equal to zero");
return;
}
}

Expand All @@ -6164,6 +6174,7 @@ PHP_FUNCTION(substr_compare)
}

if ((size_t)offset > ZSTR_LEN(s1)) {
/* TODO Check if Candidate to convert to Exception */
php_error_docref(NULL, E_WARNING, "The start position cannot exceed initial string length");
RETURN_FALSE;
}
Expand Down
10 changes: 6 additions & 4 deletions ext/standard/tests/strings/bug33605.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,12 @@
Bug #33605 (substr_compare crashes)
--FILE--
<?php
$res = substr_compare("aa", "a", -99999999, -1, 0);
var_dump($res);
try {
substr_compare("aa", "a", -99999999, -1, 0);
} catch (\Error $e) {
echo $e->getMessage();
}

?>
--EXPECTF--
Warning: substr_compare(): The length must be greater than or equal to zero in %s on line %d
bool(false)
The length must be greater than or equal to zero
Binary file modified ext/standard/tests/strings/chunk_split_variation5.phpt
Binary file not shown.
Loading