建议和规则

建议:

  • 理解数组的工作方式

  • 获取数组的长度时不要对指针应用sizeof操作符

  • 显示地指定数组的边界,即使它已经由初始化值列表隐式地指定

规则:

  • 保证数组索引位于合法的范围内

  • 在所有源文件中使用一致的数组记法

  • 保证变长数组的长度参数位于合法范围之内

  • 保证复制的目标具有足够的存储空间

  • 保证表达式中的数组类型是兼容的

  • 不允许循环迭代到数组尾部之后

  • 不要对两个并不指向同一个数组的指针进行相减或比较

  • 不要把一个指向非数组对象的指针加上或减去一个整数

  • 如果结果值并不引用合法的数组元素,不要把指针加上或减去一个整数

本文地址:http://www.cnblogs.com/archimedes/p/c-security-array.html,转载请注明源地址。

获取数组的长度时不要对指针应用sizeof操作符

代码:

void clear(int array[]) {
for(size_t i = ; i < sizeof(array) / sizeof(array[]); i++) {
array[i] = ;
}
}
void dowork(void) {
int dis[];
clear(dis);
/*...*/
}

clear()使用sizeof(array) / sizeof(array[0])这种用法确定这个数组的元素数量,但由于array是一个形参,因此它是指针类型,sizeof(array) = sizeof(int *) = 4  (32位OS)

当sizeof操作符应用于声明为数组或函数类型的形参时,它产生经过调整的(指针)类型的长度

解决方案:

void clear(int array[], size_t len) {
for(size_t i = ; i < len; i++) {
array[i] = ;
}
} void dowork(void) {
int dis[];
clear(dis, sizeof(dis) / sizeof(dis[]));
/*...*/
}

保证数组索引位于合法的范围内:

代码:

enum {TABLESIZE = };
int *table = NULL;
int insert_in_table(int pos, int value) {
if(!table) {
table = (int *)malloc(sizeof(int) *TABLESIZE);
}
if(pos >= TABLESIZE) {
return -;
}
table[pos] = value;
return ;
}

pos为int类型,可能为负数,导致在数组所引用的内存边界之外进行写入

解决方案:

enum {TABLESIZE = };
int *table = NULL;
int insert_in_table(size_t pos, int value) {
if(!table) {
table = (int *)malloc(sizeof(int) *TABLESIZE);
}
if(pos >= TABLESIZE) {
return -;
}
table[pos] = value;
return ;
}

在所有源文件中使用一致的数组记法

当在同一文件中时,void func(char *a);  和  void func(char a[]); 完全等价

但在函数原型之外,如果一个数组在一个文件中声明为指针,在另一个不同的文件中声明为数组,它们是不等价的

代码:

//main.c
#include<stdlib.h>
enum {ARRAYSIZE = };
char *a;
void insert_a(void);
int main(void) {
a = (char*)malloc(ARRAYSIZE);
if(a == NULL) {
//处理分配错误
}
insert_a();
return ;
}
//insert_a.c
char a[];
void insert_a(void) {
a[] = 'a';
}

解决方案:

//insert_a.h
enum {ARRAYSIZE = };
extern char *a;
void insert_a(void); //insert_a.c
#include "insert_a.h"
char *a;
void insert_a(void) {
a[] = 'a';
} //main.c
#include<stdlib.h>
#include"insert_a.h"
int main(void){
a = (char*)malloc(ARRAYSIZE);
if(a == NULL) {
//处理分配错误
}
insert_a();
return ;
}

保证变长数组的长度参数位于合法范围之内

代码:

void func(size_t s) {
int vla[s];
/*...*/
}
/*...*/
func(size);
/*...*/

解决方案:

enum {MAX_ARRAY = };
void func(size_t s) {
if(s < MAX_ARRAY && s != ) {
int vla[s];
/*...*/
} else {
//错误处理
}
}
/*...*/
func(size);
/*...*/

保证复制的目标具有足够的存储空间

代码:

enum {WORKSPACE_SIZE = };
void func(const int src[], size_t len) {
int dest[WORKSPACE_SIZE];
if(len > WORKSPACE_SIZE) {
//错误处理
}
memcpy(dest, src, sizeof(int) * len);
/*...*/
}

保证表达式中的数组类型是兼容的

代码:

enum {a = , b = , c = };
int arr1[c][b];
int (*arr2)[a];
arr2 = arr1; //不匹配 a != b

解决方案:

enum {a = , b = , c = };
int arr1[c][b];
int (*arr2)[a];
arr2 = arr1; //匹配 a == b

不要把一个指向非数组对象的指针加上或减去一个整数

代码:

struct numbers {
short num1;
short num2;
/*...*/
short num9;
};
int sum_numbers(const struct numbers *numb) {
int total = ;
const int *numb_ptr;
for(numb_ptr = &numb->num1; numb_ptr <= &numb->num9; numb_ptr++) {
total += *(numb_ptr);
}
return total;
}
int main(void) {
struct numbers my_numbers = {,,,,,,,,};
sum_numbers(&my_numbers);
return ;
}

上面的代码试图用指针运算访问结构的元素,这是危险的,因为结构中的字段并不保证在内存中是连续的

解决方案(使用数组):

struct numbers {
short num1;
short num2;
/*...*/
short num9;
};
int sum_numbers(const short *numb, size_t dim) {
int total = ;
const int *numb_ptr;
for(numb_ptr = numb; numb_ptr < numb + dim; numb_ptr++) {
total += *(numb_ptr);
}
return total;
}
int main(void) {
short my_numbers[] = {,,,,,,,,};
sum_numbers(my_numbers, sizeof(my_numbers) / sizeof(my_numbers[]));
return ;
}

参考资料

《C安全编码标准》

C安全编码--数组的更多相关文章

  1. php从接口获取数据转成可以用的数组或其他(含转换编码)

    程序开发,时常会用到将接口的json数据转换成程序可以用的,因为今天看到一个比较好的程序,贴上来,以备随时查看: /** * 将对象转成数组,并按要求转换编码 * * @param array $ar ...

  2. YTU 3027: 哈夫曼编码

    原文链接:https://www.dreamwings.cn/ytu3027/2899.html 3027: 哈夫曼编码 时间限制: 1 Sec  内存限制: 128 MB 提交: 2  解决: 2 ...

  3. 将汉字转化为拼音,正则表达式和得到汉字的Unicode编码

    一:上图,不清楚的看代码注解,很详细了 二:具体代码 窗体代码 using System; using System.Collections.Generic; using System.Compone ...

  4. IO流(随机流,数组内存流

    File file1=new File("test1.txt"); RandomAccessFile in2=new RandomAccessFile(file1,"rw ...

  5. Base64编码的java实现

    Java本身是提供了Base64编码的工具包的,做项目的时候自己实现了个,在这里记录一下: /** Base64编码数组 */ private static final String base64En ...

  6. Asterisk1.8 sip编码协商分析

    在开始分析之前,先对编码协商中可能涉及的asterisk数据结构和变量作些说明.ast_channel:定义一个通用的通道数据结构 struct ast_channel { const struct ...

  7. PHP保存数组到数据库

    数组是 PHP 开发中使用最多的数据类型之一,对于结构化的数据尤为重要. 很多时候我们需要把数组保存到数据库中,实现对结构化数据的直接存储和读取. 其中一个案例就是,对于 Form 提交的多选 che ...

  8. 图论:Prufer编码

    BZOJ1211:使用prufer编码解决限定结点度数的树的计数问题 首先学习一下prufer编码是干什么用的 prufer编码可以与无根树形成一一对应的关系 一种无根树就对应了一种prufer编码 ...

  9. c# 自定义Base16编码解码

               一.自定义Base16编码原理                  Base16编码跟Base64编码原理上有点不同,当然前面转换是一样的,都是是将输入的字符串根据默认编码转换成一 ...

随机推荐

  1. 【cs229-Lecture15】奇异值分解

    PCA的实现一般有两种,一种是用特征值分解去实现的,一种是用奇异值分解去实现的. 内容: PCA  (主成份分析)是一种直接的降维方法,通过求解特征值与特征向量,并选取特征值较大的一些特征向量来达到降 ...

  2. dSYM atos crash log 定位到代码行的方法(转)

    做iOS开发的时候,常常会遇到crash,需要分析call stack的时候.有时候App在别人的设备崩溃,把crash report在自己的机器上打开,Xcode没有自动的进行符号化.这时候就需要自 ...

  3. Unity 模型导入导出

    从3DMAX导出,参考: http://tieba.baidu.com/p/2807225555 -> 使用3dmax 2013,会自带导出 fbx 的功能 -> 从 3dmax 导出 - ...

  4. 《微信小程序七日谈》- 第三天:玩转Page组件的生命周期

    <微信小程序七日谈>系列文章: 第一天:人生若只如初见: 第二天:你可能要抛弃原来的响应式开发思维: 第三天:玩转Page组件的生命周期: 第四天:页面路径最多五层?导航可以这么玩 前两篇 ...

  5. jquery操作常用HTML控件

    设置checkbox选中: $("[id='checkbox_id3']").attr("checked", true); 设置class下所有input不可用 ...

  6. Microsoft OneScript 团队发布的最新一版在 SQL Server Management Studio 中运行的脚本,可以帮助我们获取更详细的版本信息。

    该脚本有以下几点: 1. SQL Server 的主要版本.服务级别和版本类别 2. 已安装SP包.累计更新CU,历史更新的QFE\ GDR 3. 推荐当前SP包可以安装最新的CU,并给到相关资源地地 ...

  7. SQL Server里等待统计(Wait Statistics)介绍

    在今天的文章里我想详细谈下SQL Server里的统计等待(Wait Statistics),还有她们如何帮助你立即为什么你的SQL Server当前很慢.一提到性能调优,对我来说统计等待是SQL S ...

  8. 希望早几年知道的5个Unix命令

    原文: http://spin.atomicobject.com/2013/09/09/5-unix-commands/ 希望早几年知道的5个Unix命令 使用*nix系统已经有一段时间了.但是还是有 ...

  9. 一篇通俗易懂的讲解OpenGL ES的文章

    电脑或者手机上做图像处理有很多方式,但是目前为止最高效的方法是有效地使用图形处理单元,或者叫 GPU.你的手机包含两个不同的处理单元,CPU 和 GPU.CPU 是个多面手,并且不得不处理所有的事情, ...

  10. 点餐系统mealsystem.sql

    /* Navicat MySQL Data Transfer Source Server : localhost Source Server Version : 50162 Source Host : ...