Skip to content

Instantly share code, notes, and snippets.

@pnkfelix
Last active August 29, 2015 14:14
Show Gist options
  • Save pnkfelix/2e2b73092c2fd5b38228 to your computer and use it in GitHub Desktop.
Save pnkfelix/2e2b73092c2fd5b38228 to your computer and use it in GitHub Desktop.
illustrates erroneous deallocate calls both with and without `-O` on Mac OS X
#![feature(lang_items)]
#![feature(int_uint)]
#![no_std]
#![allow(unstable)]
#![allow(unused_variables)]
#![allow(non_camel_case_types)]
#![allow(non_upper_case_globals)]
extern crate core;
// extern crate alloc;
extern crate libc;
use core::mem;
use core::ptr::{self, PtrExt, Unique};
use core::str::StrExt;
use core::slice::SliceExt;
use libc::{c_int};
#[inline(never)]
fn box_1() -> Box<[i8; 1]> {
let v = [1i8];
// Box::new(v)
let b : Box<[i8; 1]> = unsafe {
let p = allocate(mem::size_of_val(&v),
mem::align_of_val(&v));
mem::transmute(p)
};
b
}
#[inline(never)]
fn box_2() -> Box<[i8; 2]> {
let v = [1i8, 2];
// Box::new(v)
let b : Box<[i8; 2]> = unsafe {
let p = allocate(mem::size_of_val(&v),
mem::align_of_val(&v));
mem::transmute(p)
};
b
}
#[inline(never)]
fn box_3() -> Box<[i8; 3]> {
let v = [1i8, 2, 3];
// Box::new(v)
let b : Box<[i8; 3]> = unsafe {
let p = allocate(mem::size_of_val(&v),
mem::align_of_val(&v));
mem::transmute(p)
};
b
}
#[inline(never)]
fn box_4() -> Box<[i8; 4]> {
let v = [1i8, 2, 3, 4];
// Box::new(v)
let b : Box<[i8; 4]> = unsafe {
let p = allocate(mem::size_of_val(&v),
mem::align_of_val(&v));
mem::transmute(p)
};
b
}
pub fn main() {
print0("Hello World 1\n\0");
let _: Box<[i8]> = match 2 {
1 => box_1(),
2 => box_2(),
3 => box_3(),
_ => box_4(),
};
print0("Hello World 2\n\0");
}
#[lang = "owned_box"]
pub struct Box<T>(Unique<T>);
#[lang = "start"]
fn lang_start(_main: *const u8, argc: isize, argv: *const *const u8) -> isize {
main();
0
}
pub const EMPTY: *mut () = 0x1 as *mut ();
#[lang="exchange_malloc"]
#[inline(never)]
unsafe fn exchange_malloc(size: uint, align: uint) -> *mut u8 {
if size == 0 {
EMPTY as *mut u8
} else {
let ptr = allocate(size, align);
if ptr.is_null() { print0("Uh oh\n\0"); loop { } }
ptr
}
}
#[lang="exchange_free"]
#[inline(never)]
unsafe fn exchange_free(ptr: *mut u8, old_size: uint, align: uint) {
print_p(" exchange_free ptr %p (no-op)\n\0", ptr);
print_us(" exchange_free old_size %ld\n\0", old_size);
print_us(" exchange_free align %ld\n\0", align);
let low = &central_store[0];
let high = &central_store[offset];
let low : *const u8 = mem::transmute(low);
let high : *const u8 = mem::transmute(high);
print_p(" exchange_free low %p\n\0", low);
print_p(" exchange_free high %p\n\0", high);
let low : *mut u8 = mem::transmute(low);
let high : *mut u8 = mem::transmute(high);
if ptr < low || ptr >= high {
print_p("WARNING: called exchange_free on %p \
which is out of range\n\0", ptr);
}
}
#[inline(never)]
pub unsafe fn allocate(size: uint, align: uint) -> *mut u8 {
print_us(" allocate size: %ld\n\0", size);
print_us(" allocate align: %ld\n\0", align);
let mut p;
loop {
p = &central_store[offset];
if mem::transmute::<_, usize>(p) % align == 0 {
break;
}
if offset > STORE_SIZE - 1 {
let p : *const u8 = ptr::null();
print_p(" allocate returns %p\n\0", p);
return mem::transmute(p);
}
offset += 1;
}
if offset > STORE_SIZE - size {
let p : *const u8 = ptr::null();
print_p(" allocate returns %p\n\0", p);
return mem::transmute(p);
}
offset += size;
let p: *const u8 = mem::transmute(p);
print_p(" allocate returns %p\n\0", p);
return mem::transmute(p);
}
const STORE_SIZE: usize = 1024;
static mut central_store: [u8; STORE_SIZE] = [0; STORE_SIZE];
static mut offset: usize = 0;
extern {
fn printf(format: *const u8, ...);
}
fn print0(s: &str) {
unsafe {
printf(s.as_bytes().as_ptr());
}
}
fn print_p<T>(s: &str, p: *const T) {
unsafe {
printf(s.as_bytes().as_ptr(), p);
}
}
fn print_us(s: &str, us: usize) {
unsafe {
printf(s.as_bytes().as_ptr(), us);
}
}
#[lang="eh_personality"]
extern fn rust_eh_personality(
version: c_int,
actions: uw::_Unwind_Action,
exception_class: uw::_Unwind_Exception_Class,
ue_header: *mut uw::_Unwind_Exception,
context: *mut uw::_Unwind_Context)
-> uw::_Unwind_Reason_Code
{
loop { }
}
#[lang = "panic_fmt"]
pub extern fn rust_begin_unwind(
msg: fmt::Arguments,
file: &'static str,
line: usize)
-> !
{
loop { }
}
#[lang = "stack_exhausted"]
extern fn stack_exhausted() {
loop { }
}
mod uw {
use libc;
#[repr(C)]
pub enum _Unwind_Reason_Code {
_URC_NO_REASON = 0,
_URC_FOREIGN_EXCEPTION_CAUGHT = 1,
_URC_FATAL_PHASE2_ERROR = 2,
_URC_FATAL_PHASE1_ERROR = 3,
_URC_NORMAL_STOP = 4,
_URC_END_OF_STACK = 5,
_URC_HANDLER_FOUND = 6,
_URC_INSTALL_CONTEXT = 7,
_URC_CONTINUE_UNWIND = 8,
_URC_FAILURE = 9, // used only by ARM EABI
}
pub enum _Unwind_Context {}
#[repr(C)]
pub struct _Unwind_Exception {
pub exception_class: _Unwind_Exception_Class,
pub exception_cleanup: _Unwind_Exception_Cleanup_Fn,
pub private: [_Unwind_Word; unwinder_private_data_size],
}
pub type _Unwind_Exception_Class = u64;
#[repr(C)]
pub enum _Unwind_Action {
_UA_SEARCH_PHASE = 1,
_UA_CLEANUP_PHASE = 2,
_UA_HANDLER_FRAME = 4,
_UA_FORCE_UNWIND = 8,
_UA_END_OF_STACK = 16,
}
pub type _Unwind_Exception_Cleanup_Fn =
extern "C" fn(unwind_code: _Unwind_Reason_Code,
exception: *mut _Unwind_Exception);
pub type _Unwind_Word = libc::uintptr_t;
#[cfg(target_arch = "x86")]
pub const unwinder_private_data_size: uint = 5;
#[cfg(target_arch = "x86_64")]
pub const unwinder_private_data_size: uint = 6;
#[cfg(all(target_arch = "arm", not(target_os = "ios")))]
pub const unwinder_private_data_size: uint = 20;
#[cfg(all(target_arch = "arm", target_os = "ios"))]
pub const unwinder_private_data_size: uint = 5;
#[cfg(target_arch = "aarch64")]
pub const unwinder_private_data_size: uint = 2;
#[cfg(any(target_arch = "mips", target_arch = "mipsel"))]
pub const unwinder_private_data_size: uint = 2;
}
mod fmt {
pub struct Arguments;
}
% rustc -O /tmp/coerce_match_calls4.rs && ./coerce_match_calls4
Hello World 1
allocate size: 2
allocate align: 1
allocate returns 0x10319b1d0
exchange_free ptr 0x10319b1d0 (no-op)
exchange_free old_size 2
exchange_free align 1
exchange_free low 0x10319b1d0
exchange_free high 0x10319b1d2
exchange_free ptr 0x80000000903 (no-op)
exchange_free old_size 4
exchange_free align 1
exchange_free low 0x10319b1d0
exchange_free high 0x10319b1d2
WARNING: called exchange_free on 0x80000000903 which is out of range
exchange_free ptr 0xe0000000f03 (no-op)
exchange_free old_size 3
exchange_free align 1
exchange_free low 0x10319b1d0
exchange_free high 0x10319b1d2
WARNING: called exchange_free on 0xe0000000f03 which is out of range
exchange_free ptr 0x140000001503 (no-op)
exchange_free old_size 1
exchange_free align 1
exchange_free low 0x10319b1d0
exchange_free high 0x10319b1d2
WARNING: called exchange_free on 0x140000001503 which is out of range
Hello World 2
% rustc /tmp/coerce_match_calls4.rs && ./coerce_match_calls4
Hello World 1
allocate size: 2
allocate align: 1
allocate returns 0x1025c2220
exchange_free ptr 0x1025c2220 (no-op)
exchange_free old_size 2
exchange_free align 1
exchange_free low 0x1025c2220
exchange_free high 0x1025c2222
exchange_free ptr 0x1 (no-op)
exchange_free old_size 1
exchange_free align 1
exchange_free low 0x1025c2220
exchange_free high 0x1025c2222
WARNING: called exchange_free on 0x1 which is out of range
Hello World 2
%
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment