diff --git a/ext/pdo_odbc/odbc_stmt.c b/ext/pdo_odbc/odbc_stmt.c index 33da34114664..efeda2e96cae 100644 --- a/ext/pdo_odbc/odbc_stmt.c +++ b/ext/pdo_odbc/odbc_stmt.c @@ -763,10 +763,14 @@ static int odbc_stmt_get_col(pdo_stmt_t *stmt, int colno, zval *result, enum pdo * changed from 256 byte to LONG_COLUMN_BUFFER_SIZE. */ ssize_t to_fetch_len; - if (orig_fetched_len == SQL_NO_TOTAL) { - to_fetch_len = C->datalen > (LONG_COLUMN_BUFFER_SIZE - 1) ? (LONG_COLUMN_BUFFER_SIZE - 1) : C->datalen; - } else { + if (orig_fetched_len == SQL_NO_TOTAL && C->datalen > (LONG_COLUMN_BUFFER_SIZE - 1)) { + to_fetch_len = C->datalen; + } else if (orig_fetched_len > 0) { + /* implicitly not SQL_NO_TOTAL, should be OK */ to_fetch_len = orig_fetched_len; + } else { + /* size must be > 0 to actually get data */ + to_fetch_len = (LONG_COLUMN_BUFFER_SIZE - 1); } ssize_t to_fetch_byte = to_fetch_len + 1; char *buf2 = emalloc(to_fetch_byte); diff --git a/ext/pdo_odbc/tests/gh23443.phpt b/ext/pdo_odbc/tests/gh23443.phpt new file mode 100644 index 000000000000..00505868760d --- /dev/null +++ b/ext/pdo_odbc/tests/gh23443.phpt @@ -0,0 +1,24 @@ +--TEST-- +GH-23443 (infinite loop / 100% CPU when fetching a large nvarchar(max)) +--EXTENSIONS-- +pdo_odbc +--SKIPIF-- + +--FILE-- +query("SELECT REPLICATE(CAST(N'A' AS nvarchar(max)), $n) AS v")->fetch(PDO::FETCH_ASSOC); +echo "ok\n"; +?> +--EXPECT-- +ok