Skip to content

Commit 837a949

Browse files
committed
Merge branch 'PHP-7.3' into PHP-7.4
* PHP-7.3: Fix #76448: Stack buffer overflow in firebird_info_cb Fix #76449: SIGSEGV in firebird_handle_doer Fix #76450: SIGSEGV in firebird_stmt_execute Fix #76452: Crash while parsing blob data in firebird_fetch_blob Fix #81122: SSRF bypass in FILTER_VALIDATE_URL
2 parents 4d8eb89 + 67afa32 commit 837a949

File tree

12 files changed

+156
-4
lines changed

12 files changed

+156
-4
lines changed

ext/filter/logical_filters.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -632,7 +632,9 @@ void php_filter_validate_url(PHP_INPUT_FILTER_PARAM_DECL) /* {{{ */
632632
RETURN_VALIDATION_FAILED
633633
}
634634

635-
if (url->user != NULL && !is_userinfo_valid(url->user)) {
635+
if (url->user != NULL && !is_userinfo_valid(url->user)
636+
|| url->pass != NULL && !is_userinfo_valid(url->pass)
637+
) {
636638
php_url_free(url);
637639
RETURN_VALIDATION_FAILED
638640

ext/filter/tests/bug81122.phpt

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
--TEST--
2+
Bug #81122 (SSRF bypass in FILTER_VALIDATE_URL)
3+
--SKIPIF--
4+
<?php
5+
if (!extension_loaded('filter')) die("skip filter extension not available");
6+
?>
7+
--FILE--
8+
<?php
9+
$urls = [
10+
"https://example.com:\\@test.com/",
11+
"https://user:\\epass@test.com",
12+
"https://user:\\@test.com",
13+
];
14+
foreach ($urls as $url) {
15+
var_dump(filter_var($url, FILTER_VALIDATE_URL));
16+
}
17+
?>
18+
--EXPECT--
19+
bool(false)
20+
bool(false)
21+
bool(false)

ext/pdo_firebird/firebird_driver.c

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -206,8 +206,17 @@ static zend_long firebird_handle_doer(pdo_dbh_t *dbh, const char *sql, size_t sq
206206
if (result[0] == isc_info_sql_records) {
207207
unsigned i = 3, result_size = isc_vax_integer(&result[1],2);
208208

209+
if (result_size > sizeof(result)) {
210+
ret = -1;
211+
goto free_statement;
212+
}
209213
while (result[i] != isc_info_end && i < result_size) {
210214
short len = (short)isc_vax_integer(&result[i+1],2);
215+
/* bail out on bad len */
216+
if (len != 1 && len != 2 && len != 4) {
217+
ret = -1;
218+
goto free_statement;
219+
}
211220
if (result[i] != isc_info_req_select_count) {
212221
ret += isc_vax_integer(&result[i+3],len);
213222
}
@@ -509,14 +518,16 @@ static int firebird_handle_set_attribute(pdo_dbh_t *dbh, zend_long attr, zval *v
509518
}
510519
/* }}} */
511520

521+
#define INFO_BUF_LEN 512
522+
512523
/* callback to used to report database server info */
513524
static void firebird_info_cb(void *arg, char const *s) /* {{{ */
514525
{
515526
if (arg) {
516527
if (*(char*)arg) { /* second call */
517-
strcat(arg, " ");
528+
strlcat(arg, " ", INFO_BUF_LEN);
518529
}
519-
strcat(arg, s);
530+
strlcat(arg, s, INFO_BUF_LEN);
520531
}
521532
}
522533
/* }}} */
@@ -527,7 +538,7 @@ static int firebird_handle_get_attribute(pdo_dbh_t *dbh, zend_long attr, zval *v
527538
pdo_firebird_db_handle *H = (pdo_firebird_db_handle *)dbh->driver_data;
528539

529540
switch (attr) {
530-
char tmp[512];
541+
char tmp[INFO_BUF_LEN];
531542

532543
case PDO_ATTR_AUTOCOMMIT:
533544
ZVAL_LONG(val,dbh->auto_commit);

ext/pdo_firebird/firebird_statement.c

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,8 +136,14 @@ static int firebird_stmt_execute(pdo_stmt_t *stmt) /* {{{ */
136136
}
137137
if (result[0] == isc_info_sql_records) {
138138
unsigned i = 3, result_size = isc_vax_integer(&result[1], 2);
139+
if (result_size > sizeof(result)) {
140+
goto error;
141+
}
139142
while (result[i] != isc_info_end && i < result_size) {
140143
short len = (short) isc_vax_integer(&result[i + 1], 2);
144+
if (len != 1 && len != 2 && len != 4) {
145+
goto error;
146+
}
141147
if (result[i] != isc_info_req_select_count) {
142148
affected_rows += isc_vax_integer(&result[i + 3], len);
143149
}
@@ -161,6 +167,7 @@ static int firebird_stmt_execute(pdo_stmt_t *stmt) /* {{{ */
161167
return 1;
162168
} while (0);
163169

170+
error:
164171
RECORD_ERROR(stmt);
165172

166173
return 0;
@@ -302,6 +309,11 @@ static int firebird_fetch_blob(pdo_stmt_t *stmt, int colno, char **ptr, /* {{{ *
302309
unsigned short seg_len;
303310
ISC_STATUS stat;
304311

312+
/* prevent overflow */
313+
if (*len == ZEND_ULONG_MAX) {
314+
result = 0;
315+
goto fetch_blob_end;
316+
}
305317
*ptr = S->fetch_buf[colno] = erealloc(S->fetch_buf[colno], *len+1);
306318

307319
for (cur_len = stat = 0; (!stat || stat == isc_segment) && cur_len < *len; cur_len += seg_len) {

ext/pdo_firebird/tests/bug_76448.data

749 Bytes
Binary file not shown.

ext/pdo_firebird/tests/bug_76448.phpt

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
--TEST--
2+
Bug #76448 (Stack buffer overflow in firebird_info_cb)
3+
--SKIPIF--
4+
<?php
5+
if (!extension_loaded('pdo_firebird')) die("skip podo_firebird extension not available");
6+
if (!extension_loaded('sockets')) die("skip sockets extension not available");
7+
?>
8+
--FILE--
9+
<?php
10+
require_once "payload_server.inc";
11+
12+
$address = run_server(__DIR__ . "/bug_76448.data");
13+
14+
// no need to change the credentials; we're running against a falke server
15+
$dsn = "firebird:dbname=inet://$address/test";
16+
$username = 'SYSDBA';
17+
$password = 'masterkey';
18+
19+
$dbh = new PDO($dsn, $username, $password, [PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION]);
20+
var_dump($dbh->getAttribute(PDO::ATTR_SERVER_INFO));
21+
?>
22+
--EXPECT--
23+
bool(false)

ext/pdo_firebird/tests/bug_76449.data

464 Bytes
Binary file not shown.

ext/pdo_firebird/tests/bug_76449.phpt

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
--TEST--
2+
Bug #76449 (SIGSEGV in firebird_handle_doer)
3+
--SKIPIF--
4+
<?php
5+
if (!extension_loaded('pdo_firebird')) die("skip pdo_firebird extension not available");
6+
if (!extension_loaded('sockets')) die("skip sockets extension not available");
7+
?>
8+
--FILE--
9+
<?php
10+
require_once "payload_server.inc";
11+
12+
$address = run_server(__DIR__ . "/bug_76449.data");
13+
14+
// no need to change the credentials; we're running against a fake server
15+
$dsn = "firebird:dbname=inet://$address/test";
16+
$username = 'SYSDBA';
17+
$password = 'masterkey';
18+
19+
$dbh = new PDO($dsn, $username, $password, [PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION]);
20+
var_dump($dbh->exec("INSERT INTO test VALUES ('hihi2', 'xxxxx')"));
21+
?>
22+
--EXPECT--
23+
bool(false)

ext/pdo_firebird/tests/bug_76450.data

464 Bytes
Binary file not shown.

ext/pdo_firebird/tests/bug_76450.phpt

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
--TEST--
2+
Bug #76450 (SIGSEGV in firebird_stmt_execute)
3+
--SKIPIF--
4+
<?php
5+
if (!extension_loaded('pdo_firebird')) die("skip pdo_firebird extension not available");
6+
if (!extension_loaded('sockets')) die("skip sockets extension not available");
7+
?>
8+
--FILE--
9+
<?php
10+
require_once "payload_server.inc";
11+
12+
$address = run_server(__DIR__ . "/bug_76450.data");
13+
14+
// no need to change the credentials; we're running against a fake server
15+
$dsn = "firebird:dbname=inet://$address/test";
16+
$username = 'SYSDBA';
17+
$password = 'masterkey';
18+
19+
$dbh = new PDO($dsn, $username, $password, [PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION]);
20+
$sql = "EXECUTE PROCEDURE test_proc 123";
21+
$query = $dbh->prepare($sql);
22+
try {
23+
$query->execute();
24+
} catch (Exception $ex) {
25+
echo "{$ex->getMessage()}\n";
26+
}
27+
?>
28+
--EXPECT--
29+
SQLSTATE[HY000]: General error

ext/pdo_firebird/tests/bug_76452.data

856 Bytes
Binary file not shown.

ext/pdo_firebird/tests/bug_76452.phpt

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
--TEST--
2+
Bug ##76452 (Crash while parsing blob data in firebird_fetch_blob)
3+
--SKIPIF--
4+
<?php require('skipif.inc'); ?>
5+
--FILE--
6+
<?php
7+
require_once "payload_server.inc";
8+
9+
$address = run_server(__DIR__ . "/bug_76452.data");
10+
11+
// no need to change the credentials; we're running against a falke server
12+
$dsn = "firebird:dbname=inet://$address/test";
13+
$username = 'SYSDBA';
14+
$password = 'masterkey';
15+
16+
$dbh = new PDO($dsn, $username, $password, [PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION]);
17+
$query = $dbh->prepare("select * from test");
18+
$query->execute();
19+
var_dump($query->fetch());
20+
?>
21+
--EXPECT--
22+
array(4) {
23+
["AAA"]=>
24+
string(4) "hihi"
25+
[0]=>
26+
string(4) "hihi"
27+
["BBBB"]=>
28+
NULL
29+
[1]=>
30+
NULL
31+
}

0 commit comments

Comments
 (0)