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

Участник массива с переменными границами задал с нулевым размером или один

Описание

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

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

struct record {
    size_t len;
    double desc[]; 
};
До C99 вы можете использовать специфичные для компилятора методы, чтобы задать массивы с переменными границами. Например, вы использовали массивы единицы или нули размера:
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);
}

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

Группа: хорошая практика
Language:C (средство проверки, отключенное, если анализ работает на коде C90, обозначенном опцией -c-version c90),
Значение по умолчанию: 'off'
Синтаксис командной строки: FLEXIBLE_ARRAY_MEMBER_INCORRECT_SIZE
Влияние: низко

Введенный в R2018b