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; 
} 

現在執行代碼分析,它會報告沒有警告。

相關問題