Skip to content

Commit c31f989

Browse files
dougqhdevflow.devflow-routing-intake
andauthored
Guard Undertow port() against internal NPE (quick fix) (DataDog#12373)
Guard Undertow port() against internal NPE HttpServerExchange.getHostPort() can NPE inside Undertow itself when there's no Host header, the scheme isn't http/https, and the connection's local address isn't an InetSocketAddress (e.g. AJP or a Unix domain socket transport). Fall back to 0 (the existing "no port" sentinel used throughout URIUtils) rather than letting the NPE propagate into the instrumented application. Co-Authored-By: Claude Sonnet 5 <[email protected]> Guard UndertowDecorator.peerPort() against the same null destination-address NPE The port() fix in HttpServerExchangeURIDataAdapter only covers the Host-port lookup; HttpServerDecorator.onRequest() also calls peerPort(), which reads exchange.getDestinationAddress().getPort() directly outside any try/catch, so the same null-destination-address condition (AJP, Unix domain socket transport, wrapped/detached ServerConnection) still NPEs one call site later. Co-Authored-By: Claude Sonnet 5 <[email protected]> Merge branch 'master' into dougqh/fix-undertow-port-npe Merge branch 'master' into dougqh/fix-undertow-port-npe Suppress SpotBugs DCN_NULLPOINTER_EXCEPTION for Undertow port() NPE guard Undertow's getHostPort() NPEs internally in some transports (AJP, unix domain sockets) rather than on a null we could check beforehand, so the catch is intentional and can't be replaced with a null-check. Co-Authored-By: Claude Sonnet 5 <[email protected]> Guard HttpServerExchangeURIDataAdapter.host() against the same NPE as port() Undertow's getHostName() falls back to getDestinationAddress().getHostString() when there's no Host header, which NPEs the same way getHostPort() does when the destination address is null (AJP, Unix domain socket, or wrapped connections). Found by jordan-wong via a live error-tracking hit on this exact file/line. Co-Authored-By: Claude Sonnet 5 <[email protected]> Merge branch 'master' into dougqh/fix-undertow-port-npe Co-authored-by: devflow.devflow-routing-intake <[email protected]>
1 parent a41bd4c commit c31f989

2 files changed

Lines changed: 29 additions & 3 deletions

File tree

‎dd-java-agent/instrumentation/undertow/undertow-common/src/main/java/datadog/trace/instrumentation/undertow/HttpServerExchangeURIDataAdapter.java‎

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package datadog.trace.instrumentation.undertow;
22

33
import datadog.trace.bootstrap.instrumentation.api.URIRawDataAdapter;
4+
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
45
import io.undertow.server.HttpServerExchange;
56

67
final class HttpServerExchangeURIDataAdapter extends URIRawDataAdapter {
@@ -16,13 +17,33 @@ public String scheme() {
1617
}
1718

1819
@Override
20+
@SuppressFBWarnings(
21+
value = "DCN_NULLPOINTER_EXCEPTION",
22+
justification =
23+
"getHostName() NPEs inside Undertow itself, not on a null we could check beforehand"
24+
+ " (e.g. no Host header and a connection whose local address isn't an"
25+
+ " InetSocketAddress, such as AJP or a Unix domain socket transport)")
1926
public String host() {
20-
return httpServerExchange.getHostName();
27+
try {
28+
return httpServerExchange.getHostName();
29+
} catch (final NullPointerException e) {
30+
return null;
31+
}
2132
}
2233

2334
@Override
35+
@SuppressFBWarnings(
36+
value = "DCN_NULLPOINTER_EXCEPTION",
37+
justification =
38+
"getHostPort() NPEs inside Undertow itself, not on a null we could check beforehand"
39+
+ " (e.g. no Host header and a connection whose local address isn't an"
40+
+ " InetSocketAddress, such as AJP or a Unix domain socket transport)")
2441
public int port() {
25-
return httpServerExchange.getHostPort();
42+
try {
43+
return httpServerExchange.getHostPort();
44+
} catch (final NullPointerException e) {
45+
return 0;
46+
}
2647
}
2748

2849
@Override

‎dd-java-agent/instrumentation/undertow/undertow-common/src/main/java/datadog/trace/instrumentation/undertow/UndertowDecorator.java‎

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
import datadog.trace.bootstrap.instrumentation.decorator.HttpServerDecorator;
1313
import io.undertow.server.HttpServerExchange;
1414
import io.undertow.util.AttachmentKey;
15+
import java.net.InetSocketAddress;
1516

1617
public class UndertowDecorator
1718
extends HttpServerDecorator<
@@ -84,7 +85,11 @@ protected String peerHostIP(final HttpServerExchange exchange) {
8485

8586
@Override
8687
protected int peerPort(final HttpServerExchange exchange) {
87-
return exchange.getDestinationAddress().getPort();
88+
// getDestinationAddress() can be null in the same situations that make
89+
// HttpServerExchangeURIDataAdapter#port() NPE internally (e.g. AJP, a Unix domain socket
90+
// transport, or a wrapped/detached ServerConnection).
91+
InetSocketAddress destination = exchange.getDestinationAddress();
92+
return destination == null ? UNSET_PORT : destination.getPort();
8893
}
8994

9095
@Override

0 commit comments

Comments
 (0)