diff options
| author | Nick Wellnhofer <wellnhofer@aevum.de> | 2015-06-07 14:01:09 +0200 | 
|---|---|---|
| committer | Nick Wellnhofer <wellnhofer@aevum.de> | 2015-06-07 21:42:15 +0200 | 
| commit | a87b62a8eb42ee5bf6307f6c140bb400c860bcdd (patch) | |
| tree | c394abd35342a28c33bf9fa33fb18faabf331c05 | |
| parent | ea23e2b42f05ac4a04154e572fc5ce8c84c29c10 (diff) | |
Account for null terminator in cmark_strbuf_grow
This simplifies overflow checks.
| -rw-r--r-- | src/buffer.c | 26 | ||||
| -rw-r--r-- | src/buffer.h | 3 | 
2 files changed, 22 insertions, 7 deletions
| 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);  	}  } diff --git a/src/buffer.h b/src/buffer.h index 99e6feb..526276d 100644 --- a/src/buffer.h +++ b/src/buffer.h @@ -72,6 +72,9 @@ void cmark_strbuf_trim(cmark_strbuf *buf);  void cmark_strbuf_normalize_whitespace(cmark_strbuf *s);  void cmark_strbuf_unescape(cmark_strbuf *s); +/* Print error and abort. */ +void cmark_strbuf_overflow_err(void); +  #ifdef __cplusplus  }  #endif | 
