Skip to content

Commit f5bbde5

Browse files
author
Erik Derr
committed
HashTree refactoring
- config moved to TreeConfig class - added setter for tree config
1 parent 86f51a0 commit f5bbde5

File tree

9 files changed

+68
-76
lines changed

9 files changed

+68
-76
lines changed

src/de/infsec/tpl/hashtree/HashTree.java

Lines changed: 11 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,7 @@
1515
package de.infsec.tpl.hashtree;
1616

1717

18-
import com.google.common.hash.HashFunction;
1918
import com.google.common.hash.Hasher;
20-
import com.google.common.hash.Hashing;
2119
import com.ibm.wala.classLoader.IClass;
2220
import com.ibm.wala.classLoader.IMethod;
2321
import com.ibm.wala.ipa.cha.IClassHierarchy;
@@ -69,24 +67,7 @@ public class HashTree implements Serializable {
6967

7068
private Node rootNode;
7169

72-
protected Config config = new Config();
73-
74-
public static class Config implements Serializable {
75-
private static final long serialVersionUID = 1190771073564531337L;
76-
77-
public static HashFunction hf = Hashing.md5();
78-
public static AccessFlags accessFlagsFilter = AccessFlags.NO_FLAG;
79-
80-
// verboseness
81-
public static boolean keepPackageNames = true;
82-
public static boolean keepClassNames = false;
83-
public static boolean keepMethodSignatures = false;
84-
85-
// node pruning
86-
public static boolean pruneClasses = false;
87-
public static boolean pruneMethods = true;
88-
}
89-
70+
protected TreeConfig config = new TreeConfig();
9071

9172
public HashTree() {
9273
this(new DefaultPackageNodeComp(), new DefaultClassNodeComp(), new SignatureMethodNodeComp());
@@ -107,8 +88,7 @@ public boolean equals(Object obj) {
10788
}
10889

10990

110-
public static Node compNode(Collection<? extends Node> nodes, boolean prune) {
111-
Hasher hasher = getHasher();
91+
public static Node compNode(Collection<? extends Node> nodes, boolean prune, Hasher hasher) {
11292
nodes.stream().sorted(HashUtils.comp).forEach(n -> hasher.putBytes(n.hash));
11393

11494
Node n = new Node(hasher.hash().asBytes());
@@ -118,10 +98,6 @@ public static Node compNode(Collection<? extends Node> nodes, boolean prune) {
11898
}
11999

120100
public void generate(IClassHierarchy cha) {
121-
generate(cha, Short.MIN_VALUE);
122-
}
123-
124-
protected void generate(IClassHierarchy cha, Short nodeId) {
125101
logger.debug("Generate hash tree..");
126102

127103
int classHashCount = 0;
@@ -136,15 +112,15 @@ protected void generate(IClassHierarchy cha, Short nodeId) {
136112
Collection<IMethod> methods = clazz.getDeclaredMethods();
137113

138114
// filter methods by access flag
139-
if (Config.accessFlagsFilter != AccessFlags.NO_FLAG) {
115+
if (config.accessFlagsFilter != AccessFlags.NO_FLAG) {
140116
methods = methods.stream()
141-
.filter(m -> { int code = AccessFlags.getMethodAccessCode(m); return code > 0 && (code & Config.accessFlagsFilter.getValue()) == 0x0; }) // if predicate is true, keep in list
117+
.filter(m -> { int code = AccessFlags.getMethodAccessCode(m); return code > 0 && (code & config.accessFlagsFilter.getValue()) == 0x0; }) // if predicate is true, keep in list
142118
.collect(Collectors.toCollection(ArrayList::new));
143119
}
144120

145121
List<MethodNode> methodNodes = methods.stream()
146122
.filter(m -> !(m.isBridge() || m.isMethodSynthetic())) // normalize java|dex bytecode by skipping compiler-generated methods
147-
.map(m -> mnComp.comp(m, true /* TODO to be changed */))
123+
.map(m -> mnComp.comp(m, config))
148124
.sorted(HashUtils.comp) // sort but do not filter dups
149125
.collect(Collectors.toList());
150126

@@ -158,11 +134,7 @@ protected void generate(IClassHierarchy cha, Short nodeId) {
158134
methodHashCount += methodNodes.size();
159135
classHashCount++;
160136

161-
ClassNode clazzNode = cnComp.comp(methodNodes, clazz, Config.pruneMethods);
162-
163-
// annotate class and method nodes
164-
if (nodeId > 0)
165-
annotate(clazzNode, nodeId, true);
137+
ClassNode clazzNode = cnComp.comp(methodNodes, clazz, config);
166138

167139
// keep track on classes per package
168140
String pckgName = PackageUtils.getPackageName(clazz);
@@ -175,18 +147,12 @@ protected void generate(IClassHierarchy cha, Short nodeId) {
175147

176148
packageMap.values().forEach(l -> l.sort(HashUtils.comp)); // sort class nodes
177149
List<PackageNode> packageNodes = packageMap.keySet().stream()
178-
.map(p -> pnComp.comp(packageMap.get(p), p, cha, Config.pruneClasses))
150+
.map(p -> pnComp.comp(packageMap.get(p), p, cha, config))
179151
.sorted(HashUtils.comp)
180152
.collect(Collectors.toList());
181153

182154
// generate root
183-
rootNode = compNode(packageNodes, false);
184-
185-
// annotate root and package nodes
186-
if (nodeId > 0) {
187-
packageNodes.forEach(pn -> annotate(pn, nodeId, false));
188-
annotate(rootNode, nodeId, false);
189-
}
155+
rootNode = compNode(packageNodes, false, config.getHasher());
190156

191157
logger.debug(Utils.INDENT + "- generated " + packageNodes.size() + " package hashes.");
192158
logger.debug(Utils.INDENT + "- generated " + classHashCount + " clazz hashes.");
@@ -195,14 +161,6 @@ protected void generate(IClassHierarchy cha, Short nodeId) {
195161
}
196162

197163

198-
private void annotate(Node n, Short id, boolean inclChilds) {
199-
n.versions.add(id);
200-
201-
if (inclChilds)
202-
n.childs.forEach(c -> c.versions.add(id));
203-
}
204-
205-
206164
/*
207165
* Getter methods
208166
*/
@@ -214,16 +172,14 @@ public byte[] getRootHash() {
214172
return this.rootNode.hash;
215173
}
216174

217-
public Config getConfig() {
175+
public TreeConfig getConfig() {
218176
return this.config;
219177
}
220178

221-
public static Hasher getHasher() {
222-
return Config.hf.newHasher();
179+
public void setConfig(TreeConfig config) {
180+
this.config = config;
223181
}
224182

225-
226-
227183
public static List<PackageNode> toPackageNode(Collection<Node> col) {
228184
return col.stream()
229185
.filter(n -> n instanceof PackageNode)
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
package de.infsec.tpl.hashtree;
2+
3+
import com.google.common.hash.HashFunction;
4+
import com.google.common.hash.Hasher;
5+
import com.google.common.hash.Hashing;
6+
import de.infsec.tpl.hash.AccessFlags;
7+
8+
import java.io.Serializable;
9+
10+
public class TreeConfig implements Serializable {
11+
private static final long serialVersionUID = 1190771073563431337L;
12+
13+
public HashFunction hf = Hashing.md5();
14+
public AccessFlags accessFlagsFilter = AccessFlags.NO_FLAG;
15+
16+
// verboseness
17+
public boolean keepPackageNames = true;
18+
public boolean keepClassNames = false;
19+
public boolean keepMethodSignatures = false;
20+
21+
// node pruning
22+
public boolean pruneClasses = false;
23+
public boolean pruneMethods = true;
24+
25+
26+
public Hasher getHasher() {
27+
return hf.newHasher();
28+
}
29+
}

src/de/infsec/tpl/hashtree/comp/clazz/DefaultClassNodeComp.java

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import com.ibm.wala.classLoader.IClass;
44
import de.infsec.tpl.hashtree.HashTree;
5+
import de.infsec.tpl.hashtree.TreeConfig;
56
import de.infsec.tpl.hashtree.node.ClassNode;
67
import de.infsec.tpl.hashtree.node.Node;
78
import de.infsec.tpl.utils.WalaUtils;
@@ -12,12 +13,12 @@
1213
public class DefaultClassNodeComp implements IClassNodeComp {
1314

1415
@Override
15-
public ClassNode comp(Collection<? extends Node> methodNodes, IClass clazz, boolean prune) {
16-
String className = HashTree.Config.keepClassNames ? WalaUtils.simpleName(clazz) : "";
16+
public ClassNode comp(Collection<? extends Node> methodNodes, IClass clazz, TreeConfig config) {
17+
String className = config.keepClassNames ? WalaUtils.simpleName(clazz) : "";
1718

1819
// default behaviour, just create hash from child nodes
19-
ClassNode cn = new ClassNode(HashTree.compNode(methodNodes, true).hash, className);
20-
if (!prune) cn.childs = new ArrayList<>(methodNodes);
20+
ClassNode cn = new ClassNode(HashTree.compNode(methodNodes, true, config.getHasher()).hash, className);
21+
if (!config.pruneMethods) cn.childs = new ArrayList<>(methodNodes);
2122

2223
return cn;
2324
}
Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
package de.infsec.tpl.hashtree.comp.clazz;
22

33
import com.ibm.wala.classLoader.IClass;
4+
import de.infsec.tpl.hashtree.TreeConfig;
45
import de.infsec.tpl.hashtree.node.ClassNode;
56
import de.infsec.tpl.hashtree.node.Node;
67

78
import java.util.Collection;
89

910
public interface IClassNodeComp {
10-
ClassNode comp(Collection<? extends Node> methodNodes, IClass clazz, boolean prune);
11+
ClassNode comp(Collection<? extends Node> methodNodes, IClass clazz, TreeConfig config);
1112
}
Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
package de.infsec.tpl.hashtree.comp.method;
22

33
import com.ibm.wala.classLoader.IMethod;
4+
import de.infsec.tpl.hashtree.TreeConfig;
45
import de.infsec.tpl.hashtree.node.MethodNode;
56

67
public interface IMethodNodeComp {
7-
MethodNode comp(IMethod m, boolean prune);
8+
MethodNode comp(IMethod m, TreeConfig config);
89
}

src/de/infsec/tpl/hashtree/comp/method/SignatureMethodNodeComp.java

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import com.ibm.wala.types.ClassLoaderReference;
66
import com.ibm.wala.types.Descriptor;
77
import de.infsec.tpl.hashtree.HashTree;
8+
import de.infsec.tpl.hashtree.TreeConfig;
89
import de.infsec.tpl.hashtree.node.MethodNode;
910
import de.infsec.tpl.utils.Utils;
1011
import de.infsec.tpl.utils.WalaUtils;
@@ -17,13 +18,13 @@ public class SignatureMethodNodeComp implements IMethodNodeComp {
1718

1819

1920
@Override
20-
public MethodNode comp(IMethod m, boolean prune) {
21+
public MethodNode comp(IMethod m, TreeConfig config) {
2122
String desc = normalizeAnonymousInnerClassConstructor(m);
2223
if (desc == null)
2324
desc = getFuzzyDescriptor(m);
2425

25-
String signature = HashTree.Config.keepMethodSignatures? m.getSignature() : "";
26-
return new MethodNode(HashTree.getHasher().putBytes(desc.getBytes()).hash().asBytes(), signature);
26+
String signature = config.keepMethodSignatures? m.getSignature() : "";
27+
return new MethodNode(config.getHasher().putBytes(desc.getBytes()).hash().asBytes(), signature);
2728
}
2829

2930

src/de/infsec/tpl/hashtree/comp/pckg/DefaultPackageNodeComp.java

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import com.ibm.wala.ipa.cha.IClassHierarchy;
44
import de.infsec.tpl.hashtree.HashTree;
5+
import de.infsec.tpl.hashtree.TreeConfig;
56
import de.infsec.tpl.hashtree.node.Node;
67
import de.infsec.tpl.hashtree.node.PackageNode;
78
import org.slf4j.Logger;
@@ -14,11 +15,11 @@ public class DefaultPackageNodeComp implements IPackageNodeComp {
1415
private static final Logger logger = LoggerFactory.getLogger(HashTree.class);
1516

1617
@Override
17-
public PackageNode comp(Collection<? extends Node> classNodes, String packageName, IClassHierarchy cha, boolean prune) {
18+
public PackageNode comp(Collection<? extends Node> classNodes, String packageName, IClassHierarchy cha, TreeConfig config) {
1819

1920
// default behaviour, just create hash from child nodes
20-
PackageNode pn = new PackageNode(HashTree.compNode(classNodes, false).hash, (HashTree.Config.keepPackageNames? packageName : ""));
21-
if (!prune) pn.childs = new ArrayList<>(classNodes);
21+
PackageNode pn = new PackageNode(HashTree.compNode(classNodes, false, config.getHasher()).hash, (config.keepPackageNames? packageName : ""));
22+
if (!config.pruneClasses) pn.childs = new ArrayList<>(classNodes);
2223

2324
return pn;
2425
}
Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
package de.infsec.tpl.hashtree.comp.pckg;
22

33
import com.ibm.wala.ipa.cha.IClassHierarchy;
4+
import de.infsec.tpl.hashtree.TreeConfig;
45
import de.infsec.tpl.hashtree.node.Node;
56
import de.infsec.tpl.hashtree.node.PackageNode;
67

78
import java.util.Collection;
89

910
public interface IPackageNodeComp {
10-
PackageNode comp(Collection<? extends Node> classNodes, String packageName, IClassHierarchy cha, boolean prune);
11+
PackageNode comp(Collection<? extends Node> classNodes, String packageName, IClassHierarchy cha, TreeConfig config);
1112
}

src/de/infsec/tpl/profile/ProfileMatch.java

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424

2525
import de.infsec.tpl.config.LibScoutConfig;
2626
import de.infsec.tpl.hashtree.HashTree;
27+
import de.infsec.tpl.hashtree.TreeConfig;
2728
import de.infsec.tpl.hashtree.node.PackageNode;
2829
import de.infsec.tpl.stats.Exportable;
2930
import org.slf4j.Logger;
@@ -61,7 +62,7 @@ public enum MatchLevel {PACKAGE, CLASS, METHOD};
6162
private List<HTreeMatch> results;
6263

6364
public class HTreeMatch {
64-
public HashTree.Config config; // identifier - config
65+
public TreeConfig config; // identifier - config
6566

6667
public List<PackageNode> matchingNodes; // list of package nodes that matched (partially)
6768
public Float simScore = MATCH_HTREE_NONE; // between 0f..1f for partial match
@@ -70,7 +71,7 @@ public class HTreeMatch {
7071
public String rootPackage;
7172

7273

73-
public HTreeMatch(HashTree.Config config) {
74+
public HTreeMatch(TreeConfig config) {
7475
this.config = config;
7576
}
7677

@@ -134,7 +135,7 @@ public void addResult(HTreeMatch res) {
134135
Collections.sort(results, SIM_SCORE_COMPARATOR); // ensure that results are sorted
135136
}
136137

137-
public HTreeMatch getResultByConfig(HashTree.Config cfg) {
138+
public HTreeMatch getResultByConfig(TreeConfig cfg) {
138139
for (HTreeMatch htm: results)
139140
if (htm.config.equals(cfg))
140141
return htm;
@@ -157,7 +158,7 @@ public void printResults(int topX) {
157158
}
158159

159160

160-
public HTreeMatch createResult(HashTree.Config config) {
161+
public HTreeMatch createResult(TreeConfig config) {
161162
return new HTreeMatch(config);
162163
}
163164

@@ -228,8 +229,8 @@ public boolean isPartialMatch() {
228229

229230

230231

231-
public List<HashTree.Config> getMatchedConfigs() {
232-
ArrayList<HashTree.Config> result = new ArrayList<>();
232+
public List<TreeConfig> getMatchedConfigs() {
233+
ArrayList<TreeConfig> result = new ArrayList<>();
233234
for (HTreeMatch htm: results) {
234235
if (htm.isFullMatch())
235236
result.add(htm.config);
@@ -238,8 +239,8 @@ public List<HashTree.Config> getMatchedConfigs() {
238239
return result;
239240
}
240241

241-
public List<HashTree.Config> getPartiallyMatchedConfigs() {
242-
ArrayList<HashTree.Config> result = new ArrayList<>();
242+
public List<TreeConfig> getPartiallyMatchedConfigs() {
243+
ArrayList<TreeConfig> result = new ArrayList<>();
243244
for (HTreeMatch htm: results) {
244245
if (htm.isPartialMatch())
245246
result.add(htm.config);

0 commit comments

Comments
 (0)