about summary refs log tree commit diff
path: root/src/rt/rust_builtin.cpp
diff options
context:
space:
mode:
authorRoy Frostig <rfrostig@mozilla.com>2010-08-11 16:06:45 -0700
committerRoy Frostig <rfrostig@mozilla.com>2010-08-11 16:06:45 -0700
commitf307688bf44404b371b91b3b2a67048088695fe1 (patch)
treecfd89b43e614588ea7ee35eebd8f83eec3f5fedf /src/rt/rust_builtin.cpp
parent8e02a2bcb5f8d3dfe03816fed53c51f0a5500f71 (diff)
downloadrust-f307688bf44404b371b91b3b2a67048088695fe1.tar.gz
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.cpp87
1 files changed, 68 insertions, 19 deletions
diff --git a/src/rt/rust_builtin.cpp b/src/rt/rust_builtin.cpp
index d8d9b8d6eb4..64b587c0d2d 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)