From 5e7cd3e7ed7c894550ca35514708ffe1874a31ad Mon Sep 17 00:00:00 2001
From: Niels Dossche <7771979+nielsdos@users.noreply.github.com>
Date: Thu, 24 Oct 2024 22:02:17 +0200
Subject: [PATCH 1/8] Fix GHSA-5hqh-c84r-qjcv: Integer overflow in the dblib
 quoter causing OOB writes

(cherry picked from commit d9baa9fed8c3ba692a36b388c0c7762e5102e2e0)
(cherry picked from commit 5d9e54065ed18c51e4f25d8900635f90810c7394)
(cherry picked from commit 97546df8d6900b115536c17af9213f1da837b82e)
---
 ext/pdo_dblib/dblib_driver.c                 |  8 ++++++-
 ext/pdo_dblib/tests/GHSA-5hqh-c84r-qjcv.phpt | 24 ++++++++++++++++++++
 2 files changed, 31 insertions(+), 1 deletion(-)
 create mode 100644 ext/pdo_dblib/tests/GHSA-5hqh-c84r-qjcv.phpt

diff --git a/ext/pdo_dblib/dblib_driver.c b/ext/pdo_dblib/dblib_driver.c
index b9277a30e3..b4c65aa4ee 100644
--- a/ext/pdo_dblib/dblib_driver.c
+++ b/ext/pdo_dblib/dblib_driver.c
@@ -154,6 +154,7 @@ static int dblib_handle_quoter(pdo_dbh_t *dbh, const char *unquoted, size_t unqu
 
 	size_t i;
 	char * q;
+	size_t extralen = 0;
 	*quotedlen = 0;
 
 	if (H->assume_national_character_set_strings) {
@@ -168,7 +169,7 @@ static int dblib_handle_quoter(pdo_dbh_t *dbh, const char *unquoted, size_t unqu
 
 	/* Detect quoted length, adding extra char for doubled single quotes */
 	for (i = 0; i < unquotedlen; i++) {
-		if (unquoted[i] == '\'') ++*quotedlen;
+		if (unquoted[i] == '\'') ++extralen;
 		++*quotedlen;
 	}
 
@@ -176,6 +177,11 @@ static int dblib_handle_quoter(pdo_dbh_t *dbh, const char *unquoted, size_t unqu
 	if (use_national_character_set) {
 		++*quotedlen; /* N prefix */
 	}
+	if (UNEXPECTED(*quotedlen > ZSTR_MAX_LEN - extralen)) {
+		return 0;
+	}
+
+	*quotedlen += extralen;
 	q = *quoted = emalloc(*quotedlen + 1); /* Add byte for terminal null */
 	if (use_national_character_set) {
 		*q++ = 'N';
diff --git a/ext/pdo_dblib/tests/GHSA-5hqh-c84r-qjcv.phpt b/ext/pdo_dblib/tests/GHSA-5hqh-c84r-qjcv.phpt
new file mode 100644
index 0000000000..431c61951e
--- /dev/null
+++ b/ext/pdo_dblib/tests/GHSA-5hqh-c84r-qjcv.phpt
@@ -0,0 +1,24 @@
+--TEST--
+GHSA-5hqh-c84r-qjcv (Integer overflow in the dblib quoter causing OOB writes)
+--EXTENSIONS--
+pdo_dblib
+--SKIPIF--
+<?php
+if (PHP_INT_SIZE != 4) die("skip for 32bit platforms only");
+if (PHP_OS_FAMILY === "Windows") die("skip not for Windows because the virtual address space for application is only 2GiB");
+if (getenv("SKIP_SLOW_TESTS")) die("skip slow test");
+require __DIR__ . '/config.inc';
+getDbConnection();
+?>
+--INI--
+memory_limit=-1
+--FILE--
+<?php
+
+require __DIR__ . '/config.inc';
+$db = getDbConnection();
+var_dump($db->quote(str_repeat("'", 2147483646)));
+
+?>
+--EXPECT--
+bool(false)
-- 
2.47.0

From 72d4c4e435544c2d87d634188d480099345b601b Mon Sep 17 00:00:00 2001
From: Niels Dossche <7771979+nielsdos@users.noreply.github.com>
Date: Thu, 24 Oct 2024 22:02:36 +0200
Subject: [PATCH 2/8] Fix GHSA-5hqh-c84r-qjcv: Integer overflow in the firebird
 quoter causing OOB writes

(cherry picked from commit 69c5f68fdc3deed9ebce2cc44b4bf5e0c47cd28f)
(cherry picked from commit b4f73be75dbdde970a18cc7a636898b10400fb3f)
(cherry picked from commit 0530cbfe5c3044537de52d8382eba5d69dbac726)
---
 ext/pdo_firebird/firebird_driver.c | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/ext/pdo_firebird/firebird_driver.c b/ext/pdo_firebird/firebird_driver.c
index e2c5ea915a..9ebafe6957 100644
--- a/ext/pdo_firebird/firebird_driver.c
+++ b/ext/pdo_firebird/firebird_driver.c
@@ -243,7 +243,7 @@ free_statement:
 static int firebird_handle_quoter(pdo_dbh_t *dbh, const char *unquoted, size_t unquotedlen, /* {{{ */
 	char **quoted, size_t *quotedlen, enum pdo_param_type paramtype)
 {
-	int qcount = 0;
+	size_t qcount = 0;
 	char const *co, *l, *r;
 	char *c;
 
@@ -258,6 +258,10 @@ static int firebird_handle_quoter(pdo_dbh_t *dbh, const char *unquoted, size_t u
 	/* count the number of ' characters */
 	for (co = unquoted; (co = strchr(co,'\'')); qcount++, co++);
 
+	if (UNEXPECTED(unquotedlen + 2 > ZSTR_MAX_LEN - qcount)) {
+		return 0;
+	}
+
 	*quotedlen = unquotedlen + qcount + 2;
 	*quoted = c = emalloc(*quotedlen+1);
 	*c++ = '\'';
-- 
2.47.0

From 37056ad634d9c44bac0d6c8e730eafaec1344840 Mon Sep 17 00:00:00 2001
From: Remi Collet <remi@remirepo.net>
Date: Fri, 22 Nov 2024 15:24:16 +0100
Subject: [PATCH 3/8] backport ZSTR_MAX_LEN

---
 Zend/zend_string.h | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/Zend/zend_string.h b/Zend/zend_string.h
index 396b63b266..8ef979f37e 100644
--- a/Zend/zend_string.h
+++ b/Zend/zend_string.h
@@ -76,6 +76,9 @@ END_EXTERN_C()
 
 #define _ZSTR_STRUCT_SIZE(len) (_ZSTR_HEADER_SIZE + len + 1)
 
+#define ZSTR_MAX_OVERHEAD (ZEND_MM_ALIGNED_SIZE(_ZSTR_HEADER_SIZE + 1))
+#define ZSTR_MAX_LEN (SIZE_MAX - ZSTR_MAX_OVERHEAD)
+
 #define ZSTR_ALLOCA_ALLOC(str, _len, use_heap) do { \
 	(str) = (zend_string *)do_alloca(ZEND_MM_ALIGNED_SIZE_EX(_ZSTR_STRUCT_SIZE(_len), 8), (use_heap)); \
 	GC_SET_REFCOUNT(str, 1); \
-- 
2.47.0