fsantize=address运行良好,但修复漏洞后分段错误仍然存在:C语言程序设计

bogh5gae  于 2023-01-20  发布在  其他
关注(0)|答案(1)|浏览(123)

下面是代码。堆栈跟踪指示fclose(跟踪文件)的一些问题;
我的观察是,程序能够显示多达146条记录,有时151条记录,然后在这一行(fclose(TrcFile);)得到分段错误。不确定出了什么问题,以及如何修复这个确切。

void WriteTrace( char *cEntryText ) {

    char cTimeStamp[40];                         /* time stamp variable */
    char cTimeFormat[]="%H:%M:%S: ";             /* time stamp format */

    GetTimeStamp( &cTimeStamp[0], sizeof(cTimeStamp), &cTimeFormat[0] );
    TrcFile = fopen( cTraceFile, cTrcOpenFlag ); /* open the file */
    cTrcOpenFlag[0] = 'a';                       /* after first, always app} */
    fprintf(TrcFile, "%s",   cTimeStamp);        /* write the time stamp */
    fprintf(TrcFile, "%s\n", cEntryText);        /* write the entry */
    fclose(TrcFile);                             /* close the trace file */
    return;                                      /* return to caller */
}



/*****************************************************************************/
/* Variables used for STP11421 changes                                       */
/*****************************************************************************/
/* Variables and Subroutines to create a Trace file for Debugging            */
char         cTraceFile[32]="/opt/cao/logs/caoforms.trc.log";   /* name of trace file */
static FILE  *TrcFile;                                          /* file handle for tracing */
static char  cTrcOpenFlag[2] = "w";                             /* initially, overwrite existing file */
void WriteTrace( char *cEntryText );
void GetTimeStamp( char *cTimeStamp, int iTimeStampLen, char *cTimeFormat );
char        cLogText[250];

下面是调用WriteTrace()的地方。

void convert_text(char string[30],int  size) {

    int z,m,n;
    char    A[30],B[30];
  
/* TDT,II - 02 May 2006 - Added Level 1 Debugging */
    if ( iDebug >= 1 )
        WriteTrace( "Running convert_text" );
        
        

    memcpy(B,string,size);
    for ( m=0;m<=size;m++ ) {
        if ( B[m]!='\0' )
            A[m]=B[m];
        else {
            for ( n=m;n<=size;n++ ) {
                A[n]=' ';
            }
            break;
        }
    }
    memcpy(string,A,size);
}

下面是堆栈跟踪。

#0  0x00007ffff34bea9f in raise () from /lib64/libc.so.6
#1  0x00007ffff3491e05 in abort () from /lib64/libc.so.6
#2  0x00007ffff3501047 in __libc_message () from /lib64/libc.so.6
#3  0x00007ffff350819c in malloc_printerr () from /lib64/libc.so.6
#4  0x00007ffff350844c in munmap_chunk () from /lib64/libc.so.6
#5  0x00007ffff34f72e5 in fclose@@GLIBC_2.2.5 () from /lib64/libc.so.6
#6  0x000000000047337e in WriteTrace (cEntryText=0x488d73 "Running convert_text") at caomenu.pc:18426
#7  0x000000000045014a in convert_text (string=0x1a50276 "TESTER233", size=10) at caomenu.pc:12795
#8  0x0000000000450cca in load_user_data () at caomenu.pc:12922
#9  0x00000000004500c1 in display_user_security () at caomenu.pc:12772
#10 0x0000000000403862 in menu1 () at caomenu.pc:993
#11 0x00000000004017fa in main (ac=2, av=0x7fffffffe208) at caomenu.pc:562

正如开发人员在问题下面的评论中所建议的那样,我也使用过valgrind。顺便说一句,它没有报告内存泄漏。欢迎对解决这个问题的方法提出建议。

31moq8wy

31moq8wy1#

考虑到这里有限的知识,我猜这可能是问题的根源。

TrcFile = fopen( cTraceFile, cTrcOpenFlag );

这一行没有什么固有的错误(除了我不知道cTrcOpenFlag的值是什么),但是fopen可能会失败!您必须检查这里的返回值,因为fopen在失败时可能会返回NULL。它在fclose上崩溃的事实可能无关紧要,因为一旦您传递NULL指针,所有赌注都将取消。尝试以下操作:

TrcFile = fopen( cTraceFile, cTrcOpenFlag );
if (TrcFile == NULL) {
    perror(cTraceFile);
    abort();  // replace this with correct error handling...
}

这将向控制台/终端打印出相应的错误消息。
我看到的另一个问题是,索引似乎在数组末尾运行:

memcpy(B,string,size);
    for ( m=0;m<=size;m++ ) {
        if ( B[m]!='\0' )
            A[m]=B[m];
        else {
            for ( n=m;n<=size;n++ ) {
                A[n]=' ';
            }
            break;
        }
    }
    memcpy(string,A,size);

根据memcpy调用,假定size是正确的。两个for循环似乎都运行传递的size。以下循环从0到size(包括0和size)迭代:

for ( m=0;m<=size;m++ ) {
for ( n=m;n<=size;n++ ) {

最后一次迭代将访问A[size]B[size],这超出了size的限制,这是否会导致崩溃取决于我看不到的程序部分。
因此,我将这些for循环修复为:

for ( m=0;m<size;m++ ) {
for ( n=m;n<size;n++ ) {

此时,如果size为30或更大,您将溢出数组。这是未定义的行为,将使您陷入鼻音困扰的境地。将此添加到函数的顶部以捕获此问题。

if (size >= 30) {
   fprintf(stderr, "size >= 30\n");
   abort();
}

请记住,这些abort只是调试的存根。如果它遇到abort,它将看起来像exit(1),可以被调试器捕获。一旦你修复了bug,你就不会把它们留在那里。

相关问题