summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristoph M. Becker <cmbecker69@gmx.de>2020-06-08 23:19:43 +0200
committerChristoph M. Becker <cmbecker69@gmx.de>2020-06-08 23:19:43 +0200
commit12c59f6660706321f9d42c55421ff6864439c8b7 (patch)
tree0299fd1b063fac265d0b5a84eb1331ec831d8862
parentceae81665cc6d8dadf2103a3f9266150b076ab2a (diff)
downloadphp-git-12c59f6660706321f9d42c55421ff6864439c8b7.tar.gz
Fix #74267: segfault with streams and invalid data
If the current character is a line break character, it cannot be a tab or space character, so we would always fail with an invalid sequence error. Obviously, these `scan_stat == 4` conditions are meant to be exclusive. Furthermore, if `in_pp == NULL || in_left_p == NULL` is true, we hit a segfault if we are not returning right away. Obviously, the additional constraints don't make sense, so we remove them.
-rw-r--r--NEWS3
-rw-r--r--ext/standard/filters.c7
-rw-r--r--ext/standard/tests/filters/bug74267.phpt26
3 files changed, 32 insertions, 4 deletions
diff --git a/NEWS b/NEWS
index 39a9806330..717029d56b 100644
--- a/NEWS
+++ b/NEWS
@@ -14,6 +14,9 @@ PHP NEWS
. Fixed bug #79664 (PDOStatement::getColumnMeta fails on empty result set).
(cmb)
+- Standard:
+ . Fixed bug #74267 (segfault with streams and invalid data). (cmb)
+
?? ??? ????, PHP 7.3.19
- Core:
diff --git a/ext/standard/filters.c b/ext/standard/filters.c
index 7b039cd18f..9b2dcf08aa 100644
--- a/ext/standard/filters.c
+++ b/ext/standard/filters.c
@@ -788,7 +788,7 @@ static php_conv_err_t php_conv_qprint_encode_convert(php_conv_qprint_encode *ins
lb_ptr = inst->lb_ptr;
lb_cnt = inst->lb_cnt;
- if ((in_pp == NULL || in_left_p == NULL) && (lb_ptr >=lb_cnt)) {
+ if (in_pp == NULL || in_left_p == NULL) {
return PHP_CONV_ERR_SUCCESS;
}
@@ -1016,7 +1016,7 @@ static php_conv_err_t php_conv_qprint_decode_convert(php_conv_qprint_decode *ins
lb_ptr = inst->lb_ptr;
lb_cnt = inst->lb_cnt;
- if ((in_pp == NULL || in_left_p == NULL) && lb_cnt == lb_ptr) {
+ if (in_pp == NULL || in_left_p == NULL) {
if (inst->scan_stat != 0) {
return PHP_CONV_ERR_UNEXPECTED_EOS;
}
@@ -1113,8 +1113,7 @@ static php_conv_err_t php_conv_qprint_decode_convert(php_conv_qprint_decode *ins
*ps == (unsigned char)inst->lbchars[lb_cnt]) {
lb_cnt++;
scan_stat = 5;
- }
- if (*ps != '\t' && *ps != ' ') {
+ } else if (*ps != '\t' && *ps != ' ') {
err = PHP_CONV_ERR_INVALID_SEQ;
goto out;
}
diff --git a/ext/standard/tests/filters/bug74267.phpt b/ext/standard/tests/filters/bug74267.phpt
new file mode 100644
index 0000000000..17d7996b7f
--- /dev/null
+++ b/ext/standard/tests/filters/bug74267.phpt
@@ -0,0 +1,26 @@
+--TEST--
+Bug #74267 (segfault with streams and invalid data)
+--FILE--
+<?php
+$stream = fopen('php://memory', 'w');
+stream_filter_append($stream, 'convert.quoted-printable-decode', STREAM_FILTER_WRITE, ['line-break-chars' => "\r\n"]);
+
+$lines = [
+ "\r\n",
+ " -=()\r\n",
+ " -=\r\n",
+ "\r\n"
+ ];
+
+foreach ($lines as $line) {
+ fwrite($stream, $line);
+}
+
+fclose($stream);
+echo "done\n";
+?>
+--EXPECTF--
+Warning: fwrite(): stream filter (convert.quoted-printable-decode): invalid byte sequence in %s on line %d
+
+Warning: fwrite(): stream filter (convert.quoted-printable-decode): invalid byte sequence in %s on line %d
+done