Created
December 4, 2014 04:08
-
-
Save kongtomorrow/c5e3494452e419cbf016 to your computer and use it in GitHub Desktop.
Address sanitizer squawkage
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
ken@Nepheli-20 /tmp> | |
~/bin/clang/bin/clang -O3 -g -fsanitize=address -isysroot /Volumes/Data/Users/ken/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.10.sdk -framework Foundation /tmp/asanBarf.m | |
ken@Nepheli-20 /tmp> ./a.out | |
================================================================= | |
==91531==ERROR: AddressSanitizer: global-buffer-overflow on address 0x00010caf8f1f at pc 0x00010caf8dc2 bp 0x7fff531077a0 sp 0x7fff53107798 | |
READ of size 32 at 0x00010caf8f1f thread T0 | |
#0 0x10caf8dc1 (/private/tmp/./a.out+0x100000dc1) | |
#1 0x10caf8de4 (/private/tmp/./a.out+0x100000de4) | |
#2 0x7fff8cdc25c8 (/usr/lib/system/libdyld.dylib+0x35c8) | |
#3 0x0 (<unknown module>) | |
0x00010caf8f1f is located 24 bytes to the right of global variable '<string literal>' defined in '/tmp/asanBarf.m:48:33' (0x10caf8f00) of size 7 | |
'<string literal>' is ascii string 'hello!' | |
Shadow bytes around the buggy address: | |
0x10002195f190: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | |
0x10002195f1a0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | |
0x10002195f1b0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | |
0x10002195f1c0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | |
0x10002195f1d0: 00 00 00 00 00 00 00 00 00 00 00 00 f9 f9 f9 f9 | |
=>0x10002195f1e0: 07 f9 f9[f9]f9 f9 f9 f9 00 00 00 00 00 00 00 00 | |
0x10002195f1f0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | |
0x10002195f200: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | |
0x10002195f210: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | |
0x10002195f220: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | |
0x10002195f230: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | |
Shadow byte legend (one shadow byte represents 8 application bytes): | |
Addressable: 00 | |
Partially addressable: 01 02 03 04 05 06 07 | |
Heap left redzone: fa | |
Heap right redzone: fb | |
Freed heap region: fd | |
Stack left redzone: f1 | |
Stack mid redzone: f2 | |
Stack right redzone: f3 | |
Stack partial redzone: f4 | |
Stack after return: f5 | |
Stack use after scope: f8 | |
Global redzone: f9 | |
Global init order: f6 | |
Poisoned by user: f7 | |
Container overflow: fc | |
Array cookie: ac | |
Intra object redzone: bb | |
ASan internal: fe | |
Left alloca redzone: ca | |
Right alloca redzone: cb | |
==91531==ABORTING | |
#import <Foundation/Foundation.h> | |
#import <simd/simd.h> | |
static inline CFIndex firstSetIndex(vector_char32 x) { | |
#if defined __AVX2__ | |
return __builtin_ctz(_mm256_movemask_epi8(x)); | |
#else | |
return __builtin_ctz(_mm_movemask_epi8(x.hi) << 16 | _mm_movemask_epi8(x.lo)); | |
#endif | |
} | |
__attribute__((noinline)) Boolean __CFBytesInASCII_vec(const uint8_t *bytes, CFIndex len) { | |
// Early-out if length is zero. | |
if (len == 0) return true; | |
// Back up to a 16-byte aligned memory location. | |
const vector_char32 *aligned = (const vector_char32 *)((uintptr_t)bytes & -32); | |
const size_t adjust = bytes - (const uint8_t *)aligned; | |
// Generate a mask to zero-out the first distance bytes of a vector. | |
static const uint8_t maskSource[64] = { | |
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | |
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | |
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, | |
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, | |
}; | |
vector_char32 mask = *(const packed_char32 *)&maskSource[32 - adjust]; | |
// Load the first vector and zero out any bytes preceeding the buffer we | |
// are actually interested in. Adjust the length to account for these | |
// extra bytes as well. | |
vector_char32 data = *aligned & mask; | |
len += adjust; | |
// Now scan by aligned vectors until we either find a non-ASCII byte or | |
// we reach the end of the buffer. This may read past the end of the | |
// buffer, but it will never cross a page boundary beyond the end of the | |
// buffer, so it is safe. | |
while (!vector_any(data)) { | |
if (len <= 32) return true; | |
len -= 32; | |
data = *++aligned; | |
} | |
// We found a non-ASCII byte. If its index in the vector is less than the | |
// remaining length, return fase. Otherwise, return true. | |
return firstSetIndex(data) >= len; | |
} | |
int main(int argc, const char * argv[]) { | |
const char *shortStringBytes = "hello!"; | |
CFIndex shortLen = strlen(shortStringBytes); | |
NSLog(@"%d", __CFBytesInASCII_vec((const uint8_t *)shortStringBytes, shortLen)); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment