public void ReadField(VersionedVariable result, VersionedVariable reference, IFieldDefinition field) { if (this.CanBeSatisfiable) { this.CurrentState.ReadField(result, reference, field, this.context); } }
public void WriteReferenceField(VersionedVariable reference, IFieldDefinition field, VersionedVariable value) { int refId = GetIdFromInterpretation(this.GetInterpretation(reference)); var valIntr = this.GetInterpretation(value); this.WriteField(refId, field, valIntr); }
public void AssertInequality( VersionedVariable left, VersionedVariable right, ISymbolicHeapContext context) { this.cachedState = null; var leftState = this.GetOrCreateVariableState(left, context); var rightState = this.GetOrCreateVariableState(right, context); if (this.TryGetConstantComparisonResult(leftState, rightState) is bool areEqual) { if (areEqual) { this.IsConflicting = true; } } else { if (IsNullStateAndVarState(leftState, rightState, out var varState)) { // No need to assert it again if it has been already done before if (varState.CanBeNull) { this.variableStates[varState.Id] = varState.WithCanBeNull(false); context.AddAssertion(leftState.Representation != rightState.Representation); } } else { context.AddAssertion(leftState.Representation != rightState.Representation); } } }
public void WriteField(VersionedVariable reference, IFieldDefinition field, Expression value) { if (this.CanBeSatisfiable) { this.CurrentState.WriteField(reference, field, value, this.context); } }
public void AssignReference(VersionedVariable result, VersionedVariable value) { if (this.CanBeSatisfiable) { this.CurrentState.AssignReference(result, value, this.context); } }
public void AllocateNew(VersionedVariable result) { if (this.CanBeSatisfiable) { this.CurrentState.AllocateNew(result, this.context); } }
private VariableState TrySecureNotNull( VersionedVariable variable, ISymbolicHeapContext context) { // Secure that the variable is initialized and not null var state = this.GetVariableStateOrNull(variable); if (state == null) { state = this.CreateNewInputVariableState(variable, context, canBeNull: false); this.MapToVariableState(variable, state); context.AddAssertion(state.Representation != VariableState.Null.Representation); } else if (state == VariableState.Null) { this.IsConflicting = true; } else if (state.CanBeNull) { Contract.Assert(state.IsInput || state.IsInputDerived); this.variableStates[state.Id] = state.WithCanBeNull(false); context.AddAssertion(state.Representation != VariableState.Null.Representation); } return(state); }
private VariableState CreateNewInputVariableState(VersionedVariable variable, ISymbolicHeapContext context, bool canBeNull) { var newVar = context.CreateVariable(Sort.Int, variable.ToString()); var newState = VariableState.CreateInput(this.nextVariableStateId, newVar, canBeNull); this.nextVariableStateId++; return(newState); }
public VariableState TryGetVariableState(VersionedVariable variable) { if (this.variableToStateIdMap.TryGetValue(variable, out int stateId)) { return(this.variableStates[stateId]); } else { return(null); } }
public Expression GetEqualityExpression(bool areEqual, VersionedVariable left, VersionedVariable right) { if (!this.CanBeSatisfiable) { // Doesn't matter, the path is unreachable anyway return(ExpressionFactory.False); } var expr = this.CurrentState.GetEqualityExpression(areEqual, left, right, this.context); return(expr); }
private VariableState GetVariableStateOrNull( VersionedVariable variable) { if (this.variableToStateIdMap.TryGetValue(variable, out var varStateId)) { return(this.variableStates[varStateId]); } else { return(null); } }
public void AssertEquality(bool areEqual, VersionedVariable left, VersionedVariable right) { if (this.CanBeSatisfiable) { if (areEqual) { this.CurrentState.AssertEquality(left, right, this.context); } else { this.CurrentState.AssertInequality(left, right, this.context); } } }
private void MapToVariableState( VersionedVariable variable, VariableState state) { this.variableStates[state.Id] = state; if (this.variableToStateIdMap.TryGetValue(variable, out int curStateId)) { if (curStateId == state.Id) { if (this.variableStates[curStateId] != state) { this.variableStates[curStateId] = state; } } else { // Update the states of all the variables pointing to the old one and erase it var currentVars = this.stateIdToVariablesMap[curStateId]; var newVars = this.stateIdToVariablesMap.GetValueOrDefault(state.Id) ?? ImmutableList <VersionedVariable> .Empty; newVars = newVars.AddRange(currentVars); if (!currentVars.Any(v => v == variable)) { // TODO: Consider turning it into a set to make this more effective newVars = newVars.Add(variable); } this.variableStates.Remove(curStateId); this.stateIdToVariablesMap.Remove(curStateId); this.stateIdToVariablesMap[state.Id] = newVars; foreach (var newVar in newVars) { this.variableToStateIdMap[newVar] = state.Id; } } } else { this.variableToStateIdMap[variable] = state.Id; var curMappedVars = this.stateIdToVariablesMap.GetValueOrDefault(state.Id) ?? ImmutableList <VersionedVariable> .Empty; var newMappedVars = curMappedVars.Add(variable); this.stateIdToVariablesMap[state.Id] = newMappedVars; } }
public void ReadField( VersionedVariable result, VersionedVariable reference, IFieldDefinition field, ISymbolicHeapContext context) { this.cachedState = null; var refState = this.TrySecureNotNull(reference, context); if (this.IsConflicting) { return; } Contract.Assert(refState.IsInput); Expression resultVar; if (result.Variable.IsReference) { // Secure that the result variable is initialized var resultState = this.GetOrCreateVariableState(result, context); Contract.Assert(resultState.IsInput); resultVar = resultState.Representation; // Mark as derived from the input heap this.variableStates[resultState.Id] = resultState.WithIsInputDerived(true); } else { // Don't store scalar values in the state resultVar = context.GetNamedVariable(result); } // Initialize the particular field var fieldVar = this.GetOrAddFieldVariable(field, context); // Propagate the read to the SMT solver var selectAssert = (BoolHandle)ExpressionFactory.Equal( resultVar, fieldVar.Select(refState.Representation)); context.AddAssertion(selectAssert); }
public HeapModelLocation AllocateNew(VersionedVariable result) { int id = GetIdFromInterpretation(this.GetInterpretation(result)); // Increment the version by performing a change this.changes.Add(new FieldChange() { ReferenceId = id }); this.currentHeap.Add(id, new LocationInfo() { LastModifiedVersion = this.CurrentVersion }); return(new HeapModelLocation(id, this.CurrentVersion)); }
public HeapModelLocation GetLocation(VersionedVariable reference) { int id = GetIdFromInterpretation(this.GetInterpretation(reference)); if (this.currentHeap.TryGetValue(id, out var locationInfo) || this.inputHeap.TryGetValue(id, out locationInfo)) { return(new HeapModelLocation(id, locationInfo.LastModifiedVersion)); } else { this.inputHeap.Add(id, new LocationInfo() { LastModifiedVersion = 0 }); return(new HeapModelLocation(id, 0)); } }
private VariableState GetOrCreateVariableState( VersionedVariable variable, ISymbolicHeapContext context, bool canBeNull = true) { if (this.variableToStateIdMap.TryGetValue(variable, out var varStateId)) { return(this.variableStates[varStateId]); } else { VariableState newState = this.CreateNewInputVariableState(variable, context, canBeNull); this.MapToVariableState(variable, newState); return(newState); } }
public void WriteField( VersionedVariable reference, IFieldDefinition field, Expression value, ISymbolicHeapContext context) { this.cachedState = null; var refState = this.TrySecureNotNull(reference, context); if (this.IsConflicting) { return; } Expression valExpr; if (value.Sort == References.Sort) { if (!(value is FlowVariable valVar)) { throw new NotSupportedException("Only versioned flow variables supported as references"); } // Secure that the result variable is initialized var versionedVal = context.GetVersioned(valVar); var valState = this.GetOrCreateVariableState(versionedVal, context); valExpr = valState.Representation; } else { // Don't store scalar values in the state valExpr = value; } // Get current and new version of the field var oldFieldVar = this.GetOrAddFieldVariable(field, context); var newFieldVar = this.CreateNewFieldVariableVersion(field, context); var storeAssert = (oldFieldVar == newFieldVar.Store(refState.Representation, (Handle)valExpr)); context.AddAssertion(storeAssert); }
public void ReadField(VersionedVariable reference, IFieldDefinition field) { int refId = GetIdFromInterpretation(this.GetInterpretation(reference)); if (this.currentHeap.TryGetValue(refId, out var locationInfo)) { if (locationInfo.ContainsField(field)) { // It was read successfully return; } else if (refId > VariableState.NullValue) { // Note: This can't happen in higher level languages, because they always // initialize the fields (e.g. to zero) throw new NotSupportedException( "Unable to model reading data of explicitly allocated but uninitialized objects"); } } // Fall back to input heap if not found in the current heap if (!this.inputHeap.TryGetValue(refId, out locationInfo)) { locationInfo = new LocationInfo() { LastModifiedVersion = 0 }; this.inputHeap.Add(refId, locationInfo); } if (!locationInfo.ContainsField(field)) { // Read the value from the particular input heap array var fieldArray = this.state.GetFieldArray(field); var valueIntr = this.smtModel.GetInterpretation(fieldArray.Select(refId)); // Store either the reference ID or the value interpretation to the field locationInfo.SetField(field, valueIntr); } }
public void AllocateNew( VersionedVariable result, ISymbolicHeapContext context) { this.cachedState = null; var newState = VariableState.CreateValue(this.nextVariableStateId, this.nextReferenceValue); this.nextVariableStateId++; this.nextReferenceValue++; if (this.variableToStateIdMap.TryGetValue(result, out int curStateId)) { var curState = this.variableStates[curStateId]; Contract.Assert(curState.IsInput); // Unify a previously known value with its current allocated number context.AddAssertion(curState.Representation == newState.Representation); } this.MapToVariableState(result, newState); }
public void AssignReference( VersionedVariable result, VersionedVariable value, ISymbolicHeapContext context) { this.cachedState = null; var resultState = this.GetVariableStateOrNull(result); var valueState = this.GetVariableStateOrNull(value); if (resultState != null && valueState != null) { Contract.Assert(resultState.IsInput); context.AddAssertion(resultState.Representation == valueState.Representation); this.MapToVariableState(result, valueState); } else if (resultState == null && valueState == null) { var newVar = context.CreateVariable(Sort.Int, value.Variable.ToString()); var newState = VariableState.CreateInput(this.nextVariableStateId, newVar, true); this.nextVariableStateId++; this.MapToVariableState(result, newState); this.MapToVariableState(value, newState); } else if (resultState != null) { Contract.Assert(valueState == null); this.MapToVariableState(value, resultState); } else { Contract.Assert(valueState != null && resultState == null); this.MapToVariableState(result, valueState); } }
public void AssertEquality( VersionedVariable left, VersionedVariable right, ISymbolicHeapContext context) { this.cachedState = null; var leftState = this.GetOrCreateVariableState(left, context); var rightState = this.GetOrCreateVariableState(right, context); if (this.TryGetConstantComparisonResult(leftState, rightState) is bool areEqual) { if (!areEqual) { this.IsConflicting = true; } } else { context.AddAssertion(leftState.Representation == rightState.Representation); } }
public BoolHandle GetEqualityExpression( bool areEqual, VersionedVariable left, VersionedVariable right, ISymbolicHeapContext context) { this.cachedState = null; var leftState = this.GetOrCreateVariableState(left, context); var rightState = this.GetOrCreateVariableState(right, context); if (this.TryGetConstantComparisonResult(leftState, rightState) is bool constResult) { return(constResult); } else { return(areEqual ? leftState.Representation == rightState.Representation : leftState.Representation != rightState.Representation); } }
private Interpretation GetInterpretation(VersionedVariable reference) { var varState = this.state.TryGetVariableState(reference); if (varState == null) { // References with no operations or constraints imposed upon them will be null return((Interpretation)VariableState.Null.Representation); } else if (varState.IsInput || varState.IsInputDerived) { Contract.Assert(varState.Representation.Expression.Kind == ExpressionKind.Variable); return(this.smtModel.GetInterpretation(varState.Representation)); } else { Contract.Assert(varState.Representation.Expression.Kind == ExpressionKind.Interpretation); return((Interpretation)varState.Representation); } }