Skip to content

Commit 9a134c3

Browse files
committed
[优化] 优化部分代码逻辑防止空指针 @4ra1n
1 parent d7dbec2 commit 9a134c3

8 files changed

Lines changed: 183 additions & 92 deletions

File tree

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
- [BUG] 删除无效命令行参数 @4ra1n
66
- [优化] 命令行输出优化 @4ra1n
7+
- [优化] 优化部分代码逻辑防止空指针 @4ra1n
78
- [文档] 提供 `DATABASE.md``AI` 解释数据库结构 @4ra1n
89

910
## 1.0.0

src/main/java/me/n1ar4/jar/analyzer/core/DatabaseManager.java

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -295,7 +295,8 @@ public static void saveMethodCalls(HashMap<MethodReference.Handle,
295295
mce.setCallerClassName(caller.getClassReference().getName());
296296
mce.setCallerMethodName(caller.getName());
297297
mce.setCallerMethodDesc(caller.getDesc());
298-
mce.setCallerJarId(AnalyzeEnv.classMap.get(caller.getClassReference()).getJarId());
298+
mce.setCallerJarId(AnalyzeEnv.classMap.getOrDefault(
299+
caller.getClassReference(), notFoundClassReference).getJarId());
299300
mce.setCalleeClassName(mh.getClassReference().getName());
300301
mce.setCalleeMethodName(mh.getName());
301302
mce.setCalleeMethodDesc(mh.getDesc());
@@ -327,8 +328,10 @@ public static void saveImpls(Map<MethodReference.Handle, Set<MethodReference.Han
327328
impl.setClassName(method.getClassReference().getName());
328329
impl.setMethodName(mh.getName());
329330
impl.setMethodDesc(mh.getDesc());
330-
impl.setClassJarId(AnalyzeEnv.classMap.get(method.getClassReference()).getJarId());
331-
impl.setImplClassJarId(AnalyzeEnv.classMap.get(mh.getClassReference()).getJarId());
331+
impl.setClassJarId(AnalyzeEnv.classMap.getOrDefault(
332+
method.getClassReference(), notFoundClassReference).getJarId());
333+
impl.setImplClassJarId(AnalyzeEnv.classMap.getOrDefault(
334+
mh.getClassReference(), notFoundClassReference).getJarId());
332335
mList.add(impl);
333336
}
334337
}
@@ -351,7 +354,15 @@ public static void saveStrMap(Map<MethodReference.Handle, List<String>> strMap,
351354
List<String> strList = strEntry.getValue();
352355
for (String s : strList) {
353356
MethodReference mr = AnalyzeEnv.methodMap.get(method);
357+
if (mr == null) {
358+
logger.warn("method not found in methodMap: {}", method);
359+
continue;
360+
}
354361
ClassReference cr = AnalyzeEnv.classMap.get(mr.getClassReference());
362+
if (cr == null) {
363+
logger.warn("class not found in classMap: {}", mr.getClassReference());
364+
continue;
365+
}
355366
StringEntity stringEntity = new StringEntity();
356367
stringEntity.setValue(s);
357368
stringEntity.setAccess(mr.getAccess());
@@ -369,7 +380,15 @@ public static void saveStrMap(Map<MethodReference.Handle, List<String>> strMap,
369380
List<String> strList = strEntry.getValue();
370381
for (String s : strList) {
371382
MethodReference mr = AnalyzeEnv.methodMap.get(method);
383+
if (mr == null) {
384+
logger.warn("method not found in methodMap for anno: {}", method);
385+
continue;
386+
}
372387
ClassReference cr = AnalyzeEnv.classMap.get(mr.getClassReference());
388+
if (cr == null) {
389+
logger.warn("class not found in classMap for anno: {}", mr.getClassReference());
390+
continue;
391+
}
373392
StringEntity stringEntity = new StringEntity();
374393
stringEntity.setValue(s);
375394
stringEntity.setAccess(mr.getAccess());

src/main/java/me/n1ar4/jar/analyzer/core/InheritanceRunner.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,10 @@ private static void getAllParents(ClassReference classReference,
4646
if (parentClassReference == null) {
4747
continue;
4848
}
49-
allParents.add(parentClassReference.getHandle());
49+
if (!allParents.add(parentClassReference.getHandle())) {
50+
// Already processed this parent, skip to avoid infinite recursion
51+
continue;
52+
}
5053
getAllParents(parentClassReference, classMap, allParents);
5154
}
5255
}

src/main/java/me/n1ar4/jar/analyzer/core/reference/AnnoReference.java

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@
1010

1111
package me.n1ar4.jar.analyzer.core.reference;
1212

13+
import java.util.Objects;
14+
1315
public class AnnoReference {
1416
private String annoName;
1517
private Boolean visible;
@@ -46,6 +48,21 @@ public void setParameter(Integer parameter) {
4648
this.parameter = parameter;
4749
}
4850

51+
@Override
52+
public boolean equals(Object o) {
53+
if (this == o) return true;
54+
if (o == null || getClass() != o.getClass()) return false;
55+
AnnoReference that = (AnnoReference) o;
56+
return Objects.equals(annoName, that.annoName) &&
57+
Objects.equals(visible, that.visible) &&
58+
Objects.equals(parameter, that.parameter);
59+
}
60+
61+
@Override
62+
public int hashCode() {
63+
return Objects.hash(annoName, visible, parameter);
64+
}
65+
4966
@Override
5067
public String toString() {
5168
return "AnnoReference{" +

src/main/java/me/n1ar4/jar/analyzer/engine/EngineBuildRunner.java

Lines changed: 58 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -20,12 +20,13 @@
2020
import me.n1ar4.jar.analyzer.engine.log.Logger;
2121
import me.n1ar4.jar.analyzer.engine.utils.*;
2222
import me.n1ar4.jar.analyzer.entity.ClassFileEntity;
23+
import me.n1ar4.jar.analyzer.entity.JarEntity;
2324
import org.objectweb.asm.ClassReader;
2425

2526
import java.io.ByteArrayInputStream;
2627
import java.io.File;
27-
import java.io.FileNotFoundException;
2828
import java.io.FileOutputStream;
29+
import java.io.IOException;
2930
import java.nio.file.Files;
3031
import java.nio.file.Path;
3132
import java.nio.file.Paths;
@@ -44,7 +45,21 @@ public static void run(EngineConfig config) {
4445
callback = ProgressCallback.CONSOLE;
4546
}
4647

47-
// Clear corrupted files tracking
48+
// Clear all state for re-entrant safety
49+
AnalyzeEnv.classFileList.clear();
50+
AnalyzeEnv.discoveredClasses.clear();
51+
AnalyzeEnv.discoveredMethods.clear();
52+
AnalyzeEnv.methodsInClassMap.clear();
53+
AnalyzeEnv.classMap.clear();
54+
AnalyzeEnv.methodMap.clear();
55+
AnalyzeEnv.methodCalls.clear();
56+
AnalyzeEnv.strMap.clear();
57+
AnalyzeEnv.controllers.clear();
58+
AnalyzeEnv.interceptors.clear();
59+
AnalyzeEnv.servlets.clear();
60+
AnalyzeEnv.filters.clear();
61+
AnalyzeEnv.listeners.clear();
62+
AnalyzeEnv.stringAnnoMap.clear();
4863
AnalyzeEnv.corruptedFiles.clear();
4964

5065
// Setup JarUtil with black/white list
@@ -78,7 +93,12 @@ public static void run(EngineConfig config) {
7893
if (s.toLowerCase().endsWith(".jar") ||
7994
s.toLowerCase().endsWith(".war")) {
8095
DatabaseManager.saveJar(s);
81-
jarIdMap.put(s, DatabaseManager.getJarId(s).getJid());
96+
JarEntity jarEntity = DatabaseManager.getJarId(s);
97+
if (jarEntity != null) {
98+
jarIdMap.put(s, jarEntity.getJid());
99+
} else {
100+
logger.error("save jar failed, cannot get jar id: {}", s);
101+
}
82102
}
83103
}
84104
cfs = CoreUtil.getAllClassesFromJars(files, jarIdMap);
@@ -94,7 +114,12 @@ public static void run(EngineConfig config) {
94114
callback.onStats("totalJar", String.valueOf(jarList.size()));
95115
for (String s : jarList) {
96116
DatabaseManager.saveJar(s);
97-
jarIdMap.put(s, DatabaseManager.getJarId(s).getJid());
117+
JarEntity jarEntity = DatabaseManager.getJarId(s);
118+
if (jarEntity != null) {
119+
jarIdMap.put(s, jarEntity.getJid());
120+
} else {
121+
logger.error("save jar failed, cannot get jar id: {}", s);
122+
}
98123
}
99124
cfs = CoreUtil.getAllClassesFromJars(jarList, jarIdMap);
100125
}
@@ -103,35 +128,42 @@ public static void run(EngineConfig config) {
103128
for (ClassFileEntity cf : cfs) {
104129
String className = cf.getClassName();
105130
if (!fixClass) {
106-
int i = className.indexOf("classes");
107131
if (className.contains("BOOT-INF") || className.contains("WEB-INF")) {
108-
className = className.substring(i + 8);
132+
int i = className.indexOf("classes");
133+
if (i >= 0) {
134+
className = className.substring(i + 8);
135+
}
109136
}
110137
cf.setClassName(className);
111138
} else {
112139
Path parPath = Paths.get(EngineConst.tempDir);
113140
FixClassVisitor cv = new FixClassVisitor();
141+
byte[] fileBytes = cf.getFile();
142+
if (fileBytes == null) {
143+
logger.error("cannot read class file: {}", cf.getClassName());
144+
continue;
145+
}
114146
try {
115-
ClassReader cr = new ClassReader(cf.getFile());
147+
ClassReader cr = new ClassReader(fileBytes);
116148
cr.accept(cv, EngineConst.AnalyzeASMOptions);
117149
} catch (IndexOutOfBoundsException e) {
118-
if (!StackMapFrameHandler.handleParseException(cf.getFile(), cv,
150+
if (!StackMapFrameHandler.handleParseException(fileBytes, cv,
119151
cf.getJarName() + "!" + cf.getClassName(),
120152
logger, "fix class name", e)) {
121153
throw e;
122154
}
123155
}
124156
Path path = parPath.resolve(Paths.get(cv.getName()));
125157
File file = path.toFile();
126-
if (!file.getParentFile().mkdirs()) {
158+
if (!file.getParentFile().exists() && !file.getParentFile().mkdirs()) {
127159
logger.error("fix class mkdirs error");
128160
}
129161
className = file.getPath() + ".class";
130-
try {
131-
IOUtil.copy(new ByteArrayInputStream(cf.getFile()),
132-
new FileOutputStream(className));
133-
} catch (FileNotFoundException ignored) {
134-
logger.error("fix path copy bytes error");
162+
try (ByteArrayInputStream bis = new ByteArrayInputStream(fileBytes);
163+
FileOutputStream fos = new FileOutputStream(className)) {
164+
IOUtil.copy(bis, fos);
165+
} catch (IOException ex) {
166+
logger.error("fix path copy bytes error: {}", ex.toString());
135167
}
136168
cf.setClassName(className);
137169
cf.setPath(Paths.get(className));
@@ -209,9 +241,14 @@ public static void run(EngineConfig config) {
209241

210242
for (ClassFileEntity file : AnalyzeEnv.classFileList) {
211243
try {
244+
byte[] fileBytes = file.getFile();
245+
if (fileBytes == null) {
246+
logger.error("cannot read class file for string analysis: {}", file.getClassName());
247+
continue;
248+
}
212249
StringClassVisitor dcv = new StringClassVisitor(
213250
AnalyzeEnv.strMap, AnalyzeEnv.classMap, AnalyzeEnv.methodMap);
214-
ClassReader cr = new ClassReader(file.getFile());
251+
ClassReader cr = new ClassReader(fileBytes);
215252
cr.accept(dcv, EngineConst.AnalyzeASMOptions);
216253
} catch (IndexOutOfBoundsException e) {
217254
if (!StackMapFrameHandler.handleParseException(file,
@@ -272,6 +309,12 @@ public static void run(EngineConfig config) {
272309
AnalyzeEnv.methodMap.clear();
273310
AnalyzeEnv.methodCalls.clear();
274311
AnalyzeEnv.strMap.clear();
312+
AnalyzeEnv.stringAnnoMap.clear();
313+
AnalyzeEnv.interceptors.clear();
314+
AnalyzeEnv.servlets.clear();
315+
AnalyzeEnv.filters.clear();
316+
AnalyzeEnv.listeners.clear();
317+
AnalyzeEnv.corruptedFiles.clear();
275318
if (!quickMode) {
276319
if (AnalyzeEnv.inheritanceMap != null) {
277320
AnalyzeEnv.inheritanceMap.getInheritanceMap().clear();

src/main/java/me/n1ar4/jar/analyzer/engine/utils/DirUtil.java

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -20,30 +20,29 @@
2020
@SuppressWarnings("all")
2121
public class DirUtil {
2222
private static final Logger logger = LogManager.getLogger();
23-
private static final List<String> filenames = new ArrayList<>();
2423

2524
public static List<String> GetFiles(String path) {
26-
filenames.clear();
27-
return getFiles(path);
25+
List<String> filenames = new ArrayList<>();
26+
getFiles(path, filenames);
27+
return filenames;
2828
}
2929

30-
private static List<String> getFiles(String path) {
30+
private static void getFiles(String path, List<String> filenames) {
3131
File file = new File(path);
3232
if (file.isDirectory()) {
3333
File[] files = file.listFiles();
3434
if (files == null) {
35-
return filenames;
35+
return;
3636
}
3737
for (File value : files) {
3838
if (value.isDirectory()) {
39-
getFiles(value.getPath());
39+
getFiles(value.getPath(), filenames);
4040
} else {
4141
filenames.add(value.getAbsolutePath());
4242
}
4343
}
4444
} else {
4545
filenames.add(file.getAbsolutePath());
4646
}
47-
return filenames;
4847
}
4948
}

0 commit comments

Comments
 (0)