Skip to content

Commit 54ea5df

Browse files
dougqhdevflow.devflow-routing-intake
andauthored
Fix DB2 JDBC URL parsing failure when :// is only in a property value (quick fix) (#12803)
Fix DB2 JDBC URL parsing failure when :// is only in a property value A DB2/AS400 URL without // after the type (e.g. jdbc:as400:host;keystore=file:///x) whose only :// sits inside a ';' property value made MODIFIED_URL_LIKE take the '://' as the host delimiter while cutting urlPart1 at the earlier ';', so urlPart1.substring(hostIndex + 3) threw StringIndexOutOfBoundsException. Return the builder unchanged in that case, which is the same DBInfo the exception fallback produced, minus the exception. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Keep DB2/AS400 URL properties when :// is only in a property value The early return skipped splitQuery/populateStandardProperties, so properties such as user or schema were lost. The old parser applied them before throwing and parse() returned that builder from its catch block, so populate them before returning. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Merge branch 'master' into dougqh/jdbc-url-parser-db2 Merge branch 'master' into dougqh/jdbc-url-parser-db2 Merge branch 'master' into dougqh/jdbc-url-parser-db2 Co-authored-by: devflow.devflow-routing-intake <devflow.devflow-routing-intake@kubernetes.us1.ddbuild.io>
1 parent 329dd7c commit 54ea5df

2 files changed

Lines changed: 46 additions & 0 deletions

File tree

‎dd-java-agent/agent-bootstrap/src/main/java/datadog/trace/bootstrap/instrumentation/jdbc/JDBCConnectionUrlParser.java‎

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,12 @@ DBInfo.Builder doParse(final String jdbcUrl, final DBInfo.Builder builder) {
116116
}
117117
} else {
118118
paramLoc = jdbcUrl.indexOf(';');
119+
if (paramLoc >= 0 && paramLoc < hostIndex) {
120+
// the "://" is inside a property value (e.g. db2:mydb;x=file://...), so there is no host
121+
// part to parse, but the properties (user, schema, ...) still apply
122+
populateStandardProperties(builder, splitQuery(jdbcUrl.substring(paramLoc + 1), ';'));
123+
return builder;
124+
}
119125
urlPart1 = paramLoc >= 0 ? jdbcUrl.substring(0, paramLoc) : jdbcUrl;
120126
urlPart2 = paramLoc >= 0 ? jdbcUrl.substring(paramLoc + 1) : null;
121127
}

‎dd-java-agent/agent-bootstrap/src/test/java/datadog/trace/bootstrap/instrumentation/jdbc/JDBCConnectionUrlParserDB2Test.java‎

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
package datadog.trace.bootstrap.instrumentation.jdbc;
22

3+
import static datadog.trace.bootstrap.instrumentation.jdbc.JDBCConnectionUrlParser.DB2;
34
import static datadog.trace.bootstrap.instrumentation.jdbc.JDBCConnectionUrlParser.extractDBInfo;
45
import static org.junit.jupiter.api.Assertions.assertEquals;
6+
import static org.junit.jupiter.api.Assertions.assertNull;
57

68
import org.tabletest.junit.TableTest;
79

@@ -32,4 +34,42 @@ void db2UrlWithEqualsAndNoPortShouldParseCorrectly(
3234
assertEquals(user, info.getUser());
3335
assertEquals(db, info.getDb());
3436
}
37+
38+
/**
39+
* A URL without "//" after the type, whose only "://" is inside a ';' property value, used to
40+
* throw a {@code StringIndexOutOfBoundsException}. Calls {@code DB2.doParse} directly since
41+
* {@code extractDBInfo} swallows parse exceptions.
42+
*/
43+
@TableTest({
44+
"scenario | url | type ",
45+
"DB2 with URL in property value | db2:mydb;x=http://y | db2 ",
46+
"AS400 with file URL in property | as400:host;ssltruststore=file://x | as400",
47+
"AS400 with several properties | as400:host;libraries=a;secure=true;keystore=file:///x | as400",
48+
"Empty type suffix with property | db2:;a=b://h | db2 "
49+
})
50+
void schemeSeparatorOnlyInPropertyValueShouldNotThrow(String url, String type) {
51+
DBInfo info = DB2.doParse(url, DBInfo.DEFAULT.toBuilder().type(type)).build();
52+
assertEquals(type, info.getType());
53+
assertNull(info.getHost());
54+
assertEquals(50000, info.getPort());
55+
assertNull(info.getInstance());
56+
}
57+
58+
/**
59+
* The same URLs keep their recognized properties. The old parser applied them before throwing,
60+
* and {@code parse} returned that builder from its catch block, so they were recorded then too.
61+
*/
62+
@TableTest({
63+
"scenario | url | type | user | schema",
64+
"AS400 user before file URL | as400:host;user=alice;ssltruststore=file://x | as400 | alice | ",
65+
"DB2 schema before http URL | db2:mydb;schema=s1;x=http://y | db2 | | s1 ",
66+
"AS400 user after file URL | as400:host;keystore=file:///k;user=bob | as400 | bob | "
67+
})
68+
void schemeSeparatorOnlyInPropertyValueKeepsProperties(
69+
String url, String type, String user, String schema) {
70+
DBInfo info = DB2.doParse(url, DBInfo.DEFAULT.toBuilder().type(type)).build();
71+
assertEquals(type, info.getType());
72+
assertEquals(user, info.getUser());
73+
assertEquals(schema, info.getSchema());
74+
}
3575
}

0 commit comments

Comments
 (0)