Skip to content

Address CodeQL findings: fix real overflows, harden test file modes - #5

Merged
lemenkov merged 3 commits into
masterfrom
codeql_reports_addressing
Jul 24, 2026
Merged

Address CodeQL findings: fix real overflows, harden test file modes#5
lemenkov merged 3 commits into
masterfrom
codeql_reports_addressing

Conversation

@lemenkov

Copy link
Copy Markdown
Owner

Works through the open CodeQL code-scanning alerts. Each commit groups similar findings and was validated locally (unit suite + live integration under AddressSanitizer). The full 5-server matrix (10g/11g/21c/23ai/9i) is green under ASan on the branch tip, unchanged from baseline.

Commits — the genuinely actionable findings

  1. odbc: guard snprintf accumulation against buffer overflowcpp/overflowing-snprintf at exec.c:779 and catalog.c:212. The o += snprintf(buf+o, sizeof buf - o, ...) idiom overflows once the text exceeds the buffer (o passes sizeof, sizeof buf - o underflows to a huge size_t, next write is out of bounds). In exec.c the text is schema-derived (wide updatable table) so this is a real latent overflow; catalog.c is bounded by a static type table but shares the idiom. Every append is now guarded.

  2. common: guard iconv buffer-size arithmetic against size_t overflowcpp/uncontrolled-allocation-size at charset.c:26 and :44. in_len*2+16 and cap*2 could wrap size_t into an undersized buffer that the iconv loop then overflows. Rejects only unrepresentable sizes, so no real conversion is affected.

  3. test: create browse-DSN config files mode 0600cpp/world-writable-file-creation at test_integration.c:1304/1306. Test-only config files were created with the umask-default mode; now 0600 via an open(…,0600)+fdopen helper.

Not fixed here — triaged as non-bugs (dismissed with justification)

After reading each site, the remaining alerts are false positives, protocol requirements, or harmless style:

  • use-after-free (critical, stmt.c:1194-5) — the pointer is reassigned by malloc between the free and the use. False positive.
  • stack-address-escape ×26 (attrs/results/exec) — the ODBC contract: the application owns the lifetime of pointers it hands the driver via SQLSetStmtAttr/SQLBindCol. False positive.
  • uncontrolled-allocation ×7 (stmt/marshal/lob/writer) — sizes are bounded by seer_reader_bytes against bytes actually received, or by uint8/uint16 length fields; writer.c is a growable-buffer size hint. False positive (no fabricated caps that would break large LONG/LOB values).
  • weak-crypto DES (auth.c:86) — Oracle's O5LOGON mandates DES for pre-11g authentication. Won't fix.
  • system-data-exposure ×2 (transport.c) — error text goes to the internal log, not the SQL client. False positive.
  • constant-comparison ×5 / loop-variable-changed ×8 / complex-condition ×1 — dead defensive bounds, the standard argv[++i] idiom, and a commented boolean. Not bugs.

🤖 Generated with Claude Code

lemenkov and others added 3 commits July 24, 2026 23:40
Both seer_odbc_pos_update (exec.c) and SQLGetTypeInfo (catalog.c) build
a SQL statement with the "o += snprintf(buf + o, sizeof buf - o, ...)"
idiom. snprintf returns the length it WOULD have written, so once the
text exceeds the fixed buffer, o passes sizeof buf, "sizeof buf - o"
underflows to a huge size_t, and the next write runs out of bounds.

In exec.c the appended text is schema-derived (base table + bound column
names + count), so a wide updatable table can genuinely exceed the 4096
buffer and trip the overflow. In catalog.c the input is the static
TYPEINFO table (bounded, not attacker-influenced), so it is safe today,
but the idiom is identical and worth hardening.

Guard every append: check snprintf's return against the remaining space
before advancing, and fail with a diagnostic if the statement does not
fit, so the offset can never pass the buffer end.

Addresses CodeQL cpp/overflowing-snprintf (exec.c:779, catalog.c:212).

Verified: unit suite green; live integration under ASan on 11g passes
the FOR UPDATE / positioned-update path (40/0/11), no sanitizer report.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
seer_iconv computed its output buffer as `in_len * 2 + 16` and grew it
with `cap * 2`, both of which wrap size_t for pathological in_len/cap.
A wrapped, undersized allocation would then be overflowed by the iconv
loop writing into it.

Reject sizes whose computation cannot be represented in size_t before
allocating (initial cap and the realloc doubling). These guards reject
only unrepresentable sizes - never a real in-memory string length - so
no legitimate conversion is affected.

Addresses CodeQL cpp/uncontrolled-allocation-size at charset.c:26 and
charset.c:44. The other alerts in that rule (dalc-derived mallocs in
stmt.c / marshal.c / lob.c) are bounded by seer_reader_bytes against the
bytes actually received (and by uint8_t/uint16_t length fields), so they
are false positives handled separately, not with fabricated caps.

Verified: unit suite green; live integration under ASan on 11g clean
(40/0/11), exercising the national-charset / Unicode conversion paths.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
setup_browse_dsn wrote the temporary odbcinst.ini / odbc.ini via
fopen(path, "w"), which creates them with the umask-default mode (0666,
i.e. world-readable/0644 under a typical umask). They live inside a 0700
mkdtemp dir so this was never exploitable, but a config file has no
business being world-accessible.

Add a small fopen_private() helper (open O_CREAT with mode 0600, then
fdopen) and use it for both files. Verified the created files are 0600.

Addresses CodeQL cpp/world-writable-file-creation (test_integration.c
:1304, :1306). Test-only code, not shipped in the driver.

Verified: SQLBrowseConnect check passes under ASan on 11g (40/0/11).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@lemenkov
lemenkov merged commit 635f0ea into master Jul 24, 2026
8 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant