2012-10-05 113 views
37

我很難理解你爲什麼需要asprintf。 這裏手冊中它說爲什麼要使用Asprintf?

功能asprintf()和vasprintf()被sprintf的類似物(3)和 vsprintf中(3),不同之處在於它們分配一個字符串大到足以容納 輸出包括終止空字節,並通過第一個參數向它返回一個指針 。這個指針應該被傳遞給 免費(3),以便在不再需要時釋放分配的存儲空間。

因此,這裏是我想了解的例子:

asprintf(&buffer, "/bin/echo %s is cool", getenv("USER")); 

有什麼區別,如果緩衝區分配一個字符串足夠大VS說的char * =(字符串)

+5

'asprintf()'和'vasprintf()'是GNU擴展。添加了GNU標籤。 – alk

+3

嗯,我不知道提問者是否在這裏練習:http://exploit-exercises.com/nebula/level02? – jordanpg

+1

關於此主題的非常好的博客文章可以在這裏找到:[內存管理在C和自動](http://insanecoding.blogspot.de/2014/06/memory-management-in-c-和 - auto.html)...順便說一句。完整的博客是值得的 – antibus

回答

82

如果使用sprintf()或vsprintf(),則需要首先分配緩衝區,並且需要確保緩衝區足夠大以包含sprintf寫入的內容。否則,sprintf會高興地覆蓋超出緩衝區末端的內存。

char* x = malloc(5 * sizeof(char)); 
sprintf(x,"%s%s%s", "12", "34", "56"); // writes "123456" +null but overruns the buffer 

...寫入「6」和終止null超出分配給x的空間的端部,或者破壞某些其他變量,或引起段故障。

如果幸運的話,它會在分配的塊之間的內存上踐踏,並且不會造成傷害 - 這一次。這會導致間歇性的錯誤 - 最難診斷的錯誤。使用類似ElectricFence這樣的工具會很好,它會導致超限失效。

提供超長輸入的非惡意用戶可能會導致程序以意外的方式運行。惡意用戶可以利用這種方式將自己的可執行代碼加入系統。

對此的一個警告是使用snprintf(),它將字符串截斷爲您提供的最大長度。

char *x = malloc(5 * sizeof(char)); 
int size = snprintf(x, 5, "%s%s%s", "12", "34", "56"); // writes "1234" + null 

返回值size是長度本來書面如果空間是可利用的 - 不包括終止空

在這種情況下,如果size大於或等於5,那麼你知道,截斷髮生 - 如果你不想截斷,你可以分配一個新的字符串,然後再次嘗試snprintf()

char *x = malloc(BUF_LEN * sizeof(char)); 
int size = snprintf(x, 5, "%s%s%s", "12", "34", "56"); 
if(size >= BUF_LEN) { 
    realloc(&x,(size + 1) * sizeof(char)); 
    snprintf(x, 5, "%s%s%s", "12", "34", "56"); 
} 

(這是一個非常天真的算法,但它說明了這一點)

asprintf()做這一步爲您服務 - 計算字符串的長度,分配的內存量,並寫入字符串進去。

char *x; 
int size = asprintf(&x, "%s%s%s", "12", "34", "56"); 

在所有情況下,一旦你與x完成,你需要釋放它,或者你內存泄漏:

free(x); 

asprintf()一個隱含的malloc(),所以你必須檢查它的工作,就像使用malloc()或任何其他系統調用一樣。

if(size == -1) { 
    /* deal with error in some way */ 
} 

注意asprintf()是GNU和BSD擴展的一部分到libc - 你不能肯定它會在每一個C環境中使用。 sprintf()snprintf()是POSIX和C99標準的一部分。

+0

謝謝你的回答。清理了很多東西 –

+1

另外,[你不應該在C語言中輸入'malloc'(和family)的結果(http://www.stackoverflow.com/questions/605845/do-i-cast-the-結果-的-的malloc)。 –

+0

非常遲到我固定@ user694733的點。 – slim

18

的好處是安全。

許多程序允許系統漏洞發生時,程序員提供的緩衝區溢出時充滿用戶提供的數據。

擁有asprintf爲您分配緩衝保證不會發生。

但是,您必須檢查返回值asprintf以確保內存分配實際上成功。請參見http://blogs.23.nu/ilja/2006/10/antville-12995/

+0

我記得在這個模糊的閱讀。這是使用asprintf的唯一原因嗎? –

+2

@BrandonLing,在很多情況下,它會縮短你的代碼! – Alnitak

+4

@BrandonLing:它消除了代碼重複 - 當你想要一個永不截斷的'sprintf'時,你可以多次編寫自己的函數來完成這個任務,所以現在你已經把它全部包裝在一個單獨的,這是以便攜性爲代價的。 –