2009-01-24 58 views
5

我已經編寫了一個API,要求上下文被初始化,然後傳遞給每個API調用。調用者爲上下文分配內存,然後使用其他參數將其傳遞給init函數,這些參數描述了他們希望以後的API調用的行爲方式。背景是不透明的,所以客戶不可能真的在那裏四處遊蕩;它僅用於API函數的內部使用。驗證內存已初始化在C

我遇到的問題是調用者正在分配上下文,但沒有初始化它。因此,隨後的API函數指向無意義的垃圾,就像它是一個真實的上下文一樣。

我正在尋找一種方法來驗證傳入API函數的上下文實際上已經初始化。我不確定這是否可能。我想到的兩個想法是:

  1. 使用預定義的常量並將其存儲在上下文的「魔術」字段中,以在API調用時進行驗證。
  2. 使用上下文內容的校驗和,將其存儲在「magic」字段中並在調用時驗證它。

不幸的是我知道的這些選項的任何一個可能會導致假陽性的驗證,要麼是因爲在內存中隨機廢話相匹配的「魔術」號,或者因爲上下文恰好佔據相同的空間作爲先前初始化上下文。我認爲後一種情況更可能。

這是否簡單歸結爲概率問題?我可以在大多數情況下避免誤報,但不是全部?是否值得使用一個僅僅給我一個合理的準確概率的系統,或者這會讓調試其他問題變得更加困難?

回答

3

你的上下文變量可能是目前某種指向分配內存的指針。取而代之,將其設置爲可以明確驗證的令牌或句柄。每次上下文初始化時,都會返回一個新的令牌(不是實際的上下文對象),並將該令牌存儲在內部列表中。然後,當客戶稍後給你一個上下文時,通過查看列表來檢查它是否有效。如果是,則可以將令牌轉換爲實際上下文並使用,否則會返回錯誤。

typedef Context long; 

typedef std::map<Context, InternalContext> Contexts; 
Contexts _contexts; 

Context nextContext() 
{ 
    static Context next=0; 
    return next++; 
} 

Context initialise() 
{ 
    Context c=nextContext(); 
    _contexts.insert(make_pair(c, new InternalContext)); 
    return c; 
} 

void doSomethingWithContext(Context c) 
{ 
    Contexts::iterator it=_ _contexts.find(c); 
    if (it==_contexts.end()) 
    throw "invalid context"; 
    // otherwise do stuff with the valid context variable 
    InternalContext *internalContext=*it.second; 
} 

使用此方法,不存在無效內存訪問的風險,因爲您只能正確使用有效的上下文引用。

0

爲避開前一個上下文重複使用的內存位置問題,除了釋放上下文之外,您還可以重置該上下文並刪除「魔術」數字,假設用戶使用您的上下文釋放上下文API。這樣,當系統爲下一個上下文請求返回相同的內存塊時,幻數檢查將失敗。

6

我認爲最好的解決方案是將create()/ delete()函數添加到您的API中,並使用create來分配和初始化結構。您可以在結構的開始處添加一個簽名,以驗證您傳遞的指針指向分配有create()的內存,並在釋放內存之前使用delete()覆蓋簽名(或整個緩衝區)。

你不能真正避免在C中的誤報,因爲調用malloc'd「發生」的內存開始你的簽名;但是讓你的簽名合理長(比如說8字節)並且賠率很低。不過,通過提供create()函數從調用者手中分配配置將會有很長的路要走。

而且,是的,你最大的風險是初始化的緩衝區沒有使用delete()而是free'd,並且隨後的malloc恰好重新使用該內存塊。

1

您可以定義一個新的API調用,它接受未初始化的內存並以您需要的任何方式初始化它。然後,客戶端API的一部分是客戶端必須調用上下文初始化函數,否則會導致未定義的行爲。

0

看看你的系統用未初始化的內存來做什麼。 m $的確如此:Uninitialized memory blocks in VC++

+0

這隻適用於調試版本 - 您不能依靠此版本代碼 – 2009-01-24 08:33:22

3

請看Matt Bishop在Robust Programming的論文。使用門票或令牌(在某些方面類似於文件句柄,但也包括一次使用的隨機數)允許庫代碼確保它使用的令牌有效。實際上,您代表用戶分配數據結構,並將必須爲每個您定義的API的調用提供的票證返回給用戶。

我有一些基於該系統的代碼。標題包括評論:

/* 
** Based on the tickets in qlib.c by Matt Bishop ([email protected]) in 
** Robust Programming. Google terms: Bishop Robust Nonce. 
** http://nob.cs.ucdavis.edu/~bishop/secprog/robust.pdf 
** http://nob.cs.ucdavis.edu/classes/ecs153-1998-04/robust.html 
*/ 

我還構建了一個基於舞臺的內存分配系統,使用門票來識別不同的舞臺。