/// <summary> /// Hypothesis: Bound Analysis assumed that <code>0 ≤ len </code> and /// </summary> /// <param name="dest"></param> private SimplePartitionAbstractDomain <BoxedVariable <Variable>, BoxedExpression> HandleAllocations(APC pc, Variable dest, Variable len, SimplePartitionAbstractDomain <BoxedVariable <Variable>, BoxedExpression> data) { var lenAsExp = BoxedExpression.For(this.Context.Refine(pc, len), this.Decoder.Outdecoder); lenAsExp = this.Decoder.Stripped(lenAsExp); var destAsExp = BoxedExpression.For(this.Context.Refine(pc, dest), this.Decoder.Outdecoder); ALog.BeginTransferFunction(StringClosure.For("[P]Allocation"), ExpressionPrinter.ToStringClosure(lenAsExp, this.Decoder), PrettyPrintPC(pc), StringClosure.For(data)); var refinedDomain = data.Allocation(new BoxedVariable <Variable>(dest), lenAsExp); ALog.EndTransferFunction(StringClosure.For(data)); return(refinedDomain); }
/// <summary> /// Here we catch the calls to methods of String, so that we can apply operations on string, as concatenations. etc. /// </summary> public override SimpleStringAbstractDomain <BoxedExpression> Call <TypeList, ArgList>(APC pc, Method method, bool tail, bool virt, TypeList extraVarargs, Variable dest, ArgList args, SimpleStringAbstractDomain <BoxedExpression> data) // where ArgList : IIndexable<int> { string methodName = this.DecoderForMetaData.FullName(method); ALog.BeginTransferFunction(StringClosure.For("call"), StringClosure.For(methodName), StringClosure.For(pc), StringClosure.For(data)); SimpleStringAbstractDomain <BoxedExpression> result; SimpleStringAbstractDomain <BoxedExpression> baseResult = base.Call <TypeList, ArgList>(pc, method, tail, virt, extraVarargs, dest, args, data); if (IsACallToString(methodName)) { result = HandleCallToString(pc, methodName, dest, args, baseResult); } else { result = baseResult; } ALog.EndTransferFunction(StringClosure.For(result)); return(result); }
public override SimplePartitionAbstractDomain <BoxedVariable <Variable>, BoxedExpression> Binary(APC pc, BinaryOperator op, Variable dest, Variable s1, Variable s2, SimplePartitionAbstractDomain <BoxedVariable <Variable>, BoxedExpression> data) { Log("Binary:{0}", op); if (OperatorExtensions.IsComparisonBinaryOperator(op)) { // TODO: if s1 or s2 includes an array term, partitioning must be done. return(data); } else if (OperatorExtensions.IsBooleanBinaryOperator(op)) { // TODO: see above return(data); } else { var destAsExp = ToBoxedExpression(pc, dest); var leftAsExp = ToBoxedExpressionWithConstantRefinement(pc, s1); var rightAsExp = ToBoxedExpressionWithConstantRefinement(pc, s2); ALog.BeginTransferFunction(StringClosure.For("Assign"), StringClosure.For("{0} := {1}({2}, {3})", ExpressionPrinter.ToStringClosure(destAsExp, this.Decoder), StringClosure.For(op), ExpressionPrinter.ToStringClosure(leftAsExp, this.Decoder), ExpressionPrinter.ToStringClosure(rightAsExp, this.Decoder)), PrettyPrintPC(pc), StringClosure.For(data)); // Hypothesis : if it is a reminder or division operation, we assume that the dividend is not zero var refinedDomain = data; BoxedExpression rightOfAssignment; Log("REPACK:{1} {0} {2}", op, s1, s2); if (TryRepackAssignment(op, leftAsExp, rightAsExp, out rightOfAssignment)) { var arraysToRefine = data.arraysWithPartitionDefinedOnASubsetExpressionOf(rightOfAssignment); if (!arraysToRefine.IsEmpty) { var assignmentKnowledge = this.Encoder.CompoundExpressionFor(ExpressionType.Bool, ExpressionOperator.Equal, destAsExp, rightOfAssignment); var assignmentStrippedKnowledge = this.Encoder.CompoundExpressionFor(ExpressionType.Bool, ExpressionOperator.Equal, destAsExp, RecursiveStripped(rightOfAssignment)); assignmentKnowledge = this.Encoder.CompoundExpressionFor(ExpressionType.Bool, ExpressionOperator.And, assignmentKnowledge, assignmentStrippedKnowledge); //Log("KNOWLEDGEonREPACK:{0}", rightOfAssignment); foreach (var array in arraysToRefine) { refinedDomain = HandleIndexAssignment("", pc, array, ToBoxedVariable(dest), rightOfAssignment, assignmentKnowledge, refinedDomain); } } } //else //{ // throw new AbstractInterpretationException(); //TODO : leave the else. //} ALog.EndTransferFunction(StringClosure.For(refinedDomain)); return(refinedDomain); } }
private SimplePartitionAbstractDomain <BoxedVariable <Variable>, BoxedExpression> HandleIndexAssignment(string name, APC pc, BoxedVariable <Variable> array, BoxedVariable <Variable> index, BoxedExpression assignedAsExp, BoxedExpression assignmentKnowledge, SimplePartitionAbstractDomain <BoxedVariable <Variable>, BoxedExpression> data) { ALog.BeginTransferFunction(StringClosure.For("[P]IndexAssignement"), StringClosure.For(""), PrettyPrintPC(pc), StringClosure.For(data)); //var baseVariables = this.Decoder.VariablesIn(indexAsExp); var baseVariables = this.Decoder.VariablesIn(assignedAsExp); Log("VARIABLESIN={0}", baseVariables); var indexAsExp = ToBoxedExpression(pc, index); var indexKnowledge = gatherKnowledge(this.Context.Post(pc), indexAsExp); //TODO: post is not useful here var knowledge = this.Encoder.CompoundExpressionFor(ExpressionType.Bool, ExpressionOperator.And, indexKnowledge, assignmentKnowledge); // TODO : useless if indexAsExp is based on variables already in the partition (which space is delimited) //var indexRange = guessRange(pc, indexAsExp); //Log("LB={0}", indexRange.One); //Log("UB={0}", indexRange.Two); IPartitionAbstraction <BoxedVariable <Variable>, BoxedExpression> arrayPartition; var refinedDomain = data; if (data.TryGetValue(array, out arrayPartition)) { var singles = arrayPartition.Singles(); Log("SINGLES={0}", singles); var b = baseVariables.Remove(index); foreach (var single in singles) { if (!this.Decoder.IsConstant(single)) { var variablesInSingle = this.Decoder.VariablesIn(single); if (baseVariables.IsSubset(variablesInSingle)) { // The general case is very complicated. Here we assume that single has the form of an octagon contraint (+/- y + c) if (baseVariables.Count == 1) { var indexSubstitute = this.Encoder.Substitute(single, ToBoxedExpression(pc, baseVariables.PickAnElement()), indexAsExp); var notWanted = new Set <BoxedVariable <Variable> >(baseVariables); if (!indexSubstitute.IsVariable) // HACK due to handling of expression { notWanted.Add(this.Decoder.UnderlyingVariable(indexSubstitute)); } refinedDomain = refinedDomain.ArrayAssignment(array, indexSubstitute, knowledge, notWanted); } else // Otherwise we try to partition wrt indexAsExp { refinedDomain = refinedDomain.ArrayAssignment(array, indexAsExp, knowledge, baseVariables); } } } } } else { throw new AbstractInterpretationException(); } ALog.EndTransferFunction(StringClosure.For(data)); return(refinedDomain); }
/// <summary> /// Hypothesis: Bound Analysis assumed. /// </summary> /// <param name="dest"></param> private SimplePartitionAbstractDomain <BoxedVariable <Variable>, BoxedExpression> HandleArrayAssignment( string name, APC pc, Variable array, Variable index, SimplePartitionAbstractDomain <BoxedVariable <Variable>, BoxedExpression> data) { var arrayAsExp = BoxedExpression.For(this.Context.Refine(pc, array), this.Decoder.Outdecoder); var indexAsExp = BoxedExpression.For(this.Context.Refine(pc, index), this.Decoder.Outdecoder); ALog.BeginTransferFunction(StringClosure.For("[P]ArrayAssignement"), ExpressionPrinter.ToStringClosure(arrayAsExp, this.Decoder), PrettyPrintPC(pc), StringClosure.For(data)); var baseVariables = this.Decoder.VariablesIn(indexAsExp); Log("VARIABLESIN={0}", baseVariables); // TODO: decide wich variables you want in the partition : probably here a variable inside. You must gatherKnowledge for each variable inside, and reconstruct the bounds of interest. // eg. index: sv1; index is (sv2+1); indexKnowledge is (0,sv3); so (sv2+1) go from 1 to sv3+1 (but could be unnecessary if sv2 is already into the partition ...; var notWanted = new Set <BoxedVariable <Variable> >(); if (baseVariables.Count > 1 || !baseVariables.Contains(ToBoxedVariable(index))) { notWanted.Add(ToBoxedVariable(index)); } var knowledge = this.Encoder.ConstantFor(true); var equalityKnowledge = this.Encoder.ConstantFor(true); foreach (var e in baseVariables) { knowledge = this.Encoder.CompoundExpressionFor(ExpressionType.Bool, ExpressionOperator.And, knowledge, gatherKnowledge(this.Context.Post(pc), ToBoxedExpression(this.Context.Post(pc), e))); } if (!notWanted.IsEmpty) { // NOTE : even if notWanted will not be part of the split partition used, it can already be present in the current partition. // This is why we provide the information, to be used in simplify. PolynomialOfInt <BoxedVariable <Variable>, BoxedExpression> indexAsPoly; if (PolynomialOfInt <BoxedVariable <Variable>, BoxedExpression> .TryToPolynomialForm(indexAsExp, this.Decoder, out indexAsPoly)) { equalityKnowledge = this.Encoder.CompoundExpressionFor(ExpressionType.Bool, ExpressionOperator.Equal, indexAsExp, PolynomialOfInt <BoxedVariable <Variable>, BoxedExpression> .ToPureExpressionForm(indexAsPoly, this.Encoder)); knowledge = this.Encoder.CompoundExpressionFor(ExpressionType.Bool, ExpressionOperator.And, knowledge, equalityKnowledge); } } //var indexKnowledge = gatherKnowledge(pc, indexAsExp); foreach (var e in baseVariables) { var indexRange = guessRange(pc, ToBoxedExpression(pc, e)); // carefull : One or Two can be null. Log("LB({1})={0}", indexRange.One, e); Log("UB({1})={0}", indexRange.Two, e); } var indexRange2 = guessRange(pc, indexAsExp); // carefull : One or Two can be null. Log("LB({1})={0}", indexRange2.One, indexAsExp); Log("UB({1})={0}", indexRange2.Two, indexAsExp); var refinedDomain = data.ArrayAssignment(ToBoxedVariable(array), indexAsExp, knowledge, notWanted); //,notWanted ALog.EndTransferFunction(StringClosure.For(data)); return(refinedDomain); }