From c248081601d91beb11c3312ba1b6c3ea36e03e51 Mon Sep 17 00:00:00 2001
From: Niels Dossche <7771979+nielsdos@users.noreply.github.com>
Date: Fri, 5 Apr 2024 21:46:07 +0200
Subject: [PATCH 1/4] Fix GH-13891: memleak and segfault when using ini_set
with session.trans_sid_hosts
The hash tables used are allocated via the persistent allocator.
When using ini_set, the allocation happens via the non-persistent
allocator. When the table is then freed in GSHUTDOWN, we get a crash
because the allocators are mismatched.
As a side note, it is strange that this is designed this way, because it
means that ini_sets persist between requests...
Test credits go to Kamil Tekiela.
---
ext/session/tests/gh13891.phpt | 26 ++++++++++++++++++++++++++
ext/standard/url_scanner_ex.re | 8 ++++++--
2 files changed, 32 insertions(+), 2 deletions(-)
create mode 100644 ext/session/tests/gh13891.phpt
diff --git a/ext/session/tests/gh13891.phpt b/ext/session/tests/gh13891.phpt
new file mode 100644
index 0000000000000..ba2267cf3a842
--- /dev/null
+++ b/ext/session/tests/gh13891.phpt
@@ -0,0 +1,26 @@
+--TEST--
+GH-13891 (memleak and segfault when using ini_set with session.trans_sid_hosts)
+--INI--
+session.use_cookies=0
+session.use_only_cookies=0
+session.use_trans_sid=1
+--EXTENSIONS--
+session
+--SKIPIF--
+
+--FILE--
+
+
Click This Anchor Tag!
+External link with anchor
+External link with anchor 2
+Internal link
+--EXPECT--
+Click This Anchor Tag!
+External link with anchor
+External link with anchor 2
+Internal link
diff --git a/ext/standard/url_scanner_ex.re b/ext/standard/url_scanner_ex.re
index 8e5b43467fc88..f35990636794f 100644
--- a/ext/standard/url_scanner_ex.re
+++ b/ext/standard/url_scanner_ex.re
@@ -138,9 +138,13 @@ static int php_ini_on_update_hosts(zend_ini_entry *entry, zend_string *new_value
}
keylen = q - key;
if (keylen > 0) {
- tmp_key = zend_string_init(key, keylen, 0);
+ /* Note: the hash table is persistently allocated, so the strings must be too!
+ * FIXME: the reason this is persistent is because the tables are allocated in GINIT,
+ * so it survives the request. This also means that the values set by `init_set` carry
+ * over from request to request, which is strange... */
+ tmp_key = zend_string_init(key, keylen, true);
zend_hash_add_empty_element(hosts, tmp_key);
- zend_string_release_ex(tmp_key, 0);
+ zend_string_release_ex(tmp_key, true);
}
}
efree(tmp);
From cce8ccbc07ab681dd78c2dda661d2ce609d68cbb Mon Sep 17 00:00:00 2001
From: Niels Dossche <7771979+nielsdos@users.noreply.github.com>
Date: Fri, 5 Apr 2024 22:53:45 +0200
Subject: [PATCH 2/4] Update ext/standard/url_scanner_ex.re
Co-authored-by: Kamil Tekiela
---
ext/standard/url_scanner_ex.re | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/ext/standard/url_scanner_ex.re b/ext/standard/url_scanner_ex.re
index f35990636794f..da0d4c52a3e19 100644
--- a/ext/standard/url_scanner_ex.re
+++ b/ext/standard/url_scanner_ex.re
@@ -140,7 +140,7 @@ static int php_ini_on_update_hosts(zend_ini_entry *entry, zend_string *new_value
if (keylen > 0) {
/* Note: the hash table is persistently allocated, so the strings must be too!
* FIXME: the reason this is persistent is because the tables are allocated in GINIT,
- * so it survives the request. This also means that the values set by `init_set` carry
+ * so it survives the request. This also means that the values set by `ini_set` carry
* over from request to request, which is strange... */
tmp_key = zend_string_init(key, keylen, true);
zend_hash_add_empty_element(hosts, tmp_key);
From 03166644d9e0f272738df29f0ffa32336a702a7c Mon Sep 17 00:00:00 2001
From: Niels Dossche <7771979+nielsdos@users.noreply.github.com>
Date: Fri, 5 Apr 2024 22:57:06 +0200
Subject: [PATCH 3/4] Further review comment fixes
---
ext/session/tests/gh13891.phpt | 10 ----------
ext/standard/url_scanner_ex.re | 5 +----
2 files changed, 1 insertion(+), 14 deletions(-)
diff --git a/ext/session/tests/gh13891.phpt b/ext/session/tests/gh13891.phpt
index ba2267cf3a842..51e0a15677fd5 100644
--- a/ext/session/tests/gh13891.phpt
+++ b/ext/session/tests/gh13891.phpt
@@ -12,15 +12,5 @@ session
-Click This Anchor Tag!
-External link with anchor
-External link with anchor 2
-Internal link
--EXPECT--
-Click This Anchor Tag!
-External link with anchor
-External link with anchor 2
-Internal link
diff --git a/ext/standard/url_scanner_ex.re b/ext/standard/url_scanner_ex.re
index da0d4c52a3e19..a4a48b6bf60ee 100644
--- a/ext/standard/url_scanner_ex.re
+++ b/ext/standard/url_scanner_ex.re
@@ -138,10 +138,7 @@ static int php_ini_on_update_hosts(zend_ini_entry *entry, zend_string *new_value
}
keylen = q - key;
if (keylen > 0) {
- /* Note: the hash table is persistently allocated, so the strings must be too!
- * FIXME: the reason this is persistent is because the tables are allocated in GINIT,
- * so it survives the request. This also means that the values set by `ini_set` carry
- * over from request to request, which is strange... */
+ /* Note: the hash table is persistently allocated, so the strings must be too! */
tmp_key = zend_string_init(key, keylen, true);
zend_hash_add_empty_element(hosts, tmp_key);
zend_string_release_ex(tmp_key, true);
From c6f3138faf2e2c9407616dfe401fc12dd1bbd714 Mon Sep 17 00:00:00 2001
From: Niels Dossche <7771979+nielsdos@users.noreply.github.com>
Date: Fri, 5 Apr 2024 23:10:31 +0200
Subject: [PATCH 4/4] Add it also in the ini section for better reproducibility
---
ext/session/tests/gh13891.phpt | 1 +
1 file changed, 1 insertion(+)
diff --git a/ext/session/tests/gh13891.phpt b/ext/session/tests/gh13891.phpt
index 51e0a15677fd5..7df9bffa770bc 100644
--- a/ext/session/tests/gh13891.phpt
+++ b/ext/session/tests/gh13891.phpt
@@ -4,6 +4,7 @@ GH-13891 (memleak and segfault when using ini_set with session.trans_sid_hosts)
session.use_cookies=0
session.use_only_cookies=0
session.use_trans_sid=1
+session.trans_sid_hosts=php.net
--EXTENSIONS--
session
--SKIPIF--