diff --git a/newlib/ChangeLog b/newlib/ChangeLog index b86c96282..ff9f034e2 100644 --- a/newlib/ChangeLog +++ b/newlib/ChangeLog @@ -1,4 +1,9 @@ -2006-11-29 Kazunori Asayama +2006-11-29 Eric Blake + + * libc/stdio/fvwrite.c (__sfvwrite_r): Avoid off-by-one error in + asprintf, as well as quadratic realloc behavior. + +2006-11-29 Kazunori Asayama _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;