这是一个40行的MCVE(Minimal, Complete, Verifiable Example)-或接近最低限度-从1675行源文件中删除,该文件最初包含32个标头(其中大多数包含多个其他标头,请使用gcc -H
列出了项目和系统中的464个标头,其中许多标头多次。该文件是以前没有警告(GCC 8.3.0)但没有GCC 9.1.0编译的工作代码。所有结构,功能,类型,变量名称均已更改。
pf31.c
#include <string.h>
enum { SERVERNAME_LEN = 128 };
typedef struct ServerQueue
{
char server_name[SERVERNAME_LEN + 1];
struct ServerQueue *next;
} ServerQueue;
extern int function_under_test(char *servername);
#ifdef SUPPRESS_BUG
extern int function_using_name(char *name);
#endif /* SUPPRESS_BUG */
extern int GetServerQueue(const char *servername, ServerQueue *queue);
int
function_under_test(char *servername)
{
ServerQueue queue;
char name[SERVERNAME_LEN + 1];
if (GetServerQueue(servername, &queue) != 0)
return -1;
char *name_in_queue = queue.server_name;
if (name_in_queue)
strncpy(name, name_in_queue, SERVERNAME_LEN);
else
strncpy(name, servername, SERVERNAME_LEN);
name[SERVERNAME_LEN] = '\0';
#ifdef SUPPRESS_BUG
return function_using_name(name);
#else
return 0;
#endif /* SUPPRESS_BUG */
}
使用GCC 9.1.0进行编译时(在运行macOS 10.14.5 Mojave的Mac上,或在运行RedHat 5.x的Linux VM上-不用问!),使用选项-DSUPPRESS_BUG
,我不会错误,但使用选项-USUPPRESS_BUG
,我得到一个错误:
$ gcc -std=c11 -O3 -g -Wall -Wextra -Werror -DSUPPRESS_BUG -c pf31.c
$ gcc -std=c11 -O3 -g -Wall -Wextra -Werror -USUPPRESS_BUG -c pf31.c
In file included from /usr/include/string.h:417,
from pf31.c:1:
pf31.c: In function ‘function_under_test’:
pf31.c:30:9: error: ‘__builtin_strncpy’ output may be truncated copying 128 bytes from a string of length 128 [-Werror=stringop-truncation]
30 | strncpy(name, name_in_queue, SERVERNAME_LEN);
| ^~~~~~~
cc1: all warnings being treated as errors
$
当我使用GCC 8.3.0进行编译时,没有错误报告。
一个问题的两个侧面:
strncpy()
编译代码时,为什么GCC 9.1.0会抱怨使用-USUPPRESS_BUG
?-DSUPPRESS_BUG
编译代码时不会抱怨?
strncpy()
来限制复制的数据量,这正是它的设计目的。” 我还有另一个不错的变体,更改了function_under_test()
的签名-这是一组差异:
11c11
< extern int function_under_test(char *servername);
---
> extern int function_under_test(char *servername, ServerQueue *queue);
20c20
< function_under_test(char *servername)
---
> function_under_test(char *servername, ServerQueue *queue)
22d21
< ServerQueue queue;
25c24
< if (GetServerQueue(servername, &queue) != 0)
---
> if (GetServerQueue(servername, queue) != 0)
27c26
< char *name_in_queue = queue.server_name;
---
> char *name_in_queue = queue->server_name;
无论是否定义了SUPPRESS_BUG
,它都会干净地编译。
您可以从SUPPRESS_BUG
术语中猜到,我倾向于认为这是GCC中的错误,但对于声称它只是一个错误,我有些谨慎。
有关原始代码的更多信息:函数本身长540行; strncpy()
块出现在函数中约170行;对应于name
的变量在许多函数调用中被进一步使用,其中一些函数以name
作为参数,并为函数提供返回值。这更类似于-DSUPPRESS_BUG
代码,除了在“真实代码”中,该错误没有被抑制。
答案 0 :(得分:3)
在GCC 9.0中发现了与strncpy
相关的几个编译警告,并报告了here和here。
其中之一是问题中提到的错误,该错误似乎发生在文件string_fortified.h
中:
/usr/include/bits/string_fortified.h:106:10: warning: ‘__builtin_strncpy’ output may be truncated copying 16 bytes from a string of length 16 [-Wstringop-truncation]
106 | return __builtin___strncpy_chk (__dest, __src, __len, __bos (__dest));
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
对此的答复是在2019年4月15日给出的:
感谢您的报告,但是GCC 9仍在开发中。在当前稳定的GCC 7.4或GCC 8.3中,我们看不到上述错误。我们非常感谢您提前通知,并且会接受PR来解决针对GCC 9的问题,但目前我们的目标编译器是gcc稳定的。
因此,我认为这些错误可能是由于版本9和9.1不是稳定版本造成的。希望这些版本稳定后将被淘汰。
答案 1 :(得分:3)