exponenta event banner

CERT C: DCL38-C правил

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

Описание

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

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

Внедрение Polyspace

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

Примеры

развернуть все

Проблема

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

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

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

Риск

При определении гибких элементов массива с использованием нулевого или нулевого размера реализация зависит от компилятора. Для компиляторов, не распознающих синтаксис, int массив размера один имеет буфер для одного int переменная. При попытке выполнить запись за пределы этого буфера могут возникнуть проблемы, связанные с доступом к массиву вне границ.

При использовании стандартного синтаксиса C для определения гибкого элемента массива реализация переносится во все компиляторы, соответствующие стандарту.

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

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

Пример - элемент гибкого массива, определенный с помощью первого размера
#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 Университет Карнеги-Меллон, со специальным разрешением от его Института программного обеспечения.

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

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