Fix SIGSEGV in SQLCopyDesc when source descriptor is empty#297
Open
fdcastel wants to merge 1 commit intoFirebirdSQL:masterfrom
Open
Fix SIGSEGV in SQLCopyDesc when source descriptor is empty#297fdcastel wants to merge 1 commit intoFirebirdSQL:masterfrom
fdcastel wants to merge 1 commit intoFirebirdSQL:masterfrom
Conversation
OdbcDesc::operator= dereferenced sour.records[n] inside the copy loop without first checking that sour.records was non-NULL. Every other loop in OdbcDesc.cpp guards `if (records)`; this one did not. Reproducer: allocate two statements, fetch their implicit ARDs (no SQLBindCol calls), call SQLCopyDesc on them. Both descriptors have records == NULL and headCount == 0, the loop runs once with n=0, and sour.records[0] crashes with access violation. The Phase 7 regression tests for this bug already shipped (skipped), documenting the exact failure mode at lines 33-34. Un-skip the three tests this fix enables: CopyEmptyARDDoesNotCrash, CopyEmptyToExplicitDescriptor, CopyPopulatedThenEmpty. The four SetDescCount* tests in the same file remain skipped — they exercise a separate Phase 7 fix (SQLSetDescField(SQL_DESC_COUNT) must allocate records) that is not part of this PR. Reported by odbc-crusher v3.5.0-rc1 stress test.
Member
Author
|
@irodushka Similar to #296 — backported from the v4 plan. This isn’t urgent, but it would be great if it could also make it into -rc2. It would enable us to run odbc-crusher on the Firebird ODBC driver. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
SQLCopyDesccrashed with SIGSEGV (Linux) / access violation 0xC0000005 (Windows) when the source descriptor had no records — the typical case when the application has fetched an implicit ARD without binding any columns, or freshly allocated an explicit descriptor.Reproducer:
Caught by odbc-crusher
v3.5.0-rc1stress-test (test_copy_descin the Descriptor Tests category — the run hung on a corrupted DM after the SEGV, holding the runner for 47 minutes before being cancelled).Root cause
OdbcDesc::operator=(the functionSQLCopyDesccalls into) iteratedsour.records[n]without first checking thatsour.recordswas non-NULL:sour.recordsisNULLfor any descriptor that has never had records allocated — implicit ARDs/APDs of statements with noSQLBindCol/SQLBindParametercalls, or freshly-allocated explicit descriptors. For an empty sourceheadCount == 0, the loop runs once withn = 0, dereferencesNULL[0], crash.Every other loop in
OdbcDesc.cppalready guardsif (records)(lines 104, 119, 148, 162, 181). This one was missing the guard — fixed by inlining the same check on the access.Tests
The Phase 7 regression suite (
tests/test_phase7_crusher_fixes.cpp) already shipped tests for this exact crash — its inline comment at lines 33-34 documents the failure mode word-for-word. The tests wereGTEST_SKIP'd pending the fix.This PR un-skips the three tests that the null-guard alone enables:
CopyDescCrashTest.CopyEmptyARDDoesNotCrashCopyDescCrashTest.CopyEmptyToExplicitDescriptorCopyDescCrashTest.CopyPopulatedThenEmptyThe four
SetDescCount*tests in the same file remain skipped — they exercise a separate Phase 7 issue (SQLSetDescField(SQL_DESC_COUNT)not allocating the records array) that needs a different fix and is out of scope here.Verification
Test plan
SKIP'd regression tests now run and pass across the full CI matrix