/*
* Utility functions for hat-detect.
*/
#include <stdio.h>
#include <errno.h>
#ifdef DEBUG
#define HIDE(x) x
#else
#define HIDE(x)
#endif
#include "detectutils.h"
/* Return the next child of any of the parents in the ParentSet. */
FileOffset
nextChild (ParentSet* ps)
{
FileOffset node=0;
/* keep searching one node at a time until a valid child turns up */
do { node = childSearch(ps); } while (!node);
return node;
}
/* Skip past one node of the file, returning its position if it is a child
* of any of the parents in the ParentSet, or 0 otherwise.
*/
FileOffset
childSearch (ParentSet* ps)
{
unsigned char c; int err;
FileOffset parent, node = q_position;
if (hat_interrupted) return 3;
err = q_fread(&c,sizeof(unsigned char),1,HatFileSeq);
if (err!=1) {
return 1; /* Assume EOF */
}
HIDE(fprintf(stderr,"childSearch: 0x%x, %d\n",node,c);)
switch (lower5(c)) { /* lower 5 bits identify the TraceType */
case ExpApp:
case ExpValueApp:
case ExpValueUse:
case ExpConstUse:
case ExpProjection:
case ExpConstDef:
case ExpGuard:
case ExpCase:
case ExpIf:
case ExpFieldUpdate:
case ExpHidden:
case ExpForward:
case ExpDoStmt:
parent = q_skipNode(c);
if (elemParentSet(parent,ps)) return node; else return 0;
break;
default:
q_skipNode(c); return 0; break;
}
}
/* Print a message to stderr if the asserted condition is violated. */
void
assert (Bool cond, char *act)
{
if (!cond) {
fprintf(stderr,"Assertion failed: %s at 0x%x\n",act,q_position);
}
}
/* Look for the file node that corresponds to the definition of Main.main */
FileOffset
findMainUse (Bool findUse)
{
FileOffset fo;
FileOffset atom;
FileOffset def;
FileOffset use;
char c;
char *str;
// We should find the main module at 0x10
fseek(HatFileSeq,0x10,SEEK_SET); q_position=0x10;
q_fread(&c,sizeof(char),1,HatFileSeq);
assert (lower5(c)==Module, "Module tag");
str = q_readString();
assert (!strcmp(str,"Main"),"Module is Main");
// The next thing shoult be the atom variable belonging to that module
q_readString();
atom = q_position;
q_fread(&c,sizeof(char),1,HatFileSeq);
assert (lower5(c)==AtomVariable, "AtomVariable tag");
fo = q_readFO();
assert (fo==0x10, "AtomVariable module is Main");
{ /* skip defnpos */
int x;
q_fread(&x,sizeof(int),1,HatFileSeq);
}
{ /* skip defnpos */
int x;
q_fread(&x,sizeof(int),1,HatFileSeq);
}
{ /* skip fixity */
char x;
q_fread(&x,sizeof(char),1,HatFileSeq);
}
// Main takes no arguments
q_fread(&c,sizeof(char),1,HatFileSeq);
assert (c==0, "AtomVariable has arity 0");
// Make sure the deffinition is main
str = q_readString();
assert (!strcmp(str,"main"),"AtomVariable is main");
// Make sure there is a constant definition pointing at main
def = q_position;
q_fread(&c,sizeof(char),1,HatFileSeq);
assert (lower5(c)==ExpConstDef, "ExpConstDef tag");
q_readFO(); q_readFO();
fo = q_readFO();
assert (fo==atom, "ExpConstDef points to AtomVariable main");
// Make sure that main is called
use = q_position;
q_fread(&c,sizeof(char),1,HatFileSeq);
assert (lower5(c)==ExpConstUse, "ExpConstUse tag");
if (hasSrcPos(c)) q_readFO();
q_readFO();
fo = q_readFO();
assert(fo==def, "ExpConstUse points to ExpConstDef");
if (findUse)
{
return use;
}
else
{
return def;
}
/* postcondition: q_position points to first node following ExpConstUse */
}
/* Decide whether to ask a question in hat-detect, by determining whether
* any of the functional identifiers in an expression are untrusted.
* Originally, we thought that only the 'real' function being applied
* mattered. But in a higher-order application like (filter f ...) then
* we are probably interested in asking the question if f is suspect, even
* though filter is trusted. Even this is only an approximation, because
* (filter f [] = []) is an uninteresting question - but it is too expensive
* to search for any children of the node, just to rule it out when no
* children are found. */
Bool
anySuspect (FileOffset fo)
{
char c, i;
FileOffset ptr[20]; /* applications only recorded up to arity 15 */
FileOffset r;
if (fo==0) return False;
freadAt(fo,&c,sizeof(char),1,HatFileRandom);
switch (lower5(c)) {
case ExpApp:
HIDE(fprintf(stderr,"anysuspect: 0x%x ExpApp\n",fo);)
if (hasSrcPos(c)) { readFO(); } /* skip use position */
readFO(); readFO(); /* skip parent and result */
ptr[0] = readFO(); /* get fun */
fread(&c,sizeof(char),1,HatFileRandom); /* get arity */
for (i=1; i<=c; i++) ptr[i] = readFO(); /* get args */
if (anySuspect(ptr[0])) return True;
for (i=1; i<=c; i++) {
if (anySuspect(getResult(ptr[i],True))) return True;
}
return False; /* fall-through case */
break;
case ExpProjection:
case ExpValueUse:
HIDE(fprintf(stderr,"anysuspect: 0x%x ExpValueUse\n",fo);)
if (hasSrcPos(c)) { readFO(); } /* skip use position */
readFO(); /* skip parent */
ptr[0] = readFO(); /* get Atom */
return anySuspect(ptr[0]);
break;
case AtomVariable:
HIDE(fprintf(stderr,"anysuspect: 0x%x AtomVariable\n",fo);)
ptr[0] = readFO(); /* get Module */
return anySuspect(ptr[0]);
break;
case Module:
HIDE(fprintf(stderr,"anysuspect: 0x%x Module\n",fo);)
return tracedModule(c); /* check trust bit */
break;
default:
return False;
break;
}
}
syntax highlighted by Code2HTML, v. 0.9.1