summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStanislav Malyshev <stas@php.net>2013-06-16 16:38:49 -0700
committerStanislav Malyshev <stas@php.net>2013-06-16 16:38:49 -0700
commit7d1fef15cff64f8cd62f38eedfcd1afc8d027147 (patch)
tree3f6b54442d0a2c794b3ef42e3ded353dc8983fb0
parentac343d5c1f8de884921d8acddb2cc81227674615 (diff)
parent7bb052ee3e93790f4d9654958ab11d90f6e4734d (diff)
downloadphp-git-7d1fef15cff64f8cd62f38eedfcd1afc8d027147.tar.gz
Merge branch 'PHP-5.4' into PHP-5.5
* PHP-5.4: add more tests for bug #64166 Move unsigned char declaration to top of block trailing ws Fix #64166: quoted-printable-encode stream filter incorrectly discarding whitespace Fix #64166: quoted-printable-encode stream filter incorrectly discarding whitespace
-rw-r--r--ext/standard/filters.c57
-rw-r--r--ext/standard/tests/streams/bug64166.phpt46
-rw-r--r--ext/standard/tests/streams/bug64166_2.phpt50
-rw-r--r--ext/standard/tests/streams/bug64166_3.phpt48
4 files changed, 191 insertions, 10 deletions
diff --git a/ext/standard/filters.c b/ext/standard/filters.c
index 084860c76b..0a59039635 100644
--- a/ext/standard/filters.c
+++ b/ext/standard/filters.c
@@ -771,7 +771,7 @@ static void php_conv_qprint_encode_dtor(php_conv_qprint_encode *inst)
}
#define NEXT_CHAR(ps, icnt, lb_ptr, lb_cnt, lbchars) \
- ((lb_ptr) < (lb_cnt) ? (lbchars)[(lb_ptr)] : *(ps))
+ ((lb_ptr) < (lb_cnt) ? (lbchars)[(lb_ptr)] : *(ps))
#define CONSUME_CHAR(ps, icnt, lb_ptr, lb_cnt) \
if ((lb_ptr) < (lb_cnt)) { \
@@ -791,6 +791,7 @@ static php_conv_err_t php_conv_qprint_encode_convert(php_conv_qprint_encode *ins
unsigned int line_ccnt;
unsigned int lb_ptr;
unsigned int lb_cnt;
+ unsigned int trail_ws;
int opts;
static char qp_digits[] = "0123456789ABCDEF";
@@ -807,6 +808,7 @@ static php_conv_err_t php_conv_qprint_encode_convert(php_conv_qprint_encode *ins
icnt = *in_left_p;
pd = (unsigned char *)(*out_pp);
ocnt = *out_left_p;
+ trail_ws = 0;
for (;;) {
if (!(opts & PHP_CONV_QPRINT_OPT_BINARY) && inst->lbchars != NULL && inst->lbchars_len > 0) {
@@ -839,11 +841,13 @@ static php_conv_err_t php_conv_qprint_encode_convert(php_conv_qprint_encode *ins
if (lb_ptr >= lb_cnt && icnt <= 0) {
break;
- }
+ }
c = NEXT_CHAR(ps, icnt, lb_ptr, lb_cnt, inst->lbchars);
- if (!(opts & PHP_CONV_QPRINT_OPT_BINARY) && (c == '\t' || c == ' ')) {
+ if (!(opts & PHP_CONV_QPRINT_OPT_BINARY) &&
+ (trail_ws == 0) &&
+ (c == '\t' || c == ' ')) {
if (line_ccnt < 2 && inst->lbchars != NULL) {
if (ocnt < inst->lbchars_len + 1) {
err = PHP_CONV_ERR_TOO_BIG;
@@ -863,12 +867,44 @@ static php_conv_err_t php_conv_qprint_encode_convert(php_conv_qprint_encode *ins
err = PHP_CONV_ERR_TOO_BIG;
break;
}
- *(pd++) = c;
- ocnt--;
- line_ccnt--;
- CONSUME_CHAR(ps, icnt, lb_ptr, lb_cnt);
+
+ /* Check to see if this is EOL whitespace. */
+ if (inst->lbchars != NULL) {
+ unsigned char *ps2;
+ unsigned int j, lb_cnt2;
+
+ lb_cnt2 = 0;
+ ps2 = ps;
+ trail_ws = 1;
+
+ for (j = icnt - 1; j > 0; j--, ps2++) {
+ if (*ps2 == inst->lbchars[lb_cnt2]) {
+ lb_cnt2++;
+ if (lb_cnt2 >= inst->lbchars_len) {
+ /* Found trailing ws. Reset to top of main
+ * for loop to allow for code to do necessary
+ * wrapping/encoding. */
+ break;
+ }
+ } else if (lb_cnt2 != 0 || (*ps2 != '\t' && *ps2 != ' ')) {
+ /* At least one non-EOL character following, so
+ * don't need to encode ws. */
+ trail_ws = 0;
+ break;
+ } else {
+ trail_ws++;
+ }
+ }
+ }
+
+ if (trail_ws == 0) {
+ *(pd++) = c;
+ ocnt--;
+ line_ccnt--;
+ CONSUME_CHAR(ps, icnt, lb_ptr, lb_cnt);
+ }
}
- } else if ((!(opts & PHP_CONV_QPRINT_OPT_FORCE_ENCODE_FIRST) || line_ccnt < inst->line_len) && ((c >= 33 && c <= 60) || (c >= 62 && c <= 126))) {
+ } else if ((!(opts & PHP_CONV_QPRINT_OPT_FORCE_ENCODE_FIRST) || line_ccnt < inst->line_len) && ((c >= 33 && c <= 60) || (c >= 62 && c <= 126))) {
if (line_ccnt < 2 && inst->lbchars != NULL) {
if (ocnt < inst->lbchars_len + 1) {
err = PHP_CONV_ERR_TOO_BIG;
@@ -912,9 +948,10 @@ static php_conv_err_t php_conv_qprint_encode_convert(php_conv_qprint_encode *ins
}
*(pd++) = '=';
*(pd++) = qp_digits[(c >> 4)];
- *(pd++) = qp_digits[(c & 0x0f)];
+ *(pd++) = qp_digits[(c & 0x0f)];
ocnt -= 3;
line_ccnt -= 3;
+ trail_ws--;
CONSUME_CHAR(ps, icnt, lb_ptr, lb_cnt);
}
}
@@ -922,7 +959,7 @@ static php_conv_err_t php_conv_qprint_encode_convert(php_conv_qprint_encode *ins
*in_pp = (const char *)ps;
*in_left_p = icnt;
*out_pp = (char *)pd;
- *out_left_p = ocnt;
+ *out_left_p = ocnt;
inst->line_ccnt = line_ccnt;
inst->lb_ptr = lb_ptr;
inst->lb_cnt = lb_cnt;
diff --git a/ext/standard/tests/streams/bug64166.phpt b/ext/standard/tests/streams/bug64166.phpt
new file mode 100644
index 0000000000..e725a4b698
--- /dev/null
+++ b/ext/standard/tests/streams/bug64166.phpt
@@ -0,0 +1,46 @@
+--TEST--
+Bug #64166: quoted-printable-encode stream filter incorrectly discarding whitespace
+--FILE--
+<?php
+
+function test_64166($data) {
+ $fd = fopen('php://temp', 'w+');
+ fwrite($fd, $data);
+ rewind($fd);
+
+ $res = stream_filter_append($fd, 'convert.quoted-printable-encode', STREAM_FILTER_READ, array(
+ 'line-break-chars' => "\n",
+ 'line-length' => 74
+ ));
+ var_dump(stream_get_contents($fd, -1, 0));
+
+ stream_filter_remove($res);
+
+ rewind($fd);
+ stream_filter_append($fd, 'convert.quoted-printable-encode', STREAM_FILTER_READ, array(
+ 'line-break-chars' => "\n",
+ 'line-length' => 6
+ ));
+ var_dump(stream_get_contents($fd, -1, 0));
+
+ fclose($fd);
+}
+
+test_64166("FIRST \nSECOND");
+test_64166("FIRST \nSECOND");
+
+?>
+--EXPECT--
+string(15) "FIRST=20
+SECOND"
+string(19) "FIRST=
+=20
+SECON=
+D"
+string(18) "FIRST=20=20
+SECOND"
+string(24) "FIRST=
+=20=
+=20
+SECON=
+D"
diff --git a/ext/standard/tests/streams/bug64166_2.phpt b/ext/standard/tests/streams/bug64166_2.phpt
new file mode 100644
index 0000000000..9d6655d5c1
--- /dev/null
+++ b/ext/standard/tests/streams/bug64166_2.phpt
@@ -0,0 +1,50 @@
+--TEST--
+Bug #64166: quoted-printable-encode stream filter incorrectly discarding whitespace - split reads
+--FILE--
+<?php
+
+function test_64166($data) {
+ $fd = fopen('php://temp', 'w+');
+ fwrite($fd, $data);
+ rewind($fd);
+
+ $res = stream_filter_append($fd, 'convert.quoted-printable-encode', STREAM_FILTER_READ, array(
+ 'line-break-chars' => "\n",
+ 'line-length' => 74
+ ));
+ $str = "";
+ while(($c = fread($fd, 1))!= "") $str .= $c;
+ var_dump($str);
+
+ stream_filter_remove($res);
+
+ rewind($fd);
+ stream_filter_append($fd, 'convert.quoted-printable-encode', STREAM_FILTER_READ, array(
+ 'line-break-chars' => "\n",
+ 'line-length' => 6
+ ));
+ $str = "";
+ while(($c = fread($fd, 1))!= "") $str .= $c;
+ var_dump($str);
+
+ fclose($fd);
+}
+
+test_64166("FIRST \nSECOND");
+test_64166("FIRST \nSECOND");
+
+?>
+--EXPECT--
+string(15) "FIRST=20
+SECOND"
+string(19) "FIRST=
+=20
+SECON=
+D"
+string(18) "FIRST=20=20
+SECOND"
+string(24) "FIRST=
+=20=
+=20
+SECON=
+D"
diff --git a/ext/standard/tests/streams/bug64166_3.phpt b/ext/standard/tests/streams/bug64166_3.phpt
new file mode 100644
index 0000000000..d896ba800c
--- /dev/null
+++ b/ext/standard/tests/streams/bug64166_3.phpt
@@ -0,0 +1,48 @@
+--TEST--
+Bug #64166: quoted-printable-encode stream filter incorrectly discarding whitespace - writes
+--FILE--
+<?php
+
+function test_64166($data) {
+ $fd = fopen('php://temp', 'w+');
+ $res = stream_filter_append($fd, 'convert.quoted-printable-encode', STREAM_FILTER_WRITE, array(
+ 'line-break-chars' => "\n",
+ 'line-length' => 74
+ ));
+ fwrite($fd, $data);
+ rewind($fd);
+
+ var_dump(stream_get_contents($fd, -1, 0));
+
+ stream_filter_remove($res);
+
+ rewind($fd);
+ stream_filter_append($fd, 'convert.quoted-printable-encode', STREAM_FILTER_WRITE, array(
+ 'line-break-chars' => "\n",
+ 'line-length' => 6
+ ));
+ fwrite($fd, $data);
+ rewind($fd);
+ var_dump(stream_get_contents($fd, -1, 0));
+
+ fclose($fd);
+}
+
+test_64166("FIRST \nSECOND");
+test_64166("FIRST \nSECOND");
+
+?>
+--EXPECT--
+string(15) "FIRST=20
+SECOND"
+string(19) "FIRST=
+=20
+SECON=
+D"
+string(18) "FIRST=20=20
+SECOND"
+string(24) "FIRST=
+=20=
+=20
+SECON=
+D"