Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[asan] Intercept and wrap XPC callback blocks
On recent OS X systems, blocks used as callbacks for XPC events (set up e.g. via xpc_connection_set_event_handler) are not later executed via the public libdispatch API (dispatch_async, etc). Because we don't intercept the path where the block is executed, we can fail to register the newly created dispatch thread. To fix that, let's intercept libxpc's APIs that take a block as a callback handler, and let's wrap these blocks in the same way as we do for libdispatch API. Differential Revision: http://reviews.llvm.org/D12490 llvm-svn: 246961
- Loading branch information
1 parent
14f308e
commit dfaac29
Showing
2 changed files
with
82 additions
and
9 deletions.
There are no files selected for viewing
This file contains 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
37 changes: 37 additions & 0 deletions
37
compiler-rt/test/asan/TestCases/Darwin/xpc_interceptors.mm
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
// Check that blocks executed on the XPC callback queue are handled correctly by | ||
// ASan. | ||
|
||
// RUN: %clangxx_asan -O0 %s -o %t -framework Foundation && not %run %t 2>&1 | FileCheck %s | ||
|
||
#import <Foundation/Foundation.h> | ||
#include <sanitizer/asan_interface.h> | ||
#include <xpc/xpc.h> | ||
|
||
int main() { | ||
// Set up a 5-second timeout. | ||
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 5 * NSEC_PER_SEC), | ||
dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), | ||
^{ | ||
exit(0); | ||
}); | ||
|
||
xpc_connection_t _connection = xpc_connection_create_mach_service( | ||
"com.example.non.existing.xpc", NULL, 0); | ||
|
||
xpc_connection_set_event_handler(_connection, ^(xpc_object_t event) { | ||
char *mem = (char *)malloc(10); | ||
NSLog(@"mem = %p", mem); | ||
|
||
// Without the XPC API interceptors, this would cause an assertion failure | ||
// when describing the current thread (XPC callback thread). | ||
fprintf(stderr, "%s\n", mem + 10); // BOOM. | ||
// CHECK: ERROR: AddressSanitizer: heap-buffer-overflow | ||
// CHECK: READ of size 1 at | ||
// CHECK: allocated by thread | ||
// CHECK: {{ #0 0x.* in .*malloc}} | ||
}); | ||
|
||
xpc_connection_resume(_connection); | ||
dispatch_main(); | ||
return 0; | ||
} |