代码之家  ›  专栏  ›  技术社区  ›  Daniel YC Lin

如何评估gcc格式溢出检查大小72

gcc c
  •  3
  • Daniel YC Lin  · 技术社区  · 7 年前

    我的示例代码(t.c)

    #include <stdio.h>
    #include <time.h>
    int main() {
            /* 12345678901234567890
             * 2017/09/06 12:28:30  */
            char wtime[19];
            time_t t=time(NULL);
            struct tm *pt = localtime(&t);
            sprintf(wtime, "%04d/%02d/%02d %02d:%02d:%02d", pt->tm_year+1900,
                pt->tm_mon+1, pt->tm_mday, pt->tm_hour, pt->tm_min, pt->tm_sec);
            printf("%s %ld\n", wtime, sizeof(int));
            return 0;
    }
    

    gcc -Wall -Wformat=2 -m64 t.c (通用条款7.1.1)

    t.c:9:47: warning: ‘sprintf’ writing a terminating nul past the end of the destination [-Wformat-overflow=]
      sprintf(wtime, "%04d/%02d/%02d %02d:%02d:%02d", pt->tm_year+1900,
                                                   ^
    t.c:9:2: note: ‘sprintf’ output between 20 and 72 bytes into a destination of size 19
      sprintf(wtime, "%04d/%02d/%02d %02d:%02d:%02d", pt->tm_year+1900,
      ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
          pt->tm_mon+1, pt->tm_mday, pt->tm_hour, pt->tm_min, pt->tm_sec);
          ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    

    消息中的数字20是19和一个终止符(“\0”)。

    2 回复  |  直到 7 年前
        1
  •  10
  •   Some programmer dude    7 年前

    这个 "%d" int ,通常是32位有符号整数类型。这意味着打印时最多可以有11个字符(10位数字加上负数可能的负数)。你有六个这样的意思,最多66个字符。

    然后你还有另外五个角色(每个角色两个 '/' ':' ,和一个空格)。

    加上终止符。

    这是72。

    "04" 部分 "%04d" 这意味着它将打印四个数字,并用零填充,但如果有更多的数字,那么它将打印所有数字。这不是一个绝对极限。

        2
  •  2
  •   Mikael    7 年前

    C中的每个字符串都必须有一个空终止符,以便知道字符串的结束位置,但我想你已经从自己的名声中知道了这一点。

    错误消息表示字符串可以有20到72字节之间的任何数字,即19到71个字符加上空终止符。

    int (一个最多可以达到10位的数字),因此每个数字加11 %d