}
- /*
- public static ReachSet toCalleeContext( ReachSet rs,
- AllocSite as ) {
- assert rs != null;
- assert as != null;
- assert rs.isCanonical();
- assert as.isCanonical();
-
- CanonicalOp op =
- new CanonicalOp( CanonicalOp.REACHSET_TOCALLEECONTEXT_ALLOCSITE,
- rs,
- as );
-
- Canonical result = op2result.get( op );
- if( result != null ) {
- return (ReachSet) result;
- }
-
- // otherwise, no cached result...
- ReachSet out = ReachSet.factory();
- Iterator<ReachState> itr = rs.iterator();
- while( itr.hasNext() ) {
- ReachState state = itr.next();
- out = Canonical.add( out,
- Canonical.toCalleeContext( state, as )
- );
- }
-
- assert out.isCanonical();
- op2result.put( op, out );
- return out;
- }
- */
-
- /*
- public static ReachState toCalleeContext( ReachState state,
- AllocSite as ) {
- assert state != null;
- assert as != null;
- assert state.isCanonical();
- assert as.isCanonical();
-
- CanonicalOp op =
- new CanonicalOp( CanonicalOp.REACHSTATE_TOCALLEECONTEXT_ALLOCSITE,
- state,
- as );
-
- Canonical result = op2result.get( op );
- if( result != null ) {
- return (ReachState) result;
- }
-
- // otherwise, no cached result...
- ReachState out = ReachState.factory();
- Iterator<ReachTuple> itr = state.iterator();
- while( itr.hasNext() ) {
- ReachTuple rt = itr.next();
-
- int age = as.getAgeCategory( rt.getHrnID() );
-
- // this is the current mapping, where 0, 1, 2S were allocated
- // in the current context, 0?, 1? and 2S? were allocated in a
- // previous context, and we're translating to a future context
- //
- // 0 -> 0?
- // 1 -> 1?
- // 2S -> 2S?
- // 2S* -> 2S?*
- //
- // 0? -> 2S?
- // 1? -> 2S?
- // 2S? -> 2S?
- // 2S?* -> 2S?*
-
- if( age == AllocSite.AGE_notInThisSite ) {
- // things not from the site just go back in
- out = Canonical.union( out, rt );
-
- } else if( age == AllocSite.AGE_summary ||
- rt.isOutOfContext()
- ) {
- // the in-context summary and all existing out-of-context
- // stuff all become
- out = Canonical.union( out,
- ReachTuple.factory( as.getSummary(),
- true, // multi
- rt.getArity(),
- true // out-of-context
- )
- );
- } else {
- // otherwise everything else just goes to an out-of-context
- // version, everything else the same
- Integer I = as.getAge( rt.getHrnID() );
- assert I != null;
-
- assert !rt.isMultiObject();
-
- out = Canonical.union( out,
- ReachTuple.factory( rt.getHrnID(),
- rt.isMultiObject(),
- rt.getArity(),
- true // out-of-context
- )
- );
- }
- }
-
- out = Canonical.attach( out,
- state.getPreds()
- );
-
- assert out.isCanonical();
- op2result.put( op, out );
- return out;
- }
- */
-
-
public static ReachSet toCallerContext( ReachSet rs,
AllocSite as ) {
assert rs != null;
}
+ public static Taint attach( Taint t,
+ ExistPredSet preds ) {
+ assert t != null;
+ assert preds != null;
+ assert t.isCanonical();
+ assert preds.isCanonical();
+
+ CanonicalOp op =
+ new CanonicalOp( CanonicalOp.TAINT_ATTACH_EXISTPREDSET,
+ t,
+ preds );
+
+ Canonical result = op2result.get( op );
+ if( result != null ) {
+ return (Taint) result;
+ }
+
+ // otherwise, no cached result...
+ Taint out = new Taint( t.sese,
+ t.insetVar,
+ t.allocSite );
+ out.preds = Canonical.join( t.preds,
+ preds );
+
+ out = (Taint) makeCanonical( out );
+ op2result.put( op, out );
+ return out;
+ }
+
public static TaintSet add( TaintSet ts,
Taint t ) {
assert ts != null;
Taint t2 = ts2.containsIgnorePreds( t1 );
if( t2 != null ) {
- out.taints.add( Taint.factory( t1.callSite,
- t1.paramIndex,
- t1.sese,
+ out.taints.add( Taint.factory( t1.sese,
t1.insetVar,
t1.allocSite,
Canonical.join( t1.preds,
return out;
}
+ public static TaintSet unionORpreds( TaintSet ts1,
+ TaintSet ts2 ) {
+ assert ts1 != null;
+ assert ts2 != null;
+ assert ts1.isCanonical();
+ assert ts2.isCanonical();
+
+ CanonicalOp op =
+ new CanonicalOp( CanonicalOp.TAINTSET_UNIONORPREDS_TAINTSET,
+ ts1,
+ ts2 );
+
+ Canonical result = op2result.get( op );
+ if( result != null ) {
+ return (TaintSet) result;
+ }
+
+ // otherwise, no cached result...
+ TaintSet out = new TaintSet();
+
+ // first add everything from 1, and if it was also in 2
+ // take the OR of the predicates
+ Iterator<Taint> tItr = ts1.iterator();
+ while( tItr.hasNext() ) {
+ Taint t1 = tItr.next();
+ Taint t2 = ts2.containsIgnorePreds( t1 );
+
+ if( t2 != null ) {
+ out.taints.add( Taint.factory( t1.sese,
+ t1.insetVar,
+ t1.allocSite,
+ Canonical.join( t1.preds,
+ t2.preds
+ )
+ ) );
+ } else {
+ out.taints.add( t1 );
+ }
+ }
+
+ // then add everything in 2 that wasn't in 1
+ tItr = ts2.iterator();
+ while( tItr.hasNext() ) {
+ Taint t2 = tItr.next();
+ Taint t1 = ts1.containsIgnorePreds( t2 );
+
+ if( t1 == null ) {
+ out.taints.add( t2 );
+ }
+ }
+
+ out = (TaintSet) makeCanonical( out );
+ op2result.put( op, out );
+ return out;
+ }
+
}
edgeNew.getPreds()
)
);
-
+ edgeExisting.setTaints(
+ Canonical.unionORpreds( edgeExisting.getTaints(),
+ edgeNew.getTaints()
+ )
+ );
+
} else {
addRefEdge( src, dst, edgeNew );
}
) {
ReachSet out = ReachSet.factory();
+ // when the mapping is null it means there were no
+ // predicates satisfied
+ if( calleeStatesSatisfied == null ) {
+ return out;
+ }
+
Iterator<ReachState> itr = rs.iterator();
while( itr.hasNext() ) {
ReachState stateCallee = itr.next();
}
- // used below to convert a TaintSet's parameter index taints to
- // a TaintSet of caller taints
+ // used below to convert a ReachSet to an equivalent
+ // version with shadow IDs merged into unshadowed IDs
+ protected ReachSet unshadow( ReachSet rs ) {
+ ReachSet out = rs;
+ Iterator<AllocSite> asItr = allocSites.iterator();
+ while( asItr.hasNext() ) {
+ AllocSite as = asItr.next();
+ out = Canonical.unshadow( out, as );
+ }
+ assert out.isCanonical();
+ return out;
+ }
+
+
+ // used below to convert a TaintSet to its caller-context
+ // equivalent, just eliminate Taints with bad preds
protected TaintSet
- toCallerContext( TaintSet ts,
- FlatCall fc,
- FlatMethod fmCallee
+ toCallerContext( TaintSet ts,
+ Hashtable<Taint, ExistPredSet> calleeTaintsSatisfied
) {
-
TaintSet out = TaintSet.factory();
+ // when the mapping is null it means there were no
+ // predicates satisfied
+ if( calleeTaintsSatisfied == null ) {
+ return out;
+ }
+
Iterator<Taint> itr = ts.iterator();
while( itr.hasNext() ) {
- Taint t = itr.next();
-
- if( !t.isParamTaint() ) {
- // throw out non-parameter taints from callee
- continue;
- }
-
- // what argument does this taint map to?
- TempDescriptor tdArg =
- fc.getArgMatchingParamIndex( fmCallee,
- t.getParamIndex() );
- VariableNode vnArg = td2vn.get( tdArg );
+ Taint tCallee = itr.next();
- // what allocation site does this taint refer to?
- AllocSite as = t.getAllocSite();
-
- // look at the allocation sites that the
- // arg references in the caller context--if
- // the parameter taint matches, use the taints
- // of the argument reference to grow the output set
- Iterator<RefEdge> reItr = vnArg.iteratorToReferencees();
- while( reItr.hasNext() ) {
- RefEdge re = reItr.next();
+ if( calleeTaintsSatisfied.containsKey( tCallee ) ) {
- if( as.equals( re.getDst().getAllocSite() ) ) {
- out = Canonical.union( out,
- re.getTaints()
- );
- }
- }
+ Taint tCaller =
+ Canonical.attach( Taint.factory( tCallee.sese,
+ tCallee.insetVar,
+ tCallee.allocSite ),
+ calleeTaintsSatisfied.get( tCallee )
+ );
+ out = Canonical.add( out,
+ tCaller
+ );
+ }
}
-
+
assert out.isCanonical();
return out;
}
- // used below to convert a ReachSet to an equivalent
- // version with shadow IDs merged into unshadowed IDs
- protected ReachSet unshadow( ReachSet rs ) {
- ReachSet out = rs;
- Iterator<AllocSite> asItr = allocSites.iterator();
- while( asItr.hasNext() ) {
- AllocSite as = asItr.next();
- out = Canonical.unshadow( out, as );
- }
- assert out.isCanonical();
- return out;
- }
// use this method to make a new reach graph that is
ExistPredSet preds =
ExistPredSet.factory( pred );
- Taint paramTaint =
- Taint.factory( fc,
- index,
- null,
- null,
- hrnDstCallee.getAllocSite(),
- preds
- );
-
TaintSet taints =
- TaintSet.factory( paramTaint );
+ TaintSet.factory();
RefEdge reCallee =
new RefEdge( vnCallee,
Hashtable<RefEdge, ExistPredSet> calleeEdgesSatisfied =
new Hashtable<RefEdge, ExistPredSet>();
- Hashtable<ReachState, ExistPredSet> calleeStatesSatisfied =
- new Hashtable<ReachState, ExistPredSet>();
+ Hashtable< HeapRegionNode, Hashtable<ReachState, ExistPredSet> >
+ calleeNode2calleeStatesSatisfied =
+ new Hashtable< HeapRegionNode, Hashtable<ReachState, ExistPredSet> >();
+
+ Hashtable< RefEdge, Hashtable<ReachState, ExistPredSet> >
+ calleeEdge2calleeStatesSatisfied =
+ new Hashtable< RefEdge, Hashtable<ReachState, ExistPredSet> >();
+
+ Hashtable< RefEdge, Hashtable<Taint, ExistPredSet> >
+ calleeEdge2calleeTaintsSatisfied =
+ new Hashtable< RefEdge, Hashtable<Taint, ExistPredSet> >();
Hashtable< RefEdge, Set<RefSrcNode> > calleeEdges2oocCallerSrcMatches =
new Hashtable< RefEdge, Set<RefSrcNode> >();
- //Hashtable<Taint, ExistPredSet> taintsSatisfied =
- // new Hashtable<Taint, ExistPredSet>();
-
Iterator meItr = rgCallee.id2hrn.entrySet().iterator();
while( meItr.hasNext() ) {
stateCallee.getPreds().isSatisfiedBy( this,
callerNodeIDsCopiedToCallee
);
- if( predsIfSatis != null ) {
- ExistPredSet predsAlready = calleeStatesSatisfied.get( stateCallee );
- if( predsAlready == null ) {
- calleeStatesSatisfied.put( stateCallee, predsIfSatis );
- } else {
- calleeStatesSatisfied.put( stateCallee,
- Canonical.join( predsIfSatis,
- predsAlready
- )
- );
- }
+ if( predsIfSatis != null ) {
+ assert calleeNode2calleeStatesSatisfied.get( hrnCallee ) == null;
+
+ Hashtable<ReachState, ExistPredSet> calleeStatesSatisfied =
+ new Hashtable<ReachState, ExistPredSet>();
+ calleeStatesSatisfied.put( stateCallee, predsIfSatis );
+
+ calleeNode2calleeStatesSatisfied.put( hrnCallee, calleeStatesSatisfied );
}
}
callerNodeIDsCopiedToCallee
);
if( predsIfSatis != null ) {
- ExistPredSet predsAlready = calleeStatesSatisfied.get( stateCallee );
- if( predsAlready == null ) {
- calleeStatesSatisfied.put( stateCallee, predsIfSatis );
- } else {
- calleeStatesSatisfied.put( stateCallee,
- Canonical.join( predsIfSatis,
- predsAlready
- )
- );
- }
+ assert calleeEdge2calleeStatesSatisfied.get( reCallee ) == null;
+
+ Hashtable<ReachState, ExistPredSet> calleeStatesSatisfied =
+ new Hashtable<ReachState, ExistPredSet>();
+ calleeStatesSatisfied.put( stateCallee, predsIfSatis );
+
+ calleeEdge2calleeStatesSatisfied.put( reCallee, calleeStatesSatisfied );
+ }
+ }
+
+ // since the edge is coming over, find out which taints
+ // on it should come over, too
+ Iterator<Taint> tItr = reCallee.getTaints().iterator();
+ while( tItr.hasNext() ) {
+ Taint tCallee = tItr.next();
+
+ predsIfSatis =
+ tCallee.getPreds().isSatisfiedBy( this,
+ callerNodeIDsCopiedToCallee
+ );
+ if( predsIfSatis != null ) {
+ assert calleeEdge2calleeTaintsSatisfied.get( reCallee ) == null;
+
+ Hashtable<Taint, ExistPredSet> calleeTaintsSatisfied =
+ new Hashtable<Taint, ExistPredSet>();
+ calleeTaintsSatisfied.put( tCallee, predsIfSatis );
+
+ calleeEdge2calleeTaintsSatisfied.put( reCallee, calleeTaintsSatisfied );
}
}
}
hrnCallee.getType(), // type
hrnCallee.getAllocSite(), // allocation site
toCallerContext( hrnCallee.getInherent(),
- calleeStatesSatisfied ), // inherent reach
+ calleeNode2calleeStatesSatisfied.get( hrnCallee ) ), // inherent reach
null, // current reach
predsEmpty, // predicates
hrnCallee.getDescription() // description
}
hrnCaller.setAlpha( toCallerContext( hrnCallee.getAlpha(),
- calleeStatesSatisfied
+ calleeNode2calleeStatesSatisfied.get( hrnCallee )
)
);
reCallee.getType(),
reCallee.getField(),
toCallerContext( reCallee.getBeta(),
- calleeStatesSatisfied ),
+ calleeEdge2calleeStatesSatisfied.get( reCallee ) ),
preds,
toCallerContext( reCallee.getTaints(),
- fc,
- fmCallee )
+ calleeEdge2calleeTaintsSatisfied.get( reCallee ) )
);
ChangeSet cs = ChangeSet.factory();
);
}
}
-
- // look to see if an edge with same field exists
- // and merge with it, otherwise just add the edge
- RefEdge edgeExisting = rsnCaller.getReferenceTo( hrnDstCaller,
- reCallee.getType(),
- reCallee.getField()
- );
- if( edgeExisting != null ) {
- edgeExisting.setBeta(
- Canonical.unionORpreds( edgeExisting.getBeta(),
- reCaller.getBeta()
- )
- );
- edgeExisting.setPreds(
- Canonical.join( edgeExisting.getPreds(),
- reCaller.getPreds()
- )
- );
-
- // for reach propagation
- if( !cs.isEmpty() ) {
+ // we're just going to use the convenient "merge-if-exists"
+ // edge call below, but still take a separate look if there
+ // is an existing caller edge to build change sets properly
+ if( !cs.isEmpty() ) {
+ RefEdge edgeExisting = rsnCaller.getReferenceTo( hrnDstCaller,
+ reCallee.getType(),
+ reCallee.getField()
+ );
+ if( edgeExisting != null ) {
ChangeSet csExisting = edgePlannedChanges.get( edgeExisting );
if( csExisting == null ) {
csExisting = ChangeSet.factory();
Canonical.union( csExisting,
cs
)
- );
- }
-
- } else {
- addRefEdge( rsnCaller, hrnDstCaller, reCaller );
-
- // for reach propagation
- if( !cs.isEmpty() ) {
+ );
+ } else {
edgesForPropagation.add( reCaller );
assert !edgePlannedChanges.containsKey( reCaller );
- edgePlannedChanges.put( reCaller, cs );
+ edgePlannedChanges.put( reCaller, cs );
}
}
+
+ // then add new caller edge or merge
+ addEdgeOrMergeWithExisting( reCaller );
}
}
// a taint is applied to a reference edge, and
// is used to associate an effect with an
-// sese (rblock) and in-
+// sese (rblock) and live variable
public class Taint extends Canonical {
// an sese (rblock) and an in-set var
// only one set of identifying objects
// will be non-null
-
- // identify a parameter index
- protected FlatCall callSite;
- protected Integer paramIndex;
// identify an sese (rblock) + inset var
protected FlatSESEEnterNode sese;
protected ExistPredSet preds;
- public static Taint factory( FlatCall fc,
- Integer pi,
- FlatSESEEnterNode s,
+ public static Taint factory( FlatSESEEnterNode s,
TempDescriptor iv,
AllocSite as ) {
- Taint out = new Taint( fc, pi, s, iv, as );
+ Taint out = new Taint( s, iv, as );
out.preds = ExistPredSet.factory();
out = (Taint) Canonical.makeCanonical( out );
return out;
}
- public static Taint factory( FlatCall fc,
- Integer pi,
- FlatSESEEnterNode s,
+ public static Taint factory( FlatSESEEnterNode s,
TempDescriptor iv,
AllocSite as,
ExistPredSet eps ) {
- Taint out = new Taint( fc, pi, s, iv, as );
+ Taint out = new Taint( s, iv, as );
out.preds = eps;
out = (Taint) Canonical.makeCanonical( out );
return out;
}
- protected Taint( FlatCall fc,
- Integer pi,
- FlatSESEEnterNode s,
+ protected Taint( FlatSESEEnterNode s,
TempDescriptor iv,
- AllocSite as ) {
-
- // either fc and pi are non-null, OR s and iv are non-null
- assert
- (fc != null && pi != null && s == null && iv == null) ||
- (fc == null && pi == null && s != null && iv != null);
-
+ AllocSite as ) {
+ assert s != null;
+ assert iv != null;
assert as != null;
-
- callSite = fc;
- paramIndex = pi;
sese = s;
insetVar = iv;
allocSite = as;
}
- public boolean isParamTaint() {
- return callSite != null;
- }
-
- public boolean isSESETaint() {
- return sese != null;
- }
-
- public FlatCall getCallSite() {
- return callSite;
- }
-
- public Integer getParamIndex() {
- return paramIndex;
- }
-
public FlatSESEEnterNode getSESE() {
return sese;
}
Taint t = (Taint) o;
- boolean fcMatches = true;
- if( callSite == null ) {
- fcMatches = t.callSite == null;
- } else {
- fcMatches = callSite.equals( t.callSite );
- }
-
- boolean piMatches = true;
- if( paramIndex == null ) {
- piMatches = t.paramIndex == null;
- } else {
- piMatches = paramIndex.equals( t.paramIndex );
- }
-
- boolean sMatches = true;
- if( sese == null ) {
- sMatches = t.sese == null;
- } else {
- sMatches = sese.equals( t.sese );
- }
-
- boolean ivMatches = true;
- if( insetVar == null ) {
- ivMatches = t.insetVar == null;
- } else {
- ivMatches = insetVar.equals( t.insetVar );
- }
-
- return allocSite.equals( t.allocSite ) &&
- piMatches && sMatches && ivMatches;
+ return
+ sese .equals( t.sese ) &&
+ insetVar .equals( t.insetVar ) &&
+ allocSite.equals( t.allocSite );
}
public int hashCodeSpecific() {
int hash = allocSite.hashCode();
-
- if( callSite != null ) {
- hash = hash ^ callSite.hashCode();
- }
-
- if( paramIndex != null ) {
- hash = hash ^ paramIndex.hashCode();
- }
-
- if( sese != null ) {
- hash = hash ^ sese.hashCode();
- }
-
- if( insetVar != null ) {
- hash = hash ^ insetVar.hashCode();
- }
-
+ hash = hash ^ sese.hashCode();
+ hash = hash ^ insetVar.hashCode();
return hash;
}
public String toString() {
- String s = "(";
-
- if( isParamTaint() ) {
- s += "cs"+callSite.nodeid+"-"+paramIndex;
- } else {
- s += sese.toPrettyString()+"-"+insetVar;
- }
-
- return s+", "+allocSite.toStringBrief()+"):"+preds;
+ return
+ "("+sese.toPrettyString()+
+ "-"+insetVar+
+ ", "+allocSite.toStringBrief()+
+ "):"+preds;
}
}