7.1 【必须】防止整数溢出

    在计算时需要考虑整数溢出的可能,尤其在进行内存操作时,需要对分配、拷贝等大小进行合法校验,防止整数溢出导致的漏洞。

    错误(该例子在计算时产生整数溢出)

    正确例子

    1. int len = 1;
    2. char payload[10] = { 0 };
    3. char dst[10] = { 0 };
    4. int size = len - kMicLen;
    5. // 拷贝前对长度进行判断
    6. if (size > 0 && size < 10) {
    7. memcpy(dst, payload, size);
    8. printf("memcpy good\n");
    9. }
    10. }

    关联漏洞:

    高风险-内存破坏

    7.2 【必须】防止Off-By-One

    在进行计算或者操作时,如果使用的最大值或最小值不正确,使得该值比正确值多1或少1,可能导致安全风险。

    错误:

    1. char firstname[20];
    2. char fullname[40];
    3. fullname[0] = '\0';
    4. strncat(fullname, firstname, 20);
    5. // 第二次调用strncat()可能会追加另外20个字符。如果这20个字符没有终止空字符,则存在安全问题

    正确:

    对于 C++ 代码,再次强烈建议使用 stringvector 等组件代替原始指针和数组操作。

    关联漏洞:

    7.3 【必须】避免大小端错误

    在一些涉及大小端数据处理的场景,需要进行大小端判断,例如从大段设备取出的值,要以大段进行处理,避免端序错误使用。

    关联漏洞:

    中风险-逻辑漏洞

    7.4 【必须】检查除以零异常

    在进行除法运算时,需要判断被除数是否为零,以防导致程序不符合预期或者崩溃。

    错误:

    1. double divide(double x, double y) {
    2. return x / y;
    3. }
    4. int divide(int x, int y) {
    5. return x / y;
    6. }

    正确:

    1. double divide(double x, double y) {
    2. if (y == 0) {
    3. throw DivideByZero;
    4. }
    5. }

    关联漏洞:

    低风险-拒绝服务

    7.5 【必须】防止数字类型的错误强转

    错误例子

    正确例子

    1. void Foo() {
    2. int len = 1;
    3. int size = 9;
    4. if (len < size - 10) {
    5. printf("Bad\n");
    6. } else {
    7. printf("Good\n");
    8. }
    9. }

    关联漏洞:

    高风险-内存破坏

    中风险-逻辑漏洞

    7.6 【必须】比较数据大小时加上最小/最大值的校验

    在进行数据大小比较时,要合理地校验数据的区间范围,建议根据数字类型,对其进行最大和最小值的判断,以防止非预期错误。

    错误:

    1. void Foo(int index) {
    2. int a[30] = {0};
    3. // 此处index是int型,只考虑了index小于数组大小,但是并未判断是否大于0
    4. if (index < 30) {
    5. // 如果index为负数,则越界
    6. a[index] = 1;
    7. }

    正确:

    关联漏洞:

    高风险-内存破坏