Clang Static Analyzer False Positive с битовыми полями (C-код) - PullRequest
0 голосов
/ 12 декабря 2018

Мне интересно, является ли следующий пример ложным срабатыванием Clang SA, и если да, есть ли способ его подавить?

Ключевым моментом здесь является то, что я копирую структуру, содержащую битовые поля, преобразовывая ее как слово вместо полевой копии (или memcpy).Полевое копирование и memcpy не вызывают предупреждений, но копирование в виде слова (после приведения) вызывает предупреждение «неинициализированный доступ».Это во встроенной системе, где возможен только доступ к словам, и эти типы копий слов являются обычным явлением.

Ниже приведен пример кода:

#include <stdio.h>
#include <string.h>

struct my_fields_t {
  unsigned int f0: 16;
  unsigned int f1: 8;
  unsigned int f2: 8;
};

int main(void) {

  struct my_fields_t var1, var2;

  // initialize all the fields in var1.
  var1.f0 = 1;
  var1.f1 = 2;
  var1.f2 = 3;

  // Method #1: copy var1 -> var2 as a word (sizeof(unsigned int) = 4).
  unsigned int *src = (unsigned int *) &var1;
  unsigned int *dest = (unsigned int *) &var2;
  *dest = *src;

  // Method #2: copy var1->var2 field-by-field [NO SA WARNINGS]
  // var2.f0 = var1.f0;
  // var2.f1 = var1.f1;
  // var2.f2 = var1.f2;

  // Method #3: use memcpy to copy var1 to var2 [NO SA WARNINGS]
  // memcpy(&var2, &var1, sizeof(struct my_fields_t));

  printf("%d, %d, %d\n", var1.f0, var1.f1, var1.f2);
  printf("%d, %d, %d\n", var2.f0, var2.f1, var2.f2);  // <--- Function call argument is an uninitialized value
  printf("sizeof(unsigned int) = %ld\n", sizeof(unsigned int));
}

Вот вывод:

$ clang --version
clang version 4.0.0 (tags/RELEASE_401/final)
Target: x86_64-unknown-linux-gnu
Thread model: posix

$ clang -Wall clang_sa.c

$ ./a.out
1, 2, 3
1, 2, 3
sizeof(unsigned int) = 4

$ scan-build clang clang_sa.c
scan-build: Using '<snipped>/clang-4.0' for static analysis
clang_sa.c:33:3: warning: Function call argument is an uninitialized value
  printf("%d, %d, %d\n", var2.f0, var2.f1, var2.f2);  // <--- Function call argument is an uninitialized value
  ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1 warning generated.
scan-build: 1 bug found.

В приведенном выше примере совершенно ясно, что все поля в var2 будут инициализированы словом copy.Таким образом, clang SA не должен жаловаться на не инициализированный доступ.

Я ценю любую помощь / понимание.

1 Ответ

0 голосов
/ 12 декабря 2018

С точки зрения подавления конкретного предупреждения, из документации :

Q: Как я могу подавить предупреждение конкретного анализатора?
В настоящее время не существует надежного механизма подавления предупреждений анализатора, хотя в настоящее время это изучается....

Но в следующем вопросе показано, что вы можете пометить блок кода, который будет пропущен во время статического анализа, окружив код блоком #ifdef:

В: Как выборочно исключить код, анализируемый анализатором?
Когда статический анализатор использует clang для анализа исходных файлов, он неявно определяет макрос препроцессора __clang_analyzer__.Этот макрос можно использовать для выборочного исключения кода, анализируемого анализатором....

Итак, вы можете сделать это так:

#ifdef __clang_analyzer__
    #define COPY_STRUCT(DEST, SRC) (DEST) = (SRC)
#else
    #define COPY_STRUCT(DEST, SRC) do { \
        const unsigned int *src = (const void *)&(SRC); \
        unsigned int *dest = (void *)&(DEST); \
        *dest = *src; \
    } while(0)
#endif

COPY_STRUCT(var2, var1);
...