g++警告sprintf可能正在写入已被malloc的零长度字符串

1wnzp6jl  于 2023-10-15  发布在  其他
关注(0)|答案(2)|浏览(145)

我得到一个编译器警告,说我写入字符串,可能是0时,字符串已成功malloc'd
我将日期格式化为YYYY-MM-DD以进行打印,其中调用例程需要释放可能是nullptr的返回值。
代码类似于:

char* formatDate(const time_t dateIn){

//Allocate memory for the new date
char *formattedDate = (char*) malloc(sizeof(char) * 11);

if (formattedDate != nullptr) {
    
    memset(formattedDate, '\0', 11);
    
    //Sanity check the input
    if (dateIn == LONG_MAX){
        strncpy(formattedDate, "MAX DATE", 10);
        return formattedDate;
    }
    
    struct tm *dateInStruct = gmtime(&dateIn);  //no need to free this memory
    sprintf(formattedDate, "%4i%1c%02i%1c%02i", (dateInStruct->tm_year + 1900), '-', (dateInStruct->tm_mon + 1), '-', dateInStruct->tm_mday);
    //sprintf(formattedDate, "%4i%c%02i%c%02i", (dateInStruct->tm_year + 1900), '-', (dateInStruct->tm_mon + 1), '-', dateInStruct->tm_mday); //Also gives warning
    //sprintf(formattedDate, "%4i-%02i-%02i", (dateInStruct->tm_year + 1900), (dateInStruct->tm_mon + 1), dateInStruct->tm_mday); //Also gives warning about - as a directive
    
}

return formattedDate;
}

g++ with -Wall给出

warning: ‘%1c’ directive writing 1 byte into a region of size between 0 and 7 [-Wformat-overflow=]
  576 |                 sprintf(formattedDate, "%4i%1c%02i%1c%02i", (dateInStruct->tm_year + 1900), '-', (dateInStruct->tm_mon + 1), '-', dateInStruct->tm_mday);
      |                                            ^~~
note: directive argument in the range [-2147483647, 2147483647]
  576 |                 sprintf(formattedDate, "%4i%1c%02i%1c%02i", (dateInStruct->tm_year + 1900), '-', (dateInStruct->tm_mon + 1), '-', dateInStruct->tm_mday);
      |                                        ^~~~~~~~~~~~~~~~~~~
note: ‘sprintf’ output between 11 and 36 bytes into a destination of size 11
  576 |                 sprintf(formattedDate, "%4i%1c%02i%1c%02i", (dateInStruct->tm_year + 1900), '-', (dateInStruct->tm_mon + 1), '-', dateInStruct->tm_mday);
      |                 ~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

为了帮助我的强迫症,什么是预期的处理方法?
g++ 12.3.0

ndh0cuux

ndh0cuux1#

这个警告最终是关于写作越界的。-2147483647是11个char s,你已经分配了11个字节,所以这是一个潜在的写越界。再加上其余的你打算添加做分配的缓冲区。
你的编译器不知道你是否打算在-2147483647年运行程序。如果你能向编译器证明年份最多是4 char s(模数),它就不会抱怨这部分。对其他任何你无法控制的数字也这样做。

bjg7j2ky

bjg7j2ky2#

可能写入formattedDate的字符串可能比您为它分配的空间大,如另一个答案中所述。
解决这个问题的方法是准确地分配您需要的空间。这可以通过首先调用snprintf而不是sprintf来实现,第一个参数为NULL,第二个参数为0。这将返回要写入的字节数。然后将缓冲区扩展到该大小(为终止空字节加上1),并再次调用snprintf

int len = snprintf(NULL, 0, "%4i%1c%02i%1c%02i", 
             (dateInStruct->tm_year + 1900), '-', 
             (dateInStruct->tm_mon + 1), '-', dateInStruct->tm_mday);
formattedDate = (char*) realloc(formattedDate, sizeof(char) * len + 1);
snprintf(formattedDate, len+1, "%4i%1c%02i%1c%02i", 
             (dateInStruct->tm_year + 1900), '-', 
             (dateInStruct->tm_mon + 1), '-', dateInStruct->tm_mday);

更好的方法是使用strftime,它专门用于格式化日期/时间字符串,还允许您指定最大大小:

strftime(formattedDate, 11, "%Y-%m-%d", dateInStruct);

相关问题