diff options
author | Christoph M. Becker <cmbecker69@gmx.de> | 2020-10-29 11:52:10 +0100 |
---|---|---|
committer | Christoph M. Becker <cmbecker69@gmx.de> | 2020-10-29 11:59:12 +0100 |
commit | c21e901ba735e927e345b65a35fcd6f585d0c2f3 (patch) | |
tree | 354dae192cb27de6b6b96250ab3b7ebcc6699e5e | |
parent | 7817fc07e150620be38a16dd29e50c71e51948a7 (diff) | |
download | php-git-c21e901ba735e927e345b65a35fcd6f585d0c2f3.tar.gz |
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 GH-6281.
-rw-r--r-- | NEWS | 3 | ||||
-rw-r--r-- | ext/odbc/php_odbc.c | 26 | ||||
-rw-r--r-- | ext/odbc/tests/bug44618.phpt | 62 |
3 files changed, 87 insertions, 4 deletions
@@ -22,6 +22,9 @@ PHP NEWS . Fixed bug #80242 (imap_mail_compose() segfaults for multipart with rfc822). (cmb) +- ODBC: + . Fixed bug #44618 (Fetching may rely on uninitialized data). (cmb) + 29 Oct 2020, PHP 7.3.24 - Core: diff --git a/ext/odbc/php_odbc.c b/ext/odbc/php_odbc.c index 1bb832553c..cc0580fb83 100644 --- a/ext/odbc/php_odbc.c +++ b/ext/odbc/php_odbc.c @@ -1810,6 +1810,9 @@ static void php_odbc_fetch_hash(INTERNAL_FUNCTION_PARAMETERS, int result_type) if (rc == SQL_SUCCESS_WITH_INFO) { ZVAL_STRINGL(&tmp, buf, result->longreadlen); + } else if (rc != SQL_SUCCESS) { + php_error_docref(NULL, E_WARNING, "Cannot get data of column #%d (retcode %u)", i + 1, rc); + ZVAL_FALSE(&tmp); } else if (result->values[i].vallen == SQL_NULL_DATA) { ZVAL_NULL(&tmp); break; @@ -1962,6 +1965,9 @@ PHP_FUNCTION(odbc_fetch_into) } if (rc == SQL_SUCCESS_WITH_INFO) { ZVAL_STRINGL(&tmp, buf, result->longreadlen); + } else if (rc != SQL_SUCCESS) { + php_error_docref(NULL, E_WARNING, "Cannot get data of column #%d (retcode %u)", i + 1, rc); + ZVAL_FALSE(&tmp); } else if (result->values[i].vallen == SQL_NULL_DATA) { ZVAL_NULL(&tmp); break; @@ -2199,12 +2205,13 @@ PHP_FUNCTION(odbc_result) RETURN_FALSE; } - if (result->values[field_ind].vallen == SQL_NULL_DATA) { - zend_string_efree(field_str); - RETURN_NULL(); - } else if (rc == SQL_NO_DATA_FOUND) { + if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO) { zend_string_efree(field_str); + php_error_docref(NULL, E_WARNING, "Cannot get data of column #%d (retcode %u)", field_ind + 1, rc); RETURN_FALSE; + } else if (result->values[field_ind].vallen == SQL_NULL_DATA) { + zend_string_efree(field_str); + RETURN_NULL(); } /* Reduce fieldlen by 1 if we have char data. One day we might have binary strings... */ @@ -2250,6 +2257,12 @@ PHP_FUNCTION(odbc_result) RETURN_FALSE; } + if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO) { + php_error_docref(NULL, E_WARNING, "Cannot get data of column #%d (retcode %u)", field_ind + 1, rc); + efree(field); + RETURN_FALSE; + } + if (result->values[field_ind].vallen == SQL_NULL_DATA) { efree(field); RETURN_NULL(); @@ -2359,6 +2372,11 @@ PHP_FUNCTION(odbc_result_all) } if (rc == SQL_SUCCESS_WITH_INFO) { PHPWRITE(buf, result->longreadlen); + } else if (rc != SQL_SUCCESS) { + php_printf("</td></tr></table>"); + php_error_docref(NULL, E_WARNING, "Cannot get data of column #%d (retcode %u)", i + 1, rc); + efree(buf); + RETURN_FALSE; } else if (result->values[i].vallen == SQL_NULL_DATA) { php_printf("<td>NULL</td>"); break; diff --git a/ext/odbc/tests/bug44618.phpt b/ext/odbc/tests/bug44618.phpt new file mode 100644 index 0000000000..668cee7afa --- /dev/null +++ b/ext/odbc/tests/bug44618.phpt @@ -0,0 +1,62 @@ +--TEST-- +Bug #44618 (Fetching may rely on uninitialized data) +--SKIPIF-- +<?php include 'skipif.inc'; ?> +--FILE-- +<?php +include __DIR__ . "/config.inc"; +$conn = odbc_connect($dsn, $user, $pass, SQL_CUR_USE_ODBC); + +odbc_exec($conn, "CREATE TABLE bug44618(ID INT, real1 REAL, text1 TEXT)"); +odbc_exec($conn, "INSERT INTO bug44618 VALUES (1, 10.0199995, 'testing 1,2,3')"); + +$result = odbc_exec($conn, "SELECT * FROM bug44618"); +var_dump(odbc_fetch_array($result)); +$result = null; + +$result = odbc_exec($conn, "SELECT * FROM bug44618"); +odbc_fetch_into($result, $array); +var_dump($array); +$result = null; + +$result = odbc_exec($conn, "SELECT * FROM bug44618"); +odbc_fetch_row($result); +var_dump(odbc_result($result, "text1")); +$result = null; + +$result = odbc_exec($conn, "SELECT * FROM bug44618"); +odbc_result_all($result); +$result = null; +?> +--CLEAN-- +<?php +include __DIR__ . "/config.inc"; +$conn = odbc_connect($dsn, $user, $pass); +odbc_exec($conn, "DROP TABLE bug44618"); +?> +--EXPECTF-- +Warning: odbc_fetch_array(): Cannot get data of column #3 (retcode 100) in %s on line %d +array(3) { + ["ID"]=> + string(1) "1" + ["real1"]=> + string(5) "10.02" + ["text1"]=> + bool(false) +} + +Warning: odbc_fetch_into(): Cannot get data of column #3 (retcode 100) in %s on line %d +array(3) { + [0]=> + string(1) "1" + [1]=> + string(5) "10.02" + [2]=> + bool(false) +} + +Warning: odbc_result(): Cannot get data of column #3 (retcode 100) in %s on line %d +bool(false) +<table><tr><th>ID</th><th>real1</th><th>text1</th></tr> +<tr><td>1</td><td>10.02</td><td></td></tr></table> +Warning: odbc_result_all(): Cannot get data of column #3 (retcode 100) in %s on line %d |