Skip to content

Commit cdbd4b8

Browse files
authored
Fix SymDB when processing corrupted jars (#10453)
when processing jar file that are corrupted exceptions can be raised and will stop the process. Make sure we can process the next jars.
1 parent 76b5b63 commit cdbd4b8

File tree

4 files changed

+82
-9
lines changed

4 files changed

+82
-9
lines changed

dd-java-agent/agent-debugger/src/main/java/com/datadog/debugger/symbol/SymDBEnablement.java

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,8 @@ private void extractSymbolForLoadedClasses(SymDBReport symDBReport) {
143143
try {
144144
jarPath = JarScanner.extractJarPath(clazz, symDBReport);
145145
} catch (URISyntaxException e) {
146-
throw new RuntimeException(e);
146+
LOGGER.debug("Failed to extract jar path for class {}", clazz.getTypeName(), e);
147+
continue;
147148
}
148149
if (jarPath == null) {
149150
continue;
@@ -152,7 +153,11 @@ private void extractSymbolForLoadedClasses(SymDBReport symDBReport) {
152153
symDBReport.addMissingJar(jarPath.toString());
153154
continue;
154155
}
155-
symbolAggregator.scanJar(symDBReport, jarPath, baos, buffer);
156+
try {
157+
symbolAggregator.scanJar(symDBReport, jarPath, baos, buffer);
158+
} catch (Exception ex) {
159+
LOGGER.debug("Failed to scan jar {}", jarPath, ex);
160+
}
156161
}
157162
}
158163
}

dd-java-agent/agent-debugger/src/main/java/com/datadog/debugger/symbol/SymbolAggregator.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,11 @@ void scanQueuedJars(SymbolAggregator symbolAggregator) {
158158
while (!jarsToScanQueue.isEmpty()) {
159159
String jarPath = jarsToScanQueue.poll();
160160
LOGGER.debug("Scanning queued jar: {}", jarPath);
161-
scanJar(SymDBReport.NO_OP, Paths.get(jarPath), baos, buffer);
161+
try {
162+
scanJar(SymDBReport.NO_OP, Paths.get(jarPath), baos, buffer);
163+
} catch (Exception ex) {
164+
LOGGER.debug("Failed to scan jar {}", jarPath, ex);
165+
}
162166
}
163167
}
164168

dd-java-agent/agent-debugger/src/test/java/com/datadog/debugger/symbol/SymDBEnablementTest.java

Lines changed: 40 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,11 @@
2525
import java.io.IOException;
2626
import java.io.InputStream;
2727
import java.lang.instrument.Instrumentation;
28+
import java.net.MalformedURLException;
2829
import java.net.URISyntaxException;
2930
import java.net.URL;
3031
import java.net.URLClassLoader;
32+
import java.nio.file.Path;
3133
import java.util.Collections;
3234
import java.util.jar.JarEntry;
3335
import java.util.jar.JarFile;
@@ -111,11 +113,7 @@ public void noIncludesFilterOutDatadogClass() {
111113

112114
@Test
113115
public void parseLoadedClass() throws ClassNotFoundException, IOException {
114-
final String CLASS_NAME = "com.datadog.debugger.symbol.SymbolExtraction01";
115-
URL jarFileUrl = getClass().getResource("/debugger-symbol.jar");
116-
URL jarUrl = new URL("jar:file:" + jarFileUrl.getFile() + "!/");
117-
URLClassLoader urlClassLoader = new URLClassLoader(new URL[] {jarUrl}, null);
118-
Class<?> testClass = urlClassLoader.loadClass(CLASS_NAME);
116+
Class<?> testClass = loadSymbolClassFromJar();
119117
when(instr.getAllLoadedClasses()).thenReturn(new Class[] {testClass});
120118
when(config.getThirdPartyIncludes())
121119
.thenReturn(
@@ -130,14 +128,50 @@ public void parseLoadedClass() throws ClassNotFoundException, IOException {
130128
verify(instr).addTransformer(any(SymbolExtractionTransformer.class));
131129
ArgumentCaptor<String> captor = ArgumentCaptor.forClass(String.class);
132130
verify(symbolAggregator, times(2))
133-
.parseClass(any(), captor.capture(), any(), eq(jarFileUrl.getFile()));
131+
.parseClass(
132+
any(),
133+
captor.capture(),
134+
any(),
135+
eq(getClass().getResource("/debugger-symbol.jar").getFile()));
134136
assertEquals(
135137
"com/datadog/debugger/symbol/SymbolExtraction01.class", captor.getAllValues().get(0));
136138
assertEquals(
137139
"BOOT-INF/classes/org/springframework/samples/petclinic/vet/VetController.class",
138140
captor.getAllValues().get(1));
139141
}
140142

143+
@Test
144+
public void processCorruptedJar() throws ClassNotFoundException, MalformedURLException {
145+
Class<?> testClass = loadSymbolClassFromJar();
146+
when(instr.getAllLoadedClasses())
147+
.thenReturn(new Class[] {SymDBEnablementTest.class, testClass});
148+
ClassNameFiltering classNameFiltering = ClassNameFiltering.allowAll();
149+
SymbolAggregator symbolAggregatorMock = mock(SymbolAggregator.class);
150+
doAnswer(
151+
invocation -> {
152+
Path arg = invocation.getArgument(1, Path.class);
153+
if (arg.toString().endsWith("/debugger-symbol.jar")) {
154+
return null;
155+
}
156+
throw new IOException("Corrupted jar");
157+
})
158+
.when(symbolAggregatorMock)
159+
.scanJar(any(), any(), any(), any());
160+
SymDBEnablement symDBEnablement =
161+
new SymDBEnablement(instr, config, symbolAggregatorMock, classNameFiltering);
162+
symDBEnablement.startSymbolExtraction();
163+
verify(symbolAggregatorMock, times(2)).scanJar(any(), any(), any(), any());
164+
}
165+
166+
private Class<?> loadSymbolClassFromJar() throws MalformedURLException, ClassNotFoundException {
167+
final String CLASS_NAME = "com.datadog.debugger.symbol.SymbolExtraction01";
168+
URL jarFileUrl = getClass().getResource("/debugger-symbol.jar");
169+
URL jarUrl = new URL("jar:file:" + jarFileUrl.getFile() + "!/");
170+
URLClassLoader urlClassLoader = new URLClassLoader(new URL[] {jarUrl}, null);
171+
Class<?> testClass = urlClassLoader.loadClass(CLASS_NAME);
172+
return testClass;
173+
}
174+
141175
@Test
142176
public void parseLoadedClassFromDirectory()
143177
throws ClassNotFoundException, IOException, URISyntaxException {

dd-java-agent/agent-debugger/src/test/java/com/datadog/debugger/symbol/SymbolAggregatorTest.java

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,36 @@ void testScanQueuedJars() {
4646
captor.getAllValues().get(2));
4747
}
4848

49+
@Test
50+
void testScanQueuedCorruptedJars() {
51+
SymbolSink symbolSink = mock(SymbolSink.class);
52+
SymbolAggregator symbolAggregator =
53+
spy(new SymbolAggregator(ClassNameFiltering.allowAll(), emptyList(), symbolSink, 1));
54+
// add first a corrupted jar
55+
URL corruptedUrl = getClass().getResource("/com/datadog/debugger/classfiles/CommandLine.class");
56+
CodeSource corruptedCodeSource =
57+
new CodeSource(corruptedUrl, (java.security.cert.Certificate[]) null);
58+
ProtectionDomain corruptedProtectionDomain = new ProtectionDomain(corruptedCodeSource, null);
59+
symbolAggregator.parseClass(null, null, corruptedProtectionDomain);
60+
// add second a clean jar
61+
URL jarFileUrl = getClass().getResource("/debugger-symbol.jar");
62+
CodeSource codeSource = new CodeSource(jarFileUrl, (java.security.cert.Certificate[]) null);
63+
ProtectionDomain protectionDomain = new ProtectionDomain(codeSource, null);
64+
symbolAggregator.parseClass(null, null, protectionDomain);
65+
symbolAggregator.scanQueuedJars(null);
66+
// clean jar should have been processed
67+
ArgumentCaptor<String> captor = ArgumentCaptor.forClass(String.class);
68+
verify(symbolAggregator, atLeastOnce())
69+
.parseClass(any(), captor.capture(), any(), eq(jarFileUrl.getFile()));
70+
// captor.getAllValues().get(0) is the first argument of the first invocation of parseClass with
71+
// null
72+
assertEquals(
73+
"com/datadog/debugger/symbol/SymbolExtraction01.class", captor.getAllValues().get(1));
74+
assertEquals(
75+
"BOOT-INF/classes/org/springframework/samples/petclinic/vet/VetController.class",
76+
captor.getAllValues().get(2));
77+
}
78+
4979
@Test
5080
@DisabledIf(
5181
value = "datadog.environment.JavaVirtualMachine#isJ9",

0 commit comments

Comments
 (0)