toohtik toohtik - 11 months ago 76
iOS Question

heap-buffer-overflow on NSData converting

I've noticed interesting behavior of AddressSanitizer in XCode 8. In one case it lead to catching breakpoint: AddressSanitizer: heap-buffer-overflow on address but I really dont understand why:

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

same to:

stringOutput = [NSString stringWithUTF8String:output.bytes];

But everything fine for cases:

stringOutput = [[NSString alloc] initWithData:output

Also after some experiments I've seen that if we add '0' to end of the buffer everything will fine:

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

This behavior unexpectable for me because I've used stringWithUTF8String:output.bytes dozen times on live code without any problems... So where I'm wrong?

Answer Source

[NSString stringWithUTF8String:] takes a const char * as an argument, and reads bytes, starting the given memory location, until a terminating 0 byte is found. If there is no 0 byte within the allocated and written-to memory, it will continue to read undefined memory, or even from invalid memory locations. The method has no information about how many bytes starting at the given pointer are defined.

On the other hand [[NSString alloc] initWithData: encoding:] takes a NSData argument (which comprises both a pointer to the data and a length) and reads exactly from the bytes defined by that object.