From 1193050109dee6be85c82bd29a1c817532dde912 Mon Sep 17 00:00:00 2001 From: Nick Wellnhofer Date: Sun, 7 Jun 2015 13:16:13 +0200 Subject: Use custom type bufsize_t for string buffer sizes This makes it easier to change the type later. No functional change. The rest of the code base still has to be adjusted to use the new type. Also add some TODO comments in buffer.c. --- src/buffer.c | 56 ++++++++++++++++++++++++++++++++++++-------------------- 1 file changed, 36 insertions(+), 20 deletions(-) (limited to 'src/buffer.c') diff --git a/src/buffer.c b/src/buffer.c index e2ebc02..78d0a00 100644 --- a/src/buffer.c +++ b/src/buffer.c @@ -22,20 +22,21 @@ unsigned char cmark_strbuf__initbuf[1]; #define MIN(x,y) ((xasize = 0; buf->size = 0; buf->ptr = cmark_strbuf__initbuf; + // TODO: Check for negative initial_size. if (initial_size) cmark_strbuf_grow(buf, initial_size); } -void cmark_strbuf_grow(cmark_strbuf *buf, int target_size) +void cmark_strbuf_grow(cmark_strbuf *buf, bufsize_t target_size) { unsigned char *new_ptr; - int new_size; + bufsize_t new_size; if (target_size <= buf->asize) return; @@ -51,9 +52,11 @@ void cmark_strbuf_grow(cmark_strbuf *buf, int target_size) /* grow the buffer size by 1.5, until it's big enough * to fit our target size */ while (new_size < target_size) + // TODO: Check for overflow. new_size = (new_size << 1) - (new_size >> 1); /* round allocation up to multiple of 8 */ + // TODO: Check for overflow. new_size = (new_size + 7) & ~7; new_ptr = (unsigned char *)realloc(new_ptr, new_size); @@ -95,12 +98,13 @@ void cmark_strbuf_clear(cmark_strbuf *buf) buf->ptr[0] = '\0'; } -void cmark_strbuf_set(cmark_strbuf *buf, const unsigned char *data, int len) +void cmark_strbuf_set(cmark_strbuf *buf, const unsigned char *data, bufsize_t len) { if (len <= 0 || data == NULL) { cmark_strbuf_clear(buf); } else { if (data != buf->ptr) { + // TODO: Check for overflow. ENSURE_SIZE(buf, len + 1); memmove(buf->ptr, data, len); } @@ -117,16 +121,18 @@ void cmark_strbuf_sets(cmark_strbuf *buf, const char *string) void cmark_strbuf_putc(cmark_strbuf *buf, int c) { + // TODO: Check for overflow. ENSURE_SIZE(buf, buf->size + 2); buf->ptr[buf->size++] = c; buf->ptr[buf->size] = '\0'; } -void cmark_strbuf_put(cmark_strbuf *buf, const unsigned char *data, int len) +void cmark_strbuf_put(cmark_strbuf *buf, const unsigned char *data, bufsize_t len) { if (len <= 0) return; + // TODO: Check for overflow. ENSURE_SIZE(buf, buf->size + len + 1); memmove(buf->ptr + buf->size, data, len); buf->size += len; @@ -140,8 +146,8 @@ void cmark_strbuf_puts(cmark_strbuf *buf, const char *string) void cmark_strbuf_vprintf(cmark_strbuf *buf, const char *format, va_list ap) { - const int expected_size = buf->size + (strlen(format) * 2); - int len; + // TODO: Check for overflow. + const bufsize_t expected_size = buf->size + (strlen(format) * 2); ENSURE_SIZE(buf, expected_size); @@ -149,7 +155,7 @@ void cmark_strbuf_vprintf(cmark_strbuf *buf, const char *format, va_list ap) va_list args; va_copy(args, ap); - len = vsnprintf( + int len = vsnprintf( (char *)buf->ptr + buf->size, buf->asize - buf->size, format, args @@ -168,11 +174,13 @@ void cmark_strbuf_vprintf(cmark_strbuf *buf, const char *format, va_list ap) abort(); } + // TODO: Check for overflow. if (len + 1 <= buf->asize - buf->size) { buf->size += len; break; } + // TODO: Check for overflow. ENSURE_SIZE(buf, buf->size + len + 1); } } @@ -186,10 +194,11 @@ void cmark_strbuf_printf(cmark_strbuf *buf, const char *format, ...) va_end(ap); } -void cmark_strbuf_copy_cstr(char *data, int datasize, const cmark_strbuf *buf) +void cmark_strbuf_copy_cstr(char *data, bufsize_t datasize, const cmark_strbuf *buf) { - int copylen; + bufsize_t copylen; + // TODO: Check negative datasize. assert(data && datasize && buf); data[0] = '\0'; @@ -224,16 +233,19 @@ unsigned char *cmark_strbuf_detach(cmark_strbuf *buf) return data; } -void cmark_strbuf_attach(cmark_strbuf *buf, unsigned char *ptr, int asize) +void cmark_strbuf_attach(cmark_strbuf *buf, unsigned char *ptr, bufsize_t asize) { cmark_strbuf_free(buf); if (ptr) { buf->ptr = ptr; buf->size = strlen((char *)ptr); + // TODO: Check for negative asize. if (asize) + // TODO: Check for overflow. buf->asize = (asize < buf->size) ? buf->size + 1 : asize; else /* pass 0 to fall back on strlen + 1 */ + // TODO: Check for overflow. buf->asize = buf->size + 1; } else { cmark_strbuf_grow(buf, asize); @@ -247,19 +259,21 @@ int cmark_strbuf_cmp(const cmark_strbuf *a, const cmark_strbuf *b) (a->size < b->size) ? -1 : (a->size > b->size) ? 1 : 0; } -int cmark_strbuf_strchr(const cmark_strbuf *buf, int c, int pos) +bufsize_t cmark_strbuf_strchr(const cmark_strbuf *buf, int c, bufsize_t pos) { + // TODO: Bounds check. const unsigned char *p = (unsigned char *)memchr(buf->ptr + pos, c, buf->size - pos); if (!p) return -1; - return (int)(p - (const unsigned char *)buf->ptr); + return (bufsize_t)(p - (const unsigned char *)buf->ptr); } -int cmark_strbuf_strrchr(const cmark_strbuf *buf, int c, int pos) +bufsize_t cmark_strbuf_strrchr(const cmark_strbuf *buf, int c, bufsize_t pos) { - int i; + bufsize_t i; + // TODO: Bounds check. for (i = pos; i >= 0; i--) { if (buf->ptr[i] == (unsigned char) c) return i; @@ -268,17 +282,19 @@ int cmark_strbuf_strrchr(const cmark_strbuf *buf, int c, int pos) return -1; } -void cmark_strbuf_truncate(cmark_strbuf *buf, int len) +void cmark_strbuf_truncate(cmark_strbuf *buf, bufsize_t len) { + // TODO: Check for negative len. if (len < buf->size) { buf->size = len; buf->ptr[buf->size] = '\0'; } } -void cmark_strbuf_drop(cmark_strbuf *buf, int n) +void cmark_strbuf_drop(cmark_strbuf *buf, bufsize_t n) { if (n > 0) { + // TODO: Bounds check. buf->size = buf->size - n; if (buf->size) memmove(buf->ptr, buf->ptr + n, buf->size); @@ -304,7 +320,7 @@ void cmark_strbuf_rtrim(cmark_strbuf *buf) void cmark_strbuf_trim(cmark_strbuf *buf) { - int i = 0; + bufsize_t i = 0; if (!buf->size) return; @@ -322,7 +338,7 @@ void cmark_strbuf_trim(cmark_strbuf *buf) void cmark_strbuf_normalize_whitespace(cmark_strbuf *s) { bool last_char_was_space = false; - int r, w; + bufsize_t r, w; for (r = 0, w = 0; r < s->size; ++r) { switch (s->ptr[r]) { @@ -347,7 +363,7 @@ void cmark_strbuf_normalize_whitespace(cmark_strbuf *s) // Destructively unescape a string: remove backslashes before punctuation chars. extern void cmark_strbuf_unescape(cmark_strbuf *buf) { - int r, w; + bufsize_t r, w; for (r = 0, w = 0; r < buf->size; ++r) { if (buf->ptr[r] == '\\' && cmark_ispunct(buf->ptr[r + 1])) -- cgit v1.2.3 From 1a38daeb81db11ef2acd57690aad36b4ce3fe3da Mon Sep 17 00:00:00 2001 From: Nick Wellnhofer Date: Sat, 30 May 2015 00:38:20 +0200 Subject: Simplify oversizing of strbufs Always add 50% on top of target size. No need for a loop. --- src/buffer.c | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) (limited to 'src/buffer.c') diff --git a/src/buffer.c b/src/buffer.c index 78d0a00..8ec38b0 100644 --- a/src/buffer.c +++ b/src/buffer.c @@ -42,18 +42,15 @@ void cmark_strbuf_grow(cmark_strbuf *buf, bufsize_t target_size) return; if (buf->asize == 0) { - new_size = target_size; new_ptr = NULL; } else { - new_size = buf->asize; new_ptr = buf->ptr; } - /* grow the buffer size by 1.5, until it's big enough - * to fit our target size */ - while (new_size < target_size) - // TODO: Check for overflow. - new_size = (new_size << 1) - (new_size >> 1); + /* Oversize the buffer by 50% to guarantee amortized linear time + * complexity on append operations. */ + // TODO: Check for overflow. + new_size = target_size + target_size / 2; /* round allocation up to multiple of 8 */ // TODO: Check for overflow. -- cgit v1.2.3 From ea23e2b42f05ac4a04154e572fc5ce8c84c29c10 Mon Sep 17 00:00:00 2001 From: Nick Wellnhofer Date: Sun, 7 Jun 2015 13:41:13 +0200 Subject: Check for overflow in cmark_strbuf_grow --- src/buffer.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) (limited to 'src/buffer.c') diff --git a/src/buffer.c b/src/buffer.c index 8ec38b0..8fb2652 100644 --- a/src/buffer.c +++ b/src/buffer.c @@ -36,7 +36,6 @@ void cmark_strbuf_init(cmark_strbuf *buf, bufsize_t initial_size) void cmark_strbuf_grow(cmark_strbuf *buf, bufsize_t target_size) { unsigned char *new_ptr; - bufsize_t new_size; if (target_size <= buf->asize) return; @@ -49,13 +48,18 @@ void cmark_strbuf_grow(cmark_strbuf *buf, bufsize_t target_size) /* Oversize the buffer by 50% to guarantee amortized linear time * complexity on append operations. */ - // TODO: Check for overflow. - new_size = target_size + target_size / 2; + size_t new_size = (size_t)target_size + (size_t)target_size / 2; /* round allocation up to multiple of 8 */ - // TODO: Check for overflow. new_size = (new_size + 7) & ~7; + if (new_size < (size_t)target_size /* Integer overflow. */ + || new_size > BUFSIZE_MAX /* Truncation overflow. */ + ) { + /* Oversize by the maximum possible amount. */ + new_size = BUFSIZE_MAX; + } + new_ptr = (unsigned char *)realloc(new_ptr, new_size); if (!new_ptr) { @@ -63,7 +67,7 @@ void cmark_strbuf_grow(cmark_strbuf *buf, bufsize_t target_size) abort(); } - buf->asize = new_size; + buf->asize = (bufsize_t)new_size; buf->ptr = new_ptr; /* truncate the existing buffer size if necessary */ -- cgit v1.2.3 From a87b62a8eb42ee5bf6307f6c140bb400c860bcdd Mon Sep 17 00:00:00 2001 From: Nick Wellnhofer Date: Sun, 7 Jun 2015 14:01:09 +0200 Subject: Account for null terminator in cmark_strbuf_grow This simplifies overflow checks. --- src/buffer.c | 26 +++++++++++++++++++------- 1 file changed, 19 insertions(+), 7 deletions(-) (limited to 'src/buffer.c') diff --git a/src/buffer.c b/src/buffer.c index 8fb2652..d39828e 100644 --- a/src/buffer.c +++ b/src/buffer.c @@ -15,7 +15,7 @@ unsigned char cmark_strbuf__initbuf[1]; #define ENSURE_SIZE(b, d) \ - if ((d) > b->asize) \ + if ((d) >= b->asize) \ cmark_strbuf_grow(b, (d)); \ #ifndef MIN @@ -33,11 +33,16 @@ void cmark_strbuf_init(cmark_strbuf *buf, bufsize_t initial_size) cmark_strbuf_grow(buf, initial_size); } +void cmark_strbuf_overflow_err() { + fprintf(stderr, "String buffer overflow"); + abort(); +} + void cmark_strbuf_grow(cmark_strbuf *buf, bufsize_t target_size) { unsigned char *new_ptr; - if (target_size <= buf->asize) + if (target_size < buf->asize) return; if (buf->asize == 0) { @@ -50,12 +55,20 @@ void cmark_strbuf_grow(cmark_strbuf *buf, bufsize_t target_size) * complexity on append operations. */ size_t new_size = (size_t)target_size + (size_t)target_size / 2; + /* Account for terminating null byte. */ + new_size += 1; + /* round allocation up to multiple of 8 */ new_size = (new_size + 7) & ~7; if (new_size < (size_t)target_size /* Integer overflow. */ || new_size > BUFSIZE_MAX /* Truncation overflow. */ ) { + if (target_size >= BUFSIZE_MAX) { + /* No space for terminating null byte. */ + cmark_strbuf_overflow_err(); + return; /* unreachable */ + } /* Oversize by the maximum possible amount. */ new_size = BUFSIZE_MAX; } @@ -105,8 +118,7 @@ void cmark_strbuf_set(cmark_strbuf *buf, const unsigned char *data, bufsize_t le cmark_strbuf_clear(buf); } else { if (data != buf->ptr) { - // TODO: Check for overflow. - ENSURE_SIZE(buf, len + 1); + ENSURE_SIZE(buf, len); memmove(buf->ptr, data, len); } buf->size = len; @@ -123,7 +135,7 @@ void cmark_strbuf_sets(cmark_strbuf *buf, const char *string) void cmark_strbuf_putc(cmark_strbuf *buf, int c) { // TODO: Check for overflow. - ENSURE_SIZE(buf, buf->size + 2); + ENSURE_SIZE(buf, buf->size + 1); buf->ptr[buf->size++] = c; buf->ptr[buf->size] = '\0'; } @@ -134,7 +146,7 @@ void cmark_strbuf_put(cmark_strbuf *buf, const unsigned char *data, bufsize_t le return; // TODO: Check for overflow. - ENSURE_SIZE(buf, buf->size + len + 1); + ENSURE_SIZE(buf, buf->size + len); memmove(buf->ptr + buf->size, data, len); buf->size += len; buf->ptr[buf->size] = '\0'; @@ -182,7 +194,7 @@ void cmark_strbuf_vprintf(cmark_strbuf *buf, const char *format, va_list ap) } // TODO: Check for overflow. - ENSURE_SIZE(buf, buf->size + len + 1); + ENSURE_SIZE(buf, buf->size + len); } } -- cgit v1.2.3 From dbfd2eba6427893cb48587d914719402252855b2 Mon Sep 17 00:00:00 2001 From: Nick Wellnhofer Date: Sun, 7 Jun 2015 14:04:20 +0200 Subject: Remove useless code in cmark_strbuf_grow cmark_strbuf_grow will never truncate a buffer. --- src/buffer.c | 5 ----- 1 file changed, 5 deletions(-) (limited to 'src/buffer.c') diff --git a/src/buffer.c b/src/buffer.c index d39828e..f74c8c6 100644 --- a/src/buffer.c +++ b/src/buffer.c @@ -82,11 +82,6 @@ void cmark_strbuf_grow(cmark_strbuf *buf, bufsize_t target_size) buf->asize = (bufsize_t)new_size; buf->ptr = new_ptr; - - /* truncate the existing buffer size if necessary */ - if (buf->size >= buf->asize) - buf->size = buf->asize - 1; - buf->ptr[buf->size] = '\0'; } size_t cmark_strbuf_len(const cmark_strbuf *buf) -- cgit v1.2.3 From 996bcfb2eee238cf9a07d26b90e673f2496cbbec Mon Sep 17 00:00:00 2001 From: Nick Wellnhofer Date: Sun, 7 Jun 2015 14:33:24 +0200 Subject: Check for overflow when growing strbufs Replace macro ENSURE_SIZE with inline function S_strbuf_grow_by that checks for overflow. --- src/buffer.c | 40 +++++++++++++++++++++++++--------------- 1 file changed, 25 insertions(+), 15 deletions(-) (limited to 'src/buffer.c') diff --git a/src/buffer.c b/src/buffer.c index f74c8c6..78be967 100644 --- a/src/buffer.c +++ b/src/buffer.c @@ -4,6 +4,7 @@ #include #include #include +#include #include "config.h" #include "cmark_ctype.h" @@ -14,10 +15,6 @@ */ unsigned char cmark_strbuf__initbuf[1]; -#define ENSURE_SIZE(b, d) \ - if ((d) >= b->asize) \ - cmark_strbuf_grow(b, (d)); \ - #ifndef MIN #define MIN(x,y) ((xsize + add; + + if (target_size < add /* Integer overflow. */ + || target_size > BUFSIZE_MAX /* Truncation overflow. */ + ) { + cmark_strbuf_overflow_err(); + return; /* unreachable */ + } + + if ((bufsize_t)target_size >= buf->asize) + cmark_strbuf_grow(buf, (bufsize_t)target_size); +} + void cmark_strbuf_grow(cmark_strbuf *buf, bufsize_t target_size) { unsigned char *new_ptr; @@ -113,7 +125,8 @@ void cmark_strbuf_set(cmark_strbuf *buf, const unsigned char *data, bufsize_t le cmark_strbuf_clear(buf); } else { if (data != buf->ptr) { - ENSURE_SIZE(buf, len); + if (len >= buf->asize) + cmark_strbuf_grow(buf, len); memmove(buf->ptr, data, len); } buf->size = len; @@ -129,8 +142,7 @@ void cmark_strbuf_sets(cmark_strbuf *buf, const char *string) void cmark_strbuf_putc(cmark_strbuf *buf, int c) { - // TODO: Check for overflow. - ENSURE_SIZE(buf, buf->size + 1); + S_strbuf_grow_by(buf, 1); buf->ptr[buf->size++] = c; buf->ptr[buf->size] = '\0'; } @@ -140,8 +152,7 @@ void cmark_strbuf_put(cmark_strbuf *buf, const unsigned char *data, bufsize_t le if (len <= 0) return; - // TODO: Check for overflow. - ENSURE_SIZE(buf, buf->size + len); + S_strbuf_grow_by(buf, len); memmove(buf->ptr + buf->size, data, len); buf->size += len; buf->ptr[buf->size] = '\0'; @@ -154,10 +165,10 @@ void cmark_strbuf_puts(cmark_strbuf *buf, const char *string) void cmark_strbuf_vprintf(cmark_strbuf *buf, const char *format, va_list ap) { - // TODO: Check for overflow. - const bufsize_t expected_size = buf->size + (strlen(format) * 2); - - ENSURE_SIZE(buf, expected_size); + size_t expected_size = strlen(format); + if (expected_size <= SIZE_MAX / 2) + expected_size *= 2; + S_strbuf_grow_by(buf, expected_size); while (1) { va_list args; @@ -188,8 +199,7 @@ void cmark_strbuf_vprintf(cmark_strbuf *buf, const char *format, va_list ap) break; } - // TODO: Check for overflow. - ENSURE_SIZE(buf, buf->size + len); + S_strbuf_grow_by(buf, len); } } -- cgit v1.2.3 From ad94c00083285703144e4874642fb89dac2f5446 Mon Sep 17 00:00:00 2001 From: Nick Wellnhofer Date: Sun, 7 Jun 2015 14:42:38 +0200 Subject: Check for negative lengths in buffer.c --- src/buffer.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) (limited to 'src/buffer.c') diff --git a/src/buffer.c b/src/buffer.c index 78be967..db575ed 100644 --- a/src/buffer.c +++ b/src/buffer.c @@ -25,8 +25,7 @@ void cmark_strbuf_init(cmark_strbuf *buf, bufsize_t initial_size) buf->size = 0; buf->ptr = cmark_strbuf__initbuf; - // TODO: Check for negative initial_size. - if (initial_size) + if (initial_size > 0) cmark_strbuf_grow(buf, initial_size); } @@ -216,8 +215,9 @@ void cmark_strbuf_copy_cstr(char *data, bufsize_t datasize, const cmark_strbuf * { bufsize_t copylen; - // TODO: Check negative datasize. - assert(data && datasize && buf); + assert(buf); + if (!data || datasize <= 0) + return; data[0] = '\0'; @@ -258,8 +258,7 @@ void cmark_strbuf_attach(cmark_strbuf *buf, unsigned char *ptr, bufsize_t asize) if (ptr) { buf->ptr = ptr; buf->size = strlen((char *)ptr); - // TODO: Check for negative asize. - if (asize) + if (asize > 0) // TODO: Check for overflow. buf->asize = (asize < buf->size) ? buf->size + 1 : asize; else /* pass 0 to fall back on strlen + 1 */ @@ -302,7 +301,9 @@ bufsize_t cmark_strbuf_strrchr(const cmark_strbuf *buf, int c, bufsize_t pos) void cmark_strbuf_truncate(cmark_strbuf *buf, bufsize_t len) { - // TODO: Check for negative len. + if (len < 0) + len = 0; + if (len < buf->size) { buf->size = len; buf->ptr[buf->size] = '\0'; -- cgit v1.2.3 From 09cee35add8c8686a3982f3f31de283450b625eb Mon Sep 17 00:00:00 2001 From: Nick Wellnhofer Date: Sun, 7 Jun 2015 14:49:18 +0200 Subject: Fix check in cmark_strbuf_vprintf Avoid potential overflow and allow for different bufsize types. --- src/buffer.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'src/buffer.c') diff --git a/src/buffer.c b/src/buffer.c index db575ed..08192da 100644 --- a/src/buffer.c +++ b/src/buffer.c @@ -192,8 +192,7 @@ void cmark_strbuf_vprintf(cmark_strbuf *buf, const char *format, va_list ap) abort(); } - // TODO: Check for overflow. - if (len + 1 <= buf->asize - buf->size) { + if ((size_t)len < (size_t)(buf->asize - buf->size)) { buf->size += len; break; } -- cgit v1.2.3 From b0a0cabbee704740169c9e493d61fcf786251601 Mon Sep 17 00:00:00 2001 From: Nick Wellnhofer Date: Sun, 7 Jun 2015 15:01:43 +0200 Subject: Remove unused function cmark_strbuf_attach This function was missing a couple of range checks that I'm too lazy to fix. --- src/buffer.c | 18 ------------------ 1 file changed, 18 deletions(-) (limited to 'src/buffer.c') diff --git a/src/buffer.c b/src/buffer.c index 08192da..bc2e38f 100644 --- a/src/buffer.c +++ b/src/buffer.c @@ -250,24 +250,6 @@ unsigned char *cmark_strbuf_detach(cmark_strbuf *buf) return data; } -void cmark_strbuf_attach(cmark_strbuf *buf, unsigned char *ptr, bufsize_t asize) -{ - cmark_strbuf_free(buf); - - if (ptr) { - buf->ptr = ptr; - buf->size = strlen((char *)ptr); - if (asize > 0) - // TODO: Check for overflow. - buf->asize = (asize < buf->size) ? buf->size + 1 : asize; - else /* pass 0 to fall back on strlen + 1 */ - // TODO: Check for overflow. - buf->asize = buf->size + 1; - } else { - cmark_strbuf_grow(buf, asize); - } -} - int cmark_strbuf_cmp(const cmark_strbuf *a, const cmark_strbuf *b) { int result = memcmp(a->ptr, b->ptr, MIN(a->size, b->size)); -- cgit v1.2.3 From e2b4500209821198413fb7fb6127060034b64c87 Mon Sep 17 00:00:00 2001 From: Nick Wellnhofer Date: Sun, 7 Jun 2015 15:11:07 +0200 Subject: Missing bounds checks in buffer.c --- src/buffer.c | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) (limited to 'src/buffer.c') diff --git a/src/buffer.c b/src/buffer.c index bc2e38f..19ea677 100644 --- a/src/buffer.c +++ b/src/buffer.c @@ -259,7 +259,11 @@ int cmark_strbuf_cmp(const cmark_strbuf *a, const cmark_strbuf *b) bufsize_t cmark_strbuf_strchr(const cmark_strbuf *buf, int c, bufsize_t pos) { - // TODO: Bounds check. + if (pos >= buf->size) + return -1; + if (pos < 0) + pos = 0; + const unsigned char *p = (unsigned char *)memchr(buf->ptr + pos, c, buf->size - pos); if (!p) return -1; @@ -269,10 +273,12 @@ bufsize_t cmark_strbuf_strchr(const cmark_strbuf *buf, int c, bufsize_t pos) bufsize_t cmark_strbuf_strrchr(const cmark_strbuf *buf, int c, bufsize_t pos) { - bufsize_t i; + if (pos < 0 || buf->size == 0) + return -1; + if (pos >= buf->size) + pos = buf->size - 1; - // TODO: Bounds check. - for (i = pos; i >= 0; i--) { + for (bufsize_t i = pos; i >= 0; i--) { if (buf->ptr[i] == (unsigned char) c) return i; } @@ -294,7 +300,8 @@ void cmark_strbuf_truncate(cmark_strbuf *buf, bufsize_t len) void cmark_strbuf_drop(cmark_strbuf *buf, bufsize_t n) { if (n > 0) { - // TODO: Bounds check. + if (n > buf->size) + n = buf->size; buf->size = buf->size - n; if (buf->size) memmove(buf->ptr, buf->ptr + n, buf->size); -- cgit v1.2.3 From d49d3fd7bab4a8734e5f22318e3fb538bfe20dbb Mon Sep 17 00:00:00 2001 From: Nick Wellnhofer Date: Sun, 7 Jun 2015 16:48:01 +0200 Subject: Change return type of cmark_strbuf_len --- src/buffer.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/buffer.c') diff --git a/src/buffer.c b/src/buffer.c index 19ea677..efee41d 100644 --- a/src/buffer.c +++ b/src/buffer.c @@ -95,7 +95,7 @@ void cmark_strbuf_grow(cmark_strbuf *buf, bufsize_t target_size) buf->ptr = new_ptr; } -size_t cmark_strbuf_len(const cmark_strbuf *buf) +bufsize_t cmark_strbuf_len(const cmark_strbuf *buf) { return buf->size; } -- cgit v1.2.3 From 0641c5e4e9727ddde0d2be1aebe3fd7009d010f5 Mon Sep 17 00:00:00 2001 From: Nick Wellnhofer Date: Sun, 7 Jun 2015 17:44:11 +0200 Subject: Helper to safely call strlen --- src/buffer.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'src/buffer.c') diff --git a/src/buffer.c b/src/buffer.c index efee41d..7d16af8 100644 --- a/src/buffer.c +++ b/src/buffer.c @@ -136,7 +136,7 @@ void cmark_strbuf_set(cmark_strbuf *buf, const unsigned char *data, bufsize_t le void cmark_strbuf_sets(cmark_strbuf *buf, const char *string) { cmark_strbuf_set(buf, (const unsigned char *)string, - string ? strlen(string) : 0); + string ? cmark_strbuf_safe_strlen(string) : 0); } void cmark_strbuf_putc(cmark_strbuf *buf, int c) @@ -159,7 +159,8 @@ void cmark_strbuf_put(cmark_strbuf *buf, const unsigned char *data, bufsize_t le void cmark_strbuf_puts(cmark_strbuf *buf, const char *string) { - cmark_strbuf_put(buf, (const unsigned char *)string, strlen(string)); + cmark_strbuf_put(buf, (const unsigned char *)string, + cmark_strbuf_safe_strlen(string)); } void cmark_strbuf_vprintf(cmark_strbuf *buf, const char *format, va_list ap) -- cgit v1.2.3