Skip to content

Fix GH-22668: odbc heap over-read on oversized column value#22670

Open
iliaal wants to merge 1 commit into
php:PHP-8.4from
iliaal:fix/gh-22668-odbc-vallen-clamp
Open

Fix GH-22668: odbc heap over-read on oversized column value#22670
iliaal wants to merge 1 commit into
php:PHP-8.4from
iliaal:fix/gh-22668-odbc-vallen-clamp

Conversation

@iliaal

@iliaal iliaal commented Jul 10, 2026

Copy link
Copy Markdown
Contributor

ext/odbc builds the result string from the driver-reported vallen, which on truncation exceeds the bound displaysize+1 buffer (SQL_SUCCESS_WITH_INFO), over-reading heap into the returned value. Clamps the length to the bound capacity at the three fetch sites. Reproduces with the SQLite3 ODBC driver; the test skips without it.

Fixes #22668

Comment thread ext/odbc/tests/gh22668.phpt Outdated
--SKIPIF--
<?php
$file = tempnam(sys_get_temp_dir(), "gh22668");
$conn = @odbc_connect("Driver=SQLite3;Database=$file", null, null);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Again, see if we can use SQL Server, if possible to reproduce it if not, :memory: and we'll have to figure out adding it to CI

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Checked ext/odbc against the 2022 container directly, same as #22672: it doesn't reproduce. SQL Server reports a field length >= the value (VARCHAR(50) -> 50), or 0/INT_MAX for LOB types which take the long-column path, never a short display size against an over-long value. Switched the test to :memory:. If you'd rather it run than skip, I'll add the SQLite ODBC driver to CI, which covers #22672 as well.

ext/odbc bound a displaysize+1 buffer per column but built the result
string from the driver-reported vallen. A conforming driver truncates an
over-long value into the buffer yet reports the full length, so the fetch
over-read past the allocation and returned adjacent heap bytes to userland.
Store the bound capacity in odbc_result_value and clamp the string length to
it at the three bound-buffer fetch sites (odbc_fetch_array/object,
odbc_fetch_into, odbc_result); the SQLGetData long-column paths stay bounded
by longreadlen.

Fixes phpGH-22668
@iliaal iliaal force-pushed the fix/gh-22668-odbc-vallen-clamp branch from c542fb9 to 7e3c4e5 Compare July 10, 2026 17:27
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

2 participants