Skip to content

Instantly share code, notes, and snippets.

@kongtomorrow
Created December 4, 2014 04:08
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save kongtomorrow/c5e3494452e419cbf016 to your computer and use it in GitHub Desktop.
Save kongtomorrow/c5e3494452e419cbf016 to your computer and use it in GitHub Desktop.
Address sanitizer squawkage
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