summaryrefslogtreecommitdiffstats
path: root/buf.c
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2020-02-06 21:19:50 -0800
committerKaz Kylheku <kaz@kylheku.com>2020-02-06 21:19:50 -0800
commit52c1aef14849e0f3f4ecb4f6177c48af3b352631 (patch)
tree1bca87f87a14d49531adeec27749c99a81a04172 /buf.c
parenta7881343e163ba29c31f946e9f943685bb977d6d (diff)
downloadtxr-52c1aef14849e0f3f4ecb4f6177c48af3b352631.tar.gz
txr-52c1aef14849e0f3f4ecb4f6177c48af3b352631.tar.bz2
txr-52c1aef14849e0f3f4ecb4f6177c48af3b352631.zip
buf: bugfix: buf-set-length not setting bytes.
* buf.c (buf_grow): Function removed; logic merged into buf_do_set_len. The bug fixed is that buf_grow was initializing just the newly allocated bytes to init_val. The bytes that must actually be initialized are those which lie between the old and new length, not in the allocated area. (make_buf): In make_buf, we don't have to initialize the entire buffer, but only bytes 0 through len - 1. Now calloc is only used when the initializing value is zero, and the buffer's allocation size is the same as the length. When the length is increase to protrude into the allocated uninitialized area, buf_do_set_len will now properly initialize that to the value given at that time. * txr.1: Update make-buf documentation not to say that all the bytes of the buffer are initialized.
Diffstat (limited to 'buf.c')
-rw-r--r--buf.c64
1 files changed, 32 insertions, 32 deletions
diff --git a/buf.c b/buf.c
index b034e266..09bdd0ee 100644
--- a/buf.c
+++ b/buf.c
@@ -78,11 +78,11 @@ static cnum buf_check_index(struct buf *b, val index, val self)
val make_buf(val len, val init_val, val alloc_size)
{
val self = lit("make-buf");
- cnum l = buf_check_len(len, self);
+ cnum blen = buf_check_len(len, self);
val alloc = if3(null_or_missing_p(alloc_size), len, alloc_size);
- cnum size = buf_check_alloc_size(alloc, l, self);
+ cnum size = buf_check_alloc_size(alloc, blen, self);
cnum iv = c_u8(default_arg(init_val, zero), self);
- mem_t *data = if3(iv == 0,
+ mem_t *data = if3(iv == 0 && size == blen,
chk_calloc(size, 1),
chk_malloc(size));
val obj = make_obj();
@@ -92,8 +92,8 @@ val make_buf(val len, val init_val, val alloc_size)
obj->b.len = len;
obj->b.size = num(size);
- if (iv != 0)
- memset(data, convert(unsigned char, iv), c_num(len));
+ if (iv != 0 || size != blen)
+ memset(data, convert(unsigned char, iv), blen);
return obj;
}
@@ -153,29 +153,6 @@ val copy_buf(val buf)
make_borrowed_buf(b->len, b->data));
}
-static void buf_grow(struct buf *b, val init_val, val self)
-{
- cnum len = c_num(b->len);
- cnum oldsize = c_num(b->size), size = oldsize;
- cnum iv = c_u8(default_arg(init_val, zero), self);
-
- if (size < len) {
- if (size > INT_PTR_MAX - INT_PTR_MAX / 5) {
- size = INT_PTR_MAX;
- } else {
- size = size + size / 4;
- if (size < len)
- size = len;
- }
- }
-
- if (size > oldsize) {
- b->data = chk_realloc(b->data, size);
- b->size = num(size);
- memset(b->data + oldsize, convert(unsigned char, iv), size - oldsize);
- }
-}
-
static void buf_shrink(struct buf *b)
{
val len = b->len;
@@ -201,16 +178,39 @@ val buf_trim(val buf)
return oldsize;
}
-static val buf_do_set_len(val buf, struct buf *b, val len,
+static val buf_do_set_len(val buf, struct buf *b, val newlen,
val init_val, val self)
{
val oldlen = b->len;
+ cnum olen = c_num(oldlen), len = c_num(newlen);
+ cnum oldsize = c_num(b->size), size = oldsize;
+ cnum iv = c_u8(default_arg(init_val, zero), self);
+
if (!b->size)
uw_throwf(error_s, lit("~a: ~s is a fixed buffer"),
self, buf, nao);
- (void) buf_check_len(len, self);
- b->len = len;
- buf_grow(b, init_val, self);
+ (void) buf_check_len(newlen, self);
+
+ b->len = newlen;
+
+ if (size < len) {
+ if (size > INT_PTR_MAX - INT_PTR_MAX / 5) {
+ size = INT_PTR_MAX;
+ } else {
+ size = size + size / 4;
+ if (size < len)
+ size = len;
+ }
+ }
+
+ if (size > oldsize) {
+ b->data = chk_realloc(b->data, size);
+ b->size = num(size);
+ }
+
+ if (len > olen)
+ memset(b->data + olen, convert(unsigned char, iv), len - olen);
+
return oldlen;
}