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

📄 uno_global.c

📁 C程序漏洞检查!
💻 C
字号:
/***** uno: uno_global.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 "dtags.h"#include "uno_global.h"#include "uno_version.h"static int	debug = 0;int	longtrace;int	verbose;static Fct	*fcts = (Fct *) 0;static PlaceName *fields = (PlaceName *) 0;static Sym	*globuse = (Sym *) 0;static char	*want = "main";static char	*p_start = "main";static char	*p_stop  = "exit";static int	p_query = 0;static int	reverse = 0;static int	usecheck = 0;static Fct	*find_fct(char *);static void	fcts_reset(void);static void	gen_fct(FILE *, Fct *);static void	gen_fcts(FILE *);static void	struct_check(void);static void	uno_load(char *);static void	unused_fcts(void);extern void	run_check(void);char *emalloc(int n){	char *s;	s = (char *) malloc(n);	if (!s)	{	fprintf(stderr, "uno:global: out of memory\n");		exit(1);	}	memset(s, 0, n);	return s;}static voidunostats(void){	Sym *r;	Fct *f;	int cnt = 0, d = 0, u = 0, c = 0, x = 0;	for (f = fcts; f; f = f->nxt)	{	cnt++;		for (r = f->defs;  r; r = r->nxt)			d++;		for (r = f->uses;  r; r = r->nxt)			u++;		for (r = f->deref;  r; r = r->nxt)			x++;		for (r = f->calls; r; r = r->nxt)			c++;	}	printf("%6d	function declarations\n", cnt-1);	printf("%6d	function calls\n", c);	printf("%6d	global variable definitions\n", d);	printf("%6d	global variable uses\n", u);	printf("%6d	global variable dereferences\n", x);	cnt = 0;	for (r = globuse; r; r = r->nxt)		if (!find_fct(r->s))			cnt++;	printf("%6d	global ptr variables\n", cnt);}static voidgen_fct(FILE *fd, Fct *g){	Sym *r;	Fct *f;	if (!g || g->visited) return;	g->visited = 1;	fprintf(fd, "N%s [label=\"%s:%d\"];\n",		g->fnm, g->fnm, g->n->line);	if (reverse)	{	for (f = fcts; f; f = f->nxt)		for (r = f->calls; r; r = r->nxt)			if (strcmp(r->s, g->fnm) == 0)			{	fprintf(fd, "N%s -> N%s;\n", f->fnm, g->fnm);				gen_fct(fd, f);			}	} else	{	for (r = g->calls; r; r = r->nxt)		{	if (!(r->bits & HIDE))				fprintf(fd, "N%s -> N%s;\n", g->fnm, r->s);			gen_fct(fd, find_fct(r->s));	}	}}static voidgen_fcts(FILE *fd){	fprintf(fd, "digraph dodot {\n\tratio=auto;\n");	fcts_reset();	gen_fct(fd, find_fct(want));	fprintf(fd, "}\n");}static voidall_fcg(FILE *fd){	Fct *g;	Sym *r;	fprintf(fd, "digraph dodot {\n\tratio=auto;\n");	for (g = fcts; g; g = g->nxt)	{	fprintf(fd, "N%s [label=\"%s:%d\"];\n",			g->fnm, g->fnm, g->n->line);		for (r = g->calls; r; r = r->nxt)			fprintf(fd, "N%s -> N%s;\n",				g->fnm, r->s);	}	fprintf(fd, "}\n");}static voidglob_mark(Place *n, char *s, int bits){	Sym *r;	for (r = globuse; r; r = r->nxt)		if (strcmp(r->s, s) == 0)		{	r->bits |= bits;			break;		}	if (!r)	{	r = (Sym *) emalloc(sizeof(Sym));		r->s = s;		r->bits = bits;		r->n = n;		r->nxt = globuse;		globuse = r;	}}static voidglob_check(void){	Sym *r;	for (r = globuse; r; r = r->nxt)	{		if (find_fct(r->s))			continue;	/* fct mistaken for a var */		switch (r->bits) {	/* no match if ALIAS bits are set */		case 0:	printf("uno:global: %s:%d '%s' never used or set\n",				r->n->fnm, r->n->line, r->s);			break;		case USE:			if (usecheck)			printf("uno:global: %s:%d '%s' used but never set\n",				r->n->fnm, r->n->line, r->s);			break;		case DEF:			if (usecheck)			printf("uno:global: %s:%d '%s' set but never used\n",				r->n->fnm, r->n->line, r->s);			break;		}	}}intpath_query(Fct *g, Fct *h)	/* from, to */{	Sym *r;	Fct *f;	int found;		if (!g || g->visited) return 0;	g->visited = 1;	found = 0;	for (r = g->calls; r; r = r->nxt)	{	f = find_fct(r->s);		if (f == h)			found = 1;		else			found = path_query(g, f);		if (found)		{	fprintf(stdout, "N%s -> N%s;\n", g->fnm, r->s);			break;		}#if 0		fprintf(stdout, "N%s [label=\"%s:%d\"];\n",				g->fnm, g->fnm, g->n->line);#endif	}	return found;}intmain(int argc, char **argv){	int fcg = 0;	argc--;	argv++;	while (argc-- > 0)	{	if (strcmp(*argv, "-V") == 0)		{	printf("%s\n", VERSION);			exit(0);		}		if (strcmp(*argv, "-v") == 0)		{	verbose = 1;			printf("%s\n", VERSION);		} else if (strcmp(*argv, "-fcg") == 0		|| strcmp(*argv, "-f") == 0)			fcg = 1;		else if (strcmp(*argv, "-use") == 0		|| strcmp(*argv, "-u") == 0)			usecheck = 1;		else if (strcmp(*argv, "-l") == 0		     ||  strcmp(*argv, "-1") == 0)			longtrace = 1;		else if (strcmp(*argv, "-r") == 0)			reverse = 1;		else if (strcmp(*argv, "-p") == 0)		{	argv++; argc--;			p_start = *argv;			p_query = 1;		} else if (strcmp(*argv, "-s") == 0)		{	argv++; argc--;			p_stop = *argv;			p_query = 1;		} else if (strcmp(*argv, "-a") == 0)		{	argv++; argc--;			want = *argv;		} else if (strstr(*argv, ".uno"))			uno_load(*argv);		else		{	fprintf(stderr, "usage: uno:global [-a name] [-f] [-l] [-r] [-u] [-v] *.uno\n");			fprintf(stderr, "	-a name	target fct name (default 'main')\n");			fprintf(stderr, "	-f[cg]	function call graph (dot format) (-v -fcg all fcts)\n");			fprintf(stderr, "	-l	more detailed error traces\n");			fprintf(stderr, "	-r	reverse fcg from target fct back to main\n");			fprintf(stderr, "	-p name	path query - set start of path (default is main)\n");			fprintf(stderr, "	-s name	path query - set end   of path (default is exit)\n");			fprintf(stderr, "	-u[se]	complain about redundancies\n");			fprintf(stderr, "	-v	verbose, print some stats\n");			exit(1);		}		argv++;	}	if (fcg)	{	if (verbose)			all_fcg(stdout);		else			gen_fcts(stdout);		exit(0);	}	if (p_query)	{	fprintf(stdout, "digraph dodot {\n\tratio=auto;\n");		fcts_reset();		path_query(find_fct(p_start), find_fct(p_stop));		fprintf(stdout, "}\n");		exit(0);	}	if (usecheck)	{	struct_check();	/* unused fields in structures */		glob_check();	/* redundant vars, used but not set, set but not used */		unused_fcts();	/* consistency of use of fct return values */	}	run_check();	/* uno_fcts.c */	if (verbose) unostats();}static voidnew_fct(Place *n, char *nf, int is_static_fct){	Fct *f;	for (f = fcts; f; f = f->nxt)		if (strcmp(f->fnm, nf) == 0)		{	if (f->n->line == n->line			&&  (strstr(f->n->fnm, n->fnm)			||   strstr(n->fnm, f->n->fnm)))				break;	/* probably from same source */			fprintf(stderr, "uno:global: fct '%s' appears twice\n", nf);			fprintf(stderr, "	old: %s:%d%s\n",				f->n->fnm, f->n->line, f->is_static?" (static)":"");			fprintf(stderr, "	new: %s:%d%s (ignored)\n",				n->fnm, n->line, f->is_static?" (static)":"");			break;		}	if (!f)	{	f = (Fct *) emalloc(sizeof(Fct));		f->fnm = nf;		f->n = n;		f->is_static = is_static_fct;		f->nxt = fcts;		fcts = f;	}}static Fct *find_fct(char *nf){	Fct *f = (Fct *) 0;	if (!nf) return f;	for (f = fcts; f; f = f->nxt)		if (strcmp(f->fnm, nf) == 0)			break;	if (!f)	{	if (strcmp(nf, "_global_") == 0)		{	Place *n;			n = (Place *) emalloc(sizeof(Place));			n->fnm = "_global_";			new_fct(n, nf, 0);			f = fcts;			add_fct(nf);		} else if (debug)			fprintf(stderr, "uno:global: unknown fct %s\n", nf);	}	return f;}static voidretval(char *s, int status){	Fct *f;	if (s)	if (f = find_fct(s))	/* assign f */		f->rval = status;}static voidglob_def(Place *n, char *nf, char *s){	Sym *r;	Fct *f;	if (!(f = find_fct(nf))) return;	r = (Sym *) emalloc(sizeof(Sym));	r->s = s;	r->n = n;	r->nxt = f->defs;	f->defs = r;}static int	special = 1000;static char	g_buf[256];static voidbuild_glob(Sym *r){	if (!r) return;	build_glob(r->nxt);		sprintf(g_buf, ">%d>", special++);	handle_fct(g_buf);	sprintf(g_buf, "[G\t%s\t%s %d]", r->s, r->n->fnm, r->n->line);	/* G: DEF|DCL */	handle_fct(g_buf);}void	/* called from uno_fcts.c */add_glob_defs(void){	Fct *f;	if (!(f = find_fct("_global_"))) return;	handle_fct(": _global_	0");	build_glob(f->defs);	if (!(f = find_fct("main")))	{	printf("uno:global: no fct 'main' found, cannot do global analysis\n");		return;	}	sprintf(g_buf, ">%d>", special++);	handle_fct(g_buf);	sprintf(g_buf, "[C\tmain\t%s %d]", f->n->fnm, f->n->line);	handle_fct(g_buf);}static voidloc_fcall(Place *n, char *nf, char *s, int bits){	Sym *r;	Fct *f;	if (!(f = find_fct(nf))) return;	r = (Sym *) emalloc(sizeof(Sym));	r->s = s;	r->n = n;	r->bits = bits;	r->nxt = f->calls;	f->calls = r;	if (bits & HIDE)	{	f = find_fct(s);		if (f) f->special |= HIDE;	}	add_call(nf, s);	/* uno_fcts.c */}static voidglob_use(Place *n, char *nf, char *s){	Sym *r;	Fct *f;	if (!(f = find_fct(nf))) return;	r = (Sym *) emalloc(sizeof(Sym));	r->s = s;	r->n = n;	r->nxt = f->uses;	f->uses = r;}static voidglob_deref(Place *n, char *nf, char *s){	Sym *r;	Fct *f;	if (!(f = find_fct(nf))) return;	r = (Sym *) emalloc(sizeof(Sym));	r->s = s;	r->n = n;	r->nxt = f->deref;	f->deref = r;}static char *mknm(char *s){	char *n;	n = (char *) emalloc(strlen(s)+1);	strcpy(n, s);	return n;}static voidstruct_flds(Place *n, char *nm, int used){	PlaceName *p;	for (p = fields; p; p = p->nxt)		if (p->n->line == n->line		&&  strcmp(p->n->fnm, n->fnm) == 0		&&  strcmp(p->s, nm) == 0)		{	p->used |= used;			break;		}	if (!p)	{	p = (PlaceName *) emalloc(sizeof(PlaceName));		p->n = n;		p->s = nm;		p->used = used;		p->nxt = fields;		fields = p;	}}static voidstruct_check(void){	PlaceName *p;	for (p = fields; p; p = p->nxt)		if (p->used == 0)			printf("uno:global: %s:%d possibly redundant field '%s'\n",				p->n->fnm, p->n->line, p->s);}static voidhandle_glb(char *buf, char *f){	static	char *curfct = (char *) 0;	char	Code, Name[512], Filename[512], *nm, *other;	Place	*n;	int	Linenr, ostat;	memset(Name, 0, sizeof(Name));	memset(Filename, 0, sizeof(Filename));	if (sscanf(buf, "%c\t%s\t%s\t%d\n",		&Code, Name, Filename, &Linenr) == 4)	{		n = (Place *) emalloc(sizeof(Place));		n->fnm = mknm(Filename);		n->line = Linenr;		nm = mknm(Name);		switch (Code) {		case 'F': curfct = nm; new_fct(n, nm, 0); add_fct(nm); break; /* extern function */		case 'f': curfct = nm; new_fct(n, nm, 1); add_fct(nm); break; /* static function */		case 'X': retval(curfct, Linenr); break;	 /* return value status of last function */		case 'D': glob_def(n, curfct, nm); break;	/* global is defined in fct */		case 'U': glob_use(n, curfct, nm); break;	/* poss useb4def   in fct */		case 'R': glob_deref(n, curfct, nm); break;	/* poss derefb4def in fct */		case 'C': loc_fcall(n, curfct, nm, DEF); break;	/* fct call made, retval used */		case 'c': loc_fcall(n, curfct, nm, USE); break;	/* fct call made, retval not used */		case 'b': loc_fcall(n, curfct, nm, USE|DEF); break;		case 'h': loc_fcall(n, curfct, nm, DEF|HIDE); break; /* probably can't happen */		case 'i': loc_fcall(n, curfct, nm, USE|HIDE); break; /* can't tell when or how called */		case 'j': loc_fcall(n, curfct, nm, USE|DEF|HIDE); break;		case 'G': glob_def(n, "_global_", nm); break;	 /* global defined in declaration */		case 'a': glob_mark(n, nm, ALIAS); break;	/* global var's address taken at least once */		case 'v': glob_mark(n, nm, 0); break;		/* global var   declared but not used */		case 's': glob_mark(n, nm, DEF); break;		/* global var   set  at least once    */		case 'u': glob_mark(n, nm, USE); break;		/* global var   used at least once    */		case 't': glob_mark(n, nm, DEF|USE); break;	/* global var   set and used at least once  */		case 'y': struct_flds(n, nm, 1); break;	/* report only matching results across all files */		case 'z': struct_flds(n, nm, 0); break;	/* report only matching results across all files */		case 'p': /* fct 'Name' could call fct 'Filename' via a fct pointer */			other = n->fnm; n->fnm = "---"; ostat = n->line; n->line = 0;			loc_fcall(n, nm, other, ostat);			break;		default : fprintf(stderr, "uno:global: bad code (%c) in %s\n", Code, f); break;	}	}}static voiduno_load(char *f){	FILE	*fd;	char	buf[2048];	if (0) fprintf(stderr, "uno:global: load %s\n", f);	if ((fd = fopen(f, "r")) == NULL)	{	fprintf(stderr, "uno:global: cannot open %s\n", f);		exit(1);	}	while (fgets(buf, sizeof(buf), fd))		switch (buf[0]) {		case '{':		case '<':		case '>':		case '[':		case ':':			handle_fct(buf);			break;		default:			handle_glb(buf, f);			break;		}	fclose(fd);}static voidfcts_reset(void){	Fct *g;	for (g = fcts; g; g = g->nxt)		g->visited = 0;}static voiddfs(Fct *g){	Sym *r;	if (!g || g->visited) return;	g->visited = 1;	for (r = g->calls; r; r = r->nxt)		dfs(find_fct(r->s));}static voidwind_down(Fct *f){	Fct *g;	Sym *c;	if (f)	for (c = f->calls; c; c = c->nxt)	{	g = find_fct(c->s);		if (g && !(g->rval & 4))		{	g->rval |= 4;			wind_down(g);	}	}}static voidunused_fcts(void){	Fct *f, *g;	Sym *c;	int sawsome = 0;	fcts_reset();	dfs(find_fct("main"));	/* mark reachable fcts */	for (f = fcts; f; f = f->nxt)		if (f->rval & 4)	/* rval, 1: return value, 2: no return value, 4: cannot tell */			wind_down(f);	/* propagate mark to all fcts called */	for (f = fcts; f; f = f->nxt)		if (!f->visited		&&  !f->special		&&  !(f->rval & 4)		&&  strcmp(f->fnm, "_global_") != 0)		{	if (!sawsome)				printf("uno:global: functions declared but not used:");			if ((sawsome++) % 2 == 0)				printf("\n");			printf("\t%s:%d %s()",				f->n->fnm, f->n->line, f->fnm);		}	if (sawsome) printf("\n");	for (f = fcts; f; f = f->nxt)	{	if (strcmp(f->fnm, "_global_") == 0)			continue;		if ((f->rval & 1) && (f->rval & 2) && !f->special)			printf("uno:global: %s:%d %s() can fail to return a value\n",				f->n->fnm, f->n->line, f->fnm);		else if (f->rval == 0)			printf("uno:global: %s:%d %s() no return value status recorded\n",				f->n->fnm, f->n->line, f->fnm);	}	for (f = fcts; f; f = f->nxt)	for (c = f->calls; c; c = c->nxt)	{	g = find_fct(c->s);		if (g		&& (g->rval & 2)		&& (c->bits & USE)		&& !(c->bits & HIDE))		printf("uno:global: %s() fails to return value%s expected at %s:%d\n",			c->s, (c->bits&DEF)?" maybe":"", c->n->fnm, c->n->line);	}	if (!verbose) return;	for (f = fcts; f; f = f->nxt)	for (c = f->calls; c; c = c->nxt)	{	g = find_fct(c->s);		if (g		&& (g->rval & 1)		&&  c->bits == DEF)		printf("uno:global: return value of %s() ignored at %s:%d\n",			c->s, c->n->fnm, c->n->line);	}	for (f = fcts; f; f = f->nxt)	for (c = f->calls; c; c = c->nxt)	{	g = find_fct(c->s);		if (g		&& (g->rval & 1)		&&  c->bits == USE|DEF)		printf("uno:global: return value of %s() maybe ignored at %s:%d\n",			c->s, c->n->fnm, c->n->line);	}}

⌨️ 快捷键说明

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