Commit 1608a913 by Thomas Lively

Subzero: Instrumented realloc

parent 2c9992a5
......@@ -59,11 +59,14 @@ static char *shadow_offset = NULL;
static void __asan_error(char *, int);
static void __asan_check(char *, int, bool);
static void __asan_get_redzones(char *, char **, char **);
void __asan_init(int, void **, int *);
void __asan_check_load(char *, int);
void __asan_check_store(char *, int);
void *__asan_malloc(size_t);
void *__asan_calloc(size_t, size_t);
void *__asan_realloc(char *, size_t);
void __asan_free(char *);
void __asan_poison(char *, int);
void __asan_unpoison(char *, int);
......@@ -89,6 +92,15 @@ static void __asan_check(char *ptr, int size, bool strict) {
}
}
static void __asan_get_redzones(char *ptr, char **left, char **right) {
char *rz_left = ptr - RZ_SIZE;
char *rz_right = *(char **)rz_left;
if (left != NULL)
*left = rz_left;
if (right != NULL)
*right = rz_right;
}
void __asan_check_load(char *ptr, int size) {
// aligned single word accesses may be widened single byte accesses, but for
// all else use strict check
......@@ -161,10 +173,31 @@ void *__asan_calloc(size_t nmemb, size_t size) {
return ret;
}
void *__asan_realloc(char *ptr, size_t size) {
if (ptr == NULL)
return __asan_malloc(size);
if (size == 0) {
__asan_free(ptr);
return NULL;
}
char *rz_right;
__asan_get_redzones(ptr, NULL, &rz_right);
size_t old_size = rz_right - ptr;
if (size == old_size)
return ptr;
char *new_alloc = __asan_malloc(size);
if (new_alloc == NULL)
return NULL;
size_t copyable = (size < old_size) ? size : old_size;
memcpy(new_alloc, ptr, copyable);
__asan_free(ptr);
return new_alloc;
}
void __asan_free(char *ptr) {
DUMP("free() called on %p\n", ptr);
void *rz_left = ptr - RZ_SIZE;
void *rz_right = *(void **)rz_left;
void *rz_left, *rz_right;
__asan_get_redzones(ptr, &rz_left, &rz_right);
size_t rz_right_size = *(size_t *)rz_right;
__asan_unpoison(rz_left, RZ_SIZE);
__asan_unpoison(rz_right, rz_right_size);
......
......@@ -47,7 +47,8 @@ using string_set = std::unordered_set<std::string>;
const string_map FuncSubstitutions = {{"malloc", "__asan_malloc"},
{"free", "__asan_free"},
{"calloc", "__asan_calloc"},
{"__asan_dummy_calloc", "__asan_calloc"}};
{"__asan_dummy_calloc", "__asan_calloc"},
{"realloc", "__asan_realloc"}};
const string_set FuncBlackList = {"_Balloc"};
llvm::NaClBitcodeRecord::RecordVector sizeToByteVec(SizeT Size) {
......
......@@ -6,18 +6,24 @@
; RUN: --allow-externally-defined-symbols | FileCheck --check-prefix=DUMP %s
declare external i32 @malloc(i32)
declare external i32 @calloc(i32, i32)
declare external i32 @realloc(i32, i32)
declare external void @free(i32)
define internal void @func() {
%ptr = call i32 @malloc(i32 42)
call void @free(i32 %ptr)
%ptr1 = call i32 @malloc(i32 42)
%ptr2 = call i32 @calloc(i32 12, i32 42)
%ptr3 = call i32 @realloc(i32 0, i32 100)
call void @free(i32 %ptr1)
ret void
}
; DUMP-LABEL: ================ Instrumented CFG ================
; DUMP-NEXT: define internal void @func() {
; DUMP-NEXT: __0:
; DUMP-NEXT: %ptr = call i32 @__asan_malloc(i32 42)
; DUMP-NEXT: call void @__asan_free(i32 %ptr)
; DUMP-NEXT: %ptr1 = call i32 @__asan_malloc(i32 42)
; DUMP-NEXT: %ptr2 = call i32 @__asan_calloc(i32 12, i32 42)
; DUMP-NEXT: %ptr3 = call i32 @__asan_realloc(i32 0, i32 100)
; DUMP-NEXT: call void @__asan_free(i32 %ptr1)
; DUMP-NEXT: ret void
; DUMP-NEXT: }
\ No newline at end of file
; DUMP-NEXT: }
; Test that shrinking an allocation updates the redzones
; REQUIRES: no_minimal_build
; RUN: llvm-as %s -o - | pnacl-freeze > %t.pexe && %S/../../pydir/szbuild.py \
; RUN: --fsanitize-address --sz="-allow-externally-defined-symbols" \
; RUN: %t.pexe -o %t && %t 2>&1 | FileCheck %s
declare external i32 @malloc(i32)
declare external i32 @realloc(i32, i32)
declare external void @free(i32)
define void @_start(i32 %arg) {
%ptr16 = call i32 @malloc(i32 16)
%off12a = add i32 %ptr16, 12
%offptra = inttoptr i32 %off12a to i32*
%resa = load i32, i32* %offptra, align 1
%ptr8 = call i32 @realloc(i32 %ptr16, i32 8)
%off12b = add i32 %ptr8, 12
%offptrb = inttoptr i32 %off12b to i8*
%resb = load i8, i8* %offptrb, align 1
ret void
}
; CHECK: Illegal access of 1 bytes at
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment