2010-04-23 82 views
13

讓我們看看下面的程序:崩潰與CMD行參數的程序

#include <stdlib.h> 

int main(int argc, char **argv){ 
    int a,b; 

    if (argc != 3) 
     return -1; 

    a = atoi(argv[1]); 
    b = atoi(argv[2]); 

    a = b ? a/b : 0; 

    return a; 
} 

的任務是通過命令行參數提供給程序崩潰。

+1

@Stacker:不知道,好像是一些癡呆的面試問題。 – Quixotic 2010-04-23 19:51:39

+0

我想不可能... – Kasturi 2010-04-23 19:51:45

+2

如果我正確回答,我會得到一個cookie嗎?如果他們在面試中問你這個問題,希望他們不提供你這份工作。如果他們這樣做,跑。 – 2010-04-23 19:52:52

回答

18

通過a作爲平臺的INT_MINb爲-1。然後你會在任何二進制補碼機上發生溢出錯誤,儘管這不一定是崩潰。

+0

我很驚訝地看到這個問題在面試時並不意味着安全專家。但是,無可否認,我使用Java和Python,這不是什麼大問題。 – Uri 2010-04-23 20:01:34

5

這個問題的答案是:這取決於。

您需要知道的關鍵信息之一是atoi的實現方式以及是否符合標準。該標準對實現細節的描述很少,並且對輸入輸出行爲更具體。讓我們假設一分鐘,它確實符合標準並關注實施。

有幾種方法可以有效地使用,其中一種是遞歸的。讓我們假設它是作爲一個頭部遞歸算法來實現的,這個算法強制堆棧的建立。然後我可以通過提供一個足夠長的參數導致這個程序崩潰,它強制atoi足夠深以堆棧溢出並因此導致應用程序崩潰。

2

你可以通過排除法,逆向操作:

1)你可以結束了零一個部門?不見得。如果b爲0,則最後一個表達式爲0,如果它不爲0,則不會得到零除。

2)你可以提供不正確的參數數量和陣列訪問崩潰?不是因爲之前的argc檢查

3)如果您的參數不轉換爲數字,atoi 應該返回一個數字值。我認爲這是庫規範的一部分,因此不適用於實現變體,但我可能是錯的。

所以我不明白你會如何在這裏崩潰。

我喜歡這個問題的唯一方法是除零部分 - 它檢查你是否理解?:運算符,並且0是錯誤的。我不喜歡atoi部分,但沒有給你訪問參考手冊。我必須檢查文檔以確保。

潛在的下溢/溢出是太棘手恕我直言。如果你正在面試一位軟件安全工程師,這很好,但我不會問一個入門級的候選人,甚至只是爲了一個標準的編程工作。如果您來自其他語言(例如Python),則特別困難。

更新:我做了幾個參考的在線搜索,它似乎atoi應該返回0壞的輸入。例如,來自MSDN

每個函數返回由解釋輸入的字符 作爲數產生的int值 。如果 輸入無法轉換爲該類型的值 ,則對於atoi和_wtoi,返回 值爲0。

+1

回覆:3)沒有。將某些不能轉換爲int的東西傳遞給atoi不需要返回數字值。它調用未定義的行爲。如果你這樣做,一個實現可以免費崩潰你的程序,刻錄你的硬盤。 – nos 2010-04-23 20:01:18

+0

@nos:是這樣嗎?我查了維基百科和MSDN,它似乎是另有說明:「每個函數返回通過將輸入字符解釋爲一個數字而產生的int值。如果輸入無法轉換爲atoi和_wtoi的返回值爲0類型。」 – Uri 2010-04-23 20:06:23

+1

根據C標準,是的。 「[1]函數atof,atoi,atol和atoll不需要影響 錯誤上的整數表達式errno的值。如果結果的值不能表示,則 的行爲是未定義的。 – nos 2010-04-23 20:25:18

0

我看到的唯一可能的弱點是atoi()。也許如果它傳遞了足夠大的字符串,它會以某種方式在它內部發生錯誤。除此之外,除以0覆蓋參數計數。我能想到的唯一另外一件事就是通過將垃圾郵件發送到參數中來溢出操作系統緩衝區。不太可能。

0

我不知道大多數操作系統是如何傳遞argv數據的。它是否分配在堆棧上?它的長度本質上是有限的嗎?

你能傳遞一個非常長的命令行參數並創建堆棧溢出嗎?