From c4c7f13966ecbc0d4047a51fc49720b82cd6c291 Mon Sep 17 00:00:00 2001 From: Jeff Johnston Date: Wed, 29 Nov 2006 21:36:54 +0000 Subject: 2006-11-29 Eric Blake * libc/stdio/fvwrite.c (__sfvwrite_r): Avoid off-by-one error in asprintf, as well as quadratic realloc behavior. --- newlib/libc/stdio/fvwrite.c | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) (limited to 'newlib/libc/stdio/fvwrite.c') diff --git a/newlib/libc/stdio/fvwrite.c b/newlib/libc/stdio/fvwrite.c index 1cb6e0d1e..ef461d31d 100644 --- a/newlib/libc/stdio/fvwrite.c +++ b/newlib/libc/stdio/fvwrite.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1990 The Regents of the University of California. + * Copyright (c) 1990, 2006 The Regents of the University of California. * All rights reserved. * * Redistribution and use in source and binary forms are permitted @@ -127,13 +127,23 @@ _DEFUN(__sfvwrite_r, (ptr, fp, uio), w = fp->_w; if (fp->_flags & __SSTR) { - if (len > w && fp->_flags & __SMBF) + if (len >= w && fp->_flags & __SMBF) { /* must be asprintf family */ unsigned char *ptr; int curpos = (fp->_p - fp->_bf._base); + /* Choose a geometric growth factor to avoid + quadratic realloc behavior, but use a rate less + than (1+sqrt(5))/2 to accomodate malloc + overhead. asprintf EXPECTS us to overallocate, so + that it can add a trailing \0 without + reallocating. The new allocation should thus be + max(prev_size*1.5, curpos+len+1). */ + int newsize = fp->_bf._size * 3 / 2; + if (newsize < curpos + len + 1) + newsize = curpos + len + 1; ptr = (unsigned char *)_realloc_r (_REENT, fp->_bf._base, - curpos + len); + newsize); if (!ptr) { /* Free buffer which is no longer used. */ @@ -142,8 +152,9 @@ _DEFUN(__sfvwrite_r, (ptr, fp, uio), } fp->_bf._base = ptr; fp->_p = ptr + curpos; - fp->_bf._size = curpos + len; - w = fp->_w = len; + fp->_bf._size = newsize; + w = len; + fp->_w = newsize - curpos; } if (len < w) w = len; -- cgit v1.2.3