diff options
Diffstat (limited to 'newlib/libc/stdio/fvwrite.c')
-rw-r--r-- | newlib/libc/stdio/fvwrite.c | 21 |
1 files changed, 16 insertions, 5 deletions
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; |