diff options
author | Stanislav Malyshev <stas@php.net> | 2013-06-16 16:38:49 -0700 |
---|---|---|
committer | Stanislav Malyshev <stas@php.net> | 2013-06-16 16:38:49 -0700 |
commit | 7d1fef15cff64f8cd62f38eedfcd1afc8d027147 (patch) | |
tree | 3f6b54442d0a2c794b3ef42e3ded353dc8983fb0 | |
parent | ac343d5c1f8de884921d8acddb2cc81227674615 (diff) | |
parent | 7bb052ee3e93790f4d9654958ab11d90f6e4734d (diff) | |
download | php-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.c | 57 | ||||
-rw-r--r-- | ext/standard/tests/streams/bug64166.phpt | 46 | ||||
-rw-r--r-- | ext/standard/tests/streams/bug64166_2.phpt | 50 | ||||
-rw-r--r-- | ext/standard/tests/streams/bug64166_3.phpt | 48 |
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" |