Patch bug68063.patch for Output Control Bug #68970
Patch version 2016-01-13 02:09 UTC
Return to Bug #68970 |
Download this patch
Patch Revisions:
Developer: yohgaki@php.net
commit 4291855b3ad1ea02256f3e9aa183402f0824c589
Author: Yasuo Ohgaki <yohgaki@php.net>
Date: Sun Sep 13 07:00:38 2015 +0900
Fix #68970 output_add_rewrite_var() add session ID path begins with "//"
diff --git a/ext/session/session.c b/ext/session/session.c
index c050b71..66fcdcd 100644
--- a/ext/session/session.c
+++ b/ext/session/session.c
@@ -1498,12 +1498,11 @@ PHPAPI void php_session_reset_id(void) /* {{{ */
}
if (APPLY_TRANS_SID) {
- /* FIXME: Resetting vars are required when
- session is stop/start/regenerated. However,
- php_url_scanner_reset_vars() resets all vars
- including other URL rewrites set by elsewhere. */
- /* php_url_scanner_reset_vars(); */
- php_url_scanner_add_var(PS(session_name), strlen(PS(session_name)), ZSTR_VAL(PS(id)), ZSTR_LEN(PS(id)), 1);
+ zend_string *name;
+ name = zend_string_init(PS(session_name), strlen(PS(session_name)), 0);
+ php_url_scanner_reset_var(name, PS(id), 1);
+ php_url_scanner_add_var(ZSTR_VAL(name), ZSTR_LEN(name), ZSTR_VAL(PS(id)), ZSTR_LEN(PS(id)), 1);
+ zend_string_release(name);
}
}
/* }}} */
diff --git a/ext/session/tests/session_basic3.phpt b/ext/session/tests/session_basic3.phpt
index 3cc90a8..320a027 100644
--- a/ext/session/tests/session_basic3.phpt
+++ b/ext/session/tests/session_basic3.phpt
@@ -12,8 +12,6 @@ session.gc_divisor=1000
session.gc_maxlifetime=300
session.save_path=
session.name=PHPSESSID
---XFAIL--
-Waiting url_scanner_ex.re fix. https://bugs.php.net/bug.php?id=68970
--SKIPIF--
<?php include('skipif.inc'); ?>
--FILE--
@@ -233,15 +231,6 @@ ob_end_flush();
*** Test trans sid ***
<a href="/?PHPSESSID=testid">test</a>
-<a href="/?PHPSESSID=testid#bar">test</a>
-<a href="/?foo&PHPSESSID=testid">test</a>
-<a href="/?foo&PHPSESSID=testid#bar">test</a>
-<a href="/?foo=var&PHPSESSID=testid">test</a>
-<a href="/?foo=var&PHPSESSID=testid#bar">test</a>
-<a href="file.php?PHPSESSID=testid">test</a>
-<a href="file.php?foo&PHPSESSID=testid">test</a>
-<a href="file.php?foo=var&PHPSESSID=testid">test</a>
-<a href="/?PHPSESSID=testid">test</a>
<a href="/path?PHPSESSID=testid">test</a>
<a href="/path/?PHPSESSID=testid">test</a>
<a href="/path/?foo=var&PHPSESSID=testid">test</a>
@@ -257,14 +246,23 @@ ob_end_flush();
<a href="../path/?PHPSESSID=testid#bar">test</a>
<a href="../path/?foo=var&PHPSESSID=testid#bar">test</a>
-<a href="/?foo">test</a>
-<a href="/?foo#bar">test</a>
-<a href="/?foo=var">test</a>
-<a href="/?foo=var#bar">test</a>
-<a href="../?foo">test</a>
-<a href="../?foo#bar">test</a>
-<a href="../?foo=var">test</a>
-<a href="../?foo=var#bar">test</a>
+<a href="/?foo&PHPSESSID=testid">test</a>
+<a href="/?foo&PHPSESSID=testid#bar">test</a>
+<a href="/?foo=var&PHPSESSID=testid">test</a>
+<a href="/?foo=var&PHPSESSID=testid#bar">test</a>
+<a href="../?foo&PHPSESSID=testid">test</a>
+<a href="../?foo&PHPSESSID=testid#bar">test</a>
+<a href="../?foo=var&PHPSESSID=testid">test</a>
+<a href="../?foo=var&PHPSESSID=testid#bar">test</a>
+
+<a href="file.php?PHPSESSID=testid">test</a>
+<a href="file.php?foo&PHPSESSID=testid">test</a>
+<a href="file.php?foo=var&PHPSESSID=testid">test</a>
+<a href="file.php?foo=var&PHPSESSID=testid#bar">test</a>
+<a href="../file.php?PHPSESSID=testid">test</a>
+<a href="../file.php?foo&PHPSESSID=testid">test</a>
+<a href="../file.php?foo=var&PHPSESSID=testid">test</a>
+<a href="../file.php?foo=var&PHPSESSID=testid#bar">test</a>
<a href="http://php.net">test</a>
<a href="http://php.net/">test</a>
@@ -317,31 +315,31 @@ ob_end_flush();
<a href="//php.net/some/path/file.php?foo=var">test</a>
<a href="//php.net/some/path/file.php?foo=var#bar">test</a>
-<form action="script.php" method="post"><input type="hidden" name="PHPSESSID" value="testid" /><input type="hidden" name="PHPSESSID" value="testid" />
+<form action="script.php" method="post"><input type="hidden" name="PHPSESSID" value="testid" />
<input type="text" name="test1"></input>
<input type="text" name="test2" />
</form>
-<form action="../script.php" method="post"><input type="hidden" name="PHPSESSID" value="testid" /><input type="hidden" name="PHPSESSID" value="testid" />
+<form action="../script.php" method="post"><input type="hidden" name="PHPSESSID" value="testid" />
<input type="text" name="test1"></input>
<input type="text" name="test2" />
</form>
-<form action="/path/script.php" method="post"><input type="hidden" name="PHPSESSID" value="testid" /><input type="hidden" name="PHPSESSID" value="testid" />
+<form action="/path/script.php" method="post"><input type="hidden" name="PHPSESSID" value="testid" />
<input type="text" name="test1"></input>
<input type="text" name="test2" />
</form>
-<form action="../path/script.php" method="post"><input type="hidden" name="PHPSESSID" value="testid" /><input type="hidden" name="PHPSESSID" value="testid" />
+<form action="../path/script.php" method="post"><input type="hidden" name="PHPSESSID" value="testid" />
<input type="text" name="test1"></input>
<input type="text" name="test2" />
</form>
-<form action="http://php.net/script.php" method="post"><input type="hidden" name="PHPSESSID" value="testid" /><input type="hidden" name="PHPSESSID" value="testid" />
+<form action="http://php.net/script.php" method="post"><input type="hidden" name="PHPSESSID" value="testid" />
<input type="text" name="test1"></input>
<input type="text" name="test2" />
</form>
-<form action="https://php.net/script.php" method="post"><input type="hidden" name="PHPSESSID" value="testid" /><input type="hidden" name="PHPSESSID" value="testid" />
+<form action="https://php.net/script.php" method="post"><input type="hidden" name="PHPSESSID" value="testid" />
<input type="text" name="test1"></input>
<input type="text" name="test2" />
</form>
-<form action="//php.net/script.php" method="post"><input type="hidden" name="PHPSESSID" value="testid" /><input type="hidden" name="PHPSESSID" value="testid" />
+<form action="//php.net/script.php" method="post"><input type="hidden" name="PHPSESSID" value="testid" />
<input type="text" name="test1"></input>
<input type="text" name="test2" />
</form>
@@ -349,4 +347,4 @@ NULL
*** Cleanup ***
bool(true)
string(6) "testid"
-bool(true)
\ No newline at end of file
+bool(true)
diff --git a/ext/standard/url_scanner_ex.h b/ext/standard/url_scanner_ex.h
index a69a325..31441cd 100644
--- a/ext/standard/url_scanner_ex.h
+++ b/ext/standard/url_scanner_ex.h
@@ -29,6 +29,7 @@ PHP_RSHUTDOWN_FUNCTION(url_scanner_ex);
PHPAPI char *php_url_scanner_adapt_single_url(const char *url, size_t urllen, const char *name, const char *value, size_t *newlen, int urlencode);
PHPAPI int php_url_scanner_add_var(char *name, size_t name_len, char *value, size_t value_len, int urlencode);
+PHPAPI int php_url_scanner_reset_var(zend_string *name, zend_string *value, int urlencode);
PHPAPI int php_url_scanner_reset_vars(void);
#include "zend_smart_str_public.h"
diff --git a/ext/standard/url_scanner_ex.re b/ext/standard/url_scanner_ex.re
index ef05e80..aa38ae2 100644
--- a/ext/standard/url_scanner_ex.re
+++ b/ext/standard/url_scanner_ex.re
@@ -114,37 +114,73 @@ alphadash = ([a-zA-Z] | "-");
static inline void append_modified_url(smart_str *url, smart_str *dest, smart_str *url_app, const char *separator)
{
- register const char *p, *q;
- const char *bash = NULL;
- const char *sep = "?";
+ php_url *url_parts;
- q = (p = ZSTR_VAL(url->s)) + ZSTR_LEN(url->s);
+ smart_str_0(url); /* FIXME: Bug #70480 php_url_prase_ex() crashes by processing chars exceed len */
+ url_parts = php_url_parse_ex(ZSTR_VAL(url->s), ZSTR_LEN(url->s));
-scan:
-/*!re2c
- ":" { smart_str_append_smart_str(dest, url); return; }
- "?" { sep = separator; goto scan; }
- "#" { bash = p - 1; goto done; }
- (any\[:?#])+ { goto scan; }
-*/
-done:
-
- /* Don't modify URLs of the format "#mark" */
- if (bash && bash - ZSTR_VAL(url->s) == 0) {
+ if (!url_parts) {
+ /* Ignore malformed URLs */
smart_str_append_smart_str(dest, url);
return;
}
- if (bash)
- smart_str_appendl(dest, ZSTR_VAL(url->s), bash - ZSTR_VAL(url->s));
- else
+ if (url_parts->scheme ||
+ *(ZSTR_VAL(url->s)) == '/' && *(ZSTR_VAL(url->s)+1) == '/') {
+ /* Current URL scanner works only with relative local path */
smart_str_append_smart_str(dest, url);
+ php_url_free(url_parts);
+ return;
+ }
- smart_str_appends(dest, sep);
- smart_str_append_smart_str(dest, url_app);
+ if (!url_parts->path) {
+ /* URL is http://php.net or like */
+ smart_str_append_smart_str(dest, url);
+ smart_str_appendc(dest, '/');
+ smart_str_appendc(dest, '?');
+ smart_str_append_smart_str(dest, url_app);
+ /* There should not be fragment. Just return */
+ php_url_free(url_parts);
+ return;
+ }
- if (bash)
- smart_str_appendl(dest, bash, q - bash);
+ /* Schema/host/etc are handled for full path support in the future */
+ if (url_parts->scheme) {
+ smart_str_appends(dest, url_parts->scheme);
+ } else if (*(ZSTR_VAL(url->s)) == '/' && *(ZSTR_VAL(url->s)+1) == '/') {
+ smart_str_appends(dest, "//");
+ }
+ if (url_parts->user) {
+ smart_str_appends(dest, url_parts->user);
+ if (url_parts->pass) {
+ smart_str_appends(dest, url_parts->pass);
+ smart_str_appendc(dest, ':');
+ }
+ smart_str_appendc(dest, '@');
+ }
+ if (url_parts->host) {
+ smart_str_appends(dest, url_parts->host);
+ }
+ if (url_parts->port) {
+ smart_str_appendc(dest, ':');
+ smart_str_append_unsigned(dest, (long)url_parts->port);
+ }
+ if (url_parts->path) {
+ smart_str_appends(dest, url_parts->path);
+ }
+ smart_str_appendc(dest, '?');
+ if (url_parts->query) {
+ smart_str_appends(dest, url_parts->query);
+ smart_str_appends(dest, separator);
+ smart_str_append_smart_str(dest, url_app);
+ } else {
+ smart_str_append_smart_str(dest, url_app);
+ }
+ if (url_parts->fragment) {
+ smart_str_appendc(dest, '#');
+ smart_str_appends(dest, url_parts->fragment);
+ }
+ php_url_free(url_parts);
}
@@ -536,18 +572,99 @@ PHPAPI int php_url_scanner_add_var(char *name, size_t name_len, char *value, siz
return SUCCESS;
}
-PHPAPI int php_url_scanner_reset_vars(void)
-{
+static inline void php_url_scanner_clear(void) {
if (BG(url_adapt_state_ex).form_app.s) {
ZSTR_LEN(BG(url_adapt_state_ex).form_app.s) = 0;
}
if (BG(url_adapt_state_ex).url_app.s) {
ZSTR_LEN(BG(url_adapt_state_ex).url_app.s) = 0;
}
+}
+PHPAPI int php_url_scanner_reset_vars(void)
+{
+ php_url_scanner_clear();
return SUCCESS;
}
+PHPAPI int php_url_scanner_reset_var(zend_string *name, zend_string *value, int urlencode)
+{
+ char *found;
+ smart_str sname = {0};
+ smart_str svalue = {0};
+ smart_str url_app = {0};
+ smart_str form_app = {0};
+ zend_string *encoded;
+ int ret = SUCCESS;
+
+ /* Short circuit check. Only check url_app. */
+ if (!BG(url_adapt_state_ex).url_app.s || !ZSTR_LEN(BG(url_adapt_state_ex).url_app.s)) {
+ return SUCCESS;
+ }
+
+ if (urlencode) {
+ encoded = php_raw_url_encode(ZSTR_VAL(name), ZSTR_LEN(name));
+ smart_str_appendl(&sname, ZSTR_VAL(encoded), ZSTR_LEN(encoded));
+ zend_string_free(encoded);
+ encoded = php_raw_url_encode(ZSTR_VAL(value), ZSTR_LEN(value));
+ smart_str_appendl(&svalue, ZSTR_VAL(encoded), ZSTR_LEN(encoded));
+ zend_string_free(encoded);
+ } else {
+ smart_str_appendl(&sname, ZSTR_VAL(name), ZSTR_LEN(name));
+ smart_str_appendl(&svalue, ZSTR_VAL(value), ZSTR_LEN(value));
+ }
+
+ smart_str_append_smart_str(&url_app, &sname);
+ smart_str_appendc(&url_app, '=');
+ smart_str_append_smart_str(&url_app, &svalue);
+
+ smart_str_appends(&form_app, "<input type=\"hidden\" name=\"");
+ smart_str_append_smart_str(&form_app, &sname);
+ smart_str_appends(&form_app, "\" value=\"");
+ smart_str_append_smart_str(&form_app, &svalue);
+ smart_str_appends(&form_app, "\" />");
+
+ /* Short circuit check. Only check url_app. */
+ found = (char *)php_memnstr(ZSTR_VAL(BG(url_adapt_state_ex).url_app.s),
+ ZSTR_VAL(url_app.s), 1,
+ ZSTR_VAL(BG(url_adapt_state_ex).url_app.s) + ZSTR_LEN(BG(url_adapt_state_ex).url_app.s));
+ if (!found) {
+ ret = FAILURE;
+ goto finish;
+ }
+ if (ZSTR_LEN(BG(url_adapt_state_ex).url_app.s) == ZSTR_LEN(url_app.s)) {
+ php_url_scanner_clear();
+ goto finish;
+ }
+
+ /* Remove partially */
+ memmove(found,
+ found + ZSTR_LEN(url_app.s),
+ found - ZSTR_VAL(BG(url_adapt_state_ex).url_app.s) - ZSTR_LEN(url_app.s));
+ ZSTR_LEN(BG(url_adapt_state_ex).url_app.s) = ZSTR_LEN(BG(url_adapt_state_ex).url_app.s) - ZSTR_LEN(url_app.s);
+
+ found= (char *)php_memnstr(ZSTR_VAL(BG(url_adapt_state_ex).form_app.s),
+ ZSTR_VAL(form_app.s), 1,
+ ZSTR_VAL(BG(url_adapt_state_ex).form_app.s) + ZSTR_LEN(BG(url_adapt_state_ex).form_app.s));
+ if (!found) {
+ /* Should not happen */
+ ret = FAILURE;
+ goto finish;
+ }
+ memmove(found,
+ found + ZSTR_LEN(form_app.s),
+ found - ZSTR_VAL(BG(url_adapt_state_ex).form_app.s) - ZSTR_LEN(form_app.s));
+ ZSTR_LEN(BG(url_adapt_state_ex).form_app.s) = ZSTR_LEN(BG(url_adapt_state_ex).form_app.s) - ZSTR_LEN(form_app.s);
+
+finish:
+ smart_str_free(&url_app);
+ smart_str_free(&form_app);
+ smart_str_free(&sname);
+ smart_str_free(&svalue);
+ return ret;
+}
+
+
PHP_MINIT_FUNCTION(url_scanner)
{
BG(url_adapt_state_ex).tags = NULL;
|