簡體   English   中英

可能的緩沖區溢出問題

[英]Possible buffer overflow issue

我有以下用C ++編寫的代碼,用於提取Piece Table數據結構中給定范圍的文本。 這是PieceTable類的功能,該功能將給定范圍的文本存儲在字符數組buffer

void PieceTable::getTextInRange(unsigned __int64 startPos, unsigned __int64 endPos, char buffer[]){

    char* totalBuffer = new char[getSize() + 2];

    getBuffer(totalBuffer);

    if(endPos >= getSize())
        endPos = getSize() - 1; 

    cout<<"startPos : "<<startPos<<endl;
    cout<<"endPos : "<<endPos<<endl;

    memcpy(buffer, &totalBuffer[startPos], endPos - startPos + 1);

    buffer[endPos - startPos + 2] = '\0';

    if(totalBuffer != 0)
        delete[] totalBuffer;
    totalBuffer = 0;
}

這是我用來測試此代碼的主要方法中的一段代碼:

temp2 = new char[end - start + 2];  //changing 2 to 3 solves the problem
pieceTable.getTextInRange(Start, end, temp2);
for(int i = 0; i< end - start + 1; i++)
   cout<<temp2[i];
cout<<endl;

if( temp2 != 0)
{
  delete[] temp2;   //this line causes the heap corruption error
  temp2 = 0;
}

temp2聲明: char* temp2;

每當程序遇到delete[] temp2語句時,就會出現堆損壞錯誤。 如果我為temp2分配內存,則不會發生此問題:
temp2 = new char[end - start + 3]因此,基本上改變長度可以解決問題。 我知道我正在弄亂某個地方的長度,但我不知道在哪里。

編輯:getSize():

__int64 PieceTable::getSize()
{
    return dList.getLength(dList.getBack());
}

我正在使用一個表數據結構。 就在本文內部:http://www.cs.unm.edu/~crowley/papers/sds.pdf

我可能是錯的,但我認為getSize()不會有任何問題,因為我用來檢索整個緩沖區getBuffer的長度的函數按代碼所示工作。

PieceTable::getTextInRange ,您具有以下這一行:

buffer[endPos - startPos + 2] = '\0';

當您分配傳入的內容作為buffer您將像這樣進行分配:

temp2 = new char[end - start + 2];

讓我們輸入一些實數...

buffer[5 - 2 + 2] = '\0';

temp2 = new char[5 - 2 + 2];

等效於:

buffer[5] = '\0';

temp2 = new char[5];

好吧,那是你的問題。 如果您使用new char [5]則會得到一個數組,該數組的有效索引為0到4。5對該數組無效。

可能我建議您制定一條規則,即僅在大多數情況下才中斷,而總是像STL一樣在[begin,end)范圍內指定范圍。 這意味着您指定了最后一個所需的結束索引之后的一個。 這使范圍計算數學更容易出錯。 此外,接口與STL工作方式的一致性也使使用起來更容易。 例如,計算范圍的大小總是end - begin從此方案end - begin

EW Dijkstra發表了一篇古老的論文(大約在1982年),這給出了一些很好的理由,為什么這種表示范圍的方案是最好的方案

將代碼中的2更改為3的原因:

temp2 = new char[end - start + 2];

起作用的原因是,否則,您將在getTextInRange中的緩沖區末尾寫(您離開了一個)。


endstart上述對應的參數endPosstartPosgetTextInRange ,並在getTextInRange您有:

buffer[endPos - startPos + 2] = '\0';


您的數組范圍是[0, endPos - startPos + 2) ; 因此,位置endPos - startPos + 2處的元素比數組的末尾endPos - startPos + 2 1。 覆蓋此值將導致堆損壞。

從代碼中可以清楚地看出,您在getTextInRange使用的最后一個索引是:

endPos-startPos+2 //last index

這幾乎解釋了為什么您需要為此分配最小的內存:

endPos-startPos+3 //number of objects : memory allocation

也就是說,如果為N對象分配內存,則可以使用索引N-1 (也是該數組的最大索引)訪問數組中的最后一個對象。 索引N超出范圍。 回想一下,索引以0 ,因此它必須以N-1結尾,而不是N

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM