diff options
| author | Roy Frostig <[email protected]> | 2010-08-11 16:06:45 -0700 |
|---|---|---|
| committer | Roy Frostig <[email protected]> | 2010-08-11 16:06:45 -0700 |
| commit | f307688bf44404b371b91b3b2a67048088695fe1 (patch) | |
| tree | cfd89b43e614588ea7ee35eebd8f83eec3f5fedf /src/rt/rust_builtin.cpp | |
| parent | Fix reverse-indexing bug in _vec.init_fn. (diff) | |
| download | rust-f307688bf44404b371b91b3b2a67048088695fe1.tar.xz rust-f307688bf44404b371b91b3b2a67048088695fe1.zip | |
Add native vec[u8] to str converter. Put in workaround for leak in str to vec[u8] converter. Add testcase exercising both. Drive-by fix a potential array-out-of-bounds write on rust_str buffers.
Diffstat (limited to 'src/rt/rust_builtin.cpp')
| -rw-r--r-- | src/rt/rust_builtin.cpp | 87 |
1 files changed, 68 insertions, 19 deletions
diff --git a/src/rt/rust_builtin.cpp b/src/rt/rust_builtin.cpp index d8d9b8d6..64b587c0 100644 --- a/src/rt/rust_builtin.cpp +++ b/src/rt/rust_builtin.cpp @@ -2,19 +2,6 @@ #include "rust_internal.h" /* Native builtins. */ -extern "C" CDECL rust_str* -str_alloc(rust_task *task, size_t n_bytes) -{ - rust_dom *dom = task->dom; - size_t alloc = next_power_of_two(sizeof(rust_str) + n_bytes); - void *mem = dom->malloc(alloc); - if (!mem) { - task->fail(2); - return NULL; - } - rust_str *st = new (mem) rust_str(dom, alloc, 1, (uint8_t const *)""); - return st; -} extern "C" CDECL rust_str* last_os_error(rust_task *task) { @@ -109,6 +96,48 @@ vec_alloc(rust_task *task, type_desc *t, type_desc *elem_t, size_t n_elts) return vec; } +extern "C" CDECL void * +vec_buf(rust_task *task, type_desc *ty, rust_vec *v, size_t offset) +{ + return (void *)&v->data[ty->size * offset]; +} + +extern "C" CDECL size_t +vec_len(rust_task *task, type_desc *ty, rust_vec *v) +{ + return v->fill / ty->size; +} + +/* Helper for str_alloc and str_from_vec. Returns NULL as failure. */ +static rust_str * +str_alloc_with_data(rust_task *task, + size_t n_bytes, + size_t fill, + uint8_t const *d) +{ + rust_dom *dom = task->dom; + size_t alloc = next_power_of_two(sizeof(rust_str) + n_bytes); + void *mem = dom->malloc(alloc); + if (!mem) + return NULL; + rust_str *st = new (mem) rust_str(dom, alloc, fill, d); + return st; +} + +extern "C" CDECL rust_str* +str_alloc(rust_task *task, size_t n_bytes) +{ + rust_str *st = str_alloc_with_data(task, + n_bytes + 1, // +1 to fit at least "" + 1, + (uint8_t const *)""); + if (!st) { + task->fail(2); + return NULL; + } + return st; +} + extern "C" CDECL char const * str_buf(rust_task *task, rust_str *s) { @@ -121,17 +150,37 @@ str_byte_len(rust_task *task, rust_str *s) return s->fill - 1; // -1 for the '\0' terminator. } -extern "C" CDECL void * -vec_buf(rust_task *task, type_desc *ty, rust_vec *v, size_t offset) +extern "C" CDECL rust_str * +str_from_vec(rust_task *task, rust_vec *v) { - return (void *)&v->data[ty->size * offset]; + rust_str *st = + str_alloc_with_data(task, + v->fill + 1, // +1 to fit at least '\0' + v->fill, + v->fill ? (uint8_t const *)v->data : NULL); + if (!st) { + task->fail(2); + return NULL; + } + st->data[st->fill++] = '\0'; + return st; } -extern "C" CDECL size_t -vec_len(rust_task *task, type_desc *ty, rust_vec *v) +/* +extern "C" CDECL rust_str* +str_alloc(rust_task *task, size_t n_bytes) { - return v->fill / ty->size; + rust_dom *dom = task->dom; + size_t alloc = next_power_of_two(sizeof(rust_str) + n_bytes); + void *mem = dom->malloc(alloc); + if (!mem) { + task->fail(2); + return NULL; + } + rust_str *st = new (mem) rust_str(dom, alloc, 1, (uint8_t const *)""); + return st; } +*/ extern "C" CDECL void * rand_new(rust_task *task) |