首页 > 用户发贴区 > 编程问题提问区 > c语言关于缓存溢出的问题求助
2007
10-31

c语言关于缓存溢出的问题求助

一下是一段代码其中有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); 


} 


 


c语言关于缓存溢出的问题求助》有 1 条评论

  1. xstar 说:

    你参考的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]

留下一个回复