about summary refs log tree commit diff
path: root/src/rt/rust_task.cpp
diff options
context:
space:
mode:
authorBrian Anderson <banderson@mozilla.com>2011-12-20 11:20:54 -0800
committerBrian Anderson <banderson@mozilla.com>2011-12-20 11:48:47 -0800
commit784713ec683c7cce0a1d4aa712a376317384d62c (patch)
treed8063109957b61abc274df5fda54c30273e45eb2 /src/rt/rust_task.cpp
parent4475ec863dd6c00eba67bc8111ce5fbe72409c9e (diff)
downloadrust-784713ec683c7cce0a1d4aa712a376317384d62c.tar.gz
rust-784713ec683c7cce0a1d4aa712a376317384d62c.zip
rt: Add a canary value to the end of every stack
Check it on upcall entry and exit, and on stack deletion
Diffstat (limited to 'src/rt/rust_task.cpp')
-rw-r--r--src/rt/rust_task.cpp28
1 files changed, 27 insertions, 1 deletions
diff --git a/src/rt/rust_task.cpp b/src/rt/rust_task.cpp
index 23bd6647a04..125a2900ca0 100644
--- a/src/rt/rust_task.cpp
+++ b/src/rt/rust_task.cpp
@@ -49,6 +49,12 @@
 #endif
 #endif
 
+// A value that goes at the end of the stack and must not be touched
+const uint8_t stack_canary[] = {0xAB, 0xCD, 0xAB, 0xCD,
+                                0xAB, 0xCD, 0xAB, 0xCD,
+                                0xAB, 0xCD, 0xAB, 0xCD,
+                                0xAB, 0xCD, 0xAB, 0xCD};
+
 // Stack size
 size_t g_custom_min_stack_size = 0;
 
@@ -95,7 +101,8 @@ config_valgrind_stack(stk_seg *stk) {
     // old stack segments, since the act of popping the stack previously
     // caused valgrind to consider the whole thing inaccessible.
     size_t sz = stk->end - (uintptr_t)&stk->data[0];
-    VALGRIND_MAKE_MEM_UNDEFINED(stk->data, sz);
+    VALGRIND_MAKE_MEM_UNDEFINED(stk->data + sizeof(stack_canary),
+                                sz - sizeof(stack_canary));
 #endif
 }
 
@@ -110,6 +117,18 @@ free_stk(rust_task *task, stk_seg *stk) {
     task->free(stk);
 }
 
+static void
+add_stack_canary(stk_seg *stk) {
+    memcpy(stk->data, stack_canary, sizeof(stack_canary));
+    assert(sizeof(stack_canary) == 16 && "Stack canary was not the expected size");
+}
+
+static void
+check_stack_canary(stk_seg *stk) {
+    assert(!memcmp(stk->data, stack_canary, sizeof(stack_canary))
+      && "Somebody killed the canary");
+}
+
 static stk_seg*
 new_stk(rust_scheduler *sched, rust_task *task, size_t requested_sz)
 {
@@ -151,6 +170,7 @@ new_stk(rust_scheduler *sched, rust_task *task, size_t requested_sz)
     stk_seg *stk = (stk_seg *)task->malloc(sz, "stack");
     LOGPTR(task->sched, "new stk", (uintptr_t)stk);
     memset(stk, 0, sizeof(stk_seg));
+    add_stack_canary(stk);
     stk->prev = NULL;
     stk->next = task->stk;
     stk->end = (uintptr_t) &stk->data[rust_stk_sz + RED_ZONE_SIZE];
@@ -165,6 +185,7 @@ static void
 del_stk(rust_task *task, stk_seg *stk)
 {
     assert(stk == task->stk && "Freeing stack segments out of order!");
+    check_stack_canary(stk);
 
     task->stk = stk->next;
 
@@ -784,6 +805,11 @@ rust_task::on_rust_stack() {
     return sp_in_stk_seg(get_sp(), stk);
 }
 
+void
+rust_task::check_stack_canary() {
+    ::check_stack_canary(stk);
+}
+
 //
 // Local Variables:
 // mode: C++