Skip to content

Harden JDBC connection-string config parsing against null/wrong-type values - #3210

Open
terryozaki-wq wants to merge 1 commit into
devfrom
jdbc-config-parsing-hardening
Open

terryozaki-wq wants to merge 1 commit into
devfrom
jdbc-config-parsing-hardening

Conversation

@terryozaki-wq

Copy link
Copy Markdown

Summary

setConnectionDetailsfromMap/setConnectionDetailsFromSMSS across every QueryUtil cast Map<String,Object>/CaseInsensitiveProperties values straight to String (or coerced booleans via value + ""), so a missing key silently became null and surfaced far downstream, and a wrong-typed value threw a confusing ClassCastException instead of naming the bad key.

  • Adds getOptionalStringValue/getOptionalBooleanValue/requireNonBlank to AbstractSqlQueryUtil: optional keys get an explicit default instead of implicit string-concatenation coercion, and failures — missing, wrong-typed, or resolved-but-blank — name the offending key via IllegalArgumentException (bad input) or IllegalStateException (invalid accumulated state). These are instance methods, not static, deliberately — PGVectorDatabaseEngineUnitTests mockStatics AbstractSqlQueryUtil to stub makeConnection(), and an unstubbed static call on a Mockito static mock silently returns null/false, which would reintroduce the exact bug this fixes.
  • Applied in full (required-vs-optional judgment per key) to H2QueryUtil and the AnsiSqlQueryUtil default shared by MySQLQueryUtil/MariaDbQueryUtil/DB2QueryUtil/DerbyQueryUtil/AsterQueryUtil/CassandraQueryUtil/PhoenixQueryUtil.
  • Applied as a type-safety-only swap (existing required-key checks and messages left untouched) to the 17 other QueryUtil classes with their own override, since each has its own bespoke, already-correct required/optional logic that deserves individual review before consolidating.

Notes on the merge

20 of 23 touched files merged cleanly against dev's own independent changes to the same files. The 3 new/modified test files needed manual resolution:

  • AbstractSqlQueryUtilUnitTests.java / AnsiSqlQueryUtilUnitTests.java: both sides had added different, non-overlapping test methods — merged to keep both.
  • H2QueryUtilUnitTests.java: didn't exist on dev. Added fresh, containing only this fix's own 7 new test methods — not the H2-2.x-migration-specific tests an unrelated predecessor commit had added to it on a downstream fork, which assume H2 2.x behavior dev doesn't have yet (dev is still on H2 1.4.200).

This PR and #2332 (the H2 1.x→2.x bump) both touch H2QueryUtil.java and AbstractSqlQueryUtil.java. No functional overlap — different methods — but whichever merges second will need a routine rebase.

Test plan

  • Full mvn test-compile — BUILD SUCCESS.
  • H2QueryUtilUnitTests, AbstractSqlQueryUtilUnitTests, AnsiSqlQueryUtilUnitTests — 25/25 passing.
  • PGVectorDatabaseEngineUnitTests (explicitly called out in the original fix as sensitive to this change, since it mockStatics AbstractSqlQueryUtil) — confirmed its 19 pre-existing failures are unchanged with or without this fix (identical failure count/names/lines on a clean, unmodified dev checkout), so this fix doesn't regress it.

🤖 Generated with Claude Code

…rong-type values

setConnectionDetailsfromMap/setConnectionDetailsFromSMSS across every
QueryUtil cast Map<String,Object>/CaseInsensitiveProperties values
straight to String (or coerced booleans via `value + ""`), so a missing
key silently became null and surfaced far downstream, and a
wrong-typed value threw a confusing ClassCastException instead of
naming the bad key.

Add getOptionalStringValue/getOptionalBooleanValue/requireNonBlank to
AbstractSqlQueryUtil: optional keys get an explicit default instead of
implicit string-concatenation coercion, and failures - missing,
wrong-typed, or resolved-but-blank - name the offending key via
IllegalArgumentException (bad input) or IllegalStateException
(invalid accumulated state). These are instance methods, not static -
PGVectorDatabaseEngineUnitTests mockStatics AbstractSqlQueryUtil to
stub makeConnection(), and unstubbed static calls on a Mockito static
mock silently return null/false, which would reintroduce the exact
bug this fixes.

Applied in full (required-vs-optional judgment per key, now using
requireNonBlank) to H2QueryUtil and the AnsiSqlQueryUtil default shared
by MySQLQueryUtil/MariaDbQueryUtil/DB2QueryUtil/DerbyQueryUtil/
AsterQueryUtil/CassandraQueryUtil/PhoenixQueryUtil. Applied as a
type-safety-only swap (existing required-key checks and messages left
untouched) to the 17 other QueryUtil classes with their own override,
since each has its own bespoke, already-correct required/optional
logic that deserves individual review before consolidating.

Added missing-key/wrong-type unit tests to a new H2QueryUtilUnitTests
(dev had no existing file by this name - this fix's own additions,
without the unrelated H2-2.x-migration-specific tests an IL4-only
predecessor commit had added to its own copy of this file, which don't
apply since dev is still on H2 1.4.200), AbstractSqlQueryUtilUnitTests,
and AnsiSqlQueryUtilUnitTests (via DerbyQueryUtil, proving the shared
default works for its inheritors) - merged alongside dev's own
independent additions to both of those files.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@terryozaki-wq
terryozaki-wq requested a review from a team as a code owner October 26, 2026 16:58
@snyk-io

snyk-io Bot commented Oct 26, 2026

Copy link
Copy Markdown
Contributor

✅ Snyk checks have passed. No issues have been found so far.

Status Scan Engine Critical High Medium Low Total (0)
✅ Open Source Security 0 0 0 0 0 issues

💻 Catch issues earlier using the plugins for VS Code, JetBrains IDEs, Visual Studio, and Eclipse.

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