/* * KSetAnalysis.java - This file is part of the Jakstab project. * Copyright 2007-2015 Johannes Kinder <jk@jakstab.org> * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, see <http://www.gnu.org/licenses/>. */ package org.jakstab.analysis.explicit; import java.util.Collections; import java.util.Set; import org.jakstab.AnalysisProperties; import org.jakstab.analysis.*; import org.jakstab.cfa.CFAEdge; import org.jakstab.cfa.Location; import org.jakstab.cfa.StateTransformer; import org.jakstab.rtl.expressions.*; import org.jakstab.rtl.statements.*; import org.jakstab.util.Logger; import org.jakstab.util.Pair; /** * A K-Set analysis as used for the example in the VMCAI'09 paper. It * represents values as sets of a constant size, merging them to TOP if * the bound is exceeded. Supports memory values and register aliasing * through the generic VariableValuation class. * * For programs with procedure calls, it should be used together with a * call-stack analysis for context sensitivity. Otherwise, it will merge * the stack contents from different calling contexts, which leads to * illegal addresses used as jump targets on return. */ public class KSetAnalysis implements ConfigurableProgramAnalysis { public static void register(AnalysisProperties p) { p.setShortHand('k'); p.setName("K-Set analysis"); p.setDescription("For each variable, collect up to k values per location (non-relational)."); p.setExplicit(true); } @SuppressWarnings("unused") private static final Logger logger = Logger.getLogger(KSetAnalysis.class); private AbstractValueFactory<KSet> valueFactory; private int bound; public KSetAnalysis() { bound = BoundedAddressTracking.varThreshold.getValue();; valueFactory = new KSetFactory(bound); } @Override public Precision initPrecision(Location location, StateTransformer transformer) { return null; } @Override public AbstractState initStartState(Location location) { return new ValuationState(valueFactory); } @Override public AbstractState merge(AbstractState s1, AbstractState s2, Precision precision) { return CPAOperators.mergeJoin(s1, s2, precision); } @Override public Set<AbstractState> post(AbstractState state, CFAEdge cfaEdge, Precision precision) { final RTLStatement statement = (RTLStatement)cfaEdge.getTransformer(); final ValuationState iState = (ValuationState)state; return Collections.singleton(statement.accept(new DefaultStatementVisitor<AbstractState>() { @Override public AbstractState visit(RTLAlloc stmt) { ValuationState post = new ValuationState(iState); Writable lhs = stmt.getPointer(); MemoryRegion newRegion; if (stmt.getAllocationName() != null) { newRegion = MemoryRegion.create(stmt.getAllocationName()); } else { // TODO: Detect whether this allocation is unique to allow strong updates newRegion = MemoryRegion.createAsSummary("alloc" + stmt.getLabel()); } KSet basePointer = new KSet(bound, new BasedNumberElement(newRegion, ExpressionFactory.createNumber(0, 32))); if (lhs instanceof RTLVariable) { post.setVariableValue((RTLVariable)lhs, basePointer); } else { RTLMemoryLocation m = (RTLMemoryLocation)lhs; AbstractDomainElement evaledAddress = iState.abstractEval(m.getAddress()); post.setMemoryValue(evaledAddress, m.getBitWidth(), basePointer); } return post; } @Override public AbstractState visit(RTLVariableAssignment stmt) { ValuationState post = new ValuationState(iState); AbstractDomainElement evaledRhs = iState.abstractEval(stmt.getRightHandSide()); post.setVariableValue(stmt.getLeftHandSide(), evaledRhs); return post; } @Override public AbstractState visit(RTLMemoryAssignment stmt) { ValuationState post = new ValuationState(iState); AbstractDomainElement evaledRhs = iState.abstractEval(stmt.getRightHandSide()); RTLMemoryLocation m = stmt.getLeftHandSide(); AbstractDomainElement evaledAddress = iState.abstractEval(m.getAddress()); post.setMemoryValue(evaledAddress, m.getBitWidth(), evaledRhs); return post; } @Override public AbstractState visit(RTLAssume stmt) { if (stmt.getAssumption() instanceof RTLOperation) { RTLOperation operation = (RTLOperation)stmt.getAssumption(); if (operation.getOperator() == Operator.EQUAL) { RTLExpression lhs = operation.getOperands()[0]; RTLExpression rhs = operation.getOperands()[1]; AbstractDomainElement evaledRhs = iState.abstractEval(rhs); if (lhs instanceof RTLVariable) { ValuationState post = new ValuationState(iState); post.setVariableValue((RTLVariable)lhs, evaledRhs); return post; } else if (lhs instanceof RTLMemoryLocation) { ValuationState post = new ValuationState(iState); RTLMemoryLocation m = (RTLMemoryLocation)lhs; AbstractDomainElement evaledAddress = iState.abstractEval(m.getAddress()); post.setMemoryValue(evaledAddress, m.getBitWidth(), evaledRhs); return post; } } } return iState; } @Override protected AbstractState visitDefault(RTLStatement stmt) { return iState; } })); } @Override public Pair<AbstractState, Precision> prec(AbstractState s, Precision precision, ReachedSet reached) { return Pair.create(s, precision); } @Override public boolean stop(AbstractState s, ReachedSet reached, Precision precision) { return CPAOperators.stopJoin(s, reached, precision); } @Override public AbstractState strengthen(AbstractState s, Iterable<AbstractState> otherStates, CFAEdge cfaEdge, Precision precision) { return s; } }