一下是一段代码其中有2处有缓存溢出的漏洞,请求各位大哥帮忙修改一下,小弟不才是在解决不了,万分感谢
#include <stdio.h>
#include <time.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
/* Error in command line: prints `msg’, `usage’, and halts the program. */
void arg_error(char *msg);
/* Error in banner file: prints `msg’ and halts the program. */
void file_error(char *msg);
/* Reads compressed banner from `filename’ and displays it to `stdout’: */
void show_file(char *filename, char compression, char *buf);
/* Prints current date: */
void show_date(char *msg);
/* Maximum banner name length */
#define MAXNAMELENGTH 8
/* Maximum banner dimensions */
#define MAXROWS 600
#define MAXCOLS 800
/* Banner buffer size (= MAXCOLS + 1) */
#define IMGBUFSIZE 80l
/* Maximum repeat count */
#define MAXREPEAT 10
static char *usage = “demo [ -z | -r | -n COUNT | BANNERNAME ]…”;
int main(int argn, char **argc)
{
int i;
char filename[MAXNAMELENGTH];
unsigned int repeat = 1;
char compression = ‘z’;
char buf[IMGBUFSIZE];
int j;
/* Parse command line arguments */
for (i = 1; i < argn; i++)
{
if (strcmp(argc[i],“-z”) == 0)
{ compression = ‘z’; }
else if (strcmp(argc[i],“-r”) == 0)
{ compression = ‘r’; }
else if (strcmp(argc[i],“-n”) == 0)
{ char *rest; double rep;
i++;
if (i >= argn) { arg_error(“no repeat count”); }
rep = strtod(argc[i], &rest);
if ((*rest != ‘\0′) || (rep < 0) || (rep > MAXREPEAT) || (rep != (int)rep))
{ arg_error(“invalid repeat count”); }
repeat = (int)rep;
}
else
{
/* Check name length (including final ‘\0′): */
if (strlen(argc[i]) > MAXNAMELENGTH+1)
{ arg_error(“banner name too long”); }
else
{
strcpy(filename, argc[i]);
strcat(filename, “.img”);
if (compression == ‘z’) { strcat(filename, “.z”); }
for (j = 0; j < repeat; j++)
{
printf(“\033[H\033[2J\n"); /* Clear screen */
printf("%s (%s)\n", argc[i], filename);
usleep(300000);
show_file(filename, compression, &(buf[0]));
usleep(500000);
}
}
}
}
show_date(“demo finished on “);
return(0);
}
void show_file(char *filename, char compression, char *buf)
{
/*
Read a pictorial text (banner, ascii-art image, etc.)
from the given `filename’ and prints it to standard out.
If the `compression’ argument is `r’ (“raw”), the file is printed
as is. Otherwise, the file is assumed to be in a compressed
format, and is uncompressed before being printed.
Currently, the only compression method supported is a variant of
run-length encoding (`compression = ‘z”). In this encoding, each
line of the file consists of a series of “groups”. Each group
consists of one “control” byte, possibly followed by a data
byte. The control byte consists of a `type’ bit and a seven-bit
`val’ field. If `type == 1′, then the byte `val + 32′is
inserted as the next banner pixel. If `type == 0′, then the
following byte is taken to be a banner pixel which is
to be replicated `val + 1′ times.
The caller must provide a pixel buffer `buf’, with at least
MAXCOLS+1 characters (MAXCOLS pixels plus a final `\0′). */
int c, d, type, count;
int col;
FILE *f;
f = fopen(filename, “r”);
if (f == NULL) { file_error(“file not found”); }
while((c = fgetc(f)) != EOF)
{ col = 0;
while(c != ‘\n’)
{ switch(compression)
{
case ‘r’:
/* Raw format: */
if (col >= MAXCOLS)
{ file_error(“too many pixels in row”); }
else
{ buf[col] = c; col++; }
break;
case ‘z’:
/* Compressed format: */
type = (c >> 7);
if (type == 1)
{ /* Verbatim pixel: */
if (col >= MAXCOLS)
{ file_error(“too many pixels in row”); }
else
{ buf[col] = (c & 127) + 32; col++; }
}
else
{ /* Replication group: */
if (((d = fgetc(f)) == EOF) || ( d == ‘\n’))
{ file_error(“premature EOF/EOL in replicated group”); }
count = (c & 127) + 1;
while(count > 0)
{ if (col >= MAXCOLS)
{ file_error(“too many pixels in row”); }
else
{ buf[col] = d; col++; count–; }
}
}
break;
default:
fprintf(stderr, “compression = `%c’\n“, compression);
file_error(“invalid compression code”);
}
c = fgetc(f);
if (c == EOF) { file_error(“missing end-of-line”); }
}
buf[col] = ‘\000′;
printf(“%s\n“, buf);
}
}
void show_date(char *msg)
{
time_t *now = (time_t *)malloc(sizeof(time_t));
(void)time(now);
printf(“%s%s\n“, msg, ctime(now));
}
void arg_error(char *msg)
{
fprintf(stderr, “** %s\n“, msg);
fprintf(stderr, “usage: %s\n“, usage);
exit(1);
}
void file_error(char *msg)
{
fprintf(stderr, “** %s\n“, msg);
exit(1);
}
>> 本文固定链接: http://www.vcgood.com/archives/1898
你参考的C语言书写规范似乎有些问题!!!^_^
程序的结构也有一些问题!溢出问题也指出来了!其他的自己参照检查一下!!!
[code]
#include <stdio.h>
/*#include <time.h>*/
#include <stdlib.h>
#include <time.h> /* stdio.h和stdlib.h这两个文件还是放一起的好 */
#include <string.h>
#include <unistd.h>
/* Error in command line: prints 'msg', 'usage', and halts the program. */
void arg_error( char *msg );
/* Error in banner file: prints 'msg' and halts the program. */
void file_error( char *msg );
/* Reads compressed banner from 'filename' and displays it to 'stdout': */
void show_file( char *filename, char compression, char *buf );
/* Prints current date: */
void show_date( char *msg );
#define PATH_MAX 1024
/* Maximum banner name length */
/* #define MAXNAMELENGTH 8 */
#define BAR_NAME_LENGTH 8 /* 这条按照 命名规则 来 */
/* Maximum banner dimensions */
/*
#define MAXROWS 600
#define MAXCOLS 800
*/
#define ROW_MAX 600 /* 这条按照 命名规则 来 */
#define COL_MAX 800 /* 这条按照 命名规则 来 */
/* Banner buffer size (= MAXCOLS + 1) */
/* #define IMGBUFSIZE 80l */
#define IMG_BUF_SIZE (COL_MAX + 1) /* 直接定义数字的话,修改比较麻烦 */
/* Maximum repeat count */
/* #define MAXREPEAT 10 */
#define REPEAT_CNT 10 /* 这条按照 命名规则 来 */
static char *usage = "demo [ -z | -r | -n COUNT | BANNERNAME ]...";
/* int main(int argn, char **argc) */ /* c => count 这个缩写就错误了 */
int main( int argc, char **argv ) /* 这里按规范中的定义,不要自己修改 */
{
/*
int i;
char filename[MAXNAMELENGTH];
unsigned int repeat = 1;
char compression = 'z';
char buf[IMGBUFSIZE];
int j;
*/
int i, j; /* 同类型的,同功能的可以放一行,其他的分开 */
/* char barname[ BAR_NAME_LENGTH ]; */ /* 原来的名字比较容易误解 filename一般有 PATH_MAX 长 */
char filename[ PATH_MAX ];
char barname[ PATH_MAX ]; /* 原来的名字比较容易误解 filename一般有 PATH_MAX 长 */
char compression = 'z';
char buf[ IMG_BUF_SIZE ];
int repeat = 1;
if (argc == 1)
{
arg_error( "error" );
exit(1);
}
/* Parse command line arguments */
for (i = 1; i < argc; i++)
{
if (strcmp( argv[i], "-z" ) == 0)
{
compression = 'z';
} else if (strcmp( argv[i], "-r" ) == 0) {
compression = 'r';
} else if (strcmp( argv[i], "-n" ) == 0) {
/* 这里的判断是否太复杂了点呢??? 完全可以用atoi等来代替,
char *rest;
double rep;
i++;
if (i >= argc)
{
arg_error("no repeat count");
}
rep = strtod (argv[i], &rest );
if ((*rest != '\0')
|| (rep < 0)
|| (rep > REPEAT_CNT)
|| (rep != (int)rep))
{
arg_error("invalid repeat count");
}
repeat = (int)rep;
*/
i++;
if (i >= argc )
{
arg_error( "no repeat count" );
}
repeat = atoi( argv[ i ] );
if ((repeat < 0) && (repeat > REPEAT_CNT))
{
arg_error( "invalid repeat count" );
}
} else { /* bar name */
/* Check name length (including final '\0'): */
if (strlen( argv[i] ) > (BAR_NAME_LENGTH + 1))
{
arg_error( "banner name too long" );
} else {
strcpy( filename, argv[i] );
strcpy( barname, argv[i] ); /* 这里的一些代码存在访问越界问题 */
strcat (barname, ".img" ); /* barname只定义了BAR_NAME_LENGTH的长度 */
if (compression == 'z') /* 一般文件名的buf要定义为PATH_MAX的长度 */
{ /* 长度可以单独定义一个常量来判断 */
strcat( barname, ".z" ); /* 修改前面的barname定义 */
}
/* 每段的功能相对独立,前面都是获取参数的
具体的操作就不要在这里做了
for (j = 0; j < repeat; j++)
{
printf("\033[H\033[2J\n");
printf("%s (%s)\n", argv[i], barname);
usleep(300000);
show_file(barname, compression, &(buf[0]));
usleep(500000);
}
*/
}
}
}
/* 具体的功能开始 这里要注意检查参数是否合法!虽然前面获取的时候检查了一遍,
不过防止有些检查没进入,这里还是需要检查的,而且也方面写成子函数 */
for (j = 0; j < repeat; j++)
{
printf("\033[H\033[2J\n"); /* 这样的清屏代码是否合法!!!!确认后在写 */
printf("%s\n", barname);
usleep(300000);
show_file(filename, compression, &(buf[0]));
usleep(500000);
}
show_date("demo finished on ");
return(0);
}
void show_file(char *filename, char compression, char *buf)
{
/* 这里还是命名规则的问题,c => ch等,
这个函数没仔细检查,不过有几个地方有点疑问,位运算最好少用!!!(除非算法要求)
你这里位运算和算术比较一起用,比如count这个变量,这个是不好的习惯
关于这里的算法, */
int c, d, type, count;
int col;
FILE *f;
f = fopen(filename, "r");
if (f == NULL)
{
file_error("file not found");
}
while ((c = fgetc(f)) != EOF)
{
col = 0;
while (c != '\n')
{
switch(compression)
{
case 'r': /* Raw format: */
if (col >= COL_MAX)
{
file_error("too many pixels in row");
} else {
buf[ col ] = c;
col++;
}
break;
case 'z': /* Compressed format: */
type = (c >> 7);
if (type == 1)
{
/* Verbatim pixel: */
if (col >= COL_MAX)
{
file_error("too many pixels in row");
} else {
buf[col] = (c & 127) + 32;
col++;
}
} else { /* Replication group: */
if (((d = fgetc(f)) == EOF) || ( d == '\n'))
{
file_error("premature EOF/EOL in replicated group");
}
count = (c & 127) + 1;
while(count > 0)
{
if (col >= COL_MAX)
{
file_error("too many pixels in row");
} else {
buf[col] = d;
col++;
count--;
}
}
}
break;
default:
fprintf(stderr, "compression = '%c'\n", compression);
file_error("invalid compression code");
}
c = fgetc(f);
if (c == EOF)
{
file_error("missing end-of-line");
}
}
/* buf[col] = '\000'; */ /* \0 结尾的东西就直接写 \0 不要自己多加东西 */
buf[ col ] = '\0';
printf( "%s\n", buf );
}
}
void show_date(char *msg)
{
/* 这里分配了内存而没释放
time_t *now = (time_t *)malloc( sizeof( time_t ) );
(void)time( now );
printf("%s%s\n", msg, ctime( now ) );
*/
time_t now; /* 改用这种形式 */
(void)time( &now );
printf( "%s%s\n", msg, ctime( &now ) );
}
void arg_error(char *msg)
{
fprintf( stderr, "** %s\n", msg );
/* fprintf(stderr, "usage: %s\n", usage);*/ /* 全局变量尽量少用 */
fprintf( stderr, "usage: %s\n", "demo [ -z | -r | -n COUNT | BANNERNAME ]..." );
exit( 1 );
}
void file_error(char *msg)
{
fprintf( stderr, "** %s\n", msg );
exit( 1 );
}
[/code]