如何抑制sprintf()警告'指令在1到11个字节之间写入大小为6的区域'

问题描述 投票:1回答:4

我使用sprintf()创建一个字符串,literal是一个整数。

char tag[16];
sprintf(tag, "Literal - %d", literal); 

但项目制定的是将所有警告视为错误并引发错误:

error: ‘%d’ directive writing between 1 and 11 bytes into a region of size 6 [-Werror=format-overflow=]   sprintf(tag, "Literal - %d", literal);    //snprintf(tag, 16, "Literal - %d", literal);
                          ^~ apps/ziptest/test_literals_lzma.c:42:15: note: directive argument in the range [-2147483648, 255]   sprintf(tag, "Literal - %d", literal);    //snprintf(tag, 16, "Literal
- %d", literal);
               ^~~~~~~~~~~~~~ apps/ziptest/test_literals_lzma.c:42:2: note: ‘sprintf’ output between 12 and 22 bytes into a destination of size 16   sprintf(tag, "Literal - %d", literal);    //snprintf(tag, 16, "Literal - %d", literal);   ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ cc1: all warnings being treated as errors Makefile:370: recipe for target 

这个警告可以避免吗? (字面值从0到255)

c
4个回答
3
投票

sprintf(tag, "Literal - %d", literal); 

因为你的缓冲区是16个字节,前缀是10个字节,所以留下5个字节来写literal的字符串表示。

由于int在您的系统上可能是32位,它的范围可达2147483647,负数-2147483648(11个字符),编译器会发出警告(因为它能够计算所有大小)

现在你知道范围不能超出0-255,只需减少literal大小,例如,将其声明为unsigned shortshort可以是6个字节长的字符串:-32768作为chux在评论中注明)所以你有余地你的价值。

unsigned short literal = 123;
sprintf(tag, "Literal - %hu", literal); 

(您可以使用unsigned char,其范围恰好在0到255之间,使用%hhu格式说明符)

或者只是在打印时施放:

sprintf(tag, "Literal - %hu", (unsigned short)literal); 

%u可能也有效,但取决于编译器的智能程度:它只分析变量args的格式或大小吗?)

让我们不要忘记最明显的解决方案,因为我们知道警告发生的原因:让我们定义一个足够大的数组。

char tag[25];  // 21 would have been okay

应该这样做。除非你的资源不足,否则将它剃得太近通常不是一个好主意。


2
投票

此警告是有效的,因为tag不足以容纳要构造的字符串的所有可能值。

假设32位的整数需要最多11个字符来存储其字符串表示。在整数值之前有10个字符写入tag,因此剩下6个字节来写入其他数据。这就是警告告诉你的。

由于literal的范围为0到255,因此您可以将值转换为unsigned char并使用%hhu作为格式说明符,该格式说明符指出参数为unsigned char


2
投票

一般来说,sprintf被认为是不安全的,因为它不检查其输出数组的界限。在写入固定大小的缓冲区时,您应该考虑使用snprintf

snprintf(tag, sizeof(tag), "Literal - %d", literal);

0
投票

作为其他答案的补充 - 来自警告消息,看起来你已经在literal上提供了255的上限,但没有下限。也许你有一个if (literal >= 256)导致无法达到此代码?如果你还提供一个下限(也许是检查if (literal < 0 || literal >= 256))那么警告应该消失。

更一般地说,虽然你没有在这段代码中显示足够的上下文来知道实际发生了什么,但是这种警告来自编译器试图确保你清理用户的输入,检查以确保它是合理的如果它不合理,可能会导致未定义的行为。因此,警告表明您的输入错误检查不充分。

© www.soinside.com 2019 - 2024. All rights reserved.