diff options
-rw-r--r-- | ChangeLog | 10 | ||||
-rw-r--r-- | lib.c | 36 | ||||
-rw-r--r-- | lib.h | 2 | ||||
-rw-r--r-- | stream.c | 11 |
4 files changed, 46 insertions, 13 deletions
@@ -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. @@ -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; @@ -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); @@ -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); |