protected ArraySegmentation <Elements, BoxedVariable <Variable>, BoxedExpression> MaterializeArray <Elements>( APC postPC, ArraySegmentationEnvironment <Elements, BoxedVariable <Variable>, BoxedExpression> preState, Func <BoxedExpression, FlatAbstractDomain <bool> > CheckIfNonZero, Variable arrayValue, Elements initialValue, Elements bottom) where Elements : class, IAbstractDomainForArraySegmentationAbstraction <Elements, BoxedVariable <Variable> > { Contract.Requires(preState != null); Contract.Requires(initialValue != null); var boxSym = new BoxedVariable <Variable>(arrayValue); ArraySegmentation <Elements, BoxedVariable <Variable>, BoxedExpression> arraySegment; if (preState.TryGetValue(boxSym, out arraySegment)) { return(arraySegment); // already materialized } Variable array_Length; if (this.Context.ValueContext.TryGetArrayLength(postPC, arrayValue, out array_Length)) { var isNonEmpty = CheckIfNonZero(this.ToBoxedExpression(postPC, array_Length)).IsTrue(); var limits = new NonNullList <SegmentLimit <BoxedVariable <Variable> > >() { new SegmentLimit <BoxedVariable <Variable> >(NormalizedExpression <BoxedVariable <Variable> > .For(0), false), // { 0 } new SegmentLimit <BoxedVariable <Variable> >(NormalizedExpression <BoxedVariable <Variable> > .For(new BoxedVariable <Variable>(array_Length)), !isNonEmpty) // { symb.Length } }; var elements = new NonNullList <Elements>() { initialValue }; var newSegment = new ArraySegmentation <Elements, BoxedVariable <Variable>, BoxedExpression>( limits, elements, bottom, this.ExpressionManager); preState.AddElement(new BoxedVariable <Variable>(arrayValue), newSegment); return(newSegment); } return(null); }
public override ArrayState Assume(APC pc, string tag, Variable source, object provenance, ArrayState data) { Contract.Assume(data != null); if (tag != "false") { data = this.Assert(pc, "assume", source, provenance, data); Contract.Assert(data != null); var convertedExp = ToBoxedExpression(pc, source); if (convertedExp == null) { // abort return(data); } Variable v1, v2; BoxedExpression bLeft, bRight, x; int k; if (convertedExp.IsCheckExp1EqExp2(out bLeft, out bRight) && // bLeft == bRight bRight.IsCheckExp1EqConst(out x, out k) && // bRight == x + 1 bLeft.TryGetFrameworkVariable(out v1) && x.TryGetFrameworkVariable(out v2) ) { var vNormExp = NormalizedExpression <BoxedVariable <Variable> > .For(new BoxedVariable <Variable>(v1)); var sumNormExp = NormalizedExpression <BoxedVariable <Variable> > .For(new BoxedVariable <Variable>(v2), k); var mySubState = Select(data); mySubState = mySubState.TestTrueEqualAsymmetric(vNormExp, sumNormExp); mySubState = mySubState.TestTrueEqualAsymmetric(sumNormExp, vNormExp); data = data.UpdatePluginAt(this.Id, mySubState); } } return(data.UpdatePluginAt(this.Id, Select(data).ReduceWith(data.Numerical))); }
public override ArrayState Binary(APC pc, BinaryOperator op, Variable dest, Variable s1, Variable s2, ArrayState data) { Variable var; int k; if (TryMatchVariableConstant(pc, op, Strip(pc, s1), Strip(pc, s2), data.Numerical, out var, out k) && k != Int32.MinValue) { var mySubState = Select(data); var normExpression = NormalizedExpression <BoxedVariable <Variable> > .For(new BoxedVariable <Variable>(var), k); var normVariable = NormalizedExpression <BoxedVariable <Variable> > .For(new BoxedVariable <Variable>(dest)); var array = mySubState.TestTrueEqualAsymmetric(normVariable, normExpression); normExpression = NormalizedExpression <BoxedVariable <Variable> > .For(new BoxedVariable <Variable>(dest), -k); normVariable = NormalizedExpression <BoxedVariable <Variable> > .For(new BoxedVariable <Variable>(var)); return(data.UpdatePluginAt(this.Id, mySubState.TestTrueEqualAsymmetric(normExpression, normVariable))); } return(data); }
static public NormalizedExpression <BoxedVariable <Variable> > ToNormalizedExpression(Variable v) { Contract.Ensures(Contract.Result <NormalizedExpression <BoxedVariable <Variable> > >() != null); return(NormalizedExpression <BoxedVariable <Variable> > .For(new BoxedVariable <Variable>(v))); }
ArrayCounterInitialization <AbstractDomain>(APC pc, Local local, Variable source, ArrayState resultState, ArraySegmentationEnvironment <AbstractDomain, BoxedVariable <Variable>, BoxedExpression> mySubState) where AbstractDomain : class, IAbstractDomainForArraySegmentationAbstraction <AbstractDomain, BoxedVariable <Variable> > { Contract.Ensures(Contract.Result <ArraySegmentationEnvironment <AbstractDomain, BoxedVariable <Variable>, BoxedExpression> >() != null); var sourceExp = ToBoxedExpression(pc, source); // we look for loop initializations i == var Variable localValue; if (sourceExp.IsVariable && this.Context.ValueContext.TryLocalValue(this.Context.MethodContext.CFG.Post(pc), local, out localValue)) { // If source >= 0, we check if source <= arr.Length, for some array 'arr' // If this is the case, then we can try to refine the segmentation including source and locValue if (resultState.Numerical.CheckIfGreaterEqualThanZero(sourceExp).IsTrue()) { var sourceNorm = ToNormalizedExpression(source); var toUpdate = new Dictionary <BoxedVariable <Variable>, ArraySegmentation <AbstractDomain, BoxedVariable <Variable>, BoxedExpression> >(); foreach (var pair in mySubState.Elements) { if (!pair.Value.IsEmptyArray && pair.Value.IsNormal && // We do the trick only for arrays {0} val {Len} as otherwise we should be more careful where we refine the segmentation, as for instance the update below may be too rough. However, I haven't find any interesting non-artificial example for it pair.Value.Elements.Count() == 1) { foreach (var limit in pair.Value.LastLimit) { if (resultState.Numerical.CheckIfLessEqualThan(sourceExp, limit.Convert(this.Encoder)).IsTrue()) { IAbstractDomain abstractValue; if (pair.Value.TryGetAbstractValue( NormalizedExpression <BoxedVariable <Variable> > .For(0), sourceNorm, resultState.Numerical, out abstractValue) && abstractValue is AbstractDomain) { ArraySegmentation <AbstractDomain, BoxedVariable <Variable>, BoxedExpression> newSegment; if (pair.Value.TrySetAbstractValue(sourceNorm, (AbstractDomain)abstractValue, resultState.Numerical, out newSegment)) { toUpdate.Add(pair.Key, newSegment); break; // We've already updated this segmentation } } } } } } foreach (var pair in toUpdate) { mySubState[pair.Key] = pair.Value; } } } return(mySubState); }
protected ArrayState UpdateArrayAbstractValue(APC pc, BoxedVariable <Variable> arr, NormalizedExpression <BoxedVariable <Variable> > index, NonRelationalValueAbstraction <BoxedVariable <Variable>, BoxedExpression> ael, ArrayState prevState) { Contract.Requires(prevState != null); Contract.Ensures(Contract.Result <ArrayState>() != null); ArraySegmentation <NonRelationalValueAbstraction <BoxedVariable <Variable>, BoxedExpression>, BoxedVariable <Variable>, BoxedExpression> prev, updated; if (prevState.Array.TryGetValue(arr, out prev)) { if (index != null) { IAbstractDomain prevAel; if (prev.TryGetAbstractValue(index, prevState.Numerical, out prevAel) && prevAel is NonRelationalValueAbstraction <BoxedVariable <Variable>, BoxedExpression> ) { ael = ael.Meet(prevAel as NonRelationalValueAbstraction <BoxedVariable <Variable>, BoxedExpression>); } if (prev.TrySetAbstractValue(index, ael, prevState.Numerical, out updated)) { prevState.Array[arr] = updated; } } } return(prevState); }
protected bool TryCreateArraySegment(BoxedExpression low, BoxedExpression upp, Variable arrayLen, AbstractDomain intv, INumericalAbstractDomain <BoxedVariable <Variable>, BoxedExpression> numDom, out ArraySegmentation <AbstractDomain, BoxedVariable <Variable>, BoxedExpression> arraySegmentation) { #region Contracts Contract.Requires(low != null); Contract.Requires(upp != null); Contract.Requires(intv != null); Contract.Requires(arrayLen != null); Contract.Requires(numDom != null); Contract.Ensures(!Contract.Result <bool>() || Contract.ValueAtReturn(out arraySegmentation) != null); #endregion var lowerBounds = new Set <NormalizedExpression <BoxedVariable <Variable> > >(); lowerBounds.AddIfNotNull(low.ToNormalizedExpression <Variable>()); var upperBounds = new Set <NormalizedExpression <BoxedVariable <Variable> > >(); upperBounds.AddIfNotNull(upp.ToNormalizedExpression <Variable>()); upperBounds.AddIfNotNull(upp.ToNormalizedExpression <Variable>(true)); upperBounds.AddIfNotNull(upp.Simplify(this.DecoderForMetaData).ToNormalizedExpression <Variable>()); upperBounds.AddIfNotNull(this.Decoder.Stripped(upp).ToNormalizedExpression <Variable>()); if (lowerBounds.Count == 0 || upperBounds.Count == 0) { arraySegmentation = null; return(false); } var segments = new NonNullList <SegmentLimit <BoxedVariable <Variable> > >(); var elements = new NonNullList <AbstractDomain>(); #region Build the prefix // Check if low is zero int lowValue; if (low.IsConstantInt(out lowValue)) { if (lowValue < 0) { arraySegmentation = default(ArraySegmentation <AbstractDomain, BoxedVariable <Variable>, BoxedExpression>); return(false); } // { 0 } Top { lowValue } if (lowValue > 0) { segments.Add(new SegmentLimit <BoxedVariable <Variable> >(NormalizedExpression <BoxedVariable <Variable> > .For(0), false)); elements.Add((AbstractDomain)intv.Top); } // .. { lowValue } intv segments.Add(new SegmentLimit <BoxedVariable <Variable> >(lowerBounds, false)); elements.Add(intv); } else if (numDom.CheckIfGreaterEqualThanZero(low).IsTrue()) { // { 0 } Top { low }? segments.Add(new SegmentLimit <BoxedVariable <Variable> >(NormalizedExpression <BoxedVariable <Variable> > .For(0), false)); elements.Add((AbstractDomain)intv.Top); // intv { upp }? segments.Add(new SegmentLimit <BoxedVariable <Variable> >(lowerBounds, true)); // F: we can improve precision by asking if low != 0 elements.Add(intv); } else { arraySegmentation = default(ArraySegmentation <AbstractDomain, BoxedVariable <Variable>, BoxedExpression>); return(false); } #endregion #region Build the suffix // ... { upperBounds } if (arrayLen.Equals(upp.UnderlyingVariable) || arrayLen.Equals(this.Decoder.Stripped(upp).UnderlyingVariable)) { segments.Add(new SegmentLimit <BoxedVariable <Variable> >(upperBounds, false)); } else // ... { upperBounds } Top { arrayLen }? { segments.Add(new SegmentLimit <BoxedVariable <Variable> >(upperBounds, false)); elements.Add((AbstractDomain)intv.Top); segments.Add( new SegmentLimit <BoxedVariable <Variable> >( NormalizedExpression <BoxedVariable <Variable> > .For(new BoxedVariable <Variable>(arrayLen)), true)); } #endregion arraySegmentation = new ArraySegmentation <AbstractDomain, BoxedVariable <Variable>, BoxedExpression>( segments, elements, (AbstractDomain)intv.Bottom, this.ExpressionManager); return(true); }
public override ArrayState Stelem( APC pc, Type type, Variable array, Variable index, Variable value, ArrayState data) { Contract.Assume(data != null); var state = Select(data); var bArray = new BoxedVariable <Variable>(array); ArraySegmentation <TwoValuesLattice <BoxedVariable <Variable> >, BoxedVariable <Variable>, BoxedExpression> segment, newSegment; if (state.TryGetValue(bArray, out segment)) { var indexExp = ToBoxedExpression(pc, index); var indexNormExp = indexExp.ToNormalizedExpression <Variable>(); if (indexNormExp == null) { // Try to find a numerical bounds var indexValue = data.Numerical.BoundsFor(indexExp).AsInterval; if (indexValue.IsSingleton && indexValue.LowerBound.IsInteger) { indexNormExp = NormalizedExpression <BoxedVariable <Variable> > .For((Int32)indexValue.LowerBound); Contract.Assert(indexNormExp != null); } else { // We have a range of addresses Int32 low, upp; if (indexValue.IsFiniteAndInt32(out low, out upp)) { var lowExp = NormalizedExpression <BoxedVariable <Variable> > .For(low); var uppExp = NormalizedExpression <BoxedVariable <Variable> > .For(upp); if (segment.TrySetAbstractValue(lowExp, uppExp, MAYBEMODIFIED, data.Numerical, out newSegment)) { state.Update(new BoxedVariable <Variable>(array), newSegment); return(data.UpdatePluginAt(this.Id, state)); } } state.RemoveElement(new BoxedVariable <Variable>(array)); return(data.UpdatePluginAt(this.Id, state)); } } if (segment.TrySetAbstractValue(indexNormExp, MAYBEMODIFIED, data.Numerical, out newSegment)) { // We explicty add the constant for indexNormExp, if we have one Rational val; if (data.Numerical.BoundsFor(indexExp).TryGetSingletonValue(out val) && val.IsInteger) { var k = (Int32)val; // Add k == indexNormExp newSegment = newSegment.TestTrueEqualAsymmetric(NormalizedExpression <BoxedVariable <Variable> > .For(k), indexNormExp); } // Add the sv = constants informations newSegment = newSegment.TestTrueWithIntConstants(data.Numerical.IntConstants.ToNormalizedExpressions()); state.Update(new BoxedVariable <Variable>(array), newSegment); } else // For some reason, we were unable to set the abstract value, so we smash all the array to one { state.RemoveElement(new BoxedVariable <Variable>(array)); } } return(data.UpdatePluginAt(this.Id, state)); }