Skip to content

Commit c21e901

Browse files
committed
Fix #44618: Fetching may rely on uninitialized data
Unless `SQLGetData()` returns `SQL_SUCCESS` or `SQL_SUCCESS_WITH_INFO`, the `StrLen_or_IndPtr` output argument is not guaranteed to be properly set. Thus we handle retrieval failure other than `SQL_ERROR` by yielding `false` for those column values and raising a warning. Closes phpGH-6281.
1 parent 7817fc0 commit c21e901

File tree

3 files changed

+87
-4
lines changed

3 files changed

+87
-4
lines changed

NEWS

+3
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,9 @@ PHP NEWS
2222
. Fixed bug #80242 (imap_mail_compose() segfaults for multipart with rfc822).
2323
(cmb)
2424

25+
- ODBC:
26+
. Fixed bug #44618 (Fetching may rely on uninitialized data). (cmb)
27+
2528
29 Oct 2020, PHP 7.3.24
2629

2730
- Core:

ext/odbc/php_odbc.c

+22-4
Original file line numberDiff line numberDiff line change
@@ -1810,6 +1810,9 @@ static void php_odbc_fetch_hash(INTERNAL_FUNCTION_PARAMETERS, int result_type)
18101810

18111811
if (rc == SQL_SUCCESS_WITH_INFO) {
18121812
ZVAL_STRINGL(&tmp, buf, result->longreadlen);
1813+
} else if (rc != SQL_SUCCESS) {
1814+
php_error_docref(NULL, E_WARNING, "Cannot get data of column #%d (retcode %u)", i + 1, rc);
1815+
ZVAL_FALSE(&tmp);
18131816
} else if (result->values[i].vallen == SQL_NULL_DATA) {
18141817
ZVAL_NULL(&tmp);
18151818
break;
@@ -1962,6 +1965,9 @@ PHP_FUNCTION(odbc_fetch_into)
19621965
}
19631966
if (rc == SQL_SUCCESS_WITH_INFO) {
19641967
ZVAL_STRINGL(&tmp, buf, result->longreadlen);
1968+
} else if (rc != SQL_SUCCESS) {
1969+
php_error_docref(NULL, E_WARNING, "Cannot get data of column #%d (retcode %u)", i + 1, rc);
1970+
ZVAL_FALSE(&tmp);
19651971
} else if (result->values[i].vallen == SQL_NULL_DATA) {
19661972
ZVAL_NULL(&tmp);
19671973
break;
@@ -2199,12 +2205,13 @@ PHP_FUNCTION(odbc_result)
21992205
RETURN_FALSE;
22002206
}
22012207

2202-
if (result->values[field_ind].vallen == SQL_NULL_DATA) {
2203-
zend_string_efree(field_str);
2204-
RETURN_NULL();
2205-
} else if (rc == SQL_NO_DATA_FOUND) {
2208+
if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO) {
22062209
zend_string_efree(field_str);
2210+
php_error_docref(NULL, E_WARNING, "Cannot get data of column #%d (retcode %u)", field_ind + 1, rc);
22072211
RETURN_FALSE;
2212+
} else if (result->values[field_ind].vallen == SQL_NULL_DATA) {
2213+
zend_string_efree(field_str);
2214+
RETURN_NULL();
22082215
}
22092216
/* Reduce fieldlen by 1 if we have char data. One day we might
22102217
have binary strings... */
@@ -2250,6 +2257,12 @@ PHP_FUNCTION(odbc_result)
22502257
RETURN_FALSE;
22512258
}
22522259

2260+
if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO) {
2261+
php_error_docref(NULL, E_WARNING, "Cannot get data of column #%d (retcode %u)", field_ind + 1, rc);
2262+
efree(field);
2263+
RETURN_FALSE;
2264+
}
2265+
22532266
if (result->values[field_ind].vallen == SQL_NULL_DATA) {
22542267
efree(field);
22552268
RETURN_NULL();
@@ -2359,6 +2372,11 @@ PHP_FUNCTION(odbc_result_all)
23592372
}
23602373
if (rc == SQL_SUCCESS_WITH_INFO) {
23612374
PHPWRITE(buf, result->longreadlen);
2375+
} else if (rc != SQL_SUCCESS) {
2376+
php_printf("</td></tr></table>");
2377+
php_error_docref(NULL, E_WARNING, "Cannot get data of column #%d (retcode %u)", i + 1, rc);
2378+
efree(buf);
2379+
RETURN_FALSE;
23622380
} else if (result->values[i].vallen == SQL_NULL_DATA) {
23632381
php_printf("<td>NULL</td>");
23642382
break;

ext/odbc/tests/bug44618.phpt

+62
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
--TEST--
2+
Bug #44618 (Fetching may rely on uninitialized data)
3+
--SKIPIF--
4+
<?php include 'skipif.inc'; ?>
5+
--FILE--
6+
<?php
7+
include __DIR__ . "/config.inc";
8+
$conn = odbc_connect($dsn, $user, $pass, SQL_CUR_USE_ODBC);
9+
10+
odbc_exec($conn, "CREATE TABLE bug44618(ID INT, real1 REAL, text1 TEXT)");
11+
odbc_exec($conn, "INSERT INTO bug44618 VALUES (1, 10.0199995, 'testing 1,2,3')");
12+
13+
$result = odbc_exec($conn, "SELECT * FROM bug44618");
14+
var_dump(odbc_fetch_array($result));
15+
$result = null;
16+
17+
$result = odbc_exec($conn, "SELECT * FROM bug44618");
18+
odbc_fetch_into($result, $array);
19+
var_dump($array);
20+
$result = null;
21+
22+
$result = odbc_exec($conn, "SELECT * FROM bug44618");
23+
odbc_fetch_row($result);
24+
var_dump(odbc_result($result, "text1"));
25+
$result = null;
26+
27+
$result = odbc_exec($conn, "SELECT * FROM bug44618");
28+
odbc_result_all($result);
29+
$result = null;
30+
?>
31+
--CLEAN--
32+
<?php
33+
include __DIR__ . "/config.inc";
34+
$conn = odbc_connect($dsn, $user, $pass);
35+
odbc_exec($conn, "DROP TABLE bug44618");
36+
?>
37+
--EXPECTF--
38+
Warning: odbc_fetch_array(): Cannot get data of column #3 (retcode 100) in %s on line %d
39+
array(3) {
40+
["ID"]=>
41+
string(1) "1"
42+
["real1"]=>
43+
string(5) "10.02"
44+
["text1"]=>
45+
bool(false)
46+
}
47+
48+
Warning: odbc_fetch_into(): Cannot get data of column #3 (retcode 100) in %s on line %d
49+
array(3) {
50+
[0]=>
51+
string(1) "1"
52+
[1]=>
53+
string(5) "10.02"
54+
[2]=>
55+
bool(false)
56+
}
57+
58+
Warning: odbc_result(): Cannot get data of column #3 (retcode 100) in %s on line %d
59+
bool(false)
60+
<table><tr><th>ID</th><th>real1</th><th>text1</th></tr>
61+
<tr><td>1</td><td>10.02</td><td></td></tr></table>
62+
Warning: odbc_result_all(): Cannot get data of column #3 (retcode 100) in %s on line %d

0 commit comments

Comments
 (0)