summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristoph M. Becker <cmbecker69@gmx.de>2020-02-17 22:53:50 +0100
committerChristoph M. Becker <cmbecker69@gmx.de>2020-02-17 22:54:16 +0100
commit3090c88f55f53d0a8af4e9dbec2664a24c1fa702 (patch)
tree1f9bf4fec55e7ecce081437b15cf6e0fc64fc7ac
parent8db8d66df0e4b7cf202120273ab9c5d01a3f0d1c (diff)
parent08073b06581c6dc9234cfb2e9b187a598154c8ab (diff)
downloadphp-git-3090c88f55f53d0a8af4e9dbec2664a24c1fa702.tar.gz
Merge branch 'PHP-7.3' into PHP-7.4
* PHP-7.3: Fix #79038: PDOStatement::nextRowset() leaks column values
-rw-r--r--NEWS3
-rw-r--r--ext/pdo_odbc/odbc_stmt.c24
-rw-r--r--ext/pdo_odbc/php_pdo_odbc_int.h3
3 files changed, 24 insertions, 6 deletions
diff --git a/NEWS b/NEWS
index b56bb2134f..abd7cf0c68 100644
--- a/NEWS
+++ b/NEWS
@@ -29,6 +29,9 @@ PHP NEWS
. Fixed bug #79257 (Duplicate named groups (?J) prefer last alternative even
if not matched). (Nikita)
+- PDO_ODBC:
+ . Fixed bug #79038 (PDOStatement::nextRowset() leaks column values). (cmb)
+
- Standard:
. Fixed bug #79254 (getenv() w/o arguments not showing changes). (cmb)
diff --git a/ext/pdo_odbc/odbc_stmt.c b/ext/pdo_odbc/odbc_stmt.c
index e67acbc6e8..18abc475b9 100644
--- a/ext/pdo_odbc/odbc_stmt.c
+++ b/ext/pdo_odbc/odbc_stmt.c
@@ -126,13 +126,14 @@ static void free_cols(pdo_stmt_t *stmt, pdo_odbc_stmt *S)
if (S->cols) {
int i;
- for (i = 0; i < stmt->column_count; i++) {
+ for (i = 0; i < S->col_count; i++) {
if (S->cols[i].data) {
efree(S->cols[i].data);
}
}
efree(S->cols);
S->cols = NULL;
+ S->col_count = 0;
}
}
@@ -262,14 +263,14 @@ static int odbc_stmt_execute(pdo_stmt_t *stmt)
SQLRowCount(S->stmt, &row_count);
stmt->row_count = row_count;
- if (!stmt->executed) {
+ if (S->cols == NULL) {
/* do first-time-only definition of bind/mapping stuff */
SQLSMALLINT colcount;
/* how many columns do we have ? */
SQLNumResultCols(S->stmt, &colcount);
- stmt->column_count = (int)colcount;
+ stmt->column_count = S->col_count = (int)colcount;
S->cols = ecalloc(colcount, sizeof(pdo_odbc_column));
S->going_long = 0;
}
@@ -847,13 +848,25 @@ static int odbc_stmt_next_rowset(pdo_stmt_t *stmt)
free_cols(stmt, S);
/* how many columns do we have ? */
SQLNumResultCols(S->stmt, &colcount);
- stmt->column_count = (int)colcount;
+ stmt->column_count = S->col_count = (int)colcount;
S->cols = ecalloc(colcount, sizeof(pdo_odbc_column));
S->going_long = 0;
return 1;
}
+static int odbc_stmt_close_cursor(pdo_stmt_t *stmt)
+{
+ SQLRETURN rc;
+ pdo_odbc_stmt *S = (pdo_odbc_stmt*)stmt->driver_data;
+
+ rc = SQLCloseCursor(S->stmt);
+ if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO) {
+ return 0;
+ }
+ return 1;
+}
+
const struct pdo_stmt_methods odbc_stmt_methods = {
odbc_stmt_dtor,
odbc_stmt_execute,
@@ -864,5 +877,6 @@ const struct pdo_stmt_methods odbc_stmt_methods = {
odbc_stmt_set_param,
odbc_stmt_get_attr, /* get attr */
NULL, /* get column meta */
- odbc_stmt_next_rowset
+ odbc_stmt_next_rowset,
+ odbc_stmt_close_cursor
};
diff --git a/ext/pdo_odbc/php_pdo_odbc_int.h b/ext/pdo_odbc/php_pdo_odbc_int.h
index e6098f4951..922b89a686 100644
--- a/ext/pdo_odbc/php_pdo_odbc_int.h
+++ b/ext/pdo_odbc/php_pdo_odbc_int.h
@@ -151,7 +151,8 @@ typedef struct {
zend_ulong convbufsize;
unsigned going_long:1;
unsigned assume_utf8:1;
- unsigned _spare:30;
+ signed col_count:16;
+ unsigned _spare:14;
} pdo_odbc_stmt;
typedef struct {