2016-09-28 75 views
2

我注意到XCode 8中AddressSanitizer有趣的行爲。在一種情況下,它導致捕獲斷點:AddressSanitizer:地址上的堆緩衝區溢出,但我真的不明白爲什麼:NSData轉換堆緩衝區溢出

char * buffer = malloc(length); 
    memset(buffer, 0, length); 
    [output getBytes:buffer 
       length:length]; 
    stringOutput = [NSString stringWithUTF8String:buffer]; // here is crash 

相同於:

stringOutput = [NSString stringWithUTF8String:output.bytes]; 

但一切罰款情況:

stringOutput = [[NSString alloc] initWithData:output 
             encoding:NSUTF8StringEncoding]; 

而且經過一些實驗,我已經看到了,如果我們加「0」到緩衝區一切都會精細的結尾:

char * buffer = malloc(length + 1); 
memset(buffer, 0, length + 1); 
[output getBytes:buffer 
      length:length]; 
stringOutput = [NSString stringWithUTF8String:buffer]; 

這種行爲不可預料的我,因爲我使用stringWithUTF8String:output.bytes現場代碼十幾次沒有任何問題...所以我錯了?

+1

'[NSString stringWithUTF8String:buffer]'讀取字節,直到找到NUL終結符。如果分配和填充的內存中沒有零字節,則將讀取未定義的內存。 –

+0

但爲什麼stringOutput = [NSString stringWithUTF8String:output.bytes];導致崩潰?我認爲可可巧妙地解決了這種問題? – toohtik

+0

因爲該方法*無法知道*現在許多字節被定義或有效。 –

回答

2

[NSString stringWithUTF8String:]需要const char *作爲參數, 和讀取字節,在啓動給定的存儲器位置,直到終止0字節 被發現。 如果在已分配和寫入的 內存中沒有0字節,它將繼續讀取未定義的內存,或甚至從 無效的內存位置。該方法具有無信息約 定義了從給定指針開始的多少個字節。

在另一方面[[NSString alloc] initWithData: encoding:] 需要NSData參數(其包括兩個的指針數據的長度),並從該對象通過 定義的字節完全讀取。

+0

很酷,謝謝Martin。只是從來沒有想過,這可能是在那個地方的問題... – toohtik