diff options
author | Kaz Kylheku <kaz@kylheku.com> | 2020-02-06 21:19:50 -0800 |
---|---|---|
committer | Kaz Kylheku <kaz@kylheku.com> | 2020-02-06 21:19:50 -0800 |
commit | 52c1aef14849e0f3f4ecb4f6177c48af3b352631 (patch) | |
tree | 1bca87f87a14d49531adeec27749c99a81a04172 /buf.c | |
parent | a7881343e163ba29c31f946e9f943685bb977d6d (diff) | |
download | txr-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.c | 64 |
1 files changed, 32 insertions, 32 deletions
@@ -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; } |