Skip to content

Commit d92ff94

Browse files
committed
Fix muzzle range for jetty-appsec-9.3/9.4: split at 9.4.10
_multiPartInputStream was replaced by _multiParts in Jetty 9.4.10.v20180503. Early 9.4.x versions (9.4.0–9.4.9) still use _multiPartInputStream like 9.3.x, so extend jetty-appsec-9.3 to cover [9.3, 9.4.10) and narrow jetty-appsec-9.4 to [9.4.10, 11.0). The classLoaderMatcher in jetty-appsec-9.4 (checking for _multiParts) now correctly matches only versions >= 9.4.10.
1 parent b9f5a74 commit d92ff94

File tree

4 files changed

+56
-7
lines changed

4 files changed

+56
-7
lines changed

dd-java-agent/instrumentation/jetty/jetty-appsec/jetty-appsec-9.3/build.gradle

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ muzzle {
22
pass {
33
group = 'org.eclipse.jetty'
44
module = 'jetty-server'
5-
versions = '[9.3,9.4)'
5+
versions = '[9.3,9.4.10)'
66
assertInverse = true
77
}
88
}

dd-java-agent/instrumentation/jetty/jetty-appsec/jetty-appsec-9.3/src/main/java/datadog/trace/instrumentation/jetty93/RequestExtractContentParametersInstrumentation.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -58,9 +58,10 @@ public void methodAdvice(MethodTransformer transformer) {
5858
getClass().getName() + "$GetFilenamesFromMultiPartAdvice");
5959
}
6060

61-
// Discriminates Jetty 9.3.x ([9.3, 9.4)):
61+
// Discriminates Jetty 9.3.x–9.4.9.x ([9.3, 9.4.10)):
6262
// - _contentParameters + extractContentParameters(void) exist from 9.3+ (excludes 9.2)
63-
// - _multiPartInputStream exists only in 9.3.x (excludes 9.4+ where it became _multiParts)
63+
// - _multiPartInputStream exists in 9.3.x and early 9.4.x (< 9.4.10); replaced by _multiParts
64+
// in 9.4.10 (covered by jetty-appsec-9.4)
6465
private static final Reference REQUEST_REFERENCE =
6566
new Reference.Builder("org.eclipse.jetty.server.Request")
6667
.withMethod(new String[0], 0, "extractContentParameters", "V")

dd-java-agent/instrumentation/jetty/jetty-appsec/jetty-appsec-9.4/build.gradle

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ muzzle {
22
pass {
33
group = 'org.eclipse.jetty'
44
module = 'jetty-server'
5-
versions = '[9.4,11.0)'
5+
versions = '[9.4.10,11.0)'
66
assertInverse = true
77
}
88
}

dd-java-agent/instrumentation/jetty/jetty-appsec/jetty-appsec-9.4/src/main/java/datadog/trace/instrumentation/jetty94/RequestExtractContentParametersInstrumentation.java

Lines changed: 51 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,19 @@
1818
import datadog.trace.api.gateway.RequestContextSlot;
1919
import datadog.trace.bootstrap.CallDepthThreadLocalMap;
2020
import datadog.trace.bootstrap.instrumentation.api.AgentTracer;
21+
import java.io.IOException;
22+
import java.io.InputStream;
2123
import java.util.Collection;
2224
import java.util.List;
2325
import java.util.function.BiFunction;
2426
import javax.servlet.http.Part;
2527
import net.bytebuddy.asm.Advice;
2628
import net.bytebuddy.implementation.bytecode.assign.Assigner;
29+
import net.bytebuddy.jar.asm.ClassReader;
30+
import net.bytebuddy.jar.asm.ClassVisitor;
31+
import net.bytebuddy.jar.asm.FieldVisitor;
32+
import net.bytebuddy.jar.asm.Opcodes;
33+
import net.bytebuddy.matcher.ElementMatcher;
2734
import org.eclipse.jetty.server.Request;
2835
import org.eclipse.jetty.util.MultiMap;
2936

@@ -58,15 +65,18 @@ public void methodAdvice(MethodTransformer transformer) {
5865
getClass().getName() + "$GetFilenamesFromMultiPartAdvice");
5966
}
6067

61-
// Discriminates Jetty 9.4–10.x ([9.4, 11.0)):
68+
// Discriminates Jetty 9.4.10–10.x ([9.4.10, 11.0)):
6269
// - _contentParameters + extractContentParameters(void) exist from 9.3+ (excludes 9.2)
63-
// - _multiParts exists from 9.4+ (excludes 9.3.x where only _multiPartInputStream existed)
6470
// - javax.servlet.http.Part exists in 9.4–10.x classpath (excludes Jetty 11+ which uses jakarta)
71+
// - classLoaderMatcher checks _multiParts field exists (any type) to exclude Jetty 9.3.x and
72+
// early 9.4.x (< 9.4.10) which use _multiPartInputStream instead (covered by
73+
// jetty-appsec-9.3).
74+
// The _multiParts field type changed between 9.4.10 (MultiParts) and 10.x
75+
// (MultiPartFormInputStream), so a typed muzzle reference cannot cover the full range.
6576
private static final Reference REQUEST_REFERENCE =
6677
new Reference.Builder("org.eclipse.jetty.server.Request")
6778
.withMethod(new String[0], 0, "extractContentParameters", "V")
6879
.withField(new String[0], 0, "_contentParameters", MULTI_MAP_INTERNAL_NAME)
69-
.withField(new String[0], 0, "_multiParts", "Lorg/eclipse/jetty/server/MultiParts;")
7080
.build();
7181

7282
private static final Reference JAVAX_PART_REFERENCE =
@@ -77,6 +87,44 @@ public Reference[] additionalMuzzleReferences() {
7787
return new Reference[] {REQUEST_REFERENCE, JAVAX_PART_REFERENCE};
7888
}
7989

90+
/** Accepts classloaders where {@code Request._multiParts} field exists (any type). */
91+
@Override
92+
public ElementMatcher.Junction<ClassLoader> classLoaderMatcher() {
93+
return MultiPartsFieldMatcher.INSTANCE;
94+
}
95+
96+
public static class MultiPartsFieldMatcher
97+
extends ElementMatcher.Junction.ForNonNullValues<ClassLoader> {
98+
public static final ElementMatcher.Junction<ClassLoader> INSTANCE =
99+
new MultiPartsFieldMatcher();
100+
101+
@Override
102+
protected boolean doMatch(ClassLoader cl) {
103+
try (InputStream is = cl.getResourceAsStream("org/eclipse/jetty/server/Request.class")) {
104+
if (is == null) {
105+
return false;
106+
}
107+
ClassReader cr = new ClassReader(is);
108+
final boolean[] found = {false};
109+
cr.accept(
110+
new ClassVisitor(Opcodes.ASM9) {
111+
@Override
112+
public FieldVisitor visitField(
113+
int access, String name, String descriptor, String signature, Object value) {
114+
if ("_multiParts".equals(name)) {
115+
found[0] = true;
116+
}
117+
return null;
118+
}
119+
},
120+
ClassReader.SKIP_CODE);
121+
return found[0];
122+
} catch (IOException e) {
123+
return false;
124+
}
125+
}
126+
}
127+
80128
@RequiresRequestContext(RequestContextSlot.APPSEC)
81129
public static class ExtractContentParametersAdvice {
82130
@Advice.OnMethodEnter(suppress = Throwable.class)

0 commit comments

Comments
 (0)