Skip to content

Commit 8bf0272

Browse files
authored
Merge pull request #2137 from MarcMil/mdev
Do not alter semantics when propagating class constants
2 parents 0c81657 + ce07530 commit 8bf0272

File tree

5 files changed

+127
-4
lines changed

5 files changed

+127
-4
lines changed

src/main/java/soot/dexpler/DalvikThrowAnalysis.java

+4
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@
4848
import soot.NullType;
4949
import soot.PrimType;
5050
import soot.RefLikeType;
51+
import soot.RefType;
5152
import soot.Scene;
5253
import soot.Singletons;
5354
import soot.SootMethod;
@@ -297,6 +298,9 @@ public void caseClassConstant(ClassConstant c) {
297298
// would be detected there.
298299
//
299300
// result = result.add(mgr.RESOLVE_CLASS_ERRORS);
301+
302+
// that being said, a NoClassDefFoundError is possible nonetheless.
303+
result = result.add(RefType.v("java.lang.NoClassDefFoundError"));
300304
}
301305

302306
@Override
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
package soot.jimple.toolkits.scalar;
2+
3+
import soot.Body;
4+
import soot.FastHierarchy;
5+
import soot.RefType;
6+
import soot.Scene;
7+
import soot.Trap;
8+
import soot.Unit;
9+
import soot.UnitPatchingChain;
10+
import soot.Value;
11+
import soot.ValueBox;
12+
import soot.jimple.ClassConstant;
13+
import soot.jimple.DefinitionStmt;
14+
import soot.toolkits.graph.ExceptionalUnitGraph;
15+
import soot.toolkits.graph.ExceptionalUnitGraph.ExceptionDest;
16+
17+
/*-
18+
* #%L
19+
* Soot - a J*va Optimization Framework
20+
* %%
21+
* Copyright (C) 2000 Patrick Lam
22+
* %%
23+
* This program is free software: you can redistribute it and/or modify
24+
* it under the terms of the GNU Lesser General Public License as
25+
* published by the Free Software Foundation, either version 2.1 of the
26+
* License, or (at your option) any later version.
27+
*
28+
* This program is distributed in the hope that it will be useful,
29+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
30+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
31+
* GNU General Lesser Public License for more details.
32+
*
33+
* You should have received a copy of the GNU General Lesser Public
34+
* License along with this program. If not, see
35+
* <http://www.gnu.org/licenses/lgpl-2.1.html>.
36+
* #L%
37+
*/
38+
39+
/**
40+
* Contains utility methods for constant propagation
41+
*/
42+
public class ConstantPropagatorUtils {
43+
44+
/**
45+
* Checks whether propagating <i>propagatedValue</i> from <i>defFrom</i> to <i>defTo</i> is safe.
46+
* @param graph an exceptional unit graph
47+
* @param propagatedValue the propagated value
48+
* @param defFrom definition source
49+
* @param defTo target
50+
* @param targetBox the target box
51+
* @return true if and only if propagation is safe w.r.t. trap handling
52+
*/
53+
public static boolean mayPropagate(ExceptionalUnitGraph graph, Value propagatedValue, DefinitionStmt defFrom, Unit defTo,
54+
ValueBox targetBox) {
55+
if (!targetBox.canContainValue(propagatedValue)) {
56+
return false;
57+
}
58+
if (propagatedValue instanceof ClassConstant) {
59+
//Class Constants can trigger a NoClassDefFoundError.
60+
//Therefore, we must not propagate them, since we might change the semantics of the original
61+
//program w.r.t. traps.
62+
RefType rt = RefType.v("java.lang.NoClassDefFoundError");
63+
Trap trap = null;
64+
for (ExceptionDest d : graph.getExceptionDests(defFrom)) {
65+
if (d.getThrowables().catchableAs(rt)) {
66+
trap = d.getTrap();
67+
break;
68+
}
69+
}
70+
Body body = graph.getBody();
71+
FastHierarchy fh = Scene.v().getOrMakeFastHierarchy();
72+
UnitPatchingChain chain = body.getUnits();
73+
74+
//this is not super fast, but the exceptional unit graph is not helpful here, since
75+
//we would need to rebuild it after propagation to reflect the changes, which would be more expensive.
76+
for (Trap i : body.getTraps()) {
77+
if (trap != null && i.getHandlerUnit() != trap.getHandlerUnit()) {
78+
continue;
79+
}
80+
if (fh.canStoreType(rt, i.getException().getType())) {
81+
Unit u = i.getBeginUnit();
82+
while (u != i.getEndUnit()) {
83+
if (u == defTo) {
84+
//when the original code had the same handling unit, this is fine.
85+
//if there is none, this is not fine.
86+
return trap != null;
87+
}
88+
u = chain.getSuccOf(u);
89+
}
90+
}
91+
}
92+
//we have not found a trap, so the original code must not have one, either
93+
return trap == null;
94+
}
95+
96+
return true;
97+
}
98+
99+
private static Unit getTrapHandler(ExceptionalUnitGraph graph, Unit def, RefType rtException) {
100+
for (ExceptionDest d : graph.getExceptionDests(def)) {
101+
if (d.getThrowables().catchableAs(rtException)) {
102+
return d.getHandlerNode();
103+
}
104+
}
105+
return null;
106+
}
107+
108+
}

src/main/java/soot/jimple/toolkits/scalar/CopyPropagator.java

+4-3
Original file line numberDiff line numberDiff line change
@@ -57,9 +57,9 @@
5757
import soot.tagkit.SourceLnPosTag;
5858
import soot.tagkit.Tag;
5959
import soot.toolkits.exceptions.ThrowAnalysis;
60+
import soot.toolkits.graph.ExceptionalUnitGraph;
6061
import soot.toolkits.graph.ExceptionalUnitGraphFactory;
6162
import soot.toolkits.graph.PseudoTopologicalOrderer;
62-
import soot.toolkits.graph.UnitGraph;
6363
import soot.toolkits.scalar.LocalDefs;
6464

6565
public class CopyPropagator extends BodyTransformer {
@@ -137,7 +137,7 @@ protected void internalTransform(Body b, String phaseName, Map<String, String> o
137137
int fastCopyPropagationCount = 0;
138138
int slowCopyPropagationCount = 0;
139139

140-
UnitGraph graph
140+
ExceptionalUnitGraph graph
141141
= ExceptionalUnitGraphFactory.createExceptionalUnitGraph(b, throwAnalysis, forceOmitExceptingUnitEdges);
142142
LocalDefs localDefs = G.v().soot_toolkits_scalar_LocalDefsFactory().newLocalDefs(graph);
143143
CPOptions options = new CPOptions(opts);
@@ -192,10 +192,11 @@ protected void internalTransform(Body b, String phaseName, Map<String, String> o
192192
final Value rightOp = def.getRightOp();
193193

194194
if (rightOp instanceof Constant) {
195-
if (useBox.canContainValue(rightOp)) {
195+
if (ConstantPropagatorUtils.mayPropagate(graph, rightOp, def, u, useBox)) {
196196
useBox.setValue(rightOp);
197197
copyLineTags(useBox, def);
198198
}
199+
199200
} else if (rightOp instanceof CastExpr) {
200201
CastExpr ce = (CastExpr) rightOp;
201202
if (ce.getCastType() instanceof RefLikeType) {

src/main/java/soot/toolkits/exceptions/UnitThrowAnalysis.java

+1
Original file line numberDiff line numberDiff line change
@@ -892,6 +892,7 @@ public void caseStringConstant(StringConstant c) {
892892

893893
@Override
894894
public void caseClassConstant(ClassConstant c) {
895+
result = result.add(RefType.v("java.lang.NoClassDefFoundError"));
895896
}
896897

897898
@Override

src/main/java/soot/toolkits/scalar/FlowSensitiveConstantPropagator.java

+10-1
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@
4444
import soot.dexpler.DexNullArrayRefTransformer;
4545
import soot.dexpler.DexNullThrowTransformer;
4646
import soot.jimple.AssignStmt;
47+
import soot.jimple.ClassConstant;
4748
import soot.jimple.CmpgExpr;
4849
import soot.jimple.CmplExpr;
4950
import soot.jimple.Constant;
@@ -344,7 +345,15 @@ protected void flowThrough(ConstantState in, Unit d, ConstantState out) {
344345
Object rop = assign.getRightOp();
345346
Constant value = null;
346347
if (rop instanceof Constant) {
347-
value = (Constant) rop;
348+
//Class Constants can trigger a NoClassDefFoundError.
349+
//Therefore, cannot not propagate them in some cases, since we might change the semantics of the original
350+
//program w.r.t. traps.
351+
//The normal constant propagator propagates them when they are safe to propagate.
352+
//Implementing this here is harder,
353+
//since we need to keep track of trap handlers at all assigns in the original code.
354+
if (!(rop instanceof ClassConstant)) {
355+
value = (Constant) rop;
356+
}
348357
} else {
349358
if (rop instanceof Local) {
350359
value = in.getConstant((Local) rop);

0 commit comments

Comments
 (0)