Skip to content

Commit 4a79a5a

Browse files
nielsdosbukka
authored andcommitted
Fix GHSA-5hqh-c84r-qjcv: Integer overflow in the dblib quoter causing OOB writes
1 parent ef5844a commit 4a79a5a

File tree

2 files changed

+32
-2
lines changed

2 files changed

+32
-2
lines changed

ext/pdo_dblib/dblib_driver.c

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,7 @@ static zend_string* dblib_handle_quoter(pdo_dbh_t *dbh, const zend_string *unquo
148148
bool use_national_character_set = 0;
149149
size_t i;
150150
char *q;
151-
size_t quotedlen = 0;
151+
size_t quotedlen = 0, extralen = 0;
152152
zend_string *quoted_str;
153153

154154
if (H->assume_national_character_set_strings) {
@@ -163,14 +163,20 @@ static zend_string* dblib_handle_quoter(pdo_dbh_t *dbh, const zend_string *unquo
163163

164164
/* Detect quoted length, adding extra char for doubled single quotes */
165165
for (i = 0; i < ZSTR_LEN(unquoted); i++) {
166-
if (ZSTR_VAL(unquoted)[i] == '\'') ++quotedlen;
166+
if (ZSTR_VAL(unquoted)[i] == '\'') ++extralen;
167167
++quotedlen;
168168
}
169169

170170
quotedlen += 2; /* +2 for opening, closing quotes */
171171
if (use_national_character_set) {
172172
++quotedlen; /* N prefix */
173173
}
174+
175+
if (UNEXPECTED(quotedlen > ZSTR_MAX_LEN - extralen)) {
176+
return NULL;
177+
}
178+
179+
quotedlen += extralen;
174180
quoted_str = zend_string_alloc(quotedlen, 0);
175181
q = ZSTR_VAL(quoted_str);
176182
if (use_national_character_set) {
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
--TEST--
2+
GHSA-5hqh-c84r-qjcv (Integer overflow in the dblib quoter causing OOB writes)
3+
--EXTENSIONS--
4+
pdo_dblib
5+
--SKIPIF--
6+
<?php
7+
if (PHP_INT_SIZE != 4) die("skip for 32bit platforms only");
8+
if (PHP_OS_FAMILY === "Windows") die("skip not for Windows because the virtual address space for application is only 2GiB");
9+
if (getenv("SKIP_SLOW_TESTS")) die("skip slow test");
10+
require __DIR__ . '/config.inc';
11+
getDbConnection();
12+
?>
13+
--INI--
14+
memory_limit=-1
15+
--FILE--
16+
<?php
17+
18+
require __DIR__ . '/config.inc';
19+
$db = getDbConnection();
20+
var_dump($db->quote(str_repeat("'", 2147483646)));
21+
22+
?>
23+
--EXPECT--
24+
bool(false)

0 commit comments

Comments
 (0)