From 24dbc542d1ef501479dcd365f1bc53a859981dc0 Mon Sep 17 00:00:00 2001 From: sim1984 Date: Mon, 25 Jun 2018 21:35:51 +0300 Subject: [PATCH 1/9] Fix bug #76488 Memory leak when fetching a BLOB field Add a phpt test (cherry picked from commit 3847a6fcb63c362548e9434b195232f2dcf7a6c7) (cherry picked from commit b671a8dd887ae7f661f6233e734179e8bca3daf6) --- ext/pdo_firebird/firebird_statement.c | 4 ++-- ext/pdo_firebird/tests/bug_76488.phpt | 32 +++++++++++++++++++++++++++ 2 files changed, 34 insertions(+), 2 deletions(-) create mode 100644 ext/pdo_firebird/tests/bug_76488.phpt diff --git a/ext/pdo_firebird/firebird_statement.c b/ext/pdo_firebird/firebird_statement.c index d1f1012637..8b8f82252a 100644 --- a/ext/pdo_firebird/firebird_statement.c +++ b/ext/pdo_firebird/firebird_statement.c @@ -267,8 +267,8 @@ static int firebird_fetch_blob(pdo_stmt_t *stmt, int colno, char **ptr, /* {{{ * unsigned short seg_len; ISC_STATUS stat; - *ptr = S->fetch_buf[colno] = erealloc(*ptr, *len+1); - + *ptr = S->fetch_buf[colno] = erealloc(S->fetch_buf[colno], *len+1); + for (cur_len = stat = 0; (!stat || stat == isc_segment) && cur_len < *len; cur_len += seg_len) { unsigned short chunk_size = (*len-cur_len) > USHRT_MAX ? USHRT_MAX diff --git a/ext/pdo_firebird/tests/bug_76488.phpt b/ext/pdo_firebird/tests/bug_76488.phpt new file mode 100644 index 0000000000..dba6734c28 --- /dev/null +++ b/ext/pdo_firebird/tests/bug_76488.phpt @@ -0,0 +1,32 @@ +--TEST-- +PDO_Firebird: Bug #76488 Memory leak when fetching a BLOB field +--SKIPIF-- + +--FILE-- +prepare($sql); + $sth->execute(); + $rows = $sth->fetchAll(); + unset($rows); + unset($sth); + } + unset($dbh); + echo "OK"; +?> +--EXPECT-- +OK \ No newline at end of file -- 2.31.1 From 7024ff99e8659d9e2d80299ea35f9a78292fa064 Mon Sep 17 00:00:00 2001 From: "Christoph M. Becker" Date: Wed, 5 May 2021 12:42:17 +0200 Subject: [PATCH 2/9] Fix #76452: Crash while parsing blob data in firebird_fetch_blob We need to prevent integer overflow when calling `erealloc()` with `len+1`. (cherry picked from commit 286162e9b03071c4308e7e92597bca4239f49d89) --- ext/pdo_firebird/firebird_statement.c | 5 +++++ ext/pdo_firebird/tests/bug_76452.data | Bin 0 -> 856 bytes ext/pdo_firebird/tests/bug_76452.phpt | 31 ++++++++++++++++++++++++++ 3 files changed, 36 insertions(+) create mode 100644 ext/pdo_firebird/tests/bug_76452.data create mode 100644 ext/pdo_firebird/tests/bug_76452.phpt diff --git a/ext/pdo_firebird/firebird_statement.c b/ext/pdo_firebird/firebird_statement.c index 8b8f82252a..cb7e4bd83a 100644 --- a/ext/pdo_firebird/firebird_statement.c +++ b/ext/pdo_firebird/firebird_statement.c @@ -267,6 +267,11 @@ static int firebird_fetch_blob(pdo_stmt_t *stmt, int colno, char **ptr, /* {{{ * unsigned short seg_len; ISC_STATUS stat; + /* prevent overflow */ + if (*len == ZEND_ULONG_MAX) { + result = 0; + goto fetch_blob_end; + } *ptr = S->fetch_buf[colno] = erealloc(S->fetch_buf[colno], *len+1); for (cur_len = stat = 0; (!stat || stat == isc_segment) && cur_len < *len; cur_len += seg_len) { From b0fed22401d1237a26ec9ac951ca4c7abf512883 Mon Sep 17 00:00:00 2001 From: "Christoph M. Becker" Date: Fri, 30 Apr 2021 14:10:50 +0200 Subject: [PATCH 3/9] Fix #76450: SIGSEGV in firebird_stmt_execute We need to verify that the `result_size` is not larger than our buffer, and also should make sure that the `len` which is passed to `isc_vax_integer()` has a permissible value; otherwise we bail out. (cherry picked from commit bcbf8aa0c96d8d9e81ec3428232485555fae0b37) --- ext/pdo_firebird/firebird_statement.c | 9 +++++++- ext/pdo_firebird/tests/bug_76450.data | Bin 0 -> 464 bytes ext/pdo_firebird/tests/bug_76450.phpt | 29 ++++++++++++++++++++++++++ 3 files changed, 37 insertions(+), 1 deletion(-) create mode 100644 ext/pdo_firebird/tests/bug_76450.data create mode 100644 ext/pdo_firebird/tests/bug_76450.phpt diff --git a/ext/pdo_firebird/firebird_statement.c b/ext/pdo_firebird/firebird_statement.c index cb7e4bd83a..a87bcc1d40 100644 --- a/ext/pdo_firebird/firebird_statement.c +++ b/ext/pdo_firebird/firebird_statement.c @@ -120,8 +120,14 @@ static int firebird_stmt_execute(pdo_stmt_t *stmt TSRMLS_DC) /* {{{ */ } if (result[0] == isc_info_sql_records) { unsigned i = 3, result_size = isc_vax_integer(&result[1], 2); + if (result_size > sizeof(result)) { + goto error; + } while (result[i] != isc_info_end && i < result_size) { short len = (short) isc_vax_integer(&result[i + 1], 2); + if (len != 1 && len != 2 && len != 4) { + goto error; + } if (result[i] != isc_info_req_select_count) { affected_rows += isc_vax_integer(&result[i + 3], len); } @@ -145,7 +151,8 @@ static int firebird_stmt_execute(pdo_stmt_t *stmt TSRMLS_DC) /* {{{ */ return 1; } while (0); - RECORD_ERROR(stmt); +error: + RECORD_ERROR(stmt); return 0; } From d5572d9dbcc90366e043521b43e7553b75d20662 Mon Sep 17 00:00:00 2001 From: "Christoph M. Becker" Date: Fri, 30 Apr 2021 13:53:21 +0200 Subject: [PATCH 4/9] Fix #76449: SIGSEGV in firebird_handle_doer We need to verify that the `result_size` is not larger than our buffer, and also should make sure that the `len` which is passed to `isc_vax_integer()` has a permissible value; otherwise we bail out. (cherry picked from commit 08da7c73726f7b86b67d6f0ff87c73c585a7834a) --- ext/pdo_firebird/firebird_driver.c | 9 +++++++++ ext/pdo_firebird/tests/bug_76449.data | Bin 0 -> 464 bytes ext/pdo_firebird/tests/bug_76449.phpt | 23 +++++++++++++++++++++++ 3 files changed, 32 insertions(+) create mode 100644 ext/pdo_firebird/tests/bug_76449.data create mode 100644 ext/pdo_firebird/tests/bug_76449.phpt diff --git a/ext/pdo_firebird/firebird_driver.c b/ext/pdo_firebird/firebird_driver.c index a3f34d554f..fef58cb3b4 100644 --- a/ext/pdo_firebird/firebird_driver.c +++ b/ext/pdo_firebird/firebird_driver.c @@ -253,8 +253,17 @@ static long firebird_handle_doer(pdo_dbh_t *dbh, const char *sql, long sql_len T if (result[0] == isc_info_sql_records) { unsigned i = 3, result_size = isc_vax_integer(&result[1],2); + if (result_size > sizeof(result)) { + ret = -1; + goto free_statement; + } while (result[i] != isc_info_end && i < result_size) { short len = (short)isc_vax_integer(&result[i+1],2); + /* bail out on bad len */ + if (len != 1 && len != 2 && len != 4) { + ret = -1; + goto free_statement; + } if (result[i] != isc_info_req_select_count) { ret += isc_vax_integer(&result[i+3],len); } From 2e174eac00ecffc4dd4884e801d15d22f80ffa98 Mon Sep 17 00:00:00 2001 From: "Christoph M. Becker" Date: Thu, 29 Apr 2021 15:26:22 +0200 Subject: [PATCH 5/9] Fix #76448: Stack buffer overflow in firebird_info_cb We ensure not to overflow the stack allocated buffer by using `strlcat`. (cherry picked from commit 67afa32541ebc4abbf633cb1e7e879b2fbb616ad) --- ext/pdo_firebird/firebird_driver.c | 10 ++++++---- ext/pdo_firebird/tests/bug_76448.data | Bin 0 -> 749 bytes ext/pdo_firebird/tests/bug_76448.phpt | 23 +++++++++++++++++++++++ 3 files changed, 29 insertions(+), 4 deletions(-) create mode 100644 ext/pdo_firebird/tests/bug_76448.data create mode 100644 ext/pdo_firebird/tests/bug_76448.phpt diff --git a/ext/pdo_firebird/firebird_driver.c b/ext/pdo_firebird/firebird_driver.c index fef58cb3b4..5f3d3cdb02 100644 --- a/ext/pdo_firebird/firebird_driver.c +++ b/ext/pdo_firebird/firebird_driver.c @@ -540,14 +540,16 @@ static int firebird_handle_set_attribute(pdo_dbh_t *dbh, long attr, zval *val TS } /* }}} */ +#define INFO_BUF_LEN 512 + /* callback to used to report database server info */ static void firebird_info_cb(void *arg, char const *s) /* {{{ */ { if (arg) { if (*(char*)arg) { /* second call */ - strcat(arg, " "); + strlcat(arg, " ", INFO_BUF_LEN); } - strcat(arg, s); + strlcat(arg, s, INFO_BUF_LEN); } } /* }}} */ @@ -558,8 +560,8 @@ static int firebird_handle_get_attribute(pdo_dbh_t *dbh, long attr, zval *val TS pdo_firebird_db_handle *H = (pdo_firebird_db_handle *)dbh->driver_data; switch (attr) { - char tmp[512]; - + char tmp[INFO_BUF_LEN]; + case PDO_ATTR_AUTOCOMMIT: ZVAL_LONG(val,dbh->auto_commit); return 1; From bd5936bc8ce2e3c8497b9083f5530e83f5a19616 Mon Sep 17 00:00:00 2001 From: Dorin Marcoci Date: Sat, 24 Dec 2016 13:57:03 +0200 Subject: [PATCH 7/9] Fixes #65689. PDO_Firebrid / exec() does not free allocated statement. (cherry picked from commit e926bf65076cb5c8da6bf8f32635f696de5ff9aa) --- ext/pdo_firebird/firebird_driver.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/ext/pdo_firebird/firebird_driver.c b/ext/pdo_firebird/firebird_driver.c index 5f3d3cdb02..589312ac3a 100644 --- a/ext/pdo_firebird/firebird_driver.c +++ b/ext/pdo_firebird/firebird_driver.c @@ -240,14 +240,16 @@ static long firebird_handle_doer(pdo_dbh_t *dbh, const char *sql, long sql_len T /* execute the statement */ if (isc_dsql_execute2(H->isc_status, &H->tr, &stmt, PDO_FB_SQLDA_VERSION, &in_sqlda, &out_sqlda)) { RECORD_ERROR(dbh); - return -1; + ret = -1; + goto free_statement; } /* find out how many rows were affected */ if (isc_dsql_sql_info(H->isc_status, &stmt, sizeof(info_count), const_cast(info_count), sizeof(result), result)) { RECORD_ERROR(dbh); - return -1; + ret = -1; + goto free_statement; } if (result[0] == isc_info_sql_records) { @@ -276,6 +278,12 @@ static long firebird_handle_doer(pdo_dbh_t *dbh, const char *sql, long sql_len T RECORD_ERROR(dbh); } +free_statement: + + if (isc_dsql_free_statement(H->isc_status, &stmt, DSQL_drop)) { + RECORD_ERROR(dbh); + } + return ret; } /* }}} */ -- 2.31.1 From 79aadb61954cb38b7b97897482e0a3a08cd90874 Mon Sep 17 00:00:00 2001 From: Anatol Belski Date: Mon, 6 Jun 2016 13:30:17 +0200 Subject: [PATCH 8/9] fix ibase handle initialization, mostly compiler warnings (cherry picked from commit 3e6c02b91a62e3fd640dfa199f8e4178a6680821) --- ext/pdo_firebird/firebird_driver.c | 4 ++-- ext/pdo_firebird/firebird_statement.c | 4 ++-- ext/pdo_firebird/php_pdo_firebird_int.h | 6 ++++++ 3 files changed, 10 insertions(+), 4 deletions(-) diff --git a/ext/pdo_firebird/firebird_driver.c b/ext/pdo_firebird/firebird_driver.c index 589312ac3a..84de8affd6 100644 --- a/ext/pdo_firebird/firebird_driver.c +++ b/ext/pdo_firebird/firebird_driver.c @@ -140,7 +140,7 @@ static int firebird_handle_preparer(pdo_dbh_t *dbh, const char *sql, long sql_le HashTable *np; do { - isc_stmt_handle s = NULL; + isc_stmt_handle s = PDO_FIREBIRD_HANDLE_INITIALIZER; XSQLDA num_sqlda; static char const info[] = { isc_info_sql_stmt_type }; char result[8]; @@ -221,7 +221,7 @@ static int firebird_handle_preparer(pdo_dbh_t *dbh, const char *sql, long sql_le static long firebird_handle_doer(pdo_dbh_t *dbh, const char *sql, long sql_len TSRMLS_DC) /* {{{ */ { pdo_firebird_db_handle *H = (pdo_firebird_db_handle *)dbh->driver_data; - isc_stmt_handle stmt = NULL; + isc_stmt_handle stmt = PDO_FIREBIRD_HANDLE_INITIALIZER; static char const info_count[] = { isc_info_sql_records }; char result[64]; int ret = 0; diff --git a/ext/pdo_firebird/firebird_statement.c b/ext/pdo_firebird/firebird_statement.c index a87bcc1d40..dc64c19687 100644 --- a/ext/pdo_firebird/firebird_statement.c +++ b/ext/pdo_firebird/firebird_statement.c @@ -230,7 +230,7 @@ static int firebird_fetch_blob(pdo_stmt_t *stmt, int colno, char **ptr, /* {{{ * { pdo_firebird_stmt *S = (pdo_firebird_stmt*)stmt->driver_data; pdo_firebird_db_handle *H = S->H; - isc_blob_handle blobh = NULL; + isc_blob_handle blobh = PDO_FIREBIRD_HANDLE_INITIALIZER; char const bl_item = isc_info_blob_total_length; char bl_info[20]; unsigned short i; @@ -424,7 +424,7 @@ static int firebird_bind_blob(pdo_stmt_t *stmt, ISC_QUAD *blob_id, zval *param T { pdo_firebird_stmt *S = (pdo_firebird_stmt*)stmt->driver_data; pdo_firebird_db_handle *H = S->H; - isc_blob_handle h = NULL; + isc_blob_handle h = PDO_FIREBIRD_HANDLE_INITIALIZER; unsigned long put_cnt = 0, rem_cnt; unsigned short chunk_size; int result = 1; diff --git a/ext/pdo_firebird/php_pdo_firebird_int.h b/ext/pdo_firebird/php_pdo_firebird_int.h index 796f3837c8..09cd485121 100644 --- a/ext/pdo_firebird/php_pdo_firebird_int.h +++ b/ext/pdo_firebird/php_pdo_firebird_int.h @@ -61,6 +61,12 @@ typedef void (*info_func_t)(char*); #define min(a,b) ((a)<(b)?(a):(b)) #endif +#if defined(_LP64) || defined(__LP64__) || defined(__arch64__) || defined(_WIN64) +# define PDO_FIREBIRD_HANDLE_INITIALIZER 0U +#else +# define PDO_FIREBIRD_HANDLE_INITIALIZER NULL +#endif + typedef struct { /* the result of the last API call */ -- 2.31.1 From 82b3778dcb7ad665e6fd299e0c811bb94195bf49 Mon Sep 17 00:00:00 2001 From: Remi Collet Date: Mon, 28 Jun 2021 14:31:02 +0200 Subject: [PATCH 9/9] adapt for 5.6 without ZEND_ULONG_MAX --- ext/pdo_firebird/firebird_statement.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext/pdo_firebird/firebird_statement.c b/ext/pdo_firebird/firebird_statement.c index dc64c19687..ea3c704fbb 100644 --- a/ext/pdo_firebird/firebird_statement.c +++ b/ext/pdo_firebird/firebird_statement.c @@ -275,7 +275,7 @@ static int firebird_fetch_blob(pdo_stmt_t *stmt, int colno, char **ptr, /* {{{ * ISC_STATUS stat; /* prevent overflow */ - if (*len == ZEND_ULONG_MAX) { + if (*len == (LONG_MAX * 2UL +1UL)) { result = 0; goto fetch_blob_end; } -- 2.31.1 From 7ce2b28871fcf07a9f3ac0947bb6c4973b28224f Mon Sep 17 00:00:00 2001 From: Stanislav Malyshev Date: Sun, 20 Jun 2021 22:20:38 -0700 Subject: [PATCH 6/9] Update NEWS (cherry picked from commit c68a687566591e2268f35d124a90c7d556ce968b) (cherry picked from commit 7598733c51af30611aa64e456c9a777069d2efb9) --- NEWS | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/NEWS b/NEWS index 659bab855a..03d8a03ec1 100644 --- a/NEWS +++ b/NEWS @@ -1,6 +1,19 @@ PHP NEWS ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| +Backported from 7.3.29 + +- Core: + . Fixed #81122: SSRF bypass in FILTER_VALIDATE_URL. (CVE-2021-21705) (cmb) + +- PDO_Firebird: + . Fixed #76448: Stack buffer overflow in firebird_info_cb. (CVE-2021-21704) + (cmb) + . Fixed #76449: SIGSEGV in firebird_handle_doer. (CVE-2021-21704) (cmb) + . Fixed #76450: SIGSEGV in firebird_stmt_execute. (CVE-2021-21704) (cmb) + . Fixed #76452: Crash while parsing blob data in firebird_fetch_blob. + (CVE-2021-21704) (cmb) + Backported from 7.3.28 - Imap: -- 2.31.1