Skip to content

Commit 744dc04

Browse files
Fix verify error when ctor params are used after a call site
1 parent 40561cd commit 744dc04

File tree

6 files changed

+58
-5
lines changed

6 files changed

+58
-5
lines changed

dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/bytebuddy/csi/Advices.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -370,7 +370,8 @@ void onConstantPool(
370370
@Nonnull TypeDescription type, @Nonnull ConstantPool pool, final byte[] classFile);
371371
}
372372

373-
private interface TypedAdvice {
373+
// Kept public only for testing
374+
public interface TypedAdvice {
374375
byte getType();
375376

376377
static CallSiteAdvice withType(final CallSiteAdvice advice, final byte type) {

dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/bytebuddy/csi/CallSiteTransformer.java

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -360,10 +360,12 @@ public void visitMethodInsn(
360360
@Override
361361
public void advice(final String owner, final String name, final String descriptor) {
362362
if (isSuperCall) {
363-
// append this to the stack after super call
364-
mv.visitIntInsn(Opcodes.ALOAD, 0);
363+
mv.visitIntInsn(Opcodes.ALOAD, 0); // append this to the stack after super call
364+
mv.visitMethodInsn(Opcodes.INVOKESTATIC, owner, name, descriptor, false);
365+
mv.visitInsn(Opcodes.POP); // pop the result of the advice call
366+
} else {
367+
mv.visitMethodInsn(Opcodes.INVOKESTATIC, owner, name, descriptor, false);
365368
}
366-
mv.visitMethodInsn(Opcodes.INVOKESTATIC, owner, name, descriptor, false);
367369
}
368370

369371
@Override

dd-java-agent/agent-tooling/src/test/groovy/datadog/trace/agent/tooling/csi/BaseCallSiteTest.groovy

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ class BaseCallSiteTest extends DDSpecification {
5454
advices
5555
.computeIfAbsent(owner, t -> [:])
5656
.computeIfAbsent(method, m -> [:])
57-
.put(descriptor, advice)
57+
.put(descriptor, Advices.TypedAdvice.withType(advice, type))
5858
}
5959
addHelpers(_ as String[]) >> {
6060
Collections.addAll(helpers, it[0] as String[])
@@ -83,6 +83,9 @@ class BaseCallSiteTest extends DDSpecification {
8383
getHelpers() >> {
8484
helpers as String[]
8585
}
86+
typeOf(_ as CallSiteAdvice) >> {
87+
((Advices.TypedAdvice) it[0]).type
88+
}
8689
}
8790
}
8891

dd-java-agent/agent-tooling/src/test/java/datadog/trace/agent/tooling/csi/SuperInCtorExample.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,5 +6,8 @@ public class SuperInCtorExample extends StringReader {
66

77
public SuperInCtorExample(String s) {
88
super(s + new StringReader(s + "Test" + new StringBuilder("another test")));
9+
if (s.isEmpty()) { // triggers APPSEC-58131
10+
throw new IllegalArgumentException();
11+
}
912
}
1013
}

dd-java-agent/instrumentation/java-io/src/test/groovy/datadog/trace/instrumentation/java/io/InputStreamReaderCallSiteTest.groovy

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package datadog.trace.instrumentation.java.io
22

33
import datadog.trace.api.iast.InstrumentationBridge
44
import datadog.trace.api.iast.propagation.PropagationModule
5+
import foo.bar.TestCustomInputStreamReader
56
import foo.bar.TestInputStreamReaderSuite
67

78
import java.nio.charset.Charset
@@ -27,4 +28,21 @@ class InputStreamReaderCallSiteTest extends BaseIoCallSiteTest{
2728
[new ByteArrayInputStream("test".getBytes())]// Reader input
2829
]
2930
}
31+
32+
void 'test InputStreamReader.<init> with super call and parameter'(){
33+
// XXX: Do not modify the constructor call here. Regression test for APPSEC-58131.
34+
given:
35+
PropagationModule iastModule = Mock(PropagationModule)
36+
InstrumentationBridge.registerIastModule(iastModule)
37+
38+
when:
39+
new TestCustomInputStreamReader(*args)
40+
41+
then:
42+
1 * iastModule.taintObjectIfTainted(_ as InputStreamReader, _ as InputStream)
43+
0 * _
44+
45+
where:
46+
args << [[new ByteArrayInputStream("test".getBytes()), Charset.defaultCharset()],]
47+
}
3048
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
package foo.bar;
2+
3+
import java.io.IOException;
4+
import java.io.InputStream;
5+
import java.io.InputStreamReader;
6+
import java.nio.charset.Charset;
7+
8+
public class TestCustomInputStreamReader extends InputStreamReader {
9+
10+
public TestCustomInputStreamReader(final InputStream in) throws IOException {
11+
super(in);
12+
}
13+
14+
public TestCustomInputStreamReader(final InputStream in, final Charset charset)
15+
throws IOException {
16+
// XXX: DO NOT MODIFY THIS CODE. This is testing a very specific error (APPSEC-58131).
17+
// This caused the following error:
18+
// VerifyError: Inconsistent stackmap frames at branch target \d
19+
// Reason: urrent frame's stack size doesn't match stackmap.
20+
// To trigger this, it is necessary to consume an argument after the super call.
21+
super(in, charset);
22+
if (charset != null) {
23+
System.out.println("Using charset: " + charset.name());
24+
}
25+
}
26+
}

0 commit comments

Comments
 (0)