diff --git a/dd-java-agent/appsec/build.gradle b/dd-java-agent/appsec/build.gradle index 10ea2882dc9..461adcb0ec3 100644 --- a/dd-java-agent/appsec/build.gradle +++ b/dd-java-agent/appsec/build.gradle @@ -89,7 +89,9 @@ ext { 'com.datadog.appsec.config.AppSecFeatures.AutoUserInstrum', 'com.datadog.appsec.AppSecModule.AppSecModuleActivationException', 'com.datadog.appsec.event.ReplaceableEventProducerService', + 'com.datadog.appsec.event.data.IntrospectionExcludedTypesTrie', 'com.datadog.appsec.api.security.ApiSecuritySampler.NoOp', + 'com.datadog.appsec.sca.ScaStackExclusionTrie', ] excludedClassesBranchCoverage = [ 'com.datadog.appsec.gateway.GatewayBridge', diff --git a/dd-java-agent/appsec/src/test/java/com/datadog/appsec/sca/ScaBytecodeTestUtils.java b/dd-java-agent/appsec/src/test/java/com/datadog/appsec/sca/ScaBytecodeTestUtils.java new file mode 100644 index 00000000000..3b2e4a02d04 --- /dev/null +++ b/dd-java-agent/appsec/src/test/java/com/datadog/appsec/sca/ScaBytecodeTestUtils.java @@ -0,0 +1,42 @@ +package com.datadog.appsec.sca; + +import static org.junit.jupiter.api.Assertions.assertNotNull; + +import java.io.ByteArrayOutputStream; +import java.io.InputStream; +import net.bytebuddy.jar.asm.ClassReader; +import net.bytebuddy.jar.asm.ClassWriter; + +final class ScaBytecodeTestUtils { + + private ScaBytecodeTestUtils() {} + + static byte[] bytecodeOf(Class clazz) throws Exception { + String path = clazz.getName().replace('.', '/') + ".class"; + try (InputStream is = clazz.getClassLoader().getResourceAsStream(path)) { + assertNotNull(is, "Cannot load bytecode for " + clazz.getName()); + ByteArrayOutputStream buf = new ByteArrayOutputStream(); + byte[] chunk = new byte[4096]; + int n; + while ((n = is.read(chunk)) != -1) { + buf.write(chunk, 0, n); + } + return buf.toByteArray(); + } + } + + static Class loadModified(byte[] bytecode) { + return new ClassLoader(ScaBytecodeTestUtils.class.getClassLoader()) { + Class define() { + return defineClass(null, bytecode, 0, bytecode.length); + } + }.define(); + } + + static byte[] bytecodeWithoutDebugInfo(Class clazz) throws Exception { + ClassReader cr = new ClassReader(bytecodeOf(clazz)); + ClassWriter cw = new ClassWriter(0); + cr.accept(cw, ClassReader.SKIP_DEBUG); + return cw.toByteArray(); + } +} diff --git a/dd-java-agent/appsec/src/test/java/com/datadog/appsec/sca/ScaCveDatabaseTest.java b/dd-java-agent/appsec/src/test/java/com/datadog/appsec/sca/ScaCveDatabaseTest.java index 0c02a3941e5..5fe9efdbcad 100644 --- a/dd-java-agent/appsec/src/test/java/com/datadog/appsec/sca/ScaCveDatabaseTest.java +++ b/dd-java-agent/appsec/src/test/java/com/datadog/appsec/sca/ScaCveDatabaseTest.java @@ -1,9 +1,11 @@ package com.datadog.appsec.sca; +import static java.util.Collections.singletonList; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; import java.io.StringReader; @@ -125,6 +127,29 @@ void multipleEntriesForSameClass() throws Exception { assertEquals(2, entries.size()); } + @Test + void scaEntryMatchesVersions() { + List expectedRanges = singletonList("< 2.0.0"); + List symbols = singletonList(new ScaSymbol("com/example/Foo", "op")); + ScaEntry entry = new ScaEntry("GHSA-entry", "com.example:lib", expectedRanges, symbols); + + assertEquals(expectedRanges, entry.versionRanges()); + assertTrue(entry.isVersionVulnerable("1.9.9")); + assertFalse(entry.isVersionVulnerable("2.0.0")); + } + + @Test + void scaEntryExposesImmutableLists() { + List ranges = singletonList("< 2.0.0"); + List symbols = singletonList(new ScaSymbol("com/example/Foo", "op")); + ScaEntry entry = new ScaEntry("GHSA-entry", "com.example:lib", ranges, symbols); + + assertThrows(UnsupportedOperationException.class, () -> entry.versionRanges().add("< 3.0.0")); + assertThrows( + UnsupportedOperationException.class, + () -> entry.symbols().add(new ScaSymbol("com/example/Bar", "op"))); + } + @Test void entryWithMultipleSymbolsInSameClassIndexedOnce() throws Exception { // An entry with two symbols for the same class (e.g. Yaml.load + Yaml.loadAll) must appear diff --git a/dd-java-agent/appsec/src/test/java/com/datadog/appsec/sca/ScaReachabilityMethodLevelTest.java b/dd-java-agent/appsec/src/test/java/com/datadog/appsec/sca/ScaReachabilityMethodLevelTest.java index 7ee88fa8ffa..5083745e48f 100644 --- a/dd-java-agent/appsec/src/test/java/com/datadog/appsec/sca/ScaReachabilityMethodLevelTest.java +++ b/dd-java-agent/appsec/src/test/java/com/datadog/appsec/sca/ScaReachabilityMethodLevelTest.java @@ -1,5 +1,8 @@ package com.datadog.appsec.sca; +import static com.datadog.appsec.sca.ScaBytecodeTestUtils.bytecodeOf; +import static com.datadog.appsec.sca.ScaBytecodeTestUtils.bytecodeWithoutDebugInfo; +import static com.datadog.appsec.sca.ScaBytecodeTestUtils.loadModified; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertNotNull; @@ -10,8 +13,6 @@ import datadog.trace.api.telemetry.ScaReachabilityDependencyRegistry.DependencySnapshot; import datadog.trace.api.telemetry.ScaReachabilityHit; import datadog.trace.bootstrap.appsec.sca.ScaReachabilityCallback; -import java.io.ByteArrayOutputStream; -import java.io.InputStream; import java.io.StringReader; import java.lang.reflect.Method; import java.util.ArrayList; @@ -43,6 +44,24 @@ public String safeMethod() { } } + /** Fixture compiled normally, then stripped of line numbers before callback injection. */ + public static class ClassToBeStrippedOfLineNumber { + // Intentionally non-final so javac emits a field read instead of inlining a constant. + private static int runtimeFieldValue = 7; + + public static int readField() { + return runtimeFieldValue; + } + + public static Object returnArgument(Object value) { + return value; + } + + public static String callToString(Object value) { + return value.toString(); + } + } + private ScaCveDatabase db; private ScaReachabilityTransformer transformer; @@ -171,6 +190,38 @@ void inject_injectsMultipleMethodsIndependently() throws Exception { assertTrue(hits.stream().anyMatch(h -> h.symbolName().equals("safeMethod"))); } + @Test + void inject_withoutLineNumbersInjectsBeforeFirstInstruction() throws Exception { + byte[] original = bytecodeWithoutDebugInfo(ClassToBeStrippedOfLineNumber.class); + String className = ClassToBeStrippedOfLineNumber.class.getName(); + Map> callbacks = new HashMap<>(); + callbacks.put( + "readField", + Collections.singletonList( + spec("GHSA-field", "com.example:lib", "1.0.0", className, "readField"))); + callbacks.put( + "returnArgument", + Collections.singletonList( + spec("GHSA-var", "com.example:lib", "1.0.0", className, "returnArgument"))); + callbacks.put( + "callToString", + Collections.singletonList( + spec("GHSA-method", "com.example:lib", "1.0.0", className, "callToString"))); + + Class cls = loadModified(ScaMethodCallbackInjector.inject(original, callbacks)); + + assertEquals(7, cls.getMethod("readField").invoke(null)); + assertEquals("value", cls.getMethod("returnArgument", Object.class).invoke(null, "value")); + assertEquals("value", cls.getMethod("callToString", Object.class).invoke(null, "value")); + + List hits = drainHits(); + assertEquals(3, hits.size()); + assertTrue(hits.stream().allMatch(hit -> hit.line() == 1)); + assertTrue(hits.stream().anyMatch(hit -> hit.symbolName().equals("readField"))); + assertTrue(hits.stream().anyMatch(hit -> hit.symbolName().equals("returnArgument"))); + assertTrue(hits.stream().anyMatch(hit -> hit.symbolName().equals("callToString"))); + } + @Test void inject_sameMethodNameInDifferentClassesProduceIndependentHits() throws Exception { // Regression test for dedup key bug: if two classes in the same artifact share a method @@ -325,24 +376,4 @@ private static ScaMethodCallbackInjector.MethodCallbackSpec spec( return new ScaMethodCallbackInjector.MethodCallbackSpec( vulnId, artifact, version, dotClass, method); } - - private static byte[] bytecodeOf(Class clazz) throws Exception { - String path = clazz.getName().replace('.', '/') + ".class"; - try (InputStream is = clazz.getClassLoader().getResourceAsStream(path)) { - assertNotNull(is, "Cannot load bytecode for " + clazz.getName()); - ByteArrayOutputStream buf = new ByteArrayOutputStream(); - byte[] chunk = new byte[4096]; - int n; - while ((n = is.read(chunk)) != -1) buf.write(chunk, 0, n); - return buf.toByteArray(); - } - } - - private static Class loadModified(byte[] bytecode) { - return new ClassLoader(ScaReachabilityMethodLevelTest.class.getClassLoader()) { - Class define() { - return defineClass(null, bytecode, 0, bytecode.length); - } - }.define(); - } } diff --git a/dd-java-agent/appsec/src/test/java/com/datadog/appsec/sca/ScaReachabilitySystemCallsiteTest.java b/dd-java-agent/appsec/src/test/java/com/datadog/appsec/sca/ScaReachabilitySystemCallsiteTest.java index 3dc3d2e6d80..38dbb4130f5 100644 --- a/dd-java-agent/appsec/src/test/java/com/datadog/appsec/sca/ScaReachabilitySystemCallsiteTest.java +++ b/dd-java-agent/appsec/src/test/java/com/datadog/appsec/sca/ScaReachabilitySystemCallsiteTest.java @@ -33,6 +33,20 @@ void findCallsite_returnsDirectCallerWhenNoIntermediateLibrary() { assertEquals("yamlHitDirect", result.getMethodName()); } + @Test + void findCallsite_skipsRepeatedVulnerableFrames() { + StackTraceElement[] stack = { + frame(VULNERABLE_CLASS, "load"), + frame(VULNERABLE_CLASS, "loadAll"), + frame("sca.test.TestController", "yamlHitRecursive"), + }; + + StackTraceElement result = ScaReachabilitySystem.findCallsite(VULNERABLE_CLASS, stack); + + assertEquals("sca.test.TestController", result.getClassName()); + assertEquals("yamlHitRecursive", result.getMethodName()); + } + @Test void findCallsite_skipsIntermediateLibraryFrameAndReturnsClientCode() { // com.google.* is excluded by the SCA trie (value >= 1) diff --git a/dd-java-agent/appsec/src/test/java/com/datadog/appsec/sca/ScaReachabilitySystemTest.java b/dd-java-agent/appsec/src/test/java/com/datadog/appsec/sca/ScaReachabilitySystemTest.java new file mode 100644 index 00000000000..82c7f62a9ca --- /dev/null +++ b/dd-java-agent/appsec/src/test/java/com/datadog/appsec/sca/ScaReachabilitySystemTest.java @@ -0,0 +1,53 @@ +package com.datadog.appsec.sca; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import datadog.trace.api.telemetry.ScaReachabilityDependencyRegistry; +import datadog.trace.api.telemetry.ScaReachabilityHit; +import datadog.trace.bootstrap.appsec.sca.ScaReachabilityCallback; +import java.lang.instrument.Instrumentation; +import java.util.List; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.Test; + +class ScaReachabilitySystemTest { + + @AfterEach + void tearDown() { + ScaReachabilityDependencyRegistry.INSTANCE.resetForTesting(); + ScaReachabilityCallback.register(null); + } + + @Test + void startRegistersTransformerCallbackAndPeriodicWork() { + Instrumentation instrumentation = mock(Instrumentation.class); + when(instrumentation.getAllLoadedClasses()).thenReturn(new Class[0]); + + ScaReachabilitySystem.start(instrumentation); + + verify(instrumentation).addTransformer(any(ScaReachabilityTransformer.class), eq(true)); + assertNotNull(ScaReachabilityDependencyRegistry.INSTANCE.getPeriodicWorkCallback()); + + ScaReachabilityCallback.onMethodHit( + "GHSA-start", "com.example:lib", "1.0.0", "missing.Vulnerable", "danger", 42); + + List snapshots = + ScaReachabilityDependencyRegistry.INSTANCE.drainPendingDependencies(); + assertEquals(1, snapshots.size()); + assertEquals("com.example:lib", snapshots.get(0).artifact); + assertEquals("1.0.0", snapshots.get(0).version); + assertEquals(1, snapshots.get(0).cves.size()); + ScaReachabilityHit hit = snapshots.get(0).cves.get(0).hit; + assertNotNull(hit); + assertEquals("GHSA-start", hit.vulnId()); + assertEquals("missing.Vulnerable", hit.className()); + assertEquals("danger", hit.symbolName()); + assertEquals(42, hit.line()); + } +} diff --git a/dd-java-agent/appsec/src/test/java/com/datadog/appsec/sca/ScaReachabilityTransformerJava9Test.java b/dd-java-agent/appsec/src/test/java/com/datadog/appsec/sca/ScaReachabilityTransformerJava9Test.java index 57da31fc9ab..48bfa48b1a9 100644 --- a/dd-java-agent/appsec/src/test/java/com/datadog/appsec/sca/ScaReachabilityTransformerJava9Test.java +++ b/dd-java-agent/appsec/src/test/java/com/datadog/appsec/sca/ScaReachabilityTransformerJava9Test.java @@ -1,19 +1,26 @@ package com.datadog.appsec.sca; +import static com.datadog.appsec.sca.ScaBytecodeTestUtils.bytecodeOf; +import static java.util.Collections.emptyList; +import static java.util.Collections.singletonList; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertSame; +import static org.junit.jupiter.api.Assertions.assertTrue; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; import datadog.telemetry.dependency.Dependency; +import datadog.trace.api.telemetry.ScaReachabilityDependencyRegistry; import java.io.StringReader; import java.lang.instrument.Instrumentation; import java.net.URLClassLoader; import java.util.Arrays; -import java.util.Collections; +import java.util.List; +import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.condition.EnabledForJreRange; import org.junit.jupiter.api.condition.JRE; @@ -52,6 +59,11 @@ class ScaReachabilityTransformerJava9Test { + "\"symbols\":[{\"class\":\"com/fasterxml/jackson/databind/ObjectMapper\",\"method\":\"readValue\"}]" + "}]}"; + @AfterEach + void resetRegistry() { + ScaReachabilityDependencyRegistry.INSTANCE.resetForTesting(); + } + @Test @EnabledForJreRange(min = JRE.JAVA_9) void systemClassLoaderIsNotUrlClassLoaderOnJava9Plus() { @@ -103,8 +115,7 @@ void matchVersion_exactMatchReturnsVersion() { Dependency dep = new Dependency("com.github.junrar:junrar", "7.5.5", "junrar-7.5.5.jar", null); assertEquals( "7.5.5", - ScaReachabilityTransformer.matchVersion( - "com.github.junrar:junrar", Collections.singletonList(dep))); + ScaReachabilityTransformer.matchVersion("com.github.junrar:junrar", singletonList(dep))); } @Test @@ -114,8 +125,7 @@ void matchVersion_artifactIdOnlyFallbackForNoPomJar() { Dependency dep = new Dependency("junrar", "7.5.5", "junrar-7.5.5.jar", null); assertEquals( "7.5.5", - ScaReachabilityTransformer.matchVersion( - "com.github.junrar:junrar", Collections.singletonList(dep)), + ScaReachabilityTransformer.matchVersion("com.github.junrar:junrar", singletonList(dep)), "artifact-ID fallback must match 'junrar' against 'com.github.junrar:junrar'"); } @@ -125,16 +135,13 @@ void matchVersion_artifactIdFallbackDoesNotMatchWhenGroupIdPresent() { // "org.other:junrar" should NOT match "com.github.junrar:junrar". Dependency dep = new Dependency("org.other:junrar", "1.0.0", "junrar-1.0.0.jar", null); assertNull( - ScaReachabilityTransformer.matchVersion( - "com.github.junrar:junrar", Collections.singletonList(dep)), + ScaReachabilityTransformer.matchVersion("com.github.junrar:junrar", singletonList(dep)), "artifact-ID fallback must not fire when dep.name already has a group ID"); } @Test void matchVersion_emptyListReturnsNull() { - assertNull( - ScaReachabilityTransformer.matchVersion( - "com.github.junrar:junrar", Collections.emptyList())); + assertNull(ScaReachabilityTransformer.matchVersion("com.github.junrar:junrar", emptyList())); } @Test @@ -229,13 +236,108 @@ void performPendingRetransforms_prewarms_classpathArtifactCache_for_aggregator_a + "if empty, findArtifactVersionInClasspath() would run under JVM retransform locks"); } + @Test + void transform_retransform_injectsCallbacksWhenVersionResolvedFromCache() throws Exception { + String internalName = + ScaReachabilityMethodLevelTest.TargetClass.class.getName().replace('.', '/'); + String json = + "{\"version\":1,\"entries\":[{" + + "\"vuln_id\":\"GHSA-transform\"," + + "\"artifact\":\"com.example:lib\"," + + "\"version_ranges\":[\"< 999.0.0\"]," + + "\"symbols\":[{\"class\":\"" + + internalName + + "\",\"method\":\"vulnerableMethod\"}]" + + "}]}"; + ScaCveDatabase db = ScaCveDatabase.parse(new StringReader(json)); + ScaReachabilityTransformer transformer = new ScaReachabilityTransformer(db, null); + transformer.jarCache.put( + ScaReachabilityMethodLevelTest.TargetClass.class + .getProtectionDomain() + .getCodeSource() + .getLocation() + .toURI(), + singletonList(new Dependency("com.example:lib", "1.2.3", "test.jar", null))); + + byte[] transformed = + transformer.transform( + null, + internalName, + ScaReachabilityMethodLevelTest.TargetClass.class, + ScaReachabilityMethodLevelTest.TargetClass.class.getProtectionDomain(), + bytecodeOf(ScaReachabilityMethodLevelTest.TargetClass.class)); + + assertNotNull(transformed); + assertTrue(transformer.pendingRetransformNames.isEmpty()); + List snapshots = + ScaReachabilityDependencyRegistry.INSTANCE.drainPendingDependencies(); + assertEquals(1, snapshots.size()); + assertEquals("com.example:lib", snapshots.get(0).artifact); + assertEquals("1.2.3", snapshots.get(0).version); + assertEquals("GHSA-transform", snapshots.get(0).cves.get(0).vulnId); + assertNull(snapshots.get(0).cves.get(0).hit); + } + + @Test + void checkAlreadyLoadedClassesSchedulesOnlyMatchingNonBootstrapClasses() throws Exception { + String internalName = + ScaReachabilityMethodLevelTest.TargetClass.class.getName().replace('.', '/'); + String json = + "{\"version\":1,\"entries\":[" + + "{\"vuln_id\":\"GHSA-target\",\"artifact\":\"com.example:lib\"," + + "\"version_ranges\":[\"< 999.0.0\"]," + + "\"symbols\":[{\"class\":\"" + + internalName + + "\",\"method\":\"vulnerableMethod\"}]}," + + "{\"vuln_id\":\"GHSA-jdk\",\"artifact\":\"com.example:jdk\"," + + "\"version_ranges\":[\"< 999.0.0\"]," + + "\"symbols\":[{\"class\":\"java/lang/String\",\"method\":\"substring\"}]}" + + "]}"; + + Instrumentation mockInstr = mock(Instrumentation.class); + when(mockInstr.getAllLoadedClasses()) + .thenReturn( + new Class[] { + null, String[].class, String.class, ScaReachabilityMethodLevelTest.TargetClass.class, + }); + ScaReachabilityTransformer transformer = + new ScaReachabilityTransformer(ScaCveDatabase.parse(new StringReader(json)), mockInstr); + + transformer.checkAlreadyLoadedClasses(); + + assertEquals(1, transformer.pendingRetransform.size()); + assertSame( + ScaReachabilityMethodLevelTest.TargetClass.class, transformer.pendingRetransform.peek()); + } + + @Test + void performPendingRetransforms_noopsWithoutInstrumentation() throws Exception { + ScaReachabilityTransformer transformer = + new ScaReachabilityTransformer( + ScaCveDatabase.parse(new StringReader("{\"version\":1,\"entries\":[]}")), null); + transformer.pendingRetransform.add(ScaReachabilityMethodLevelTest.TargetClass.class); + + transformer.performPendingRetransforms(); + + assertSame( + ScaReachabilityMethodLevelTest.TargetClass.class, transformer.pendingRetransform.peek()); + } + + @Test + void resolveArtifactDep_returnsCachedClasspathArtifact() throws Exception { + ScaReachabilityTransformer transformer = + new ScaReachabilityTransformer(ScaCveDatabase.parse(new StringReader(JACKSON_JSON)), null); + Dependency cached = new Dependency("com.example:lib", "1.0.0", "lib.jar", null); + transformer.classpathArtifactCache.put("com.example:lib", cached); + + assertSame(cached, transformer.resolveArtifactDep("com.example:lib", emptyList())); + } + @Test void matchVersion_nullDepNameDoesNotThrow() { // guessFallbackNoPom can produce Dependency(name=null, ...) for JARs with unrecognizable names. Dependency nullName = new Dependency(null, "1.0", "foo.jar", null); - assertNull( - ScaReachabilityTransformer.matchVersion( - "com.example:foo", Collections.singletonList(nullName))); + assertNull(ScaReachabilityTransformer.matchVersion("com.example:foo", singletonList(nullName))); } /** @@ -261,7 +363,7 @@ void resolveArtifactDep_noPomJar_returnsArtifactIdOnlyName() throws Exception { Dependency resolved = transformer.resolveArtifactDep( - "com.fasterxml.jackson.core:jackson-databind", Collections.singletonList(noPomDep)); + "com.fasterxml.jackson.core:jackson-databind", singletonList(noPomDep)); assertNotNull(resolved, "should resolve via artifactId-only fallback"); assertEquals( diff --git a/dd-java-agent/appsec/src/test/java/com/datadog/appsec/sca/ScaRealLibraryBytecodeTest.java b/dd-java-agent/appsec/src/test/java/com/datadog/appsec/sca/ScaRealLibraryBytecodeTest.java index 3e568a3c370..40303c46bf2 100644 --- a/dd-java-agent/appsec/src/test/java/com/datadog/appsec/sca/ScaRealLibraryBytecodeTest.java +++ b/dd-java-agent/appsec/src/test/java/com/datadog/appsec/sca/ScaRealLibraryBytecodeTest.java @@ -1,5 +1,7 @@ package com.datadog.appsec.sca; +import static com.datadog.appsec.sca.ScaBytecodeTestUtils.bytecodeOf; +import static com.datadog.appsec.sca.ScaBytecodeTestUtils.loadModified; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertTrue; @@ -9,9 +11,7 @@ import datadog.trace.api.telemetry.ScaReachabilityDependencyRegistry.DependencySnapshot; import datadog.trace.api.telemetry.ScaReachabilityHit; import datadog.trace.bootstrap.appsec.sca.ScaReachabilityCallback; -import java.io.ByteArrayOutputStream; import java.io.File; -import java.io.InputStream; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; @@ -198,24 +198,4 @@ private static ScaMethodCallbackInjector.MethodCallbackSpec spec( return new ScaMethodCallbackInjector.MethodCallbackSpec( vulnId, artifact, version, dotClass, method); } - - private static byte[] bytecodeOf(Class clazz) throws Exception { - String path = clazz.getName().replace('.', '/') + ".class"; - try (InputStream is = clazz.getClassLoader().getResourceAsStream(path)) { - assertNotNull(is, "Cannot load bytecode for " + clazz.getName()); - ByteArrayOutputStream buf = new ByteArrayOutputStream(); - byte[] chunk = new byte[4096]; - int n; - while ((n = is.read(chunk)) != -1) buf.write(chunk, 0, n); - return buf.toByteArray(); - } - } - - private static Class loadModified(byte[] bytecode) { - return new ClassLoader(ScaRealLibraryBytecodeTest.class.getClassLoader()) { - Class define() { - return defineClass(null, bytecode, 0, bytecode.length); - } - }.define(); - } }