exponenta event banner

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

Гибкий элемент массива, определенный с нулевым размером или единицей

Описание

Этот дефект возникает, когда для определения структуры с гибким элементом массива не используется стандартный синтаксис 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);
}

Информация о результатах

Группа «Надлежащая практика»
Язык: C (проверка отключена, если анализ выполняется по коду C90 указанному опцией-c-version c90)
По умолчанию: Откл.
Синтаксис командной строки: FLEXIBLE_ARRAY_MEMBER_INCORRECT_SIZE
Воздействие: Низкий
Представлен в R2018b