Commit d93536ce authored by Nadim Kobeissi's avatar Nadim Kobeissi 💾
Browse files

Add essential missing sanity check on primitive inputs

parent 1103c973
Pipeline #810 passed with stages
in 1 minute and 18 seconds
...@@ -65,7 +65,7 @@ func attackerStateAbsorbPhaseValues(valPrincipalState *PrincipalState) error { ...@@ -65,7 +65,7 @@ func attackerStateAbsorbPhaseValues(valPrincipalState *PrincipalState) error {
attackerStateShared.PrincipalState, valPrincipalStateClone, attackerStateShared.PrincipalState, valPrincipalStateClone,
) )
} }
aa, _, err := valueResolveValueInternalValuesFromPrincipalState( aa, err := valueResolveValueInternalValuesFromPrincipalState(
a, a, i, valPrincipalState, attackerStateShared, true, a, a, i, valPrincipalState, attackerStateShared, true,
) )
if err != nil { if err != nil {
......
...@@ -19,6 +19,7 @@ func mutationMapInit( ...@@ -19,6 +19,7 @@ func mutationMapInit(
Mutations: [][]*Value{}, Mutations: [][]*Value{},
Combination: []*Value{}, Combination: []*Value{},
DepthIndex: []int{}, DepthIndex: []int{},
Worthwhile: false,
OutOfMutations: false, OutOfMutations: false,
} }
InfoMessage(fmt.Sprintf( InfoMessage(fmt.Sprintf(
...@@ -147,7 +148,7 @@ func mutationMapReplacePrimitive( ...@@ -147,7 +148,7 @@ func mutationMapReplacePrimitive(
} }
} }
case typesEnumPrimitive: case typesEnumPrimitive:
a, _, err = valueResolveValueInternalValuesFromPrincipalState( a, err = valueResolveValueInternalValuesFromPrincipalState(
a, a, rootIndex, valPrincipalState, valAttackerState, false, a, a, rootIndex, valPrincipalState, valAttackerState, false,
) )
if err != nil { if err != nil {
...@@ -205,11 +206,15 @@ func mutationMapReplaceEquation( ...@@ -205,11 +206,15 @@ func mutationMapReplaceEquation(
} }
func mutationMapNext(valMutationMap MutationMap) MutationMap { func mutationMapNext(valMutationMap MutationMap) MutationMap {
valMutationMap.Worthwhile = false
if len(valMutationMap.Combination) == 0 { if len(valMutationMap.Combination) == 0 {
valMutationMap.OutOfMutations = true valMutationMap.OutOfMutations = true
return valMutationMap return valMutationMap
} }
for i := 0; i < len(valMutationMap.Combination); i++ { for i := 0; i < len(valMutationMap.Combination); i++ {
if i >= valMutationMap.LastIncrement {
valMutationMap.Worthwhile = true
}
valMutationMap.Combination[i] = valMutationMap.Mutations[i][valMutationMap.DepthIndex[i]] valMutationMap.Combination[i] = valMutationMap.Mutations[i][valMutationMap.DepthIndex[i]]
if i != len(valMutationMap.Combination)-1 { if i != len(valMutationMap.Combination)-1 {
continue continue
......
...@@ -170,7 +170,7 @@ func sanityPrimitive(p *Primitive, outputs []*Constant) error { ...@@ -170,7 +170,7 @@ func sanityPrimitive(p *Primitive, outputs []*Constant) error {
if p.Check && !check { if p.Check && !check {
return fmt.Errorf("primitive is checked but does not support checking") return fmt.Errorf("primitive is checked but does not support checking")
} }
return nil return sanityCheckPrimitiveArgumentOutputs(p)
} }
func sanityQueries(m Model, valKnowledgeMap *KnowledgeMap) error { func sanityQueries(m Model, valKnowledgeMap *KnowledgeMap) error {
...@@ -381,6 +381,37 @@ func sanityFailOnFailedCheckedPrimitiveRewrite(failedRewrites []*Primitive) erro ...@@ -381,6 +381,37 @@ func sanityFailOnFailedCheckedPrimitiveRewrite(failedRewrites []*Primitive) erro
return nil return nil
} }
func sanityCheckPrimitiveArgumentOutputs(p *Primitive) error {
for i := 0; i < len(p.Arguments); i++ {
switch p.Arguments[i].Kind {
case typesEnumPrimitive:
var output []int
if primitiveIsCorePrim(p.Arguments[i].Data.(*Primitive).ID) {
prim, err := primitiveCoreGet(p.Arguments[i].Data.(*Primitive).ID)
if err != nil {
return err
}
output = prim.Output
} else {
prim, err := primitiveGet(p.Arguments[i].Data.(*Primitive).ID)
if err != nil {
return err
}
output = prim.Output
}
if !intInSlice(1, output) {
return fmt.Errorf(
"primitive %s cannot have %s as an argument, since %s necessarily produces more than one output",
prettyPrimitive(p),
prettyPrimitive(p.Arguments[i].Data.(*Primitive)),
prettyPrimitive(p.Arguments[i].Data.(*Primitive)),
)
}
}
}
return nil
}
func sanityCheckEquationRootGenerator(e *Equation) error { func sanityCheckEquationRootGenerator(e *Equation) error {
if len(e.Values) > 3 { if len(e.Values) > 3 {
return fmt.Errorf( return fmt.Errorf(
......
...@@ -325,6 +325,7 @@ type MutationMap struct { ...@@ -325,6 +325,7 @@ type MutationMap struct {
Constants []*Constant Constants []*Constant
Mutations [][]*Value Mutations [][]*Value
Combination []*Value Combination []*Value
Worthwhile bool
DepthIndex []int DepthIndex []int
} }
......
...@@ -550,16 +550,12 @@ func valueResolveEquationInternalValuesFromKnowledgeMap( ...@@ -550,16 +550,12 @@ func valueResolveEquationInternalValuesFromKnowledgeMap(
func valueResolveValueInternalValuesFromPrincipalState( func valueResolveValueInternalValuesFromPrincipalState(
a *Value, rootValue *Value, rootIndex int, valPrincipalState *PrincipalState, a *Value, rootValue *Value, rootIndex int, valPrincipalState *PrincipalState,
valAttackerState AttackerState, forceBeforeMutate bool, valAttackerState AttackerState, forceBeforeMutate bool,
) (*Value, []*Value, error) { ) (*Value, error) {
var v []*Value
switch a.Kind { switch a.Kind {
case typesEnumConstant: case typesEnumConstant:
if valueEquivalentValueInValues(a, v) < 0 {
v = append(v, a)
}
nextRootIndex := valueGetPrincipalStateIndexFromConstant(valPrincipalState, a.Data.(*Constant)) nextRootIndex := valueGetPrincipalStateIndexFromConstant(valPrincipalState, a.Data.(*Constant))
if nextRootIndex < 0 { if nextRootIndex < 0 {
return &Value{}, []*Value{}, errors.New("invalid index") return &Value{}, errors.New("invalid index")
} }
switch nextRootIndex { switch nextRootIndex {
case rootIndex: case rootIndex:
...@@ -597,23 +593,23 @@ func valueResolveValueInternalValuesFromPrincipalState( ...@@ -597,23 +593,23 @@ func valueResolveValueInternalValuesFromPrincipalState(
} }
switch a.Kind { switch a.Kind {
case typesEnumConstant: case typesEnumConstant:
return a, v, nil return a, nil
case typesEnumPrimitive: case typesEnumPrimitive:
return valueResolvePrimitiveInternalValuesFromPrincipalState( return valueResolvePrimitiveInternalValuesFromPrincipalState(
a, v, rootValue, rootIndex, valPrincipalState, valAttackerState, forceBeforeMutate, a, rootValue, rootIndex, valPrincipalState, valAttackerState, forceBeforeMutate,
) )
case typesEnumEquation: case typesEnumEquation:
return valueResolveEquationInternalValuesFromPrincipalState( return valueResolveEquationInternalValuesFromPrincipalState(
a, v, rootValue, rootIndex, valPrincipalState, valAttackerState, forceBeforeMutate, a, rootValue, rootIndex, valPrincipalState, valAttackerState, forceBeforeMutate,
) )
} }
return a, v, nil return a, nil
} }
func valueResolvePrimitiveInternalValuesFromPrincipalState( func valueResolvePrimitiveInternalValuesFromPrincipalState(
a *Value, v []*Value, rootValue *Value, rootIndex int, valPrincipalState *PrincipalState, a *Value, rootValue *Value, rootIndex int, valPrincipalState *PrincipalState,
valAttackerState AttackerState, forceBeforeMutate bool, valAttackerState AttackerState, forceBeforeMutate bool,
) (*Value, []*Value, error) { ) (*Value, error) {
if valPrincipalState.Creator[rootIndex] == valPrincipalState.ID { if valPrincipalState.Creator[rootIndex] == valPrincipalState.ID {
forceBeforeMutate = false forceBeforeMutate = false
} }
...@@ -627,27 +623,22 @@ func valueResolvePrimitiveInternalValuesFromPrincipalState( ...@@ -627,27 +623,22 @@ func valueResolvePrimitiveInternalValuesFromPrincipalState(
}, },
} }
for i := 0; i < len(a.Data.(*Primitive).Arguments); i++ { for i := 0; i < len(a.Data.(*Primitive).Arguments); i++ {
s, vv, err := valueResolveValueInternalValuesFromPrincipalState( s, err := valueResolveValueInternalValuesFromPrincipalState(
a.Data.(*Primitive).Arguments[i], rootValue, rootIndex, valPrincipalState, a.Data.(*Primitive).Arguments[i], rootValue, rootIndex, valPrincipalState,
valAttackerState, forceBeforeMutate, valAttackerState, forceBeforeMutate,
) )
if err != nil { if err != nil {
return &Value{}, []*Value{}, err return &Value{}, err
} }
r.Data.(*Primitive).Arguments = append(r.Data.(*Primitive).Arguments, s) r.Data.(*Primitive).Arguments = append(r.Data.(*Primitive).Arguments, s)
for _, vvv := range vv {
if valueEquivalentValueInValues(vvv, v) < 0 {
v = append(v, vvv)
}
}
} }
return r, v, nil return r, nil
} }
func valueResolveEquationInternalValuesFromPrincipalState( func valueResolveEquationInternalValuesFromPrincipalState(
a *Value, v []*Value, rootValue *Value, rootIndex int, valPrincipalState *PrincipalState, a *Value, rootValue *Value, rootIndex int, valPrincipalState *PrincipalState,
valAttackerState AttackerState, forceBeforeMutate bool, valAttackerState AttackerState, forceBeforeMutate bool,
) (*Value, []*Value, error) { ) (*Value, error) {
r := &Value{ r := &Value{
Kind: typesEnumEquation, Kind: typesEnumEquation,
Data: &Equation{ Data: &Equation{
...@@ -667,53 +658,37 @@ func valueResolveEquationInternalValuesFromPrincipalState( ...@@ -667,53 +658,37 @@ func valueResolveEquationInternalValuesFromPrincipalState(
if forceBeforeMutate { if forceBeforeMutate {
aa[aai] = valPrincipalState.BeforeMutate[i] aa[aai] = valPrincipalState.BeforeMutate[i]
} }
if valueEquivalentValueInValues(aa[aai], v) < 0 {
v = append(v, aa[aai])
}
} }
} }
for aai := range aa { for aai := range aa {
switch aa[aai].Kind { switch aa[aai].Kind {
case typesEnumConstant: case typesEnumConstant:
r.Data.(*Equation).Values = append(r.Data.(*Equation).Values, aa[aai]) r.Data.(*Equation).Values = append(r.Data.(*Equation).Values, aa[aai])
if valueEquivalentValueInValues(aa[aai], v) < 0 {
v = append(v, aa[aai])
}
case typesEnumPrimitive: case typesEnumPrimitive:
aaa, vv, err := valueResolvePrimitiveInternalValuesFromPrincipalState( aaa, err := valueResolvePrimitiveInternalValuesFromPrincipalState(
aa[aai], v, rootValue, rootIndex, aa[aai], rootValue, rootIndex,
valPrincipalState, valAttackerState, forceBeforeMutate, valPrincipalState, valAttackerState, forceBeforeMutate,
) )
if err != nil { if err != nil {
return &Value{}, []*Value{}, err return &Value{}, err
} }
r.Data.(*Equation).Values = append(r.Data.(*Equation).Values, aaa) r.Data.(*Equation).Values = append(r.Data.(*Equation).Values, aaa)
for _, vvv := range vv {
if valueEquivalentValueInValues(vvv, v) < 0 {
v = append(v, vvv)
}
}
case typesEnumEquation: case typesEnumEquation:
aaa, vv, err := valueResolveEquationInternalValuesFromPrincipalState( aaa, err := valueResolveEquationInternalValuesFromPrincipalState(
aa[aai], v, rootValue, rootIndex, aa[aai], rootValue, rootIndex,
valPrincipalState, valAttackerState, forceBeforeMutate, valPrincipalState, valAttackerState, forceBeforeMutate,
) )
if err != nil { if err != nil {
return &Value{}, []*Value{}, err return &Value{}, err
} }
if aai == 0 { if aai == 0 {
r.Data.(*Equation).Values = aaa.Data.(*Equation).Values r.Data.(*Equation).Values = aaa.Data.(*Equation).Values
} else { } else {
r.Data.(*Equation).Values = append(r.Data.(*Equation).Values, aaa.Data.(*Equation).Values[1:]...) r.Data.(*Equation).Values = append(r.Data.(*Equation).Values, aaa.Data.(*Equation).Values[1:]...)
} }
for _, vvv := range vv {
if valueEquivalentValueInValues(vvv, v) < 0 {
v = append(v, vvv)
}
}
} }
} }
return r, v, nil return r, nil
} }
func valueConstantIsUsedByPrincipalInKnowledgeMap( func valueConstantIsUsedByPrincipalInKnowledgeMap(
...@@ -744,14 +719,14 @@ func valueResolveAllPrincipalStateValues( ...@@ -744,14 +719,14 @@ func valueResolveAllPrincipalStateValues(
var err error var err error
valPrincipalStateClone := constructPrincipalStateClone(valPrincipalState, false) valPrincipalStateClone := constructPrincipalStateClone(valPrincipalState, false)
for i := range valPrincipalState.Assigned { for i := range valPrincipalState.Assigned {
valPrincipalStateClone.Assigned[i], _, err = valueResolveValueInternalValuesFromPrincipalState( valPrincipalStateClone.Assigned[i], err = valueResolveValueInternalValuesFromPrincipalState(
valPrincipalState.Assigned[i], valPrincipalState.Assigned[i], i, valPrincipalState, valPrincipalState.Assigned[i], valPrincipalState.Assigned[i], i, valPrincipalState,
valAttackerState, valueShouldResolveToBeforeMutate(i, valPrincipalState), valAttackerState, valueShouldResolveToBeforeMutate(i, valPrincipalState),
) )
if err != nil { if err != nil {
return &PrincipalState{}, err return &PrincipalState{}, err
} }
valPrincipalStateClone.BeforeRewrite[i], _, err = valueResolveValueInternalValuesFromPrincipalState( valPrincipalStateClone.BeforeRewrite[i], err = valueResolveValueInternalValuesFromPrincipalState(
valPrincipalState.BeforeRewrite[i], valPrincipalState.BeforeRewrite[i], i, valPrincipalState, valPrincipalState.BeforeRewrite[i], valPrincipalState.BeforeRewrite[i], i, valPrincipalState,
valAttackerState, valueShouldResolveToBeforeMutate(i, valPrincipalState), valAttackerState, valueShouldResolveToBeforeMutate(i, valPrincipalState),
) )
...@@ -767,7 +742,7 @@ func valueContainsFreshValues( ...@@ -767,7 +742,7 @@ func valueContainsFreshValues(
valPrincipalState *PrincipalState, valAttackerState AttackerState, valPrincipalState *PrincipalState, valAttackerState AttackerState,
) (bool, error) { ) (bool, error) {
i := valueGetPrincipalStateIndexFromConstant(valPrincipalState, c) i := valueGetPrincipalStateIndexFromConstant(valPrincipalState, c)
v, _, err := valueResolveValueInternalValuesFromPrincipalState( v, err := valueResolveValueInternalValuesFromPrincipalState(
v, v, i, valPrincipalState, valAttackerState, false, v, v, i, valPrincipalState, valAttackerState, false,
) )
if err != nil { if err != nil {
...@@ -822,17 +797,3 @@ func valueDeepCopy(v *Value) Value { ...@@ -822,17 +797,3 @@ func valueDeepCopy(v *Value) Value {
} }
return d return d
} }
func valueNestedConstantInResolvedValue(
c *Constant, a *Value,
valPrincipalState *PrincipalState, valAttackerState AttackerState,
) bool {
i := valueGetPrincipalStateIndexFromConstant(valPrincipalState, c)
_, v, _ := valueResolveValueInternalValuesFromPrincipalState(
a, a, i, valPrincipalState, valAttackerState, true,
)
return valueEquivalentValueInValues(&Value{
Kind: typesEnumConstant,
Data: c,
}, v) >= 0
}
...@@ -14,9 +14,11 @@ import ( ...@@ -14,9 +14,11 @@ import (
// Verify runs the main verification engine for Verifpal on a model loaded from a file. // Verify runs the main verification engine for Verifpal on a model loaded from a file.
// It returns a slice of verifyResults and a "results code". // It returns a slice of verifyResults and a "results code".
func Verify(filePath string) ([]VerifyResult, string, error) { func Verify(filePath string) ([]VerifyResult, string, error) {
// f, _ := os.Create("cpu.pprof") /*
// pprof.StartCPUProfile(f) f, _ := os.Create("cpu.pprof")
// defer pprof.StopCPUProfile() pprof.StartCPUProfile(f)
defer pprof.StopCPUProfile()
*/
m, err := libpegParseModel(filePath, true) m, err := libpegParseModel(filePath, true)
if err != nil { if err != nil {
return []VerifyResult{}, "", err return []VerifyResult{}, "", err
......
...@@ -90,11 +90,10 @@ func verifyActiveScan( ...@@ -90,11 +90,10 @@ func verifyActiveScan(
scanGroup.Done() scanGroup.Done()
return err return err
} }
valPrincipalStateClone := constructPrincipalStateClone(valPrincipalState, true) if valMutationMap.Worthwhile {
valPrincipalStateMutated, isWorthwhileMutation := verifyActiveMutatePrincipalState( valPrincipalStateMutated := verifyActiveMutatePrincipalState(
valPrincipalStateClone, valAttackerState, valMutationMap, constructPrincipalStateClone(valPrincipalState, true), valAttackerState, valMutationMap,
) )
if isWorthwhileMutation {
scanGroup.Add(1) scanGroup.Add(1)
go func() { go func() {
err = verifyAnalysis( err = verifyAnalysis(
...@@ -124,12 +123,12 @@ func verifyActiveScan( ...@@ -124,12 +123,12 @@ func verifyActiveScan(
func verifyActiveMutatePrincipalState( func verifyActiveMutatePrincipalState(
valPrincipalState *PrincipalState, valAttackerState AttackerState, valMutationMap MutationMap, valPrincipalState *PrincipalState, valAttackerState AttackerState, valMutationMap MutationMap,
) (*PrincipalState, bool) { ) *PrincipalState {
isWorthwhileMutation := false MutationLoop:
for i := 0; i < len(valMutationMap.Constants); i++ { for i := 0; i < len(valMutationMap.Constants); i++ {
ai, ii := valueResolveConstant(valMutationMap.Constants[i], valPrincipalState) ai, ii := valueResolveConstant(valMutationMap.Constants[i], valPrincipalState)
ac := valMutationMap.Combination[i] ac := valMutationMap.Combination[i]
ar, _, _ := valueResolveValueInternalValuesFromPrincipalState( ar, _ := valueResolveValueInternalValuesFromPrincipalState(
ai, ai, ii, valPrincipalState, valAttackerState, true, ai, ai, ii, valPrincipalState, valAttackerState, true,
) )
switch ar.Kind { switch ar.Kind {
...@@ -152,24 +151,22 @@ func verifyActiveMutatePrincipalState( ...@@ -152,24 +151,22 @@ func verifyActiveMutatePrincipalState(
ac.Data.(*Primitive).Output = ar.Data.(*Primitive).Output ac.Data.(*Primitive).Output = ar.Data.(*Primitive).Output
ac.Data.(*Primitive).Check = ar.Data.(*Primitive).Check ac.Data.(*Primitive).Check = ar.Data.(*Primitive).Check
} }
acc := valueGetConstantsFromValue(ac)
for acci := 0; acci < len(acc); acci++ {
if acc[acci].ID == valMutationMap.Constants[i].ID {
continue MutationLoop
}
}
} }
switch { switch {
case valueEquivalentValues(ac, ar, true): case valueEquivalentValues(ac, ar, true):
continue continue
case valueNestedConstantInResolvedValue(valMutationMap.Constants[i], ac, valPrincipalState, valAttackerState):
continue
} }
valPrincipalState.Creator[ii] = principalNamesMap["Attacker"] valPrincipalState.Creator[ii] = principalNamesMap["Attacker"]
valPrincipalState.Sender[ii] = principalNamesMap["Attacker"] valPrincipalState.Sender[ii] = principalNamesMap["Attacker"]
valPrincipalState.Mutated[ii] = true valPrincipalState.Mutated[ii] = true
valPrincipalState.Assigned[ii] = ac valPrincipalState.Assigned[ii] = ac
valPrincipalState.BeforeRewrite[ii] = ac valPrincipalState.BeforeRewrite[ii] = ac
if i >= valMutationMap.LastIncrement {
isWorthwhileMutation = true
}
}
if !isWorthwhileMutation {
return valPrincipalState, isWorthwhileMutation
} }
valPrincipalState, _ = valueResolveAllPrincipalStateValues(valPrincipalState, valAttackerState) valPrincipalState, _ = valueResolveAllPrincipalStateValues(valPrincipalState, valAttackerState)
failedRewrites, failedRewriteIndices, valPrincipalState := valuePerformAllRewrites(valPrincipalState) failedRewrites, failedRewriteIndices, valPrincipalState := valuePerformAllRewrites(valPrincipalState)
...@@ -197,7 +194,7 @@ FailedRewritesLoop: ...@@ -197,7 +194,7 @@ FailedRewritesLoop:
} }
} }
} }
return valPrincipalState, isWorthwhileMutation return valPrincipalState
} }
func verifyActiveDropPrincipalStateAfterIndex(valPrincipalState *PrincipalState, f int) *PrincipalState { func verifyActiveDropPrincipalStateAfterIndex(valPrincipalState *PrincipalState, f int) *PrincipalState {
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment