2004-07-19 14:31:44 +01:00
/*!\file modelchecker.c
* \ brief The main procedures guiding the ( optimized ) traversal of the state space .
*
* This file implements various traversal methods through the state space .
*/
2004-04-23 11:58:43 +01:00
# include <stdlib.h>
# include <stdio.h>
# include <limits.h>
2004-07-24 20:07:29 +01:00
# include "substitution.h"
2004-04-23 11:58:43 +01:00
# include "knowledge.h"
2004-07-24 16:08:35 +01:00
# include "system.h"
2004-04-23 11:58:43 +01:00
# include "debug.h"
# include "modelchecker.h"
# include "report.h"
# include "memory.h"
# include "match_basic.h"
# include "match_clp.h"
# include "output.h"
# include "tracebuf.h"
# include "attackminimize.h"
2004-07-24 20:07:29 +01:00
# include "claim.h"
2004-04-23 11:58:43 +01:00
/*
A model checker . Really .
*/
extern Term CLAIM_Secret ;
extern Term CLAIM_Nisynch ;
2004-07-25 19:24:50 +01:00
extern Term CLAIM_Niagree ;
2004-04-23 11:58:43 +01:00
/*
Some forward declarations .
*/
2004-07-20 21:42:53 +01:00
__inline__ int traverseSimple ( const System oldsys ) ;
__inline__ int traverseNonReads ( const System oldsys ) ;
__inline__ int traversePOR4 ( const System oldsys ) ;
__inline__ int traversePOR5 ( const System oldsys ) ;
__inline__ int traversePOR6 ( const System oldsys ) ;
__inline__ int traversePOR7 ( const System oldsys ) ;
__inline__ int traversePOR8 ( const System oldsys ) ;
2004-04-23 11:58:43 +01:00
int propertyCheck ( const System sys ) ;
int executeTry ( const System sys , int run ) ;
int claimSecrecy ( const System sys , const Term t ) ;
int violateClaim ( const System sys , int length , int claimev , Termlist reqt ) ;
Termlist secrecyUnfolding ( Term t , const Knowledge know ) ;
/*
Main code .
*/
void
statePrint ( const System sys )
{
int i , s ;
Roledef rd ;
indent ( ) ;
printf ( " state %i: " , sys - > step ) ;
for ( i = 0 ; i < sys - > maxruns ; i + + )
{
s = 0 ;
rd = runPointerGet ( sys , i ) ;
while ( rd ! = NULL )
{
rd = rd - > next ;
s + + ;
}
printf ( " %i " , s ) ;
}
printf ( " - phase %i, done %i " , sys - > PORphase , sys - > PORdone ) ;
printf ( " \n " ) ;
}
2004-07-28 12:39:08 +01:00
//! Scenario selection makes sure implicit and explicit chooses are selected first.
/**
* This help function traverses any chooses first .
*/
__inline__ int
traverse_chooses_first ( const System sys )
{
int run_scan ;
for ( run_scan = 0 ; run_scan < sys - > maxruns ; run_scan + + )
{
Roledef rd_scan ;
rd_scan = runPointerGet ( sys , run_scan ) ;
if ( rd_scan ! = NULL & & // Not empty run
rd_scan = = sys - > runs [ run_scan ] . start & & // First event
rd_scan - > type = = READ ) // Read
{
if ( executeTry ( sys , run_scan ) )
return 1 ;
}
}
return 0 ;
}
//! Main traversal call.
/**
* Branches into submethods .
*/
2004-04-23 11:58:43 +01:00
int
traverse ( const System sys )
{
2004-07-28 12:39:08 +01:00
/* maybe chooses have precedence over _all_ methods */
if ( sys - > switchChooseFirst )
{
if ( traverse_chooses_first ( sys ) )
return 1 ;
}
2004-04-23 11:58:43 +01:00
/* branch for traversal methods */
switch ( sys - > traverse )
{
case 1 :
return traverseSimple ( sys ) ;
case 2 :
return traverseNonReads ( sys ) ;
case 3 :
case 4 :
case 5 :
case 6 :
case 7 :
2004-07-21 13:42:04 +01:00
error ( " %i is an obsolete traversal method. " , sys - > traverse ) ;
2004-04-23 11:58:43 +01:00
case 8 :
return traversePOR4 ( sys ) ;
2004-07-13 21:20:58 +01:00
case 9 :
return traversePOR5 ( sys ) ;
2004-07-15 12:04:15 +01:00
case 10 :
return traversePOR6 ( sys ) ;
2004-07-17 22:11:35 +01:00
case 11 :
return traversePOR7 ( sys ) ;
2004-07-20 21:42:53 +01:00
case 12 :
return traversePOR8 ( sys ) ;
2004-04-23 11:58:43 +01:00
default :
2004-07-21 13:42:04 +01:00
error ( " %i is NOT an existing traversal method. " , sys - > traverse ) ;
2004-04-23 11:58:43 +01:00
}
}
2004-07-12 14:58:41 +01:00
//! Progress counters to next step.
/**
2004-04-23 11:58:43 +01:00
* Does not really execute anything , it ' s just bookkeeping , progressing
* counters and such .
*
2004-07-12 14:58:41 +01:00
* @ returns If it returns TRUE , explore . If false , don ' t traverse .
2004-04-23 11:58:43 +01:00
*/
int
executeStep ( const System sys , const int run )
{
Roledef runPoint ;
runPoint = runPointerGet ( sys , run ) ;
# ifdef DEBUG
if ( DEBUGL ( 3 ) )
{
indent ( ) ;
printf ( " exec: " ) ;
roledefPrint ( runPoint ) ;
printf ( " #%i \n " , run ) ;
}
# endif
2004-07-14 07:55:05 +01:00
sys - > runs [ run ] . step + + ;
2004-04-23 11:58:43 +01:00
runPointerSet ( sys , run , runPoint - > next ) ;
/* store knowledge for this step */
( sys - > step ) + + ;
sys - > traceKnow [ sys - > step ] = sys - > know ;
/* check for properties */
propertyCheck ( sys ) ;
/* set indent for printing */
indentSet ( sys - > step ) ;
/* hmmm, but what should it return if not exploring? */
if ( ! sys - > explore )
return 0 ;
/* we want to explore it, but are we allowed by pruning? */
if ( sys - > step > = sys - > maxtracelength )
{
/* cut off traces that are too long */
# ifdef DEBUG
if ( DEBUGL ( 4 ) )
{
indent ( ) ;
printf ( " trace cut off. \n " ) ;
if ( DEBUGL ( 5 ) )
{
( sys - > step ) - - ;
tracePrint ( sys ) ;
( sys - > step ) + + ;
}
}
# endif
return 0 ;
}
/* we will explore this state, so count it. */
2004-07-21 11:35:39 +01:00
sys - > states = statesIncrease ( sys - > states ) ;
2004-04-23 11:58:43 +01:00
2004-07-30 13:04:38 +01:00
/* what about scenario exploration? */
if ( sys - > switchScenario & & sys - > step + 1 > sys - > switchScenarioSize )
{
/* count states within scenario */
sys - > statesScenario = statesIncrease ( sys - > statesScenario ) ;
}
2004-04-23 11:58:43 +01:00
/* show progression */
if ( sys - > switchS > 0 )
{
2004-07-21 11:35:39 +01:00
sys - > interval = statesIncrease ( sys - > interval ) ;
if ( ! statesSmallerThan ( sys - > interval , ( unsigned long int ) sys - > switchS ) )
2004-04-23 11:58:43 +01:00
{
2004-07-30 13:04:38 +01:00
globalError + + ;
2004-07-21 11:35:39 +01:00
sys - > interval = STATES0 ;
2004-07-30 13:04:38 +01:00
eprintf ( " States " ) ;
statesFormat ( sys - > states ) ;
eprintf ( " \r " ) ;
globalError - - ;
2004-04-23 11:58:43 +01:00
}
}
2004-07-12 14:58:41 +01:00
2004-07-13 12:10:06 +01:00
/* store new node numbder */
2004-07-21 11:35:39 +01:00
sys - > traceNode [ sys - > step ] = sys - > states ;
2004-07-12 14:58:41 +01:00
/* the construction below always assumes MAX_GRAPH_STATES to be smaller than the unsigned long it, which seems realistic. */
2004-07-29 11:13:13 +01:00
if ( sys - > output = = STATESPACE & & statesSmallerThan ( sys - > states , MAX_GRAPH_STATES ) )
2004-07-12 14:58:41 +01:00
{
/* display graph */
graphNode ( sys ) ;
}
2004-04-23 11:58:43 +01:00
return 1 ;
}
2004-07-14 13:10:39 +01:00
/**
2004-07-14 14:18:08 +01:00
* Determine for a roledef that is instantiated , the uninteresting ends bits .
*
2004-07-17 20:43:20 +01:00
* @ todo " What is interesting " relies on the fact that there are only secrecy , sychnr and agreement properties .
2004-07-14 13:10:39 +01:00
*/
2004-07-14 13:46:11 +01:00
Roledef removeIrrelevant ( const System sys , const int run , Roledef rd )
2004-07-14 13:10:39 +01:00
{
Roledef rdkill ;
int killclaims ;
if ( untrustedAgent ( sys , sys - > runs [ run ] . agents ) )
killclaims = 1 ;
else
killclaims = 0 ;
rdkill = rd ;
while ( rd ! = NULL )
{
if ( rd - > type = = SEND | | ( ! killclaims & & rd - > type = = CLAIM ) )
rdkill = rd ;
rd = rd - > next ;
}
/* report part */
/*
2004-07-14 13:17:38 +01:00
rd = rdkill - > next ;
2004-07-14 13:10:39 +01:00
killclaims = 0 ;
while ( rd ! = NULL )
{
killclaims + + ;
rd = rd - > next ;
}
2004-07-14 13:17:38 +01:00
if ( killclaims > 1 )
{
warning ( " %i events stripped from run %i. " , killclaims , run ) ;
runPrint ( rdkill - > next ) ;
}
2004-07-14 13:10:39 +01:00
*/
/* remove after rdkill */
2004-07-14 13:46:11 +01:00
return rdkill ;
2004-07-14 13:10:39 +01:00
}
2004-07-24 21:30:00 +01:00
//! Unblock any waiting sends of my type.
/**
* Note that the caller must ensure that rd - > forbidden is restored afterwards .
* \ sa tryChoiceSend ( )
*/
void
unblock_synchronising_labels ( const System sys , const int run , const Roledef rd )
{
if ( rd - > type ! = READ | | rd - > internal )
return ;
if ( ! inTermlist ( sys - > synchronising_labels , rd - > label ) )
return ;
// This read possibly unblocks other sends
int run_scan ;
for ( run_scan = 0 ; run_scan < sys - > maxruns ; run_scan + + )
{
if ( run_scan ! = run )
{
Roledef rd_scan ;
rd_scan = sys - > runs [ run_scan ] . index ;
if ( rd_scan ! = NULL & &
rd_scan - > type = = SEND & &
rd_scan - > forbidden ! = NULL & &
isTermEqual ( rd_scan - > label , rd - > label ) & &
isTermEqual ( rd_scan - > message , rd - > message ) & &
isTermEqual ( rd_scan - > from , rd - > from ) & &
isTermEqual ( rd_scan - > to , rd - > to ) )
{
rd_scan - > forbidden = NULL ;
}
}
}
return ;
}
2004-07-13 13:36:50 +01:00
//! Explores the system state given by the next step of a run.
2004-07-19 13:03:29 +01:00
/** Grandiose naming scheme (c) sjors dubya.
*
* After an event was instantiated , this function is called to explore the
* remainder of the system .
*
* Note that some additional pruning is done , so this function
* also determines the enabledness of the event that was just instantiated .
*
* @ returns 1 ( true ) if the event was enabled .
* \ sa match_basic ( ) , executeTry ( )
2004-04-23 11:58:43 +01:00
*/
int
2004-07-17 20:43:20 +01:00
explorify ( const System sys , const int run )
2004-04-23 11:58:43 +01:00
{
2004-07-17 20:43:20 +01:00
Roledef rd ;
2004-04-23 11:58:43 +01:00
int flag ;
2004-07-14 07:55:05 +01:00
int myStep ;
2004-07-14 13:46:11 +01:00
Roledef roleCap , roleCapPart ;
2004-07-24 21:30:00 +01:00
Knowledge forbiddenBuffer ;
2004-04-23 11:58:43 +01:00
2004-07-17 20:43:20 +01:00
rd = runPointerGet ( sys , run ) ;
myStep = sys - > runs [ run ] . step ;
2004-07-14 13:46:11 +01:00
roleCap = NULL ;
2004-07-14 07:55:05 +01:00
2004-07-17 20:43:20 +01:00
if ( rd = = NULL )
2004-04-23 11:58:43 +01:00
{
2004-07-19 13:03:29 +01:00
error ( " Trying to progress completed run! \n " ) ;
2004-04-23 11:58:43 +01:00
}
2004-07-13 13:36:50 +01:00
flag = 0 ;
2004-07-12 14:58:41 +01:00
2004-07-24 21:30:00 +01:00
/**
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
* Is the event really enabled ?
* Typically , a read event is only instantiated
* at this point , so we can only now do some
* instantiation related determinings .
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
*/
2004-07-13 14:34:04 +01:00
/*
2004-07-13 16:24:47 +01:00
* Special checks after ( implicit ) choose events ; always first in run reads .
2004-07-13 13:36:50 +01:00
*/
2004-07-17 20:43:20 +01:00
if ( myStep = = 0 & & rd - > type = = READ )
2004-07-13 13:36:50 +01:00
{
2004-07-17 20:43:20 +01:00
int rid ;
if ( inTermlist ( sys - > untrusted , agentOfRun ( sys , run ) ) )
2004-07-13 14:34:04 +01:00
{
/* this run is executed by an untrusted agent, do not explore */
return 0 ;
}
2004-07-13 16:24:47 +01:00
/* executed by trusted agent */
2004-07-14 13:10:39 +01:00
/* Special check 1: if agents have been instantiated in such a way that no more claims in any run
* need to be evaluated , then we can skip
2004-07-13 16:24:47 +01:00
* further traversal .
*/
2004-07-17 22:11:35 +01:00
//!@todo This implementation relies on the fact that there are only secrecy, synchr and agreement properties.
2004-07-19 10:44:54 +01:00
if ( sys - > switchNomoreClaims & & sys - > secrets = = NULL )
2004-07-13 16:24:47 +01:00
{ /* there are no remaining secrecy claims to be checked */
Roledef rdscan ;
int validclaim ;
2004-07-17 20:43:20 +01:00
rid = 0 ;
2004-07-13 16:24:47 +01:00
validclaim = 0 ;
/* check for each run */
2004-07-17 20:43:20 +01:00
while ( rid < sys - > maxruns )
2004-07-13 16:24:47 +01:00
{
/* are claims in this run evaluated anyway? */
2004-07-17 20:43:20 +01:00
if ( ! untrustedAgent ( sys , sys - > runs [ rid ] . agents ) )
2004-07-13 16:24:47 +01:00
{ /* possibly claims to be checked in this run */
2004-07-17 20:43:20 +01:00
rdscan = runPointerGet ( sys , rid ) ;
2004-07-13 16:24:47 +01:00
while ( rdscan ! = NULL )
{
if ( rdscan - > type = = CLAIM )
2004-07-13 14:34:04 +01:00
{
2004-07-13 16:24:47 +01:00
/* force abort of loop */
validclaim = 1 ;
rdscan = NULL ;
2004-07-17 20:43:20 +01:00
rid = sys - > maxruns ;
2004-07-13 16:24:47 +01:00
}
else
{
rdscan = rdscan - > next ;
2004-07-13 14:34:04 +01:00
}
}
}
2004-07-17 20:43:20 +01:00
rid + + ;
2004-07-13 16:24:47 +01:00
}
2004-07-17 20:43:20 +01:00
if ( validclaim = = 0 )
2004-07-13 16:24:47 +01:00
{ /* no valid claims, abort */
return 0 ;
2004-07-13 14:34:04 +01:00
}
2004-07-13 13:36:50 +01:00
}
2004-07-14 09:17:49 +01:00
2004-07-28 12:39:08 +01:00
/* Special check 2: Symmetry reduction on chooses.
2004-07-14 09:17:49 +01:00
* If the run we depend upon has already been activated ( otherwise warn ! ) check for instance ordering
*/
2004-07-19 10:34:46 +01:00
if ( sys - > switchAgentSymm & & sys - > runs [ run ] . prevSymmRun ! = - 1 )
2004-07-14 09:17:49 +01:00
{
/* there is such a run on which we depend */
int ridSymm ;
2004-07-17 20:43:20 +01:00
ridSymm = sys - > runs [ run ] . prevSymmRun ;
if ( sys - > runs [ ridSymm ] . step = = 0 )
2004-07-14 09:17:49 +01:00
{
2004-07-14 09:33:28 +01:00
/*
2004-07-17 20:43:20 +01:00
* dependency run was not chosen yet , so we can ' t do anything now
2004-07-14 09:33:28 +01:00
*/
2004-07-17 20:43:20 +01:00
// warning ("Symmetrical run dependency #%i (for run #%i) has not chosen yet!", ridSymm, run);
2004-07-14 09:17:49 +01:00
}
else
{
/* dependent run has chosen, so we can compare */
2004-07-17 20:43:20 +01:00
if ( termlistOrder ( sys - > runs [ run ] . agents ,
sys - > runs [ ridSymm ] . agents ) < 0 )
2004-07-14 09:17:49 +01:00
{
/* we only explore the other half */
return 0 ;
}
}
}
2004-07-14 13:10:39 +01:00
/* Special check 3: if after choosing, this run ends on (read|skippedclaim)*, we can remove that part already.
*/
2004-07-19 10:44:54 +01:00
if ( sys - > switchReduceEndgame )
roleCap = removeIrrelevant ( sys , run , rd ) ;
2004-07-15 12:04:15 +01:00
2004-07-14 13:10:39 +01:00
/* Special check x: if all agents in each run send only encrypted stuff, and all agents are trusted,
2004-07-13 16:24:47 +01:00
* there is no way for the intruder to learn anything else than encrypted terms , so secrecy claims will not
* be violated anymore if they contain no terms that are encrypted with such keys */
//!@todo For now, there is no check that the runs only send publicly encrypted stuff! Just an assumption to be made true using static analysis.
/*
rid = 0 ;
while ( rid < sys - > maxruns )
{
2004-07-17 20:43:20 +01:00
if ( ! untrustedAgent ( sys , sys - > runs [ rid ] . agents ) )
2004-07-13 16:24:47 +01:00
{
}
rid + + ;
}
*/
2004-04-23 11:58:43 +01:00
}
2004-07-13 16:24:47 +01:00
2004-07-15 12:04:15 +01:00
/*
* Special check b1 : symmetry reduction part II on similar read events for equal roles .
*/
if ( sys - > switchReadSymm )
{
2004-07-17 20:43:20 +01:00
if ( sys - > runs [ run ] . firstNonAgentRead = = myStep )
2004-07-15 12:04:15 +01:00
{
/* Apparently, we have a possible ordering with our symmetrical friend.
* Check if it has progressed enough , and has the same agents .
*/
int ridSymm ;
2004-07-17 20:43:20 +01:00
if ( rd - > type ! = READ )
2004-07-15 12:04:15 +01:00
{
error ( " firstNonAgentRead is not a read?! " ) ;
}
2004-07-17 20:43:20 +01:00
ridSymm = sys - > runs [ run ] . prevSymmRun ;
if ( isTermlistEqual ( sys - > runs [ run ] . agents , sys - > runs [ ridSymm ] . agents ) )
2004-07-15 12:04:15 +01:00
{
/* same agents, so relevant */
2004-07-17 20:43:20 +01:00
if ( myStep > 0 & & sys - > runs [ ridSymm ] . step < myStep )
2004-07-15 12:04:15 +01:00
{
2004-07-17 20:43:20 +01:00
// warning ("Symmetrical firstread dependency #%i (for run #%i) has not chosen yet!", ridSymm, run);
2004-07-15 12:04:15 +01:00
}
else
{
2004-07-17 20:43:20 +01:00
if ( sys - > runs [ ridSymm ] . step < = myStep )
2004-07-15 12:04:15 +01:00
{
2004-07-17 20:43:20 +01:00
// warning ("Symmetrical firstread dependency #%i (for run #%i) has not read it's firstNonAgentRead %i yet, as it is only at %i!", ridSymm, run, myStep, sys->runs[ridSymm].step);
2004-07-15 12:04:15 +01:00
}
else
{
/* read was done, so we can compare them */
int i ;
Roledef rdSymm ;
2004-07-17 20:43:20 +01:00
rdSymm = sys - > runs [ ridSymm ] . start ;
2004-07-15 12:04:15 +01:00
i = myStep ;
while ( i > 0 )
{
rdSymm = rdSymm - > next ;
i - - ;
}
/* rdSymm now points to the instance of the symmetrical read */
2004-07-17 20:43:20 +01:00
i = termOrder ( rdSymm - > message , rd - > message ) ;
2004-07-15 12:04:15 +01:00
if ( i < 0 )
{
/* only explore symmetrical variant */
2004-07-15 14:32:09 +01:00
return 0 ;
2004-07-15 12:04:15 +01:00
}
}
}
}
}
}
2004-07-15 14:32:09 +01:00
/* Special check b2: symmetry order reduction.
*
* Concept : when there are two identical runs w . r . t . agents , we can make sure one goes before the other .
* Depends on prevSymm , skipping chooses even .
*/
2004-07-17 20:43:20 +01:00
if ( sys - > switchSymmOrder & & myStep = = sys - > runs [ run ] . firstReal )
2004-07-15 14:32:09 +01:00
{
2004-07-17 20:43:20 +01:00
if ( sys - > runs [ run ] . prevSymmRun ! = - 1 )
{
/* there is such a run on which we depend */
int ridSymm ;
2004-07-15 14:32:09 +01:00
2004-07-17 20:43:20 +01:00
ridSymm = sys - > runs [ run ] . prevSymmRun ;
/* equal runs? */
2004-07-15 14:32:09 +01:00
2004-07-17 20:43:20 +01:00
if ( isTermlistEqual ( sys - > runs [ run ] . agents , sys - > runs [ ridSymm ] . agents ) )
2004-07-15 14:32:09 +01:00
{
2004-07-17 20:43:20 +01:00
/* so, we have an identical partner */
/* is our partner there already? */
if ( sys - > runs [ ridSymm ] . step < = myStep )
{
/* not yet there, this is not a valid exploration */
/* verify !! */
return 0 ;
}
2004-07-15 14:32:09 +01:00
}
}
}
2004-07-28 12:39:08 +01:00
/**
* Final special check ; we must be sure that chooses have been done . Only
* necessary for scenario ! = 0.
*
* Note : any choose selection after this would result in empty scenarios , so this
* should be the last special check .
*/
if ( sys - > switchScenario ! = 0 )
{
2004-07-29 15:47:46 +01:00
/* two variants. If scenario size is 0, we operate on the old method involving chooses */
if ( sys - > switchScenarioSize = = 0 )
2004-07-28 12:39:08 +01:00
{
2004-07-29 15:47:46 +01:00
/* only after chooses */
if ( myStep = = 0 & &
rd - > type = = READ )
2004-07-28 12:39:08 +01:00
{
2004-07-29 15:47:46 +01:00
if ( run = = sys - > lastChooseRun )
2004-07-28 12:39:08 +01:00
{
2004-07-29 15:47:46 +01:00
/* We are just after the last choose instance */
/* count this instance */
if ( sys - > countScenario < INT_MAX )
{
sys - > countScenario + + ;
}
/* If we are displaying scenarios, print it */
if ( sys - > output = = SCENARIOS )
{
printf ( " %i \t " , sys - > countScenario ) ;
scenarioPrint ( sys ) ;
printf ( " \n " ) ;
}
/* If it is not the selected one, abort */
if ( sys - > switchScenario ! = sys - > countScenario )
{
/* this branch is not interesting */
/* unfortunately, it is also not drawn in the state graph because of this */
if ( sys - > output = = STATESPACE )
{
graphScenario ( sys , run , rd ) ;
}
/* act as if executed, but don't really explore it. */
return 1 ;
}
}
}
}
else
{
/* scenario size is not zero */
//!@todo Optimization: if the good scenario is already traversed, other trace prefixes need not be explored any further.
if ( sys - > step + 1 = = sys - > switchScenarioSize )
{
/* Now, the prefix has been set. Count it */
if ( sys - > countScenario < INT_MAX )
{
sys - > countScenario + + ;
2004-07-28 12:39:08 +01:00
}
2004-07-29 11:13:13 +01:00
if ( sys - > output = = SCENARIOS )
2004-07-28 12:39:08 +01:00
{
2004-07-29 15:47:46 +01:00
/* apparently we want the output */
int index ;
eprintf ( " %i \t " , sys - > countScenario ) ;
index = 0 ;
while ( index < sys - > switchScenarioSize )
{
roledefPrint ( sys - > traceEvent [ index ] ) ;
eprintf ( " #%i; " , sys - > traceRun [ index ] ) ;
index + + ;
}
eprintf ( " \n " ) ;
2004-07-28 12:39:08 +01:00
}
2004-07-29 15:47:46 +01:00
/* Is this the selected one? */
2004-07-28 12:39:08 +01:00
if ( sys - > switchScenario ! = sys - > countScenario )
{
/* unfortunately, it is also not drawn in the state graph because of this */
2004-07-29 11:13:13 +01:00
if ( sys - > output = = STATESPACE )
2004-07-28 12:39:08 +01:00
{
graphScenario ( sys , run , rd ) ;
}
2004-07-29 15:47:46 +01:00
/* act as if executed, but don't really explore it. */
return 1 ;
2004-07-28 12:39:08 +01:00
}
}
}
}
2004-07-24 21:30:00 +01:00
/**
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
* Now we assume the event is indeed enabled !
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
*/
/* (Possibly) do some local damage */
// Unblock any sends
forbiddenBuffer = rd - > forbidden ;
if ( sys - > synchronising_labels ! = NULL )
{
unblock_synchronising_labels ( sys , run , rd ) ;
}
// Cap roles
2004-07-14 13:46:11 +01:00
if ( roleCap ! = NULL )
{
roleCapPart = roleCap - > next ;
roleCap - > next = NULL ;
}
2004-07-24 21:30:00 +01:00
/* And explore the resulting system */
2004-07-17 20:43:20 +01:00
if ( executeStep ( sys , run ) )
2004-07-13 14:34:04 +01:00
{
/* traverse the system after the step */
flag = traverse ( sys ) ;
}
2004-07-19 10:32:12 +01:00
/* restore executeStep "damage" */
runPointerSet ( sys , run , rd ) ; // reset rd pointer
sys - > runs [ run ] . step = myStep ; // reset local index
sys - > step - - ;
indentSet ( sys - > step ) ;
2004-07-24 21:30:00 +01:00
/* restore local damage */
rd - > forbidden = forbiddenBuffer ;
2004-07-14 13:46:11 +01:00
if ( roleCap ! = NULL )
{
roleCap - > next = roleCapPart ;
}
2004-07-19 13:03:29 +01:00
return 1 ; // The event was indeed enabled (irrespective of traverse!)
2004-04-23 11:58:43 +01:00
}
2004-07-24 21:30:00 +01:00
//! Simple nondeterministic traversal.
2004-07-20 21:42:53 +01:00
__inline__ int
2004-04-23 11:58:43 +01:00
traverseSimple ( const System sys )
{
int run ;
int flag = 0 ;
for ( run = 0 ; run < ( sys - > maxruns ) ; run + + )
{
if ( runPointerGet ( sys , run ) ! = NULL )
{
flag = 1 ;
executeTry ( sys , run ) ;
}
}
if ( ! flag )
{
/* trace was not succesful */
}
return flag ;
}
2004-07-21 13:42:04 +01:00
/**
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
*
* Traversal Methods
*
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
*/
/*
* Some assistance macros
*/
# define predRead(sys,rd) ( rd->type == READ && !rd->internal )
# define isRead(sys,rd) ( rd != NULL && predRead(sys,rd) )
# define nonRead(sys,rd) ( rd != NULL && !predRead(sys,rd) )
2004-04-23 11:58:43 +01:00
/*
* nonReads
*
* Do a certain type of action first , i . e . that which satisfies nonRead ( System ,
* Roledef ) . Use the inverse of this predicate to detect the other type of
* event .
*/
2004-07-20 21:42:53 +01:00
__inline__ int
2004-04-23 11:58:43 +01:00
nonReads ( const System sys )
{
/* all sends first, then simple nondeterministic traversal */
int run ;
Roledef rd ;
/* check for existence of executable sends */
for ( run = 0 ; run < ( sys - > maxruns ) ; run + + )
{
rd = runPointerGet ( sys , run ) ;
if ( nonRead ( sys , rd ) )
{
2004-07-19 13:03:29 +01:00
return executeTry ( sys , run ) ;
2004-04-23 11:58:43 +01:00
}
}
return 0 ;
}
2004-07-21 13:42:04 +01:00
/*
* First traverse any non - reads , then non - deterministically the reads .
*/
2004-07-20 21:42:53 +01:00
__inline__ int
2004-04-23 11:58:43 +01:00
traverseNonReads ( const System sys )
{
if ( nonReads ( sys ) )
return 1 ;
else
return traverseSimple ( sys ) ;
}
2004-07-24 21:30:00 +01:00
//! Execute a send
/**
* \ sa unblock_synchronising_labels ( )
*/
__inline__ int
tryChoiceSend ( const System sys , const int run , const Roledef rd )
{
int flag ;
flag = 0 ;
if ( rd - > forbidden = = NULL )
{
/* this is allowed. So we either try it, or we try it later (if blocking) */
/* Note that a send in executetry will always succeed. */
/* 1. Simply try */
flag = executeTry ( sys , run ) ;
/* 2. Postpone if synchonisable */
2004-07-25 16:30:58 +01:00
if ( flag & & inTermlist ( sys - > synchronising_labels , rd - > label ) )
2004-07-24 21:30:00 +01:00
{
/* This is supposed to be blocked, so we do so */
/* It will possibly be unblocked by a corresponding read event,
* the actual code would be in explorify , post instantiation of the read event .
*/
if ( sys - > clp )
{
block_clp ( sys , run ) ;
}
else
{
block_basic ( sys , run ) ;
}
}
}
return flag ;
}
2004-07-20 21:42:53 +01:00
//! Execute a read in the knowledge postponing way, on which the partial order reduction for secrecy depends.
__inline__ int
tryChoiceRead ( const System sys , const int run , const Roledef rd )
{
int flag ;
flag = 0 ;
/* the sendsdone check only prevent
* some unneccessary inKnowledge tests ,
* and branch tests , still improves
* about 15 % */
if ( sys - > knowPhase > rd - > knowPhase )
{
/* apparently there has been a new knowledge item since the
* previous check */
/* implicit check for enabledness */
flag = executeTry ( sys , run ) ;
/* if it was enabled (flag) we postpone it if it makes sense
* to do so ( hasVariable , non internal ) */
if ( flag & & hasTermVariable ( rd - > message ) & & ! rd - > internal )
{
int stackKnowPhase = rd - > knowPhase ;
rd - > knowPhase = sys - > knowPhase ;
if ( sys - > clp )
{
block_clp ( sys , run ) ;
}
else
{
block_basic ( sys , run ) ;
}
rd - > knowPhase = stackKnowPhase ;
}
}
return flag ;
}
//! Try to execute the event at the roledef. Returns true iff it was enabled, and thus explored.
/**
* Note that rd should not be NULL
*/
__inline__ int
tryChoiceRoledef ( const System sys , const int run , const Roledef rd )
{
int flag ;
# ifdef DEBUG
if ( rd = = NULL )
error ( " tryChoiceRoledef should not be called with a NULL rd pointer " ) ;
# endif
flag = 0 ;
switch ( rd - > type )
{
case CLAIM :
flag = executeTry ( sys , run ) ;
break ;
2004-07-24 21:30:00 +01:00
case SEND :
flag = tryChoiceSend ( sys , run , rd ) ;
break ;
2004-07-20 21:42:53 +01:00
case READ :
flag = tryChoiceRead ( sys , run , rd ) ;
break ;
default :
fprintf ( stderr , " Encountered unknown event type %i. \n " , rd - > type ) ;
exit ( 1 ) ;
}
return flag ;
}
//! Try to execute the event in a given run
__inline__ int
tryChoiceRun ( const System sys , const int run )
{
Roledef rd ;
rd = runPointerGet ( sys , run ) ;
if ( rd ! = NULL )
return tryChoiceRoledef ( sys , run , rd ) ;
else
return 0 ;
}
//! Yield the last active run in the partial trace, or 0 if there is none.
__inline__ int
lastActiveRun ( const System sys )
{
if ( sys - > step = = 0 )
{
/* first step, start at 0 */
return 0 ;
}
else
{
/* there was a previous action, start scan from there */
2004-07-26 09:32:01 +01:00
# ifdef DEBUG
if ( sys - > porparam < 100 )
return sys - > traceRun [ sys - > step - 1 ] + sys - > porparam ;
# endif
return sys - > traceRun [ sys - > step - 1 ] ;
2004-07-20 21:42:53 +01:00
}
}
2004-07-20 21:58:32 +01:00
//! Determine whether a roleevent is a choose event
__inline__ int
isChooseRoledef ( const System sys , const int run , const Roledef rd )
{
return ( rd = = sys - > runs [ run ] . start & &
rd - > type = = READ & &
rd - > internal ) ;
}
2004-07-20 21:42:53 +01:00
2004-07-20 21:58:32 +01:00
//! Explore possible chooses first
2004-07-20 21:42:53 +01:00
__inline__ int
2004-07-20 21:58:32 +01:00
tryChoosesFirst ( const System sys )
2004-04-23 11:58:43 +01:00
{
2004-07-20 21:58:32 +01:00
int flag ;
2004-04-23 11:58:43 +01:00
int run ;
2004-07-20 21:58:32 +01:00
Roledef rd ;
2004-04-23 11:58:43 +01:00
2004-07-20 21:58:32 +01:00
flag = 0 ;
for ( run = 0 ; run < sys - > maxruns & & ! flag ; run + + )
{
rd = runPointerGet ( sys , run ) ;
if ( isChooseRoledef ( sys , run , rd ) )
flag = tryChoiceRoledef ( sys , run , rd ) ;
}
return flag ;
}
2004-04-23 11:58:43 +01:00
2004-07-20 21:58:32 +01:00
//! Explore left-to-right (from an offset)
__inline__ int
tryEventsOffset ( const System sys , const int offset )
{
int flag ;
int run ;
int i ;
2004-04-23 11:58:43 +01:00
2004-07-20 21:58:32 +01:00
flag = 0 ;
2004-07-17 20:43:20 +01:00
for ( i = 0 ; i < sys - > maxruns & & ! flag ; i + + )
2004-07-13 21:20:58 +01:00
{
run = ( i + offset ) % sys - > maxruns ;
2004-07-20 21:42:53 +01:00
flag = tryChoiceRun ( sys , run ) ;
2004-07-13 21:20:58 +01:00
}
return flag ;
}
2004-07-20 21:58:32 +01:00
/*
* POR4
*
* This is the simplified version of the algorithm , to be compared with
* the - t7 version .
*
* Based on some new considerations .
*/
__inline__ int
traversePOR4 ( const System sys )
{
return tryEventsOffset ( sys , lastActiveRun ( sys ) ) ;
}
2004-07-13 21:20:58 +01:00
/*
* POR5
*
* POR4 but does chooses first .
*/
2004-07-20 21:42:53 +01:00
__inline__ int
2004-07-13 21:20:58 +01:00
traversePOR5 ( const System sys )
{
2004-07-20 21:58:32 +01:00
if ( tryChoosesFirst ( sys ) )
return 1 ;
return tryEventsOffset ( sys , lastActiveRun ( sys ) ) ;
2004-07-15 12:04:15 +01:00
}
/*
* POR6
*
* POR5 but has a left - oriented scan instead of working from the current run .
*/
2004-07-20 21:42:53 +01:00
__inline__ int
2004-07-15 12:04:15 +01:00
traversePOR6 ( const System sys )
{
2004-07-20 21:58:32 +01:00
return tryEventsOffset ( sys , 0 ) ;
2004-07-17 22:11:35 +01:00
}
/*
* POR7
*
* Left - oriented scan , to ensure reductions . However , first does all initial actions .
*/
2004-07-20 21:42:53 +01:00
__inline__ int
2004-07-17 22:11:35 +01:00
traversePOR7 ( const System sys )
{
2004-07-20 21:58:32 +01:00
if ( tryChoosesFirst ( sys ) )
return 1 ;
tryEventsOffset ( sys , 0 ) ;
2004-07-20 21:42:53 +01:00
}
2004-04-23 11:58:43 +01:00
2004-07-20 21:42:53 +01:00
/*
* POR8
*
2004-07-20 21:58:32 +01:00
* POR6 , but tries to continue on the current run first . This turned out to be highly more efficient .
2004-07-20 21:42:53 +01:00
*/
2004-04-23 11:58:43 +01:00
2004-07-20 21:42:53 +01:00
__inline__ int
traversePOR8 ( const System sys )
{
2004-07-20 21:58:32 +01:00
int flag ;
2004-07-20 21:42:53 +01:00
int run ;
int last ;
2004-04-23 11:58:43 +01:00
2004-07-20 21:42:53 +01:00
last = lastActiveRun ( sys ) ;
flag = tryChoiceRun ( sys , last ) ;
for ( run = 0 ; run < sys - > maxruns & & ! flag ; run + + )
{
if ( run ! = last )
flag = tryChoiceRun ( sys , run ) ;
2004-04-23 11:58:43 +01:00
}
return flag ;
}
2004-07-20 21:42:53 +01:00
//! Check for the properties that have lasting effects throughout the trace.
/**
* Currently , only functions for secrecy .
2004-08-09 10:42:58 +01:00
* @ returns 1 ( true ) iff everything is okay , and no attack is found . 0 ( false ) if an attack is found .
2004-07-20 21:42:53 +01:00
*/
2004-04-23 11:58:43 +01:00
int
propertyCheck ( const System sys )
{
int flag = 1 ; // default: properties are true, no attack
/* for now, we only check secrecy */
if ( sys - > secrets ! = NULL )
{
Termlist scan ;
scan = sys - > secrets ;
while ( scan ! = NULL )
{
if ( ! claimSecrecy ( sys , scan - > term ) )
{
/* apparently, secrecy of this term was violated */
/* find the violated claim event */
Termlist tl = NULL ;
int claimev = - 1 ;
int i = 0 ;
while ( claimev = = - 1 & & i < = sys - > step )
{
if ( sys - > traceEvent [ i ] - > type = = CLAIM & &
sys - > traceEvent [ i ] - > to = = CLAIM_Secret )
{
Termlist tl = secrecyUnfolding ( scan - > term , sys - > know ) ;
if ( tl ! = NULL )
{
/* This was indeed a violated claim */
claimev = i ;
}
}
i + + ;
}
/* do we have it? */
if ( claimev = = - 1 )
{
/* weird, should not occur */
2004-05-12 15:07:56 +01:00
fprintf ( stderr , " Violation, but cannot locate claim. \n " ) ;
2004-04-23 11:58:43 +01:00
printf ( " A secrecy claim was supposed to be violated on term " ) ;
termPrint ( scan - > term ) ;
printf ( " but we couldn't find the corresponding claim. \n " ) ;
exit ( 1 ) ;
}
else
{
/* fine. so it's violated */
violateClaim ( sys , sys - > step , claimev , tl ) ;
termlistDelete ( tl ) ;
flag = 0 ;
}
}
scan = scan - > next ;
}
}
return flag ;
}
/* true iff the term is secret */
int
isTermSecret ( const System sys , const Term t )
{
switch ( sys - > clp )
{
case 0 :
/* test for simple inclusion */
if ( inKnowledge ( sys - > know , t ) )
return 0 ;
if ( isTermVariable ( t ) )
{
/* it's a variable! */
/* TODO that does not necessarily mean we can choose it, does
* it ? NO : the rule should be : there is at least one message
* in knowledge . We don ' t check it currently . */
return 0 ;
}
return 1 ;
case 1 :
/* CLP stuff */
return secret_clp ( sys , t ) ;
default :
return 0 ;
}
}
/* true iff the claim is valid */
int
claimSecrecy ( const System sys , const Term t )
{
int csScan ( Term t )
{
t = deVar ( t ) ;
if ( isTermTuple ( t ) )
2004-05-26 09:40:33 +01:00
return csScan ( t - > left . op1 ) & & csScan ( t - > right . op2 ) ;
2004-04-23 11:58:43 +01:00
else
return isTermSecret ( sys , t ) ;
}
if ( csScan ( t ) )
return 1 ;
else
{
/* Not reported anymore here, but only at the end */
// reportSecrecy (sys, t);
return 0 ;
}
}
/*
* Unfold the secrecy tuple and construct a list of terms that violate it .
*/
Termlist
secrecyUnfolding ( Term t , const Knowledge know )
{
t = deVar ( t ) ;
if ( isTermTuple ( t ) )
2004-05-26 09:40:33 +01:00
return termlistConcat ( secrecyUnfolding ( t - > left . op1 , know ) ,
secrecyUnfolding ( t - > right . op2 , know )
2004-04-23 11:58:43 +01:00
) ;
else
{
if ( inKnowledge ( know , t ) )
return termlistAdd ( NULL , t ) ;
else
return NULL ;
}
}
/*
* for reporting we need a more detailed output of the claims .
* Output is a termlist pointer , or - 1.
*
* in : claim roledef , knowledge for which it is violated
*
* - 1 : claim was ignored
* NULL : claim is fulfilled ( true )
* Termlist : claim was violated , termlist terms are know to the intruder .
*/
Termlist
claimViolationDetails ( const System sys , const int run , const Roledef rd , const Knowledge know )
{
if ( rd - > type ! = CLAIM )
{
2004-05-12 15:07:56 +01:00
fprintf ( stderr , " Trying to determine details of something other than a claim! \n " ) ;
2004-04-23 11:58:43 +01:00
exit ( - 1 ) ;
}
/* cases */
if ( rd - > to = = CLAIM_Secret )
{
/* secrecy claim */
if ( untrustedAgent ( sys , sys - > runs [ run ] . agents ) )
{
/* claim was skipped */
return ( Termlist ) - 1 ;
}
else
{
/* construct violating subterms list */
return secrecyUnfolding ( rd - > message , know ) ;
}
}
return NULL ;
}
2004-06-16 16:28:20 +01:00
//! A claim was violated.
/**
* This happens when we violate a claim .
2004-04-23 11:58:43 +01:00
* Lots of administration .
2004-06-16 16:28:20 +01:00
* @ returns True iff explorify is in order .
2004-04-23 11:58:43 +01:00
*/
int
violateClaim ( const System sys , int length , int claimev , Termlist reqt )
{
int flag ;
/* default = no adaption of pruning, continue search */
flag = 1 ;
/* Count the violations */
2004-07-21 11:35:39 +01:00
sys - > failed = statesIncrease ( sys - > failed ) ;
2004-04-23 11:58:43 +01:00
2004-07-13 10:14:03 +01:00
/* mark the path in the state graph? */
2004-07-29 11:13:13 +01:00
if ( sys - > output = = STATESPACE )
2004-07-13 10:14:03 +01:00
{
2004-07-13 13:19:03 +01:00
graphPath ( sys , length ) ;
2004-07-13 10:14:03 +01:00
}
2004-04-23 11:58:43 +01:00
/* Copy the current trace to the buffer, if the new one is shorter than the previous one. */
if ( sys - > attack = = NULL | | length < sys - > attack - > reallength )
{
tracebufDone ( sys - > attack ) ;
sys - > attack = tracebufSet ( sys , length , claimev ) ;
attackMinimize ( sys , sys - > attack ) ;
sys - > shortestattack = sys - > attack - > reallength ;
/* maybe there is some new pruning going on */
flag = 0 ;
switch ( sys - > prune )
{
case 0 :
flag = 1 ;
break ;
case 1 :
break ;
case 2 :
sys - > maxtracelength = sys - > shortestattack - 1 ;
break ;
}
}
return flag ;
}
2004-07-19 13:03:29 +01:00
//! Try to execute the next event in a run.
/**
* One of the core functions of the system .
* @ returns 0 ( false ) if the event was not enabled . 1 ( true ) if there was an enabled instantiation of this event .
*/
2004-04-23 11:58:43 +01:00
int
executeTry ( const System sys , int run )
{
Roledef runPoint ;
int flag = 0 ;
runPoint = runPointerGet ( sys , run ) ;
sys - > traceEvent [ sys - > step ] = runPoint ; // store for later usage, problem: variables are substituted later...
2004-07-13 12:10:06 +01:00
sys - > traceRun [ sys - > step ] = run ; // same
2004-04-23 11:58:43 +01:00
if ( runPoint = = NULL )
{
# ifdef DEBUG
/* warning, ought not to occur */
debug ( 2 , " Trying to activate completed run " ) ;
# endif
}
else
{
# ifdef DEBUG
if ( DEBUGL ( 4 ) )
{
indent ( ) ;
printf ( " try: " ) ;
roledefPrint ( runPoint ) ;
printf ( " #%i \n " , run ) ;
}
# endif
if ( runPoint - > type = = READ )
{
if ( sys - > clp )
return matchRead_clp ( sys , run , explorify ) ;
else
return matchRead_basic ( sys , run , explorify ) ;
}
if ( runPoint - > type = = SEND )
{
if ( sys - > clp )
flag = send_clp ( sys , run ) ;
else
flag = send_basic ( sys , run ) ;
return flag ;
}
2004-06-16 16:28:20 +01:00
/*
* Execute claim event
*/
2004-04-23 11:58:43 +01:00
if ( runPoint - > type = = CLAIM )
{
/* first we might dynamically determine whether the claim is valid */
if ( untrustedAgent ( sys , sys - > runs [ run ] . agents ) )
{
/* for untrusted agents we check no claim violations at all
* so : we know it ' s okay . */
/* TODO for CLP this doesn't work and call for branching, if the
* agent is a variable */
# ifdef DEBUG
if ( DEBUGL ( 3 ) )
{
indent ( ) ;
printf ( " Skipped claim in untrusted run with agents " ) ;
termlistPrint ( sys - > runs [ run ] . agents ) ;
printf ( " \n " ) ;
}
# endif
explorify ( sys , run ) ;
return 1 ;
}
/* determine type of claim, and parameters */
# ifdef DEBUG
if ( DEBUGL ( 2 ) )
{
indent ( ) ;
printf ( " claim: " ) ;
roledefPrint ( runPoint ) ;
printf ( " #%i \n " , run ) ;
}
# endif
2004-06-16 16:28:20 +01:00
/*
* update claim counters
*/
2004-07-21 11:35:39 +01:00
sys - > claims = statesIncrease ( sys - > claims ) ;
2004-04-23 11:58:43 +01:00
2004-06-16 16:28:20 +01:00
/*
* distinguish claim types
*/
2004-04-23 11:58:43 +01:00
if ( runPoint - > to = = CLAIM_Secret )
{
2004-06-16 16:28:20 +01:00
/*
* SECRECY
*/
2004-04-23 11:58:43 +01:00
/* TODO claims now have their own type, test for that */
/* TODO for now it is secrecy of the message */
Termlist oldsecrets = sys - > secrets ;
/* TODO this can be more efficient, by filtering out double occurrences */
sys - > secrets =
termlistAdd ( termlistShallow ( oldsecrets ) , runPoint - > message ) ;
flag = claimSecrecy ( sys , runPoint - > message ) ;
2004-06-16 16:28:20 +01:00
runPoint - > claiminfo - > count + + ;
2004-04-23 11:58:43 +01:00
/* now check whether the claim failed for further actions */
if ( ! flag )
{
/* violation */
Termlist tl ;
2004-06-16 16:28:20 +01:00
runPoint - > claiminfo - > failed + + ;
2004-04-23 11:58:43 +01:00
tl = claimViolationDetails ( sys , run , runPoint , sys - > know ) ;
if ( violateClaim ( sys , sys - > step + 1 , sys - > step , tl ) )
flag = explorify ( sys , run ) ;
termlistDelete ( tl ) ;
}
else
{
/* no violation */
flag = explorify ( sys , run ) ;
}
/* reset secrets list */
termlistDelete ( sys - > secrets ) ;
sys - > secrets = oldsecrets ;
}
if ( runPoint - > to = = CLAIM_Nisynch )
{
2004-06-16 16:28:20 +01:00
/*
* NISYNCH
*/
flag = check_claim_nisynch ( sys , sys - > step ) ;
if ( ! flag )
{
/* violation */
if ( violateClaim ( sys , sys - > step + 1 , sys - > step , NULL ) )
flag = explorify ( sys , run ) ;
}
else
{
/* no violation */
flag = explorify ( sys , run ) ;
}
2004-04-23 11:58:43 +01:00
}
2004-07-25 19:24:50 +01:00
if ( runPoint - > to = = CLAIM_Niagree )
{
/*
* NIAGREE
*/
flag = check_claim_niagree ( sys , sys - > step ) ;
if ( ! flag )
{
/* violation */
if ( violateClaim ( sys , sys - > step + 1 , sys - > step , NULL ) )
flag = explorify ( sys , run ) ;
}
else
{
/* no violation */
flag = explorify ( sys , run ) ;
}
}
2004-04-23 11:58:43 +01:00
}
/* a claim always succeeds */
flag = 1 ;
}
return flag ;
}