我正在尝试使用Visual Studio 2012的代码分析功能。我只是在现有项目上运行它们,并在包含的部分上发现了一些缓冲区溢出警告(C6385 / C6386)我自己实现的Knuth的减法PRNG(又名RAN3)。但是,我无法理解为什么会发生这种情况,因为它看起来很好(我看不到越界读/写)。所以我做了一个等同于(下面)的那个部分,但仍然得到了相同的警告,但无法弄清楚它们的原因。
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警告。这段代码有什么问题?我错过了什么吗?
答案 0 :(得分: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
是无符号整数,所以会溢出>>> 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]
。如果你使用整数而不是无符号整数,VS还会抱怨吗?
(使用Python,您的索引映射似乎很好:
{{1}}
不应该有任何越界错误,特别是因为你不会使用无符号整数“达到”-1。)
答案 1 :(得分:0)
打印ii的值,看看它是否超过54 由这条线计算 unsigned int ii =((21U * i)%55U) - 1U;
答案 2 :(得分:-1)
首先请理解静态分析的目的,它将执行代码库的分析以仔细检查并确保代码符合他们的行业标准。这是软件质量控制的第一步,并始终协助进行动态分析,以找出静态分析无法找到的细微问题和漏洞。模糊测试用于通过动态分析确保软件安全性和质量。
静态代码分析也可能导致代码审计员应该忽略的误报。您在此处报告的案例是误报。
#pragma warning(suppress:6385)
现在让我们深入了解你的场景,静态分析发现你的指令((21U * i)%55U)最终可以评估为零,这可能导致ii = -1;这可能会进一步导致软件崩溃甚至安全漏洞(缓冲区溢出攻击)。静态分析不会执行所有循环迭代(与动态分析不同)来断言每个代码分支都运行良好。
现在让我们谈谈您的代码,我会为您提供一些建议和改进。请介绍一些常量或#define来保存数组的大小。
#define _SIZE 55U
现在不使用硬编码数字&#39; 55&#39;和&#39; 54&#39;在代码中开始使用_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;
}
现在执行代码分析,它不会报告任何警告。