ABV.ANY_SIZE_ARRAY

缓冲区溢出 — 超出边界的未指定大小的数组索引

ABV.GENERAL 一样,ABV.ANY_SIZE_ARRAY 检查器是一种通用检查器,用于查找数组边界违规情况,即对超出该数组边界的数组元素的任何访问。ABV.ANY_SIZE_ARRAY 可在代码引用未指定大小(通常将在运行时确定)的数组时检查缺陷。

下列示例显示了定义数组时使用的不同 C 标准技术。稍后在代码中分配内存时将确定数组大小,并使用 C99 样式。这便是导致 Klocwork 生成 ABV.ANY_SIZE_ARRAY 标记的情况。

复制
  struct OldStyle{
  /* other fields */
  unsigned char array[1];
  };
  struct GccStyle{
  /* other fields */
  unsigned char array[0];
  };

 struct C99Style{
 /* other fields */
 unsigned char array[];
 };

在数组未指定大小的情况下,ABV.ANY_SIZE_ARRAY 通常用于在使用 C99 技术时从检查器结果中筛选缺陷。如果不想标记此缺陷,或者想从其他 ABV 缺陷中筛选出该缺陷,可以关闭此检查器。

漏洞与风险

缓冲区溢出的后果包括有效数据被覆盖以及执行任意和潜在恶意代码。但是,在使用任何大小的数组和密切关注它们时,关闭 ABV.ANY_SIZE_ARRAY 检查器通常是最好的选择。

代码示例 1

复制
  typedef struct NumericData {
      int           varlen;
      char          n_data[1];
  } NumericData;

  #define MAX_LEN 2048
  void init(char *data) {
      if (strlen(data) > MAX_LEN) return;
      NumericData *X = (NumericData*)malloc(sizeof(NumericData) + strlen(data));
      X->varlen = strlen(data);
      int k;
      for (k = 0; k < strlen(data); k++) {X->n_data[k] = data[k];}
      X->n_data[k-1] = '\0';
  }

Klocwork 针对第 13 行生成了缓冲区溢出报告,指出可变长度数组 n_data 的索引可能超出边界:未指定大小的数组 n_data 可以使用索引值 -1。但是,编码技术的使用其实是正确的,因此,设计人员通常可能不希望报告该缺陷,并会禁用 ABV.ANY_SIZE_ARRAY 检查器。

代码示例 2

复制
  #define MAXL 255
  typedef struct info_t_{
    unsigned char code;
    unsigned char length[2];
    unsigned char value[1];
  } info_t;

  int getshort(unsigned char *l);

 void foo(info_t *id){
   unsigned char buf[MAXL];
   int len = getshort(id->length);
   if ((len > 0) && (len <= MAXL)) {
      memcpy(buf, &id->value[0], len);
   }
 }

这是尽管使用方法正确但仍报告缺陷的另一个例子。Klocwork 针对第 14 行生成了缓冲区溢出报告,指出可变长度数组 id->value 的索引可能超出边界:未指定大小的数组 &id->value[0] 可以使用索引值 0..254。

安全培训

应用程序安全培训材料由 Secure Code Warrior 提供。

扩展

此检查器可通过 Klocwork 知识库进行扩展。有关详情,请参阅调整 C/C++ 分析。