scyther/src/tac.c

369 lines
7.1 KiB
C
Raw Normal View History

/*
* Scyther : An automatic verifier for security protocols.
2012-04-24 12:56:51 +01:00
* Copyright (C) 2007-2012 Cas Cremers
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
2004-04-23 11:58:43 +01:00
#include <stdio.h>
#include <stdlib.h>
2004-04-23 11:58:43 +01:00
#include "tac.h"
#include "memory.h"
#include "switches.h"
#include "error.h"
2004-04-23 11:58:43 +01:00
extern int yylineno;
static Tac allocatedTacs;
//! Init segment
2004-04-23 11:58:43 +01:00
void
tacInit (void)
{
allocatedTacs = NULL;
}
//! Closing segment
2004-04-23 11:58:43 +01:00
void
tacDone (void)
{
Tac ts;
2004-04-23 11:58:43 +01:00
ts = allocatedTacs;
while (ts != NULL)
{
Tac tf;
2004-04-23 11:58:43 +01:00
tf = ts;
ts = ts->allnext;
free (tf);
2004-04-23 11:58:43 +01:00
}
}
//! Copy a tac
Tac
tacCopy(Tac c)
{
Tac newTac;
newTac = (Tac) malloc (sizeof (struct tacnode));
memcpy (newTac, c, sizeof (struct tacnode));
// Store in taclist
newTac->allnext = allocatedTacs;
allocatedTacs = newTac;
return newTac;
}
//! Create a tac node of some type
2004-04-23 11:58:43 +01:00
Tac
tacCreate (int op)
{
/* maybe even store in scrapping list, so we could delete them
* all later */
Tac t = malloc (sizeof (struct tacnode));
2004-04-23 11:58:43 +01:00
t->allnext = allocatedTacs;
allocatedTacs = t;
t->lineno = yylineno;
t->op = op;
t->next = NULL;
t->prev = NULL;
t->t1.tac = NULL;
t->t2.tac = NULL;
t->t3.tac = NULL;
2004-04-23 11:58:43 +01:00
return t;
}
Tac
tacJoin (int op, Tac t1, Tac t2, Tac t3)
{
Tac t;
t = tacCreate (op);
t->t1.tac = t1;
t->t2.tac = t2;
t->t3.tac = t3;
2004-04-23 11:58:43 +01:00
return t;
}
Tac
tacCat (Tac t1, Tac t2)
{
Tac t1e;
if (t1 == NULL)
{
if (t2 == NULL)
return NULL;
else
return t2;
}
else
{
t1e = t1;
while (t1e->next != NULL)
t1e = t1e->next;
t1e->next = t2;
if (t2 != NULL)
{
t2->prev = t1e;
}
return t1;
}
}
//! List to right-associative tuple
2004-04-23 11:58:43 +01:00
Tac
tacTupleRa (Tac taclist)
2004-04-23 11:58:43 +01:00
{
Tac tc;
/* check for single node */
if (taclist->next == NULL)
{
/* just return */
tc = taclist;
}
else
{
/* otherwise, write as (x,(y,(z,..))) */
tc = tacCreate (TAC_TUPLE);
tc->t1.tac = taclist;
tc->t2.tac = tacTuple (taclist->next);
2004-04-23 11:58:43 +01:00
/* unlink list */
tc->t1.tac->next = NULL;
tc->t2.tac->prev = NULL;
2004-04-23 11:58:43 +01:00
}
return tc;
}
//! List to left-associative tuple
Tac
tacTupleLa (Tac taclist)
{
Tac tc;
/* initial node is simple the first item */
tc = taclist;
tc->prev = NULL;
/* add any other nodes (one is ensured) */
do
{
Tac tcnew;
taclist = taclist->next;
/* add a new node (taclist) to the existing thing by first making the old one into the left-hand side of a tuple */
tcnew = tacCreate (TAC_TUPLE);
tcnew->t1.tac = tc;
tcnew->t2.tac = taclist;
tc = tcnew;
/* unlink */
tc->t1.tac->next = NULL;
tc->t2.tac->prev = NULL;
}
while (taclist->next != NULL);
return tc;
}
//! Compile a list into a tuple
/* in: a list. out: a tuple (for e.g. associativity)
* Effectively, this defines how we interpret tuples with
* more than two components.
*/
Tac
tacTuple (Tac taclist)
{
if (taclist == NULL || taclist->next == NULL)
{
/* just return */
return taclist;
}
else
{
switch (switches.tupling)
{
case 0:
/* case 0: as well as */
/* DEFAULT behaviour */
/* right-associative */
return tacTupleRa (taclist);
case 1:
/* switch --la-tupling */
/* left-associative */
return tacTupleLa (taclist);
default:
error ("Unknown tupling mode (--tupling=%i)", switches.tupling);
}
}
// @TODO this should be considered an error
return NULL;
}
2004-04-23 11:58:43 +01:00
/*
* tacPrint
* Print the tac. Only for debugging purposes.
*/
void
tacPrint (Tac t)
{
if (t == NULL)
return;
switch (t->op)
{
case TAC_PROTOCOL:
printf ("protocol %s (", t->t1.sym->text);
tacPrint (t->t3.tac);
2004-04-23 11:58:43 +01:00
printf (")\n{\n");
tacPrint (t->t2.tac);
2004-04-23 11:58:43 +01:00
printf ("};\n");
break;
case TAC_ROLE:
printf ("role %s\n{\n", t->t1.sym->text);
tacPrint (t->t2.tac);
2004-04-23 11:58:43 +01:00
printf ("};\n");
break;
2012-04-25 08:53:07 +01:00
case TAC_RECV:
printf ("recv");
if (t->t1.sym != NULL)
2004-04-23 11:58:43 +01:00
{
printf ("_%s", t->t1.sym->text);
2004-04-23 11:58:43 +01:00
}
printf ("(");
tacPrint (t->t2.tac);
2004-04-23 11:58:43 +01:00
printf (");\n");
break;
case TAC_SEND:
printf ("send");
if (t->t1.sym != NULL)
2004-04-23 11:58:43 +01:00
{
printf ("_%s", t->t1.sym->text);
2004-04-23 11:58:43 +01:00
}
printf ("(");
tacPrint (t->t2.tac);
2004-04-23 11:58:43 +01:00
printf (");\n");
break;
case TAC_CLAIM:
printf ("claim");
if (t->t1.sym != NULL)
2004-04-23 11:58:43 +01:00
{
printf ("_%s", t->t1.sym->text);
2004-04-23 11:58:43 +01:00
}
printf ("(");
tacPrint (t->t2.tac);
2004-04-23 11:58:43 +01:00
printf (");\n");
break;
case TAC_CONST:
printf ("const ");
tacPrint (t->t1.tac);
if (t->t2.tac != NULL)
2004-04-23 11:58:43 +01:00
{
printf (" : ");
tacPrint (t->t2.tac);
2004-04-23 11:58:43 +01:00
}
printf (";\n");
break;
case TAC_VAR:
printf ("var ");
tacPrint (t->t1.tac);
if (t->t2.tac != NULL)
2004-04-23 11:58:43 +01:00
{
printf (" : ");
tacPrint (t->t2.tac);
2004-04-23 11:58:43 +01:00
}
printf (";\n");
break;
case TAC_UNDEF:
printf ("undefined");
if (t->next != NULL)
printf (",");
break;
case TAC_STRING:
printf ("%s", t->t1.sym->text);
2004-04-23 11:58:43 +01:00
if (t->next != NULL)
printf (",");
break;
case TAC_TUPLE:
printf ("(");
tacPrint (t->t1.tac);
2004-04-23 11:58:43 +01:00
printf (",");
tacPrint (t->t2.tac);
2004-04-23 11:58:43 +01:00
printf (")");
break;
case TAC_ENCRYPT:
printf ("{");
tacPrint (t->t1.tac);
2004-04-23 11:58:43 +01:00
printf ("}");
tacPrint (t->t2.tac);
2004-04-23 11:58:43 +01:00
if (t->next != NULL)
{
printf (",");
t = t->next;
tacPrint (t);
}
break;
case TAC_RUN:
printf ("run ");
tacPrint (t->t1.tac);
2004-04-23 11:58:43 +01:00
printf ("(");
tacPrint (t->t2.tac);
2004-04-23 11:58:43 +01:00
printf (");\n");
break;
case TAC_ROLEREF:
symbolPrint (t->t1.sym);
2004-04-23 11:58:43 +01:00
printf (".");
symbolPrint (t->t2.sym);
2004-04-23 11:58:43 +01:00
break;
case TAC_COMPROMISED:
printf ("compromised ");
tacPrint (t->t1.tac);
2004-04-23 11:58:43 +01:00
printf (";\n");
break;
case TAC_SECRET:
printf ("secret ");
tacPrint (t->t1.tac);
2004-04-23 11:58:43 +01:00
printf (";\n");
break;
case TAC_INVERSEKEYS:
printf ("inversekeys (");
tacPrint (t->t1.tac);
2004-04-23 11:58:43 +01:00
printf (",");
tacPrint (t->t2.tac);
2004-04-23 11:58:43 +01:00
printf (");\n");
break;
case TAC_HASHFUNCTION:
printf ("hashfunction ");
tacPrint (t->t1.tac);
printf (";\n");
break;
2004-04-23 11:58:43 +01:00
case TAC_UNTRUSTED:
printf ("untrusted ");
tacPrint (t->t1.tac);
2004-04-23 11:58:43 +01:00
printf (";\n");
break;
default:
printf ("[??]");
}
/* and any other stuff */
if (t->next != NULL)
{
tacPrint (t->next);
}
}