Skip to content

Commit 69adb23

Browse files
committed
Fix SymDB when processing corrupted jars
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 c5c0d11 commit 69adb23

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)