Skip to content

Commit 4216830

Browse files
committed
Consistently handle out of bounds offsets in iconv_strpos()
Same as in all other strpos() style functions, throw ValueError on out of bounds offset.
1 parent 07a2f30 commit 4216830

File tree

4 files changed

+46
-25
lines changed

4 files changed

+46
-25
lines changed

ext/iconv/iconv.c

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -884,6 +884,10 @@ static php_iconv_err_t _php_iconv_strpos(size_t *pretval,
884884

885885
iconv_close(cd);
886886

887+
if (err == PHP_ICONV_ERR_SUCCESS && offset > cnt) {
888+
return PHP_ICONV_ERR_OUT_BY_BOUNDS;
889+
}
890+
887891
return err;
888892
}
889893
/* }}} */
@@ -1764,6 +1768,10 @@ static void _php_iconv_show_error(php_iconv_err_t err, const char *out_charset,
17641768
php_error_docref(NULL, E_WARNING, "Malformed string");
17651769
break;
17661770

1771+
case PHP_ICONV_ERR_OUT_BY_BOUNDS:
1772+
zend_argument_value_error(3, "must be contained in argument #1 ($haystack)");
1773+
break;
1774+
17671775
default:
17681776
/* other error */
17691777
php_error_docref(NULL, E_NOTICE, "Unknown error (%d)", errno);
@@ -1881,12 +1889,13 @@ PHP_FUNCTION(iconv_strpos)
18811889
}
18821890
offset += haystk_len;
18831891
if (offset < 0) { /* If offset before start */
1884-
php_error_docref(NULL, E_WARNING, "Offset not contained in string.");
1885-
RETURN_FALSE;
1892+
zend_argument_value_error(3, "must be contained in argument #1 ($haystack)");
1893+
RETURN_THROWS();
18861894
}
18871895
}
18881896

18891897
if (ZSTR_LEN(ndl) < 1) {
1898+
// TODO: Support empty needles!
18901899
RETURN_FALSE;
18911900
}
18921901

ext/iconv/php_iconv.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,8 @@ typedef enum _php_iconv_err_t {
8787
PHP_ICONV_ERR_ILLEGAL_CHAR = 5,
8888
PHP_ICONV_ERR_UNKNOWN = 6,
8989
PHP_ICONV_ERR_MALFORMED = 7,
90-
PHP_ICONV_ERR_ALLOC = 8
90+
PHP_ICONV_ERR_ALLOC = 8,
91+
PHP_ICONV_ERR_OUT_BY_BOUNDS = 9
9192
} php_iconv_err_t;
9293
/* }}} */
9394

ext/iconv/tests/iconv_strpos.phpt

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,14 +16,19 @@ function foo($haystk, $needle, $offset, $to_charset = false, $from_charset = fal
1616
} catch (ValueError $exception) {
1717
echo $exception->getMessage() . "\n";
1818
}
19-
if ($to_charset !== false) {
20-
var_dump(iconv_strpos($haystk, $needle, $offset, $to_charset));
21-
} else {
22-
var_dump(iconv_strpos($haystk, $needle, $offset));
19+
try {
20+
if ($to_charset !== false) {
21+
var_dump(iconv_strpos($haystk, $needle, $offset, $to_charset));
22+
} else {
23+
var_dump(iconv_strpos($haystk, $needle, $offset));
24+
}
25+
} catch (ValueError $exception) {
26+
echo $exception->getMessage() . "\n";
2327
}
2428
}
2529
foo("abecdbcdabef", "bcd", -1);
2630
foo("abecdbcdabef", "bcd", -7);
31+
foo("abecdbcdabef", "bcd", 12);
2732
foo("abecdbcdabef", "bcd", 100000);
2833
foo("abcabcabcdabcababcdabc", "bcd", 0);
2934
foo("abcabcabcdabcababcdabc", "bcd", 10);
@@ -41,8 +46,10 @@ bool(false)
4146
bool(false)
4247
int(5)
4348
int(5)
44-
strpos(): Argument #3 ($offset) must be contained in argument #1 ($haystack)
4549
bool(false)
50+
bool(false)
51+
strpos(): Argument #3 ($offset) must be contained in argument #1 ($haystack)
52+
iconv_strpos(): Argument #3 ($offset) must be contained in argument #1 ($haystack)
4653
int(7)
4754
int(7)
4855
int(16)

ext/iconv/tests/iconv_strpos_variation5.phpt

Lines changed: 21 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -32,25 +32,29 @@ $needle_mb = base64_decode('44CC');
3232
for ($i = -30; $i <= 60; $i += 10) {
3333
echo "\n**-- Offset is: $i --**\n";
3434
echo "-- ASCII String --\n";
35-
var_dump(iconv_strpos($string_ascii, $needle_ascii, $i));
35+
try {
36+
var_dump(iconv_strpos($string_ascii, $needle_ascii, $i));
37+
} catch (ValueError $e) {
38+
echo $e->getMessage(), "\n";
39+
}
3640
echo "--Multibyte String --\n";
37-
var_dump(iconv_strpos($string_mb, $needle_mb, $i, 'UTF-8'));
41+
try {
42+
var_dump(iconv_strpos($string_mb, $needle_mb, $i, 'UTF-8'));
43+
} catch (ValueError $e) {
44+
echo $e->getMessage(), "\n";
45+
}
3846
}
3947

4048
echo "Done";
4149
?>
42-
--EXPECTF--
50+
--EXPECT--
4351
*** Testing iconv_strpos() : usage variations ***
4452

4553
**-- Offset is: -30 --**
4654
-- ASCII String --
47-
48-
Warning: iconv_strpos(): Offset not contained in string. in %s on line %d
49-
bool(false)
55+
iconv_strpos(): Argument #3 ($offset) must be contained in argument #1 ($haystack)
5056
--Multibyte String --
51-
52-
Warning: iconv_strpos(): Offset not contained in string. in %s on line %d
53-
bool(false)
57+
iconv_strpos(): Argument #3 ($offset) must be contained in argument #1 ($haystack)
5458

5559
**-- Offset is: -20 --**
5660
-- ASCII String --
@@ -84,25 +88,25 @@ int(20)
8488

8589
**-- Offset is: 30 --**
8690
-- ASCII String --
87-
bool(false)
91+
iconv_strpos(): Argument #3 ($offset) must be contained in argument #1 ($haystack)
8892
--Multibyte String --
89-
bool(false)
93+
iconv_strpos(): Argument #3 ($offset) must be contained in argument #1 ($haystack)
9094

9195
**-- Offset is: 40 --**
9296
-- ASCII String --
93-
bool(false)
97+
iconv_strpos(): Argument #3 ($offset) must be contained in argument #1 ($haystack)
9498
--Multibyte String --
95-
bool(false)
99+
iconv_strpos(): Argument #3 ($offset) must be contained in argument #1 ($haystack)
96100

97101
**-- Offset is: 50 --**
98102
-- ASCII String --
99-
bool(false)
103+
iconv_strpos(): Argument #3 ($offset) must be contained in argument #1 ($haystack)
100104
--Multibyte String --
101-
bool(false)
105+
iconv_strpos(): Argument #3 ($offset) must be contained in argument #1 ($haystack)
102106

103107
**-- Offset is: 60 --**
104108
-- ASCII String --
105-
bool(false)
109+
iconv_strpos(): Argument #3 ($offset) must be contained in argument #1 ($haystack)
106110
--Multibyte String --
107-
bool(false)
111+
iconv_strpos(): Argument #3 ($offset) must be contained in argument #1 ($haystack)
108112
Done

0 commit comments

Comments
 (0)