-
Notifications
You must be signed in to change notification settings - Fork 36
Constraint independence #124
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 27 commits
634f871
e110c7e
b537708
4c01d0b
8a823f5
e788dd2
f0a6581
e115574
3dcfc0b
d2d6cee
b0f02e9
147a3bc
e7839b4
f91a799
cee9447
22b44c1
2ca9dbd
e247715
08d1672
e4f9696
0b9188d
66756cc
4f3a431
c9dbb4a
8abad91
7251d4e
99f366d
de31156
46c76ba
c5f1e44
c27b432
487457d
ceeea20
ab925c5
66e517c
36a600a
a709a25
70abd26
173fcf8
4370685
453775e
b251e88
67d77da
b325b53
dc2170c
b6906b0
4db3cc3
b8e663d
25af3e9
6aa02e7
747a36c
fbfcf51
c33fa0b
f5b6252
545e56c
62d99e3
7794e7c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -18,30 +18,7 @@ type IMemoryAccessConstantSource = | |
| module internal Memory = | ||
|
|
||
| // ------------------------------- Primitives ------------------------------- | ||
|
|
||
| let makeEmpty() = { | ||
| pc = PC.empty | ||
| evaluationStack = EvaluationStack.empty | ||
| exceptionsRegister = NoException | ||
| stack = CallStack.empty | ||
| stackBuffers = PersistentDict.empty | ||
| classFields = PersistentDict.empty | ||
| arrays = PersistentDict.empty | ||
| lengths = PersistentDict.empty | ||
| lowerBounds = PersistentDict.empty | ||
| staticFields = PersistentDict.empty | ||
| boxedLocations = PersistentDict.empty | ||
| initializedTypes = SymbolicSet.empty | ||
| concreteMemory = Dictionary<_,_>() | ||
| physToVirt = PersistentDict.empty | ||
| allocatedTypes = PersistentDict.empty | ||
| typeVariables = (MappedStack.empty, Stack.empty) | ||
| delegates = PersistentDict.empty | ||
| currentTime = [1] | ||
| startingTime = VectorTime.zero | ||
| model = None | ||
| } | ||
|
|
||
|
|
||
| type memoryMode = | ||
| | ConcreteMemory | ||
| | SymbolicMemory | ||
|
|
@@ -53,7 +30,7 @@ module internal Memory = | |
| match memoryMode with | ||
| | ConcreteMemory -> ConcreteMemory.deepCopy state | ||
| | SymbolicMemory -> state | ||
| { state with pc = newPc } | ||
| { state with pc = newPc; id = Guid.NewGuid().ToString() } | ||
|
|
||
| let private isZeroAddress (x : concreteHeapAddress) = | ||
| x = VectorTime.zero | ||
|
|
@@ -176,7 +153,15 @@ module internal Memory = | |
| {object : term} | ||
| interface IStatedSymbolicConstantSource with | ||
| override x.SubTerms = Seq.empty | ||
| override x.Time = VectorTime.zero | ||
| override x.Time = VectorTime.zero | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Лучше убрать лишние пробелы после 'VectorTime.zero' |
||
| override x.IndependentWith otherSource = | ||
| match otherSource with | ||
| | :? hashCodeSource as otherHashCodeSource -> | ||
| match otherHashCodeSource.object, x.object with | ||
| | ConstantT(_, otherConstantSource, _), ConstantT(_, constantSource, _) -> | ||
| otherConstantSource.IndependentWith constantSource | ||
| | _ -> true | ||
| | _ -> true | ||
|
|
||
| let hashConcreteAddress (address : concreteHeapAddress) = | ||
| address.GetHashCode() |> makeNumber | ||
|
|
@@ -213,14 +198,29 @@ module internal Memory = | |
| | Some time -> time | ||
| | None -> internalfailf "Requesting time of primitive stack location %O" x.key | ||
| override x.TypeOfLocation = x.key.TypeOfLocation | ||
| override x.IndependentWith otherSource = | ||
| match otherSource with | ||
| | :? stackReading as otherReading -> x <> otherReading | ||
| | _ -> true | ||
|
|
||
| [<StructuralEquality;NoComparison>] | ||
| type private heapReading<'key, 'reg when 'key : equality and 'key :> IMemoryKey<'key, 'reg> and 'reg : equality and 'reg :> IRegion<'reg>> = | ||
| {picker : regionPicker<'key, 'reg>; key : 'key; memoryObject : memoryRegion<'key, 'reg>; time : vectorTime} | ||
| interface IMemoryAccessConstantSource with | ||
| override x.SubTerms = Seq.empty | ||
| override x.SubTerms = | ||
| let addKeySubTerms _ (regionKey : updateTreeKey<'key, term>) acc = | ||
| Seq.fold PersistentSet.add acc regionKey.key.SubTerms | ||
| RegionTree.foldr addKeySubTerms PersistentSet.empty x.memoryObject.updates | ||
| |> PersistentSet.toSeq | ||
| |> Seq.append x.key.SubTerms | ||
|
dvvrd marked this conversation as resolved.
|
||
| override x.Time = x.time | ||
| override x.TypeOfLocation = x.picker.sort.TypeOfLocation | ||
| override x.IndependentWith otherSource = | ||
| match otherSource with | ||
| | :? heapReading<'key, 'reg> as otherReading -> | ||
| let rootRegions hr = match hr.memoryObject.updates with | Node dict -> PersistentDict.keys dict | ||
| Seq.allPairs (rootRegions x) (rootRegions otherReading) |> Seq.forall (fun (reg1, reg2) -> reg1.CompareTo reg2 = Disjoint) | ||
| | _ -> true | ||
|
|
||
| let (|HeapReading|_|) (src : IMemoryAccessConstantSource) = | ||
| match src with | ||
|
|
@@ -270,6 +270,11 @@ module internal Memory = | |
| override x.SubTerms = x.baseSource.SubTerms | ||
| override x.Time = x.baseSource.Time | ||
| override x.TypeOfLocation = fromDotNetType x.field.typ | ||
| override x.IndependentWith otherSource = | ||
| match otherSource with | ||
| | :? structField as otherField -> | ||
| x.field <> otherField.field || x.baseSource.IndependentWith otherField.baseSource | ||
| | _ -> true | ||
|
|
||
| let (|StructFieldSource|_|) (src : IMemoryAccessConstantSource) = | ||
| match src with | ||
|
|
@@ -283,6 +288,10 @@ module internal Memory = | |
| override x.SubTerms = x.baseSource.SubTerms | ||
| override x.Time = x.baseSource.Time | ||
| override x.TypeOfLocation = x.baseSource.TypeOfLocation | ||
| override x.IndependentWith otherSource = | ||
| match otherSource with | ||
| | :? heapAddressSource as otherAddress -> x.baseSource.IndependentWith otherAddress.baseSource | ||
| | _ -> true | ||
|
|
||
| let (|HeapAddressSource|_|) (src : IMemoryAccessConstantSource) = | ||
| match src with | ||
|
|
@@ -295,6 +304,13 @@ module internal Memory = | |
| interface IStatedSymbolicConstantSource with | ||
| override x.SubTerms = Seq.empty | ||
| override x.Time = VectorTime.zero | ||
| override x.IndependentWith otherSource = | ||
| match otherSource with | ||
| | :? typeInitialized as otherType -> | ||
| let xDotNetType = toDotNetType x.typ | ||
| let otherDotNetType = toDotNetType otherType.typ | ||
| structuralInfimum xDotNetType otherDotNetType = None | ||
| | _ -> true | ||
|
|
||
| let (|TypeInitializedSource|_|) (src : IStatedSymbolicConstantSource) = | ||
| match src with | ||
|
|
@@ -333,6 +349,20 @@ module internal Memory = | |
| let declaringType = fromDotNetType m.DeclaringType | ||
| if isValueType declaringType then __insufficientInformation__ "Can't execute in isolation methods of value types, because we can't be sure where exactly \"this\" is allocated!" | ||
| else HeapRef (Constant "this" {baseSource = {key = ThisKey m; time = Some VectorTime.zero}} AddressType) declaringType | ||
|
|
||
| let fillWithParametersAndThis state (method : System.Reflection.MethodBase) = | ||
| let parameters = method.GetParameters() |> Seq.map (fun param -> | ||
|
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. В этом месте не уверен по поводу того, нужно ли вместе с параметрами добавить что-то в allocatedTypes у state |
||
| (ParameterKey param, None, fromDotNetType param.ParameterType)) |> List.ofSeq | ||
| let parametersAndThis = | ||
| if Reflection.hasThis method then | ||
| let t = fromDotNetType method.DeclaringType | ||
| let addr = [-1] | ||
| let thisRef = HeapRef (ConcreteHeapAddress addr) t | ||
| state.allocatedTypes <- PersistentDict.add addr t state.allocatedTypes | ||
| state.startingTime <- [-2] | ||
| (ThisKey method, Some thisRef, t) :: parameters // TODO: incorrect type when ``this'' is Ref to stack | ||
| else parameters | ||
| newStackFrame state method parametersAndThis | ||
|
|
||
| // =============== Marshalling/unmarshalling without state changing =============== | ||
|
|
||
|
|
@@ -646,48 +676,69 @@ module internal Memory = | |
| commonGuardedStatedApplyk (fun state term k -> mapper state term |> k) state term id id | ||
|
|
||
| let commonStatedConditionalExecutionk (state : state) conditionInvocation thenBranch elseBranch merge2Results k = | ||
| // Returns PC containing only constraints dependent with cond | ||
| let keepDependentWith pc cond = | ||
| PC.fragments pc | ||
| |> Seq.tryFind (PC.toSeq >> Seq.contains cond) | ||
| |> Option.defaultValue pc | ||
| let execution thenState elseState condition k = | ||
| assert (condition <> True && condition <> False) | ||
| thenBranch thenState (fun thenResult -> | ||
| elseBranch elseState (fun elseResult -> | ||
| merge2Results thenResult elseResult |> k)) | ||
| conditionInvocation state (fun (condition, conditionState) -> | ||
| conditionInvocation state (fun (condition, conditionState) -> | ||
| let negatedCondition = !!condition | ||
| let thenPc = PC.add state.pc condition | ||
| let elsePc = PC.add state.pc (!!condition) | ||
| if PC.isFalse thenPc then | ||
| let elsePc = PC.add state.pc negatedCondition | ||
| let independentThenPc = keepDependentWith thenPc condition | ||
| // In fact, this call is redundant because independentElsePc == independentThenPc with negated cond | ||
| let independentElsePc = keepDependentWith elsePc negatedCondition | ||
| if PC.isFalse independentThenPc then | ||
| conditionState.pc <- elsePc | ||
| elseBranch conditionState (List.singleton >> k) | ||
| elif PC.isFalse elsePc then | ||
| elif PC.isFalse independentElsePc then | ||
| conditionState.pc <- thenPc | ||
| thenBranch conditionState (List.singleton >> k) | ||
| else | ||
| conditionState.pc <- thenPc | ||
| conditionState.pc <- independentThenPc | ||
| match SolverInteraction.checkSat conditionState with | ||
| | SolverInteraction.SmtUnknown _ -> | ||
| conditionState.pc <- elsePc | ||
| conditionState.pc <- independentElsePc | ||
| match SolverInteraction.checkSat conditionState with | ||
| | SolverInteraction.SmtUnsat _ | ||
| | SolverInteraction.SmtUnknown _ -> | ||
| __insufficientInformation__ "Unable to witness branch" | ||
| | SolverInteraction.SmtSat model -> | ||
| conditionState.pc <- elsePc | ||
| conditionState.model <- Some model.mdl | ||
| StatedLogger.log conditionState.id $"Model stack: %s{model.mdl.state.stack.frames.ToString()}" | ||
| StatedLogger.log conditionState.id $"Branching on: %s{(independentElsePc |> PC.toSeq |> conjunction).ToString()}" | ||
| elseBranch conditionState (List.singleton >> k) | ||
| | SolverInteraction.SmtUnsat _ -> | ||
| conditionState.pc <- elsePc | ||
| StatedLogger.log conditionState.id $"Branching on: %s{(independentElsePc |> PC.toSeq |> conjunction).ToString()}" | ||
| elseBranch conditionState (List.singleton >> k) | ||
| | SolverInteraction.SmtSat model -> | ||
| conditionState.pc <- elsePc | ||
| conditionState.model <- Some model.mdl | ||
| | SolverInteraction.SmtSat thenModel -> | ||
| conditionState.pc <- independentElsePc | ||
| match SolverInteraction.checkSat conditionState with | ||
| | SolverInteraction.SmtUnsat _ | ||
| | SolverInteraction.SmtUnknown _ -> | ||
| conditionState.pc <- thenPc | ||
| conditionState.model <- Some thenModel.mdl | ||
| StatedLogger.log conditionState.id $"Model stack: %s{thenModel.mdl.state.stack.frames.ToString()}" | ||
| StatedLogger.log conditionState.id $"Branching on: %s{(independentThenPc |> PC.toSeq |> conjunction).ToString()}" | ||
| thenBranch conditionState (List.singleton >> k) | ||
| | SolverInteraction.SmtSat model -> | ||
| | SolverInteraction.SmtSat elseModel -> | ||
| conditionState.pc <- thenPc | ||
| let thenState = conditionState | ||
| let elseState = copy conditionState elsePc | ||
| elseState.model <- Some model.mdl | ||
| thenState.pc <- thenPc | ||
| StatedLogger.copy thenState.id elseState.id | ||
| StatedLogger.log thenState.id $"Model stack: %s{thenModel.mdl.state.stack.frames.ToString()}" | ||
| StatedLogger.log elseState.id $"Model stack: %s{elseModel.mdl.state.stack.frames.ToString()}" | ||
| StatedLogger.log thenState.id $"Branching on: %s{(independentThenPc |> PC.toSeq |> conjunction).ToString()}" | ||
| StatedLogger.log elseState.id $"Branching on: %s{(independentElsePc |> PC.toSeq |> conjunction).ToString()}" | ||
| elseState.model <- Some elseModel.mdl | ||
| thenState.model <- Some thenModel.mdl | ||
| execution thenState elseState condition k) | ||
|
|
||
| let statedConditionalExecutionWithMergek state conditionInvocation thenBranch elseBranch k = | ||
|
|
@@ -1482,6 +1533,7 @@ module internal Memory = | |
| let g = g1 &&& g2 &&& g3 &&& g4 &&& g5 &&& g6 | ||
| if not <| isFalse g then | ||
| return { | ||
| id = Guid.NewGuid().ToString() | ||
| pc = if isTrue g then pc else PC.add pc g | ||
| evaluationStack = evaluationStack | ||
| exceptionsRegister = exceptionRegister | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.