[英]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
中的緩沖區末尾寫(您離開了一個)。
你end
和start
上述對應的參數endPos
和startPos
在getTextInRange
,並在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.