Skip to content

Commit 15e5861

Browse files
authored
Fix stack trace inconsistency between excluded frames in vulnerability location and metastruct stack trace (#7865)
What Does This Do Parametrize StackUtils#generateUserCodeStackTrace with a predicate Add AbstractStackWalker#isNotDatadogTraceStackElement as default filter Update isNotDatadogTraceStackElement to also filter com.datadog.appsec Motivation We are filtering different stack frames according to their class to calculate the vulnerability location and the vulnerability stack trace that is reported via meta struct
1 parent 8e1ab2b commit 15e5861

File tree

3 files changed

+37
-14
lines changed

3 files changed

+37
-14
lines changed

internal-api/src/main/java/datadog/trace/util/stacktrace/AbstractStackWalker.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ final Stream<StackTraceElement> doFilterStack(Stream<StackTraceElement> stream)
1818

1919
static boolean isNotDatadogTraceStackElement(final StackTraceElement el) {
2020
final String clazz = el.getClassName();
21-
return !clazz.startsWith("datadog.trace.") && !clazz.startsWith("com.datadog.iast.");
21+
return !clazz.startsWith("datadog.trace.")
22+
&& !clazz.startsWith("com.datadog.iast.")
23+
&& !clazz.startsWith("com.datadog.appsec.");
2224
}
2325
}

internal-api/src/main/java/datadog/trace/util/stacktrace/StackUtils.java

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -60,19 +60,18 @@ public static <E extends Throwable> E filterUntil(
6060
});
6161
}
6262

63-
/** Function generates stack trace of the user code (excluding datadog classes) */
6463
public static List<StackTraceFrame> generateUserCodeStackTrace() {
64+
return generateUserCodeStackTrace(AbstractStackWalker::isNotDatadogTraceStackElement);
65+
}
66+
67+
/** Function generates stack trace of the user code (excluding datadog classes) */
68+
public static List<StackTraceFrame> generateUserCodeStackTrace(
69+
final Predicate<StackTraceElement> filterPredicate) {
6570
int stackCapacity = Config.get().getAppSecMaxStackTraceDepth();
6671
List<StackTraceElement> elements =
6772
StackWalkerFactory.INSTANCE.walk(
6873
stream ->
69-
stream
70-
.filter(
71-
elem ->
72-
!elem.getClassName().startsWith("com.datadog")
73-
&& !elem.getClassName().startsWith("datadog.trace"))
74-
.limit(stackCapacity)
75-
.collect(Collectors.toList()));
74+
stream.filter(filterPredicate).limit(stackCapacity).collect(Collectors.toList()));
7675
return IntStream.range(0, elements.size())
7776
.mapToObj(idx -> new StackTraceFrame(idx, elements.get(idx)))
7877
.collect(Collectors.toList());

internal-api/src/test/java/datadog/trace/util/stacktrace/StackUtilsTest.java

Lines changed: 27 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,12 @@
1414
import java.util.List;
1515
import java.util.Map;
1616
import java.util.function.Function;
17+
import java.util.function.Predicate;
18+
import java.util.stream.Stream;
1719
import org.junit.jupiter.api.Test;
20+
import org.junit.jupiter.params.ParameterizedTest;
21+
import org.junit.jupiter.params.provider.Arguments;
22+
import org.junit.jupiter.params.provider.MethodSource;
1823

1924
public class StackUtilsTest {
2025

@@ -92,13 +97,30 @@ public void test_filter_until() {
9297
assertThat(noRemoval.getStackTrace()).isEqualTo(stack);
9398
}
9499

95-
@Test
96-
public void test_generateUserCodeStackTrace() {
97-
List<StackTraceFrame> userCodeStack = StackUtils.generateUserCodeStackTrace();
100+
private static Stream<Arguments> test_generateUserCodeStackTrace_Params() {
101+
return Stream.of(
102+
Arguments.of((Predicate<StackTraceElement>) stack -> true, false),
103+
Arguments.of(
104+
(Predicate<StackTraceElement>) stack -> !stack.getClassName().startsWith("org.junit"),
105+
true));
106+
}
107+
108+
@ParameterizedTest
109+
@MethodSource("test_generateUserCodeStackTrace_Params")
110+
public void test_generateUserCodeStackTrace(
111+
final Predicate<StackTraceElement> filter, final boolean expected) {
112+
List<StackTraceFrame> userCodeStack = StackUtils.generateUserCodeStackTrace(filter);
98113
assertThat(userCodeStack).isNotNull();
114+
int junitFramesCounter = 0;
99115
for (StackTraceFrame frame : userCodeStack) {
100-
assertThat(frame.getClass_name()).doesNotContain("com.datadog");
101-
assertThat(frame.getClass_name()).doesNotContain("datadog.trace");
116+
if (frame.getClass_name() != null && frame.getClass_name().startsWith("org.junit")) {
117+
junitFramesCounter++;
118+
}
119+
}
120+
if (expected) {
121+
assertThat(junitFramesCounter).isEqualTo(0);
122+
} else {
123+
assertThat(junitFramesCounter).isGreaterThan(0);
102124
}
103125
}
104126

0 commit comments

Comments
 (0)