为什么GCC 9.1.0有时会抱怨使用strncpy()? [英] Why does GCC 9.1.0 sometimes complain about this use of strncpy()?

查看:1055
本文介绍了为什么GCC 9.1.0有时会抱怨使用strncpy()?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这是40行的MCVE(最小,完整,可验证的示例)-或接近最小-从一个1675行源文件,该文件最初包含32个标头(并且大多数包含多个其他标头-使用gcc -H进行编译,列出了项目和系统中的464个标头,其中许多标头多次).该文件是以前没有警告(GCC 8.3.0)但没有GCC 9.1.0编译的工作代码.所有结构,功能,类型,变量名称均已更改.

This is a 40-line MCVE (Minimal, Complete, Verifiable Example) — or something close to minimal — cut down from a 1675 line source file that originally included 32 headers (and most of those included multiple other headers — compiling it with gcc -H lists 464 headers from the project and the system, many of them several times). That file is working code that previously compiled without warnings (GCC 8.3.0), but not with GCC 9.1.0. All structure, function, type, variable names have been changed.

#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时,我得到一个错误:

Compilation

When compiled using GCC 9.1.0 (on a Mac running macOS 10.14.5 Mojave, or on a Linux VM running RedHat 5.x — don't ask!), with the option -DSUPPRESS_BUG I get no error, but with the option -USUPPRESS_BUG, I get an error:

$ 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进行编译时,没有报告任何错误.

When I compile using GCC 8.3.0, I get no errors reported.

一个问题的两个侧面:

  • 为什么使用-USUPPRESS_BUG编译代码时,GCC 9.1.0为什么抱怨使用strncpy()?
  • 为什么用-DSUPPRESS_BUG编译代码时不会抱怨?
    • 推论:有一种方法可以解决这种不必要的警告,该警告适用于较旧的GCC版本和9.1.0.我还没有找到.还有一个很强的要素:我认为没有必要,因为这是使用strncpy()来限制复制的数据量,这正是它的设计目的."
    • Why does GCC 9.1.0 complain about the use of strncpy() when the code is compiled with -USUPPRESS_BUG?
    • Why doesn't it complain when the code is compiled with -DSUPPRESS_BUG?
      • Corollary: is there a way to work around this unwanted warning that works with older GCC versions as well as 9.1.0. I've not yet found one. There's also a strong element of "I don't think it should be necessary, because this is using strncpy() to limit the amount of data copied, which is what it is designed for".

      我还有另一个很不错的变体,更改了function_under_test()的签名-这是一组差异:

      I have another non-erroring variant, changing the signature of the function_under_test() — here's a set of diffs:

      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,它都能干净地编译.

      This compiles cleanly regardless of whether SUPPRESS_BUG is defined or not.

      您可以从SUPPRESS_BUG术语中猜到,我倾向于认为这是GCC中的错误,但对于声称它只是一个问题,我还是持谨慎态度.

      As you can guess from the SUPPRESS_BUG terminology, I'm tending towards the view that this is bug in GCC, but I'm kinda cautious about claiming it is one just yet.

      有关原始代码的更多信息:函数本身长540行; strncpy()块出现在函数中约170行;在许多函数调用中,与name相对应的变量被用于该函数的下层,其中一些以name作为参数并为该函数提供返回值.这更类似于-DSUPPRESS_BUG代码,除了在真实代码"中,该错误没有被抑制.

      More about the the original code: the function itself was 540 lines long; the strncpy() block occurs about 170 lines into the function; the variable corresponding to name was used further down the function in a number of function call, some of which take name as an argument and supply a return value for the function. This corresponds more to the -DSUPPRESS_BUG code, except that in the 'real code', the bug is not suppressed.

      推荐答案

      在GCC 9.0中发现了与strncpy相关的几个编译警告,并报告了此处.

      Several compilation warnings related to strncpy were found in GCC 9.0 and reported here and here.

      其中一个是问题中提到的错误,该错误似乎发生在文件string_fortified.h中:

      One of them is the error mentioned in the question which seems to occur in the file 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日给出的:

      The response to this was given on April 15, 2019 was:

      感谢您的报告,但是GCC 9仍在开发中.在当前稳定的GCC 7.4或GCC 8.3中,我们看不到上述错误.我们非常感谢您提前通知,并且会接受PR来解决针对GCC 9的问题,但目前我们的目标编译器是gcc稳定的.

      Thank you for the report, however as GCC 9 still under development. We do not see the above errors in the current stable GCC 7.4 or GCC 8.3. We appreciate the advanced notice, and will accept PRs to fix issues against GCC 9, but for now our target compiler is gcc stable.

      所以我相信这些错误可能是由于版本9和9.1不是稳定版本造成的.希望这些版本稳定后将被淘汰.

      So I believe the errors are probably a result of versions 9 and 9.1 being not stable versions. Hopefully they will be eliminated when these versions become stable.

      这篇关于为什么GCC 9.1.0有时会抱怨使用strncpy()?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆