php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Return to Bug #68970
Patch bug68063.patch revision 2016-01-13 02:09 UTC by yohgaki@php.net

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;
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Thu Apr 18 21:01:29 2024 UTC