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

时间:2017-09-06 04:36:40

标签: c gcc

我的示例代码(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的警告信息(gcc 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和一个终结符(&#39; \ 0&#39;)。 我很奇怪,为什么会有72号?如何评估它。在此样本中,没有必要将wtime增加为72号。

2 个答案:

答案 0 :(得分:7)

"%d"格式适用于int,通常为32位有符号整数类型。这意味着打印时最多可以包含11个字符(10位数加上负数可能的减号)。你有六个这意味着最多66个字符。

然后您还有其他五个字符('/'':'各有两个字符,以及一个空格)。

Plus终结者。

那是72岁。

请记住,"04"的{​​{1}}部分意味着它会打印左边用零填充的四位数字,但如果有更多数字则会打印所有数字。这不是一个绝对的限制。

因此至少20个字符,但最多72个字符。

答案 1 :(得分:2)

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

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

通过查找最小可能字符串找到19个字符,其中包含19个字符,因为每个值的前导零。由于<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.2.3/d3.min.js"></script> <script src="https://code.jquery.com/jquery-3.1.0.js"></script> <!DOCTYPE html> <meta charset="utf-8"> <style> svg{ border-style: solid; border-color: red; } } </style> <script src="https://d3js.org/d3.v4.min.js"></script> <body> <svg width="200" height="100" overflow-y="hidden" class="overlay"> <g transform="translate(70,20)scale(1)"> <g class="node" transform="translate(30,30)"> <circle class="nodeCircle" r="10" style="fill: black"</circle> <text x="10" dy=".35em" class="nodeText" text-anchor="start" style="fill-opacity: 1;"></text> <text x="10" dy="1.5em" class="nodeText" text-anchor="start"></text> </g> </g> </svg> <svg width="200" height="100" overflow-y="hidden" class="overlay"> <g transform="translate(100,50)scale(1)"> <g class="node" transform="translate(0,0)"> <circle class="nodeCircle" r="10" style="fill: black"</circle> <text x="10" dy=".35em" class="nodeText" text-anchor="start" style="fill-opacity: 1;"></text> <text x="10" dy="1.5em" class="nodeText" text-anchor="start"></text> </g> </g> </svg> <br/> <svg width="200" height="100" overflow-y="hidden" class="overlay"> <g transform="translate(200,50)scale(1)"> <g class="node" transform="translate(0,0)"> <circle class="nodeCircle" r="10" style="fill: black"</circle> <text x="10" dy=".35em" class="nodeText" text-anchor="start" style="fill-opacity: 1;"></text> <text x="10" dy="1.5em" class="nodeText" text-anchor="start"></text> </g> </g> </svg> <svg width="200" height="100" overflow-y="hidden" class="overlay"> <g transform="translate(100,10)scale(1)"> <g class="node" transform="translate(100,40)"> <circle class="nodeCircle" r="10" style="fill: black"</circle> <text x="10" dy=".35em" class="nodeText" text-anchor="start" style="fill-opacity: 1;"></text> <text x="10" dy="1.5em" class="nodeText" text-anchor="start"></text> </g> </g> </svg> </body>的限制(最多可达10位数),此格式化的字符串最多可包含71个字符,因此在每个int次出现中总计11(最坏情况下为导致负号)加上其他字符给我们71)。

通过只有19个字节来存储字符串,不可能将它全部加上空终止符,因此错误。因此,如果将char数组的大小增加到20,则可能因为它在限制范围内而起作用,但由于数字可能超过此大小,因此无法保证。