Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -81,13 +81,26 @@ DBInfo.Builder doParse(final String jdbcUrl, final DBInfo.Builder builder) {
final String urlPart1;
final String urlPart2;
final int paramLoc;
char paramSeparator = ';';

if (type.equals("db2") || type.equals("as400")) {
if (jdbcUrl.contains("=")) {
paramLoc = jdbcUrl.lastIndexOf(':');
urlPart1 = jdbcUrl.substring(0, paramLoc);
urlPart2 = jdbcUrl.substring(paramLoc + 1);

if (paramLoc > hostIndex + 2) {
urlPart1 = jdbcUrl.substring(0, paramLoc);
urlPart2 = jdbcUrl.substring(paramLoc + 1);
} else {
// No ':' past '://': fall back to '?' query-string params
final int queryLoc = jdbcUrl.indexOf('?');
if (queryLoc >= 0) {
urlPart1 = jdbcUrl.substring(0, queryLoc);
urlPart2 = jdbcUrl.substring(queryLoc + 1);
paramSeparator = '&';
} else {
urlPart1 = jdbcUrl;
urlPart2 = null;
}
}
} else {
urlPart1 = jdbcUrl;
urlPart2 = null;
Expand All @@ -99,7 +112,7 @@ DBInfo.Builder doParse(final String jdbcUrl, final DBInfo.Builder builder) {
}

if (urlPart2 != null) {
final Map<String, String> props = splitQuery(urlPart2, ';');
final Map<String, String> props = splitQuery(urlPart2, paramSeparator);
populateStandardProperties(builder, props);
if (props.containsKey("servername")) {
serverName = props.get("servername");
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package datadog.trace.bootstrap.instrumentation.jdbc;

import static datadog.trace.bootstrap.instrumentation.jdbc.JDBCConnectionUrlParser.extractDBInfo;
import static org.junit.jupiter.api.Assertions.assertEquals;

import org.tabletest.junit.TableTest;

/**
* Tests for DB2/AS400 JDBC URL parsing when the URL contains '=' but no explicit port.
*
* <p>Without a port, {@code lastIndexOf(':')} returns the scheme colon, making {@code urlPart1} too
* short for the subsequent {@code substring()} call and causing a {@code
* StringIndexOutOfBoundsException}.
*/
class JDBCConnectionUrlParserDB2Test {

@TableTest({
"scenario | url | type | host | instance | user | db ",
"DB2 with user param, no port | jdbc:db2://db2.host/mydb?user=db2user | db2 | db2.host | mydb | db2user | mydb ",
"AS400 with user param, no port | jdbc:as400://ashost/asdb?user=asuser | as400 | ashost | asdb | asuser | asdb ",
"DB2 with multiple params, no port | jdbc:db2://db2.host/mydb?user=db2user&connectionTimeout=30 | db2 | db2.host | mydb | db2user | mydb ",
"DB2 with databasename param, no port | jdbc:db2://db2.host/mydb?user=db2user&databasename=otherdb | db2 | db2.host | mydb | db2user | otherdb",
"DB2 with port and colon params | jdbc:db2://db2.host:50000/mydb:user=db2user | db2 | db2.host | mydb | db2user | mydb ",
"DB2 no params | jdbc:db2://db2.host/mydb | db2 | db2.host | mydb | | mydb "
})
void db2UrlWithEqualsAndNoPortShouldParseCorrectly(
String url, String type, String host, String instance, String user, String db) {
DBInfo info = extractDBInfo(url, null);
assertEquals(type, info.getType());
assertEquals(host, info.getHost());
assertEquals(instance, info.getInstance());
assertEquals(user, info.getUser());
assertEquals(db, info.getDb());
}
}