summaryrefslogtreecommitdiffstats
path: root/buf.c
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2017-08-22 06:12:39 -0700
committerKaz Kylheku <kaz@kylheku.com>2017-08-22 06:12:39 -0700
commite665ad5f93d3bd2f9a4537da80d50b2b2f8e4c5d (patch)
treedaf11992de3e6b21caefdb20ab7ebec8b6270064 /buf.c
parenta9a7efc1790c6ebe663107fbf10c8b72cd76b91b (diff)
downloadtxr-e665ad5f93d3bd2f9a4537da80d50b2b2f8e4c5d.tar.gz
txr-e665ad5f93d3bd2f9a4537da80d50b2b2f8e4c5d.tar.bz2
txr-e665ad5f93d3bd2f9a4537da80d50b2b2f8e4c5d.zip
buffers: fix infinite loop in buf_grow.
* buf.c (buf_grow): When size is zero and len is nonzero, the loop doesn't terminate. Replace silly loop with straightforward calculation: grow buffer by 25%, capped at INT_PTR_MAX, or grow to the length, whichever is larger.
Diffstat (limited to 'buf.c')
-rw-r--r--buf.c14
1 files changed, 8 insertions, 6 deletions
diff --git a/buf.c b/buf.c
index b97bef41..b22ff2b2 100644
--- a/buf.c
+++ b/buf.c
@@ -143,12 +143,14 @@ static void buf_grow(struct buf *b, val init_val, val self)
cnum oldsize = c_num(b->size), size = oldsize;
cnum iv = c_u8(default_arg(init_val, zero), self);
- while (size < len) {
- cnum delta = size / 4;
- if (INT_PTR_MAX - delta >= size)
- size += delta;
- else
- size = len;
+ 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) {