簡體   English   中英

為什么GCC 9.1.0有時會抱怨使用strncpy()?

[英]Why does GCC 9.1.0 sometimes complain about this use of strncpy()?

這是一個40行的MCVE( 最小,完整,可驗證的例子 ) - 或接近最小的東西 - 從最初包含32個標題的1675行源文件中減少(其中大多數包括多個其他標題 - 用gcc -H編譯它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編譯時,我沒有報告錯誤。

一個問題的兩個方面:

  • 為什么GCC 9.1.0在使用-USUPPRESS_BUG編譯代碼時會抱怨使用strncpy()
  • 使用-DSUPPRESS_BUG編譯代碼時為什么不抱怨?
    • 推論:有沒有辦法解決這個不受歡迎的警告,它適用於較舊的GCC版本以及9.1.0。 我還沒找到一個。 還有一個強大的元素“我不認為它應該是必要的,因為這是使用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代碼,除了在“實際代碼”中,錯誤不會被抑制。

在GCC 9.0中發現了幾個與strncpy相關的編譯警告,並在此處此處進行了報告。

其中一個是問題中提到的錯誤,似乎發生在文件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 stable。

所以我認為錯誤可能是版本9和9.1不穩定版本的結果。 希望在這些版本穩定后它們將被淘汰。

這是一個跟蹤為PR88780的GCC錯誤。 根據馬丁的評論 ,這一警告在GCC 8之前並不存在。

GCC附帶此已知錯誤,因為它不被視為發布關鍵。

說實話,我不是100%肯定它錯誤。 關鍵是,存在已知的誤報。 如果您想幫助GCC項目,您可以在strncpy / Wstringop-truncation錯誤中找到最合適的錯誤並在那里發布您的示例。 如果你進一步減少它會更有幫助(比如說,有creduce ); 最小化編譯字符串也是值得贊賞的(我猜這將是相當微不足道的)。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM