summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ChangeLog10
-rw-r--r--lib.c36
-rw-r--r--lib.h2
-rw-r--r--stream.c11
4 files changed, 46 insertions, 13 deletions
diff --git a/ChangeLog b/ChangeLog
index ab68d9e7..86c746c3 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,15 @@
2014-10-30 Kaz Kylheku <kaz@kylheku.com>
+ * lib.c (chk_grow_vec): New function.
+ (string_extend): Use chk_grow_vec.
+ (vec_set_length): Avoid subtractions for comparing numbers.
+
+ * lib.h (chk_grow_vec): Declared.
+
+ * stream.c (snarf_line, string_out_put_string): Use chk_grow_vec.
+
+2014-10-30 Kaz Kylheku <kaz@kylheku.com>
+
Implementing finalization hooks.
* gc.c (struct fin_reg): New struct type.
diff --git a/lib.c b/lib.c
index cc81745c..663831cc 100644
--- a/lib.c
+++ b/lib.c
@@ -1746,6 +1746,22 @@ mem_t *chk_realloc(mem_t *old, size_t size)
return newptr;
}
+mem_t *chk_grow_vec(mem_t *old, size_t oldelems, size_t newelems,
+ size_t elsize)
+{
+ static const size_t no_oflow = convert(size_t, -1) >> (CHAR_BIT * sizeof(size_t) / 2);
+ size_t bytes = newelems * elsize;
+
+ if (elsize == 0)
+ internal_error("elsize == 0");
+
+ if (newelems <= oldelems ||
+ ((bytes > no_oflow || elsize > no_oflow) && bytes / elsize != newelems))
+ uw_throw(error_s, lit("array size overflow"));
+
+ return chk_realloc(old, bytes);
+}
+
wchar_t *chk_strdup(const wchar_t *str)
{
size_t nchar = wcslen(str) + 1;
@@ -2260,7 +2276,7 @@ val string_extend(val str, val tail)
type_check(str, STR);
{
cnum len = c_num(length_str(str));
- cnum alloc = c_num(str->st.alloc);
+ cnum oalloc = c_num(str->st.alloc), alloc = oalloc;
val needed;
val room = zero;
@@ -2285,11 +2301,15 @@ val string_extend(val str, val tail)
}
if (gt(needed, room))
- uw_throwf(error_s, lit("string-extend: overflow"), nao);
+ uw_throw(error_s, lit("string-extend: overflow"));
+
+ if (alloc != oalloc) {
+ str->st.str = coerce(wchar_t *, chk_grow_vec(coerce(mem_t *, str->st.str),
+ oalloc, alloc,
+ sizeof *str->st.str));
+ set(mkloc(str->st.alloc, str), num(alloc));
+ }
- str->st.str = coerce(wchar_t *, chk_realloc(coerce(mem_t *, str->st.str),
- alloc * sizeof *str->st.str));
- set(mkloc(str->st.alloc, str), num(alloc));
set(mkloc(str->st.len, str), plus(str->st.len, needed));
if (stringp(tail)) {
@@ -4638,14 +4658,12 @@ val vec_set_length(val vec, val length)
cnum new_length = c_num(length);
cnum old_length = c_num(vec->v.vec[vec_length]);
cnum old_alloc = c_num(vec->v.vec[vec_alloc]);
- cnum length_delta = new_length - old_length;
- cnum alloc_delta = new_length - old_alloc;
if (new_length > convert(cnum, (convert(size_t, -1)/sizeof (val) - 2)))
uw_throwf(error_s, lit("vec-set-length: cannot extend to length ~s"),
length, nao);
- if (alloc_delta > 0) {
+ if (new_length > old_alloc) {
cnum new_alloc = max(new_length, 2*old_alloc);
val *newvec = coerce(val *, chk_realloc(coerce(mem_t *, vec->v.vec - 2),
(new_alloc + 2) * sizeof *newvec));
@@ -4656,7 +4674,7 @@ val vec_set_length(val vec, val length)
#endif
}
- if (length_delta > 0) {
+ if (new_length > old_length) {
cnum i;
for (i = old_length; i < new_length; i++)
vec->v.vec[i] = nil;
diff --git a/lib.h b/lib.h
index 9a1056d1..b59eb875 100644
--- a/lib.h
+++ b/lib.h
@@ -501,6 +501,8 @@ mem_t *chk_malloc(size_t size);
mem_t *chk_malloc_gc_more(size_t size);
mem_t *chk_calloc(size_t n, size_t size);
mem_t *chk_realloc(mem_t *, size_t size);
+mem_t *chk_grow_vec(mem_t *old, size_t oldelems, size_t newelems,
+ size_t elsize);
wchar_t *chk_strdup(const wchar_t *str);
val cons(val car, val cdr);
val make_lazy_cons(val func);
diff --git a/stream.c b/stream.c
index 0d9ff3bb..fa274c51 100644
--- a/stream.c
+++ b/stream.c
@@ -313,8 +313,8 @@ static wchar_t *snarf_line(struct stdio_handle *h)
if (fill >= size) {
size_t newsize = size ? size * 2 : min_size;
- buf = coerce(wchar_t *, chk_realloc(coerce(mem_t *, buf),
- newsize * sizeof *buf));
+ buf = coerce(wchar_t *, chk_grow_vec(coerce(mem_t *, buf),
+ size, newsize, sizeof *buf));
size = newsize;
}
@@ -325,6 +325,7 @@ static wchar_t *snarf_line(struct stdio_handle *h)
buf[fill++] = ch;
}
+ /* Trim to actual size */
if (buf)
buf = coerce(wchar_t *, chk_realloc(coerce(mem_t *, buf),
fill * sizeof *buf));
@@ -943,8 +944,9 @@ static val string_out_put_string(val stream, val str)
}
if (so->size != old_size)
- so->buf = coerce(wchar_t *, chk_realloc(coerce(mem_t *, so->buf),
- so->size * sizeof *so->buf));
+ so->buf = coerce(wchar_t *, chk_grow_vec(coerce(mem_t *, so->buf),
+ old_size, so->size,
+ sizeof *so->buf));
wmemcpy(so->buf + so->fill, s, len + 1);
so->fill += len;
return t;
@@ -1238,6 +1240,7 @@ val get_string_from_stream(val stream)
stream->co.handle = 0;
+ /* Trim to actual size */
so->buf = coerce(wchar_t *, chk_realloc(coerce(mem_t *, so->buf),
(so->fill + 1) * sizeof *so->buf));
out = string_own(so->buf);