⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 uno_intervals.c

📁 C程序漏洞检查
💻 C
字号:
/***** uno: uno_intervals.c *****//* Copyright (c) 2000-2003 by Lucent Technologies - Bell Laboratories     *//* All Rights Reserved.  This software is for educational purposes only.  *//* Permission is given to distribute this code provided that this intro-  *//* ductory message is not removed and no monies are exchanged.            *//* No guarantee is expressed or implied by the distribution of this code. *//* Software written by Gerard J. Holzmann based on the public domain      *//* ANSI-C parser Ctree Version 0.14 from Shaun Flisakowski                */#include <stdio.h>#include <stdlib.h>#include <string.h>#include <limits.h>#include "symtab.h"#include "uno_lts.h"#include "gram.h"static int	debug = 0;extern int	size_ok, size_nok;extern void	explain_bound(char *, ArBound *, treenode *);extern void	uno_assert(int, char *);/* defined in this file: */static void	and_bounds(ArBound *, ArBound *);static void	copy_bound(ArBound *, ArBound *);void	negate_bound(ArBound *);int	check_bounds(ArBound *, int, treenode *);int	merge_bounds(ArBound *, ArBound *);int	same_bounds(ArBound *, ArBound *);void	sanitize(ArBound *);extern void	uno_warn(char *, treenode *, symentry_t *);/* in intervals: lowerbounds are included, upperbounds are excluded */voidnegate_bound(ArBound *b){	if (debug>1) explain_bound("negating", b, ZT);	uno_assert(!(b->bounds & (DUP|UNK)), "dup or unk in negate");	if ((b->bounds & LB)	&&  (b->bounds & UB))	{	if (b->bounds & NEG)			b->bounds &= ~NEG;		else			b->bounds |= NEG;	} else if (b->bounds & LB)	{	b->bounds &= ~LB;		b->bounds |= UB;		b->ub = b->lb;	} else if (b->bounds & UB)	{	b->bounds &= ~UB;		b->bounds |= LB;		b->lb = b->ub;	} else	{	printf("uno: zero bounds, cannot happen\n");		exit(1);	}}intunsatisfiable(ArBound *a){	if (a->bounds & UNK) return 0;	return ((a->bounds & LB) && (a->bounds & UB) && a->ub <= a->lb);}intfirst_inside_second(ArBound *a, ArBound *b)	/* is interval a inside interval b? */{	sanitize(a);	sanitize(b);	if (unsatisfiable(a)	||  unsatisfiable(b))		return 0;	if (!(a->bounds&NEG) && !(b->bounds&NEG))	/* ...[-2..-1]...[1>... */		return ((a->lb >= b->lb) && (a->ub <= b->ub));	if ((a->bounds&NEG) && (b->bounds&NEG))		return ((a->lb <= b->lb) && (a->ub >= b->ub));	if (!(a->bounds&NEG) && (b->bounds&NEG))		return (a->ub <= b->lb || a->lb >= b->ub);	if ((a->bounds&NEG) && !(b->bounds&NEG))		return (b->lb >= a->ub || b->ub <= a->lb);	/* unreachable */	return 0;}intcheck_bounds(ArBound *b, int x, treenode *nn)	/* is bound within interval 0..x-1 ? */{	char buf[512];	int result = 1;	if (b->bounds & DUP)	{	if (!b->dup)		{	if (debug>1) printf("dup not set\n");			return 1;		}		b = b->dup;	/* one step only */	}	if (unsatisfiable(b))	{	if (debug) explain_bound("unsatisfiable", b, nn);		return 1;	/* no run can get here, so this is no error */	}	if (!(b->bounds&NEG))	{	if ((b->bounds&LB) && b->lb < 0)		{	result = 0;			sprintf(buf, "array index can be negative (%d)", b->lb);		}		if ((b->bounds&UB) && b->ub > x)		{	result = 0;			sprintf(buf, "array index can exceed upper-bound (%d>%d), var",				b->ub-1, x-1);		}	} else	{	result = 0;		uno_assert((b->bounds & UB) && (b->bounds & LB), "negated non-interval");		if (b->lb == b->ub - 1)		{	sprintf(buf, "array index can be unequal to %d", b->lb);			if (debug)				printf("	dubious: <%s>\n", buf);			result = 1;	/* dubious report */		} else			sprintf(buf, "array index can be <%d or >=%d", b->lb, b->ub);	}	if (result == 0)	{	size_nok++;		if (nn)			uno_warn(buf, nn, b->s);		else if (debug)			printf("<<%s>>\n", buf);	}  else	{	size_ok++;		if (debug>1) printf(" satisfied..\n");	}	return result;}voidsanitize(ArBound *a){	if ((a->bounds&UNK)	||  (a->bounds&DUP))		return;	if (!(a->bounds&LB) && !(a->bounds & UB))		explain_bound("error", a, ZT);	uno_assert((a->bounds&LB) || (a->bounds & UB), "zerobound error");	if (!(a->bounds&UB)) a->ub =  INT_MAX;	if (!(a->bounds&LB)) a->lb = -INT_MAX;	if (!(a->bounds & NEG)	||   ((a->bounds & LB) && (a->bounds & UB)));		return;	if (a->bounds & LB)	{	a->bounds &= ~NEG;		a->bounds &= ~LB;		a->bounds |= UB;		a->ub = a->lb;	} else if (a->bounds & UB)	{	a->bounds &= ~NEG;		a->bounds &= ~UB;		a->bounds |= LB;		a->lb = a->ub;	}}static voidand_bounds(ArBound *a, ArBound *b)	/* replace 'a' with 'a/\b' */{	if (debug>1)	{	printf("start and-bounds:\n");		explain_bound("a:", a, ZT);		explain_bound("b:", b, ZT);	}	sanitize(a);	sanitize(b);	if (!(a->bounds&NEG)	&&  !(b->bounds&NEG))	{	if ((a->bounds & UB) && (b->bounds & UB))		{	if (b->ub < a->ub)				a->ub = b->ub;		}		if ((a->bounds & LB) && (b->bounds & LB))		{	if (b->lb > a->lb)				a->lb = b->lb;		}		if (!(a->bounds & UB) && (b->bounds & UB))		{	a->bounds |= UB;			a->ub = b->ub;		}		if (!(a->bounds & LB) && (b->bounds & LB))		{	a->bounds |= LB;			a->lb = b->lb;		}		goto done;	}	if ((a->bounds&NEG)	&&  (b->bounds&NEG))		/* both known to be intervals */	{	if (b->ub > a->ub)			a->ub = b->ub;		if (b->lb < a->lb)			a->lb = b->lb;		goto done;	}	if (!(a->bounds&NEG)	&&   (b->bounds&NEG))		/* b known to be an interval */	{	if ((a->bounds & UB)		&&  (a->bounds & LB))		{	if (a->lb < b->lb)			{	if (a->ub > b->ub)					a->bounds |= UNK; /* creates 2 intervals */				else					a->ub = b->lb;				goto done;			}			if (a->ub > b->ub)			{	a->lb = b->ub;				goto done;			} else			{	a->lb = a->ub = 0;	/* not satisfiable */				goto done;			}		} else if (a->bounds & UB)		{	if (a->ub > b->ub)				a->bounds |= UNK;	/* creates 2 intervals */			else				a->ub = b->lb;		} else if (a->bounds & LB)		{	if (a->lb < b->lb)				a->bounds |= UNK;	/* creates 2 intervals */			else				a->lb = b->ub;		}		goto done;	}	if ( (a->bounds&NEG)		/* a known to be an interval */	&&  !(b->bounds&NEG))	{	a->bounds &= ~NEG;		if ((b->bounds & UB)		&&  (b->bounds & LB))		{	if (b->lb < a->lb)			{	if (b->ub > a->ub)					a->bounds |= UNK; /* creates 2 intervals */				else					a->lb = b->lb;				goto done;			}			if (a->ub > b->ub)			{	a->lb = b->ub;				goto done;			} else			{	a->lb = a->ub = 0;	/* not satisfiable */				goto done;			}		} else if (a->bounds & UB)		{	if (a->ub > b->ub)				a->bounds |= UNK;	/* creates 2 intervals */			else				a->ub = b->lb;		} else if (a->bounds & LB)		{	if (a->lb < b->lb)				a->bounds |= UNK;	/* creates 2 intervals */			else				a->lb = b->ub;		}		goto done;	}done:	a->bounds &= ~FROMASGN;	a->bounds &= ~FROMEXPR;	sanitize(a);}static voidcopy_bound(ArBound *to, ArBound *from){	to->s       = from->s;	to->sameas = from->sameas;	to->dup    = from->dup;	to->bounds = from->bounds;	to->lb     = from->lb;	to->ub     = from->ub;}intsame_bounds(ArBound *a, ArBound *b)	/* true if bound a includes bound b */{	if (strcmp(a->s->nme->str, b->s->nme->str) != 0	||  (a->bounds & UNK) != (b->bounds & UNK))		return 0;	if (a->bounds & UNK)		return 1;	return first_inside_second(b, a);}intmerge_bounds(ArBound *a, ArBound *b)	/* rewrite a as (a/\b)  FIX! */{	/* returns 1 if nothing   changed */	/* returns 0 if something changed */	if (debug>1)	{	printf("merge_bounds\n");		explain_bound("a:", a, ZT);		explain_bound("b:", b, ZT);	}	uno_assert(!(a->bounds & UNK), "merging unknown a");	uno_assert(!(b->bounds & UNK), "merging unknown b");	uno_assert(!(b->bounds & DUP), "merging dup b");	if (a->bounds & DUP)	{	if (debug>1) printf("	a was dup, now unknown\n");		a->bounds |= UNK;	/* fixable dups were resolved before we got here */		return 0;	}	if (first_inside_second(a, b))	{	if (debug>1) printf("	a inside b\n");		return 1;	}	if (first_inside_second(b, a))	{	if (debug>1) printf("	b inside a\n");		copy_bound(a, b);		return 0;	}	and_bounds(a, b);	if (debug>1)	{	printf("result of AND:\n");		explain_bound("a:", a, ZT);	}	return 0;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -