2

我在尝试使用Visual Studio 2012的代码分析功能。我只是将它们运行在我现有的项目上,并在包含我自己实现的Knuth的减法PRNG(aka)的部分发现了一些缓冲区溢出警告(C6385/C6386) RAN3)。但是,我不明白为什么会发生这种情况,因为它看起来很好(我可以看到没有任何超出限制的读/写)。所以我做了一个相当短的部分(下面),但仍然得到了相同的警告,无法找出它们的原因。为什么此代码在Visual Studio 2012的代码分析中发出缓冲区溢出警告(C6385/C6386)?

int main() { 
    unsigned int k = 1U, seed = 12345U, randomNumbers[55]; 

    randomNumbers[54] = seed; 
    for(unsigned int i = 1U; i <= 54U; ++i) { 
    unsigned int ii = ((21U * i) % 55U) - 1U; 
    randomNumbers[ii] = k; 
    k = seed - k; 
    seed = randomNumbers[ii]; 
    } 

    return 0; 
} 

有了上面的代码,我上线7 C6386警告和在线9.什么不对的代码C6385?我错过了什么吗?

回答

1

g ++ 4.8和clang ++ 3.3编译没有警告或错误(使用-Wall -Werror)。事实上,我们可以使用C++ 11的std::array及其at方法来获取边界检查,并

#include <array> 

int main() { 
    unsigned int k = 1U, seed = 12345U; 
    std::array<int,55> randomNumbers; 

    randomNumbers.at(54) = seed; 

    for(unsigned int i = 1U; i <= 54U; ++i) { 
    unsigned int ii = ((21U * i) % 55U) - 1U; 
    randomNumbers.at(ii) = k; 
    k = seed - k; 
    seed = randomNumbers.at(ii); 
    } 

    return 0; 
} 

产生不出来的越界访问,当你声称。我认为你的代码很好。 VS担心((21U * i) % 55U) - 1U)行可能导致0 - 1,这会溢出,因为ii是一个unsigned int。如果你使用ints而不是unsigned int,VS仍然会抱怨吗?

(使用Python,你的索引映射似乎罚款:

>>> sorted([21*n % 55 - 1 for n in range(1,55)]) 
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53] 

不应该有任何出界外的错误,特别是因为你不会“达到”用-1无符号整数)。

+0

我尝试用'int's替换'unsigned int's:http://ideone.com/URAjjw但是发出相同的警告。嗯,他们是误报吗? –

0

打印ii的值,看看它是否超出54 由此线计算 unsigned int ii =((21U * i)%55U) - 1U;

+0

我试过了,但我没有看到任何错误... http://ideone.com/IPWgi3 –

+0

当((21U * i)%55U)= 0时,ii将为-1 =溢出 –

+2

@ AnandRathi是我最初想到的,但循环从'1'开始。 – juanchopanza

0

首先请了解静态分析的目的,它会执行代码库的分析来仔细检查并确保代码符合他们的行业标准。这是软件质量控制的第一步,并始终协助进行动态分析,以发现静态分析无法发现的细微问题和漏洞。模糊用于通过动态分析确保软件安全性和质量。

静态代码分析也会导致代码审核员应该忽略的误报。这里报告的情况是虚惊一场。

#pragma warning(suppress:6385) 

现在,让我们深入到你的情况下,静态分析后发现您的指令((21U * I)%55U)可能最终评估为零,可能导致II = -1;这可能会进一步导致软件潜在的崩溃甚至安全漏洞(缓冲区溢出攻击)。静态分析不会执行所有的循环迭代(与动态分析不同),以断言每个代码分支都执行得很好。

现在让我们谈谈你的代码,我为你提供了一些建议和改进。请介绍一些常数或#define来保存数组的大小。

#define _SIZE 55U 

现在,而不是使用硬编码数字'55'和'54'开始在您的代码中使用_SIZE。您可以引入实用程序函数以获得数组的安全范围。

int SafeBoundsInt32(int min, int max, int value) 
{ 
    if (value < 0) 
     return 0; 
    if (value >= max) 
     return max - 1; 
    //Valid value 
    return value; 
} 

我将根据介绍的功能更改您的代码。

int main() 
{ 
    unsigned int k = 1U, seed = 12345U, randomNumbers[_SIZE]; 

    randomNumbers[_SIZE - 1] = seed; 
    for (unsigned int i = 1U; i <= _SIZE - 1; ++i) 
    { 
     unsigned int ii = ((21U * i) % _SIZE) - 1U; 
     randomNumbers[SafeBoundsInt32(0, _SIZE, ii)] = k; 
     k = seed - k; 
     seed = randomNumbers[SafeBoundsInt32(0, _SIZE, ii)]; 
    } 

    return 0; 
} 

现在执行代码分析,它会报告没有警告。

相关问题