CERT C: Rule DCL38-C

Используйте правильный синтаксис при объявлении гибкого представителя массива

Описание

Определение правила

Используйте правильный синтаксис при объявлении гибкого представителя массива.[1]

Реализация Polyspace

Эта проверка проверяет Неправильный синтаксис гибкого размера представителя массива.

Примеры

расширить все

Проблема

Неправильный синтаксис гибкого размера представителя массива возникает, когда вы не используете стандартный синтаксис C для определения структуры с гибким представителем массива.

Начиная с C99, можно задать представителя гибкого массива с неопределенным размером. Для образца, desc является гибким представителем массива в этом примере:

struct record {
    size_t len;
    double desc[]; 
};
До C99 вы могли использовать специфические для компилятора методы для определения гибких массивов. Например, вы использовали массивы первого или нулевого размера:
struct record {
    size_t len;
    double desc[0]; 
};
Это использование не соответствует стандартам C, следующим C99.

Риск

Если вы задаете гибкие представители массива при помощи размера zero или one, ваша реализация зависит от компилятора. Для компиляторов, которые не распознают синтаксис, int массив размера 1 имеет буфер для одного int переменная. Если вы пытаетесь записать за пределы этого буфера, можно столкнуться с проблемами, связанными с доступом к массиву вне границ.

Если вы используете стандартный синтаксис C, чтобы задать гибкий представитель массива, ваша реализация является портативной для всех компиляторов, соответствующих стандарту.

Зафиксировать

Чтобы реализовать гибкий представитель массива в структуре, задайте массив неопределенного размера. Структура должна иметь один представитель, кроме массива, и массив должен быть последним представителем структуры.

Пример - Гибкие Представители массива, заданные с Size One
#include <stdlib.h>
  
struct flexArrayStruct {
  int num;
  int data[1];
};

unsigned int max_size = 100;
 
void func(unsigned int array_size) {
  if(array_size<= 0 || array_size > max_size)  
      exit(1);
  /* Space is allocated for the struct */
  struct flexArrayStruct *structP
    = (struct flexArrayStruct *)
     malloc(sizeof(struct flexArrayStruct)
          + sizeof(int) * (array_size - 1));
  if (structP == NULL) {
    /* Handle malloc failure */
    exit(2);
  }
   
  structP->num = array_size;
 
  /*
   * Access data[] as if it had been allocated
   * as data[array_size].
   */
  for (unsigned int i = 0; i < array_size; ++i) {
    structP->data[i] = 1;
  }
  
  free(structP);
}

В этом примере гибкий массив представителя data определяется значением размера единицы. Компиляторы, которые не распознают этот синтаксис, обрабатывают data как массив размера один. Оператор structP->data[i] = 1; можно записать в data за пределами первого представителя массива и вызвать проблемы с выходом из массива.

Коррекция - используйте синтаксис стандартного C для определения гибкого массива

Задайте гибкие представителей массива с неопределенным размером.

#include <stdlib.h>
  
struct flexArrayStruct{
  int num;
  int data[];
};

unsigned int max_size = 100;
 
void func(unsigned int array_size) {
  if(array_size<=0 || array_size > max_size)  
      exit(1);
  
  /* Allocate space for structure */
  struct flexArrayStruct *structP
    = (struct flexArrayStruct *)
    malloc(sizeof(struct flexArrayStruct)
         + sizeof(int) * array_size);
         
  if (structP == NULL) {
    /* Handle malloc failure */
    exit(2);
  }
 
  structP->num = array_size;
 
  /*
   * Access data[] as if it had been allocated
   * as data[array_size].
   */
  for (unsigned int i = 0; i < array_size; ++i) {
    structP->data[i] = 1;
  }
  
  free(structP);
}

Проверяйте информацию

Группа: Правило 02. Объявления и инициализация (DCL)
Введенный в R2019a

[1] Это программное обеспечение было создано MathWorks, включающее фрагменты: «Сайт SEI CERT-C», © 2017 Университет Карнеги Меллон, Веб-сайт SEI CERT-C + + © 2017 Университет Карнеги Меллон, "Стандарт кодирования SEI CERT C - Правила разработки безопасных, Надежные и безопасные системы - 2016 Edition ", © 2016 Университет Карнеги Меллон, и "Стандарт кодирования SEI CERT C++ - Правила разработки безопасных, Надежные и безопасные системы в C++ - 2016 Edition "© 2016 Университет Карнеги Меллон, с специального разрешения от его Института программной инженерии.

ЛЮБОЙ МАТЕРИАЛ УНИВЕРСИТЕТА КАРНЕГИ МЕЛЛОН И/ИЛИ ЕГО ИНЖЕНЕРНОГО ИНСТИТУТА ПРОГРАММНОГО ОБЕСПЕЧЕНИЯ, СОДЕРЖАЩИЙСЯ В НАСТОЯЩЕМ ДОКУМЕНТЕ, ПОСТАВЛЯЕТСЯ НА БАЗИСЕ «КАК ЕСТЬ». УНИВЕРСИТЕТ КАРНЕГИ МЕЛЛОН НЕ ДАЕТ НИКАКИХ ГАРАНТИЙ, ВЫРАЖЕННЫХ ИЛИ ПОДРАЗУМЕВАЕМЫХ, В ОТНОШЕНИИ ЛЮБОГО ВОПРОСА, ВКЛЮЧАЯ, НО НЕ ОГРАНИЧИВАЯСЬ, ГАРАНТИЮ ПРИГОДНОСТИ ДЛЯ ЦЕЛЕЙ ИЛИ КОММЕРЧЕСКОЙ ВЫГОДЫ, ИСКЛЮЧИТЕЛЬНОСТИ, ИЛИ УНИВЕРСИТЕТ КАРНЕГИ МЕЛЛОН НЕ ДАЕТ НИКАКИХ ГАРАНТИЙ В ОТНОШЕНИИ СВОБОДЫ ОТ ПАТЕНТА, ТОВАРНОГО ЗНАКА ИЛИ НАРУШЕНИЯ АВТОРСКИХ ПРАВ.

Это программное обеспечение и связанная с ним документация не были рассмотрены и не одобрены Университетом Карнеги-Меллон или его Институтом программной инженерии.