it.unive.lisa.analysis.heap.pointbased.FieldSensitivePointBasedHeap Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of lisa-analyses Show documentation
Show all versions of lisa-analyses Show documentation
A library for static analysis
The newest version!
package it.unive.lisa.analysis.heap.pointbased;
import it.unive.lisa.analysis.ScopeToken;
import it.unive.lisa.analysis.SemanticException;
import it.unive.lisa.analysis.SemanticOracle;
import it.unive.lisa.analysis.lattices.ExpressionSet;
import it.unive.lisa.analysis.lattices.GenericMapLattice;
import it.unive.lisa.analysis.nonrelational.heap.HeapEnvironment;
import it.unive.lisa.program.annotations.Annotation;
import it.unive.lisa.program.cfg.ProgramPoint;
import it.unive.lisa.symbolic.SymbolicExpression;
import it.unive.lisa.symbolic.heap.AccessChild;
import it.unive.lisa.symbolic.heap.MemoryAllocation;
import it.unive.lisa.symbolic.value.Identifier;
import it.unive.lisa.symbolic.value.MemoryPointer;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Objects;
import java.util.Set;
import java.util.function.Predicate;
/**
* A field-insensitive program point-based {@link AllocationSiteBasedAnalysis}.
* The implementation follows X. Rival and K. Yi, "Introduction to Static
* Analysis An Abstract Interpretation Perspective", Section 8.3.4
*
* @author Vincenzo Arceri
*
* @see https://mitpress.mit.edu/books/introduction-static-analysis
*/
public class FieldSensitivePointBasedHeap extends AllocationSiteBasedAnalysis {
/**
* Tracks the fields of each allocation site.
*/
public final GenericMapLattice fields;
/**
* Builds a new instance of field-sensitive point-based heap.
*/
public FieldSensitivePointBasedHeap() {
super();
this.fields = new GenericMapLattice(new ExpressionSet()).top();
}
/**
* Builds a new instance of field-sensitive point-based heap from its heap
* environment.
*
* @param heapEnv the heap environment that this instance tracks
*/
public FieldSensitivePointBasedHeap(
HeapEnvironment heapEnv) {
this(heapEnv, new GenericMapLattice(new ExpressionSet()).top());
}
/**
* Builds a new instance of field-sensitive point-based heap from its heap
* environment.
*
* @param heapEnv the heap environment that this instance tracks
* @param fields the mapping between allocation sites and their fields that
* this instance tracks
*/
public FieldSensitivePointBasedHeap(
HeapEnvironment heapEnv,
GenericMapLattice fields) {
super(heapEnv);
this.fields = fields;
}
/**
* Builds a new instance of field-sensitive point-based heap from its heap
* environment, its replacements, and its field mapping.
*
* @param heapEnv the heap environment that this instance tracks
* @param replacements the heap replacements
* @param fields the mapping between allocation sites and their fields
* that this instance tracks
*/
public FieldSensitivePointBasedHeap(
HeapEnvironment heapEnv,
List replacements,
GenericMapLattice fields) {
super(heapEnv, replacements);
this.fields = fields;
}
@Override
public FieldSensitivePointBasedHeap mk(
FieldSensitivePointBasedHeap reference) {
return reference;
}
@Override
public FieldSensitivePointBasedHeap mk(
FieldSensitivePointBasedHeap reference,
List replacements) {
return new FieldSensitivePointBasedHeap(reference.heapEnv, replacements, reference.fields);
}
@Override
protected FieldSensitivePointBasedHeap mk(
FieldSensitivePointBasedHeap reference,
HeapEnvironment heapEnv) {
return new FieldSensitivePointBasedHeap(heapEnv, reference.replacements, reference.fields);
}
@Override
public FieldSensitivePointBasedHeap shallowCopy(
Identifier id,
StackAllocationSite site,
List replacements,
ProgramPoint pp,
SemanticOracle oracle)
throws SemanticException {
// no aliasing: star_y must be cloned and the clone must
// be assigned to id
StackAllocationSite clone = new StackAllocationSite(site.getStaticType(),
id.getCodeLocation().toString(), site.isWeak(), id.getCodeLocation());
HeapEnvironment heap = heapEnv.assign(id, clone, pp, oracle);
Map newFields = new HashMap<>(fields.getMap());
// all the allocation sites fields of star_y
if (fields.getKeys().contains(site)) {
for (SymbolicExpression field : fields.getState(site)) {
StackAllocationSite cloneWithField = new StackAllocationSite(field.getStaticType(),
id.getCodeLocation().toString(), field, site.isWeak(), id.getCodeLocation());
StackAllocationSite star_yWithField = new StackAllocationSite(field.getStaticType(),
site.getCodeLocation().toString(), field, site.isWeak(),
site.getCodeLocation());
HeapReplacement replacement = new HeapReplacement();
replacement.addSource(star_yWithField);
replacement.addTarget(cloneWithField);
replacement.addTarget(star_yWithField);
// need to update also the fields of the clone
addField(clone, field, newFields);
replacements.add(replacement);
}
}
// need to be replaced also the allocation site (needed for type
// analysis)
HeapReplacement replacement = new HeapReplacement();
replacement.addSource(site);
replacement.addTarget(clone);
replacement.addTarget(site);
replacements.add(replacement);
return mk(new FieldSensitivePointBasedHeap(heap, new GenericMapLattice<>(fields.lattice, newFields)));
}
@Override
public FieldSensitivePointBasedHeap smallStepSemantics(
SymbolicExpression expression,
ProgramPoint pp,
SemanticOracle oracle)
throws SemanticException {
if (expression instanceof AccessChild) {
FieldSensitivePointBasedHeap sss = (FieldSensitivePointBasedHeap) super.smallStepSemantics(
expression,
pp,
oracle);
AccessChild accessChild = (AccessChild) expression;
Map mapping = new HashMap<>(sss.fields.getMap());
ExpressionSet exprs;
if (accessChild.getContainer().mightNeedRewriting())
exprs = rewrite(accessChild.getContainer(), pp, oracle);
else
exprs = new ExpressionSet(accessChild.getContainer());
for (SymbolicExpression rec : exprs)
if (rec instanceof MemoryPointer) {
AllocationSite site = (AllocationSite) ((MemoryPointer) rec).getReferencedLocation();
ExpressionSet childs = rewrite(accessChild.getChild(), pp, oracle);
for (SymbolicExpression child : childs)
addField(site, child, mapping);
} else if (rec instanceof AllocationSite) {
AllocationSite site = (AllocationSite) rec;
ExpressionSet childs = rewrite(accessChild.getChild(), pp, oracle);
for (SymbolicExpression child : childs)
addField(site, child, mapping);
}
return mk(new FieldSensitivePointBasedHeap(heapEnv, heapEnv.getSubstitution(),
new GenericMapLattice<>(fields.lattice, mapping)));
} else if (expression instanceof MemoryAllocation) {
String loc = expression.getCodeLocation().getCodeLocation();
Set alreadyAllocated = getAllocatedAt(loc);
FieldSensitivePointBasedHeap sss = super.smallStepSemantics(expression, pp, oracle);
HeapEnvironment env = sss.heapEnv;
if (!alreadyAllocated.isEmpty()) {
// we must turn all these sites to weak ones, including the one
// about fields
List replacements = new LinkedList<>();
for (AllocationSite site : alreadyAllocated) {
if (!site.isWeak()) {
HeapReplacement replacement = new HeapReplacement();
replacement.addSource(site);
replacement.addTarget(site.toWeak());
replacements.add(replacement);
}
if (fields.getKeys().contains(site))
for (SymbolicExpression field : fields.getState(site)) {
AllocationSite withField = site.withField(field);
if (!withField.isWeak()) {
HeapReplacement replacement = new HeapReplacement();
replacement.addSource(withField);
replacement.addTarget(withField.toWeak());
replacements.add(replacement);
}
}
}
if (!replacements.isEmpty()) {
// we must apply the replacements to our mapping as well
Map map = new HashMap<>(env.getMap());
for (Entry entry : env) {
Identifier id = entry.getKey();
AllocationSites sites = entry.getValue();
for (HeapReplacement repl : replacements) {
if (repl.getSources().contains(id))
// these are all one-to-one replacements
id = repl.getTargets().iterator().next();
sites = sites.applyReplacement(repl, pp);
}
map.put(id, sites);
}
env = new HeapEnvironment<>(env.lattice, map);
}
return mk(new FieldSensitivePointBasedHeap(env, replacements, fields));
}
}
FieldSensitivePointBasedHeap sss = super.smallStepSemantics(expression, pp, oracle);
return mk(new FieldSensitivePointBasedHeap(sss.heapEnv, fields));
}
private void addField(
AllocationSite site,
SymbolicExpression field,
Map mapping) {
Set tmp = new HashSet<>(mapping.getOrDefault(site, new ExpressionSet()).elements());
tmp.add(field);
mapping.put(site, new ExpressionSet(tmp));
}
@Override
public ExpressionSet rewrite(
SymbolicExpression expression,
ProgramPoint pp,
SemanticOracle oracle)
throws SemanticException {
return expression.accept(new Rewriter(), pp, oracle);
}
/**
* A {@link it.unive.lisa.analysis.heap.BaseHeapDomain.Rewriter} for the
* {@link FieldSensitivePointBasedHeap} domain.
*
* @author Luca Negrini
*/
public class Rewriter extends AllocationSiteBasedAnalysis.Rewriter {
@Override
public ExpressionSet visit(
AccessChild expression,
ExpressionSet receiver,
ExpressionSet child,
Object... params)
throws SemanticException {
Set result = new HashSet<>();
for (SymbolicExpression rec : receiver) {
rec = removeTypingExpressions(rec);
if (rec instanceof MemoryPointer) {
AllocationSite site = (AllocationSite) ((MemoryPointer) rec).getReferencedLocation();
populate(expression, child, result, site);
} else if (rec instanceof AllocationSite) {
AllocationSite site = (AllocationSite) rec;
populate(expression, child, result, site);
}
}
return new ExpressionSet(result);
}
private void populate(
AccessChild expression,
ExpressionSet child,
Set result,
AllocationSite site) {
for (SymbolicExpression target : child) {
AllocationSite e;
if (site instanceof StackAllocationSite)
e = new StackAllocationSite(
expression.getStaticType(),
site.getLocationName(),
target,
site.isWeak(),
site.getCodeLocation());
else
e = new HeapAllocationSite(
expression.getStaticType(),
site.getLocationName(),
target,
site.isWeak(),
site.getCodeLocation());
// propagates the annotations of the child value expression to
// the newly created allocation site
if (target instanceof Identifier)
for (Annotation ann : e.getAnnotations())
e.addAnnotation(ann);
result.add(e);
}
}
@Override
public ExpressionSet visit(
MemoryAllocation expression,
Object... params)
throws SemanticException {
String pp = expression.getCodeLocation().getCodeLocation();
boolean weak;
if (!getAllocatedAt(pp).isEmpty())
weak = true;
else
weak = false;
AllocationSite e;
if (expression.isStackAllocation())
e = new StackAllocationSite(expression.getStaticType(), pp, weak, expression.getCodeLocation());
else
e = new HeapAllocationSite(expression.getStaticType(), pp, weak, expression.getCodeLocation());
// propagates the annotations of expression
// to the newly created allocation site
for (Annotation ann : expression.getAnnotations())
e.getAnnotations().addAnnotation(ann);
return new ExpressionSet(e);
}
}
@Override
public int hashCode() {
final int prime = 31;
int result = super.hashCode();
result = prime * result + Objects.hash(fields);
return result;
}
@Override
public boolean equals(
Object obj) {
if (this == obj)
return true;
if (!super.equals(obj))
return false;
if (getClass() != obj.getClass())
return false;
FieldSensitivePointBasedHeap other = (FieldSensitivePointBasedHeap) obj;
return Objects.equals(fields, other.fields);
}
@Override
public FieldSensitivePointBasedHeap popScope(
ScopeToken scope)
throws SemanticException {
return mk(new FieldSensitivePointBasedHeap(heapEnv.popScope(scope), fields));
}
@Override
public FieldSensitivePointBasedHeap pushScope(
ScopeToken scope)
throws SemanticException {
return mk(new FieldSensitivePointBasedHeap(heapEnv.pushScope(scope), fields));
}
@Override
public FieldSensitivePointBasedHeap top() {
return mk(new FieldSensitivePointBasedHeap(heapEnv.top(), Collections.emptyList(), fields.top()));
}
@Override
public boolean isTop() {
return heapEnv.isTop() && fields.isTop();
}
@Override
public FieldSensitivePointBasedHeap bottom() {
return mk(new FieldSensitivePointBasedHeap(heapEnv.bottom(), Collections.emptyList(), fields.bottom()));
}
@Override
public boolean isBottom() {
return heapEnv.isBottom() && fields.isBottom();
}
@Override
public FieldSensitivePointBasedHeap lubAux(
FieldSensitivePointBasedHeap other)
throws SemanticException {
return mk(new FieldSensitivePointBasedHeap(heapEnv.lub(other.heapEnv),
Collections.emptyList(),
fields.lub(other.fields)));
}
@Override
public FieldSensitivePointBasedHeap glbAux(
FieldSensitivePointBasedHeap other)
throws SemanticException {
return mk(new FieldSensitivePointBasedHeap(heapEnv.glb(other.heapEnv),
Collections.emptyList(),
fields.glb(other.fields)));
}
@Override
public boolean lessOrEqualAux(
FieldSensitivePointBasedHeap other)
throws SemanticException {
return heapEnv.lessOrEqual(other.heapEnv) && fields.lessOrEqual(other.fields);
}
@Override
public FieldSensitivePointBasedHeap forgetIdentifier(
Identifier id)
throws SemanticException {
return mk(new FieldSensitivePointBasedHeap(heapEnv.forgetIdentifier(id), fields));
}
@Override
public FieldSensitivePointBasedHeap forgetIdentifiersIf(
Predicate test)
throws SemanticException {
return mk(new FieldSensitivePointBasedHeap(heapEnv.forgetIdentifiersIf(test), fields));
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy