2012-06-20 19 views
2
#include <stdio.h> 
    void wrapperPrint(char* s) 
    { 
     printf(s); 
     return; 
    } 

    int main() 
    { 

      wrapperPrint("Hello world\n"); 
      wrapperPrint("This is a string"); 

     return 0; 
    } 

如果正確的程序打印字符串(確實如此,在GCC 4.6.3測試),爲什麼我們需要的格式說明如%d,%S等,或其他潛在問題單詞,這個程序有什麼潛在的問題。與不使用格式說明與printf的

+2

試試這個:'wrapperPrint( 「%s%s%S%s%S%S%s%S」);'。你可以使程序崩潰。你可以讀取進程的內存佔用...' –

+0

哇。這是如何讀取內存佔用? +1,BTW。 – Anon

+1

@Anon:'printf'不知道有多少個參數實際傳遞給它(也不是參數的類型),所以它會爲*格式字符串*中的每個'%s'調用'va_arg'並檢索來自堆棧的值。它將每個值作爲char *'並嘗試打印每個值。上面的代碼易受格式字符串攻擊的影響。 – AusCBloke

回答

6

原來,沒有任何問題。但是,如果您傳入包含百分號的字符串,可能會導致問題,因爲printf會嘗試將其作爲轉換說明符的開頭,但1)轉換說明符的其餘部分可能不會2)當您調用printf時,您將不會傳遞匹配的參數,因此如果您確實傳遞了適當的轉換說明符,它將嘗試使用不存在的參數(給出未定義的行爲)。

1

有任何機制在printf使用格式說明的。相反,這是因爲您希望根據您使用的某種格式打印字符串printf。您可以使用其他方法(puts)輸出純字符串。

對於上面的程序,如果有格式說明字符串中,該程序將打印出的垃圾,因爲你仍然會調用下面printf

4

爲什麼我們需要像%d,%s等格式說明符?

printf格式安全。 t不明白類型本身,你必須明確告訴printf你的數據參數的格式(類型)。它告訴print你想如何將參數解釋爲:如果你不這樣做,它只是對待它是一個字符串(,如您的示例代碼)。

需要注意的是,如果有一個不匹配的格式說明和實際的數據類型,那麼你得到的是未定義行爲

2

您應該使用看跌期權(),或做的printf( 「%S」,S);

如果格式字符串恰好包含%S或任何其他格式,然後將printf的嘗試讀取你沒有通過,試圖訪問的內存隨機件參數,並且沒有定義的結果。

嘗試使用傳遞%s的運行程序,看看會發生什麼。然後嘗試在valgrind下再次運行它,以便真正看到正在發生的可怕事情。