Почему GCC 9.1.0 иногда жалуется на такое использование strncpy ()? - PullRequest
4 голосов
/ 22 мая 2019

Это 40-строчный MCVE ( Минимальный, завершенный, проверяемый пример ) - или что-то близкое к минимальному - вырезанный из исходного файла из 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 (на Mac, работающем под управлением Mac)macOS 10.14.5 Mojave или на виртуальной машине Linux с RedHat 5.x - не спрашивайте!), с опцией -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 жалуется на использование strncpy(), когда код компилируется с -USUPPRESS_BUG?
  • Почему он не жалуется, когда код компилируется с -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, за исключением того, что в «реальном коде» ошибка не подавляется.

Ответы [ 2 ]

3 голосов
/ 22 мая 2019

Это ошибка GCC, отслеженная как PR88780 .Согласно комментарию Мартина , это предупреждение не существовало до GCC 8.

GCC поставляется с этой известной ошибкой, поскольку она не считается критичной для выпуска.

Честно говоря, я не уверен на 100%, что это ошибка .Дело в том, что есть известные ложные срабатывания.Если вы хотите помочь проекту GCC, вы можете найти наиболее подходящую ошибку среди strncpy / Wstringop-truncation ошибок и опубликовать свой пример там.Было бы более полезно, если бы вы минимизировали его (скажем, с помощью creduce);также приветствуется минимизация строки компиляции (я думаю, это было бы довольно тривиально).

3 голосов
/ 22 мая 2019

Несколько предупреждений компиляции, относящихся к strncpy, были найдены в GCC 9.0 и сообщили здесь и здесь .

Одной из них является ошибка, упомянутая в вопросе, которая возникает в файле 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));
      |          ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Ответ на это был дан 15 апреля 2019 года:

Спасибо за отчет, однако GCC 9 все еще находится в стадии разработки. Мы не видим вышеуказанных ошибок в текущей стабильной GCC 7.4 или GCC 8.3. Мы признательны за предварительное уведомление и примем PR для устранения проблем с GCC 9, но пока наш целевой компилятор стабилен gcc.

Так что я считаю, что ошибки, вероятно, являются результатом того, что версии 9 и 9.1 не являются стабильными версиями. Надеюсь, они будут устранены, когда эти версии станут стабильными.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...