mirror of
https://github.com/php/php-src.git
synced 2025-08-16 05:58:45 +02:00
Fixed bug #76439
This commit is contained in:
parent
716bbd3480
commit
17afe6430f
6 changed files with 4905 additions and 4769 deletions
1
NEWS
1
NEWS
|
@ -11,6 +11,7 @@ PHP NEWS
|
||||||
properly). (Nikita)
|
properly). (Nikita)
|
||||||
. Fixed bug #76509 (Inherited static properties can be desynchronized from
|
. Fixed bug #76509 (Inherited static properties can be desynchronized from
|
||||||
their parent by ref). (Nikita)
|
their parent by ref). (Nikita)
|
||||||
|
. Fixed bug #76439 (Changed behaviour in unclosed HereDoc). (Nikita, tpunt)
|
||||||
|
|
||||||
- FPM:
|
- FPM:
|
||||||
. Fixed bug #73342 (Vulnerability in php-fpm by changing stdin to
|
. Fixed bug #73342 (Vulnerability in php-fpm by changing stdin to
|
||||||
|
|
68
Zend/tests/bug76439.phpt
Normal file
68
Zend/tests/bug76439.phpt
Normal file
|
@ -0,0 +1,68 @@
|
||||||
|
--TEST--
|
||||||
|
Bug #76439: Don't always strip leading whitespace from heredoc T_ENCAPSED_AND_WHITESPACE tokens
|
||||||
|
--FILE--
|
||||||
|
<?php
|
||||||
|
|
||||||
|
[$one, $two, $three, $four, $five, $six, $seven, $eight, $nine] = [1, 2, 3, 4, 5, 6, 7, 8, 9];
|
||||||
|
|
||||||
|
var_dump(<<<BAR
|
||||||
|
$one-
|
||||||
|
BAR);
|
||||||
|
|
||||||
|
var_dump(<<<BAR
|
||||||
|
$two -
|
||||||
|
BAR);
|
||||||
|
|
||||||
|
var_dump(<<<BAR
|
||||||
|
$three -
|
||||||
|
BAR);
|
||||||
|
|
||||||
|
var_dump(<<<BAR
|
||||||
|
$four-$four
|
||||||
|
BAR);
|
||||||
|
|
||||||
|
var_dump(<<<BAR
|
||||||
|
$five-$five-
|
||||||
|
BAR);
|
||||||
|
|
||||||
|
var_dump(<<<BAR
|
||||||
|
$six-$six-$six
|
||||||
|
BAR);
|
||||||
|
|
||||||
|
var_dump(<<<BAR
|
||||||
|
$seven
|
||||||
|
-
|
||||||
|
BAR);
|
||||||
|
|
||||||
|
var_dump(<<<BAR
|
||||||
|
$eight
|
||||||
|
-
|
||||||
|
BAR);
|
||||||
|
|
||||||
|
var_dump(<<<BAR
|
||||||
|
$nine
|
||||||
|
BAR);
|
||||||
|
|
||||||
|
var_dump(<<<BAR
|
||||||
|
-
|
||||||
|
BAR);
|
||||||
|
|
||||||
|
var_dump(<<<BAR
|
||||||
|
-
|
||||||
|
BAR);
|
||||||
|
|
||||||
|
?>
|
||||||
|
--EXPECT--
|
||||||
|
string(2) "1-"
|
||||||
|
string(3) "2 -"
|
||||||
|
string(3) "3 -"
|
||||||
|
string(3) "4-4"
|
||||||
|
string(4) "5-5-"
|
||||||
|
string(5) "6-6-6"
|
||||||
|
string(3) "7
|
||||||
|
-"
|
||||||
|
string(4) "8
|
||||||
|
-"
|
||||||
|
string(1) "9"
|
||||||
|
string(1) "-"
|
||||||
|
string(2) " -"
|
15
Zend/tests/bug76439_2.phpt
Normal file
15
Zend/tests/bug76439_2.phpt
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
--TEST--
|
||||||
|
Bug #76439: Don't always strip leading whitespace from heredoc T_ENCAPSED_AND_WHITESPACE tokens (error case)
|
||||||
|
--FILE--
|
||||||
|
<?php
|
||||||
|
|
||||||
|
$foo = 1;
|
||||||
|
|
||||||
|
var_dump(<<<BAR
|
||||||
|
$foo
|
||||||
|
$foo
|
||||||
|
BAR);
|
||||||
|
|
||||||
|
?>
|
||||||
|
--EXPECTF--
|
||||||
|
Parse error: Invalid body indentation level (expecting an indentation level of at least 1) in %s on line 7
|
File diff suppressed because it is too large
Load diff
|
@ -1109,65 +1109,86 @@ skip_escape_conversion:
|
||||||
#define HEREDOC_USING_SPACES 1
|
#define HEREDOC_USING_SPACES 1
|
||||||
#define HEREDOC_USING_TABS 2
|
#define HEREDOC_USING_TABS 2
|
||||||
|
|
||||||
static zend_bool strip_multiline_string_indentation(zval *zendlval, int newline, int indentation, zend_bool using_spaces)
|
static const char *next_newline(const char *str, const char *end, size_t *newline_len) {
|
||||||
|
for (; str < end; str++) {
|
||||||
|
if (*str == '\r') {
|
||||||
|
*newline_len = str + 1 < end && *(str + 1) == '\n' ? 2 : 1;
|
||||||
|
} else if (*str == '\n') {
|
||||||
|
*newline_len = 1;
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*newline_len = 0;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static zend_bool strip_multiline_string_indentation(
|
||||||
|
zval *zendlval, int indentation, zend_bool using_spaces,
|
||||||
|
zend_bool newline_at_start, zend_bool newline_at_end)
|
||||||
{
|
{
|
||||||
int len = Z_STRLEN_P(zendlval), new_len = len, i = 0, j = 0, skip, newline_count = 0;
|
const char *str = Z_STRVAL_P(zendlval), *end = str + Z_STRLEN_P(zendlval);
|
||||||
char *copy = Z_STRVAL_P(zendlval);
|
char *copy = Z_STRVAL_P(zendlval);
|
||||||
zend_bool trailing_newline = 0;
|
|
||||||
|
|
||||||
while (j < len) {
|
int newline_count = 0;
|
||||||
trailing_newline = 0;
|
size_t newline_len;
|
||||||
|
const char *nl;
|
||||||
|
|
||||||
for (skip = 0; skip < indentation; ++skip, ++j, --new_len) {
|
if (!newline_at_start) {
|
||||||
if (copy[j] == '\r' || copy[j] == '\n') {
|
nl = next_newline(str, end, &newline_len);
|
||||||
goto skip;
|
if (!nl) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
str = nl + newline_len;
|
||||||
|
copy = (char *) nl + newline_len;
|
||||||
|
newline_count++;
|
||||||
|
} else {
|
||||||
|
nl = str;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* <= intentional */
|
||||||
|
while (str <= end && nl) {
|
||||||
|
size_t skip;
|
||||||
|
nl = next_newline(str, end, &newline_len);
|
||||||
|
if (!nl && newline_at_end) {
|
||||||
|
nl = end;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Try to skip indentation */
|
||||||
|
for (skip = 0; skip < indentation; skip++, str++) {
|
||||||
|
if (str == nl) {
|
||||||
|
/* Don't require full indentation on whitespace-only lines */
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (copy[j] != ' ' && copy[j] != '\t') {
|
if (str == end || (*str != ' ' && *str != '\t')) {
|
||||||
CG(zend_lineno) += newline_count;
|
CG(zend_lineno) += newline_count;
|
||||||
zend_throw_exception_ex(zend_ce_parse_error, 0, "Invalid body indentation level (expecting an indentation level of at least %d)", indentation);
|
zend_throw_exception_ex(zend_ce_parse_error, 0,
|
||||||
|
"Invalid body indentation level (expecting an indentation level of at least %d)", indentation);
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((!using_spaces && copy[j] == ' ') || (using_spaces && copy[j] == '\t')) {
|
if ((!using_spaces && *str == ' ') || (using_spaces && *str == '\t')) {
|
||||||
CG(zend_lineno) += newline_count;
|
CG(zend_lineno) += newline_count;
|
||||||
zend_throw_exception(zend_ce_parse_error, "Invalid indentation - tabs and spaces cannot be mixed", 0);
|
zend_throw_exception(zend_ce_parse_error,
|
||||||
|
"Invalid indentation - tabs and spaces cannot be mixed", 0);
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
while (j < len && copy[j] != '\r' && copy[j] != '\n') {
|
if (str == end) {
|
||||||
copy[i++] = copy[j++];
|
|
||||||
}
|
|
||||||
|
|
||||||
if (j == len) {
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
skip:
|
|
||||||
if (copy[j] == '\r') {
|
|
||||||
copy[i++] = copy[j++];
|
|
||||||
trailing_newline = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (copy[j] == '\n') {
|
size_t len = nl ? (nl - str + newline_len) : (end - str);
|
||||||
copy[i++] = copy[j++];
|
memmove(copy, str, len);
|
||||||
trailing_newline = 1;
|
str += len;
|
||||||
}
|
copy += len;
|
||||||
|
newline_count++;
|
||||||
if (trailing_newline) {
|
|
||||||
++newline_count;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (YYSTATE != STATE(ST_END_HEREDOC) && trailing_newline && indentation) {
|
*copy = '\0';
|
||||||
CG(zend_lineno) += newline_count;
|
Z_STRLEN_P(zendlval) = copy - Z_STRVAL_P(zendlval);
|
||||||
zend_throw_exception_ex(zend_ce_parse_error, 0, "Invalid body indentation level (expecting an indentation level of at least %d)", indentation);
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
|
|
||||||
Z_STRVAL_P(zendlval)[new_len - newline] = '\0';
|
|
||||||
Z_STRLEN_P(zendlval) = new_len - newline;
|
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
error:
|
error:
|
||||||
|
@ -2610,12 +2631,15 @@ double_quotes_scan_done:
|
||||||
heredoc_scan_done:
|
heredoc_scan_done:
|
||||||
|
|
||||||
yyleng = YYCURSOR - SCNG(yy_text);
|
yyleng = YYCURSOR - SCNG(yy_text);
|
||||||
ZVAL_STRINGL(zendlval, yytext, yyleng);
|
ZVAL_STRINGL(zendlval, yytext, yyleng - newline);
|
||||||
|
|
||||||
if (!SCNG(heredoc_scan_ahead) && !EG(exception) && PARSER_MODE()) {
|
if (!SCNG(heredoc_scan_ahead) && !EG(exception) && PARSER_MODE()) {
|
||||||
|
zend_bool newline_at_start = *(yytext - 1) == '\n' || *(yytext - 1) == '\r';
|
||||||
zend_string *copy = Z_STR_P(zendlval);
|
zend_string *copy = Z_STR_P(zendlval);
|
||||||
|
|
||||||
if (!strip_multiline_string_indentation(zendlval, newline, heredoc_label->indentation, heredoc_label->indentation_uses_spaces)) {
|
if (!strip_multiline_string_indentation(
|
||||||
|
zendlval, heredoc_label->indentation, heredoc_label->indentation_uses_spaces,
|
||||||
|
newline_at_start, newline != 0)) {
|
||||||
RETURN_TOKEN(T_ERROR);
|
RETURN_TOKEN(T_ERROR);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2705,11 +2729,15 @@ heredoc_scan_done:
|
||||||
|
|
||||||
nowdoc_scan_done:
|
nowdoc_scan_done:
|
||||||
yyleng = YYCURSOR - SCNG(yy_text);
|
yyleng = YYCURSOR - SCNG(yy_text);
|
||||||
ZVAL_STRINGL(zendlval, yytext, yyleng);
|
ZVAL_STRINGL(zendlval, yytext, yyleng - newline);
|
||||||
|
|
||||||
if (!EG(exception) && spacing != -1 && PARSER_MODE()
|
if (!EG(exception) && spacing != -1 && PARSER_MODE()) {
|
||||||
&& !strip_multiline_string_indentation(zendlval, newline, indentation, spacing == HEREDOC_USING_SPACES)) {
|
zend_bool newline_at_start = *(yytext - 1) == '\n' || *(yytext - 1) == '\r';
|
||||||
RETURN_TOKEN(T_ERROR);
|
if (!strip_multiline_string_indentation(
|
||||||
|
zendlval, indentation, spacing == HEREDOC_USING_SPACES,
|
||||||
|
newline_at_start, newline != 0)) {
|
||||||
|
RETURN_TOKEN(T_ERROR);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
HANDLE_NEWLINES(yytext, yyleng - newline);
|
HANDLE_NEWLINES(yytext, yyleng - newline);
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/* Generated by re2c 0.16 */
|
/* Generated by re2c 1.0.1 */
|
||||||
#line 3 "Zend/zend_language_scanner_defs.h"
|
#line 3 "Zend/zend_language_scanner_defs.h"
|
||||||
|
|
||||||
enum YYCONDTYPE {
|
enum YYCONDTYPE {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue