mirror of
git://sourceware.org/git/newlib-cygwin.git
synced 2025-01-19 04:49:25 +08:00
61ccd3f94f
So far, the printf family of functions has two output helper functions called __sprint_r and __sfputs_r. Both are called from all variants of vfprintf as well as vfwprintf. There are also analogue helper functions for the string-creating functions vsprintf/vswprintf called __ssprint_r and __ssputs_r. However, the helpers are built once when building vfprintf/vsprintf with the INTEGER_ONLY flag, and then they are part of the vfiprintf.c and vsiprintf.c files. The problem is this: Even if a process only calls vfwprintf or the non-INTEGER_ONLY vfprintf it will always have to include the INTEGER_ONLY vfiprintf. Otherwise the helper functions are undefined. Analogue for the string-creating functions. That's a useless waste of space by including one (or two) big, unused function, if newlib is linked in statically. Create new files to define the printf output helpers separately and split them into byte-oriented and wide-char-oriented functions. This allows to link only the required functions. Also, simplify the string output helpers and fix a potential (but unlikely) buffer overflow in __ssprint_r. Fixes: 8a0efa53e449 ("import newlib-2000-02-17 snapshot") Fixes: 6121968b198d ("* libc/include/stdio.h (__VALIST): Guard against multiple definition.") Signed-off-by: Corinna Vinschen <corinna@vinschen.de>
70 lines
1.5 KiB
C
70 lines
1.5 KiB
C
#include <newlib.h>
|
|
|
|
#include <reent.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <errno.h>
|
|
|
|
int
|
|
__ssputs_r (struct _reent *ptr,
|
|
FILE *fp,
|
|
const char *buf,
|
|
size_t len)
|
|
{
|
|
register int w;
|
|
|
|
w = fp->_w;
|
|
if (len >= w && fp->_flags & (__SMBF | __SOPT)) {
|
|
/* must be asprintf family */
|
|
unsigned char *str;
|
|
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;
|
|
if (fp->_flags & __SOPT)
|
|
{
|
|
/* asnprintf leaves original buffer alone. */
|
|
str = (unsigned char *)_malloc_r (ptr, newsize);
|
|
if (!str)
|
|
goto err;
|
|
memcpy (str, fp->_bf._base, curpos);
|
|
fp->_flags = (fp->_flags & ~__SOPT) | __SMBF;
|
|
}
|
|
else
|
|
{
|
|
str = (unsigned char *)_realloc_r (ptr, fp->_bf._base,
|
|
newsize);
|
|
if (!str) {
|
|
/* Free unneeded buffer. */
|
|
_free_r (ptr, fp->_bf._base);
|
|
goto err;
|
|
}
|
|
}
|
|
fp->_bf._base = str;
|
|
fp->_p = str + curpos;
|
|
fp->_bf._size = newsize;
|
|
w = len;
|
|
fp->_w = newsize - curpos;
|
|
}
|
|
if (len < w)
|
|
w = len;
|
|
memmove ((void *) fp->_p, (void *) buf, (size_t) (w));
|
|
fp->_w -= w;
|
|
fp->_p += w;
|
|
|
|
return 0;
|
|
|
|
err:
|
|
_REENT_ERRNO(ptr) = ENOMEM;
|
|
fp->_flags |= __SERR;
|
|
return EOF;
|
|
}
|