diff options
author | peter <peter@FreeBSD.org> | 1997-07-06 08:42:37 +0000 |
---|---|---|
committer | peter <peter@FreeBSD.org> | 1997-07-06 08:42:37 +0000 |
commit | 0fd1a37f272d02ad6c2f6034ea52214e2e970d72 (patch) | |
tree | 12d386ba461684166c325000dc02e6fabbb397c6 /lib/libc/stdio | |
parent | b803021f6d0b7420534aafcba42db12a74bb3331 (diff) | |
download | FreeBSD-src-0fd1a37f272d02ad6c2f6034ea52214e2e970d72.zip FreeBSD-src-0fd1a37f272d02ad6c2f6034ea52214e2e970d72.tar.gz |
Rework previous commit.. I was confused by the number of diffs in the PR
and forgot what I was trying to do originally and accidently zapped
a feature. :-] The problem is that we are converting a counted buffer in
a malloc pool into a null terminated C-style string. I was calling realloc
originally to shrink the buffer to the desired size. If realloc failed, we
still returned the valid buffer - the only thing wrong was it was a tad
too large. The previous commit disabled this.
This commit now handles the three cases..
1: the buffer is exactly right for the null byte to terminate the
string (we don't call realloc).
2: it's got h.left = 0, so we must expand it to make room. If realloc
fails here, it's fatal.
3: if there's too much room, we realloc to shrink it - a failed realloc
is not fatal, we use the original buffer which is still valid.
Diffstat (limited to 'lib/libc/stdio')
-rw-r--r-- | lib/libc/stdio/vasprintf.c | 37 |
1 files changed, 29 insertions, 8 deletions
diff --git a/lib/libc/stdio/vasprintf.c b/lib/libc/stdio/vasprintf.c index fde3d8b..7b75b2c 100644 --- a/lib/libc/stdio/vasprintf.c +++ b/lib/libc/stdio/vasprintf.c @@ -24,7 +24,7 @@ */ #if defined(LIBC_RCS) && !defined(lint) -static char rcsid[] = "$Id: vasprintf.c,v 1.5 1997/02/22 15:02:39 peter Exp $"; +static char rcsid[] = "$Id: vasprintf.c,v 1.6 1997/07/06 07:54:56 peter Exp $"; #endif /* LIBC_RCS and not lint */ #include <stdio.h> @@ -104,17 +104,38 @@ vasprintf(str, fmt, ap) } ret = vfprintf(f, fmt, ap); fclose(f); - if (ret < 0) { + + /* + * clean up the wreckage. Did writehook fail or did something else + * in stdio explode perhaps? + */ + if (h.base == NULL) /* realloc failed in writehook */ + return (-1); + if (ret < 0) { /* something else? */ free(h.base); return (-1); } - if (h.base == NULL) /* failed to realloc in writehook */ - return (-1); - *str = realloc(h.base, (size_t)(h.size - h.left + 1)); - if (*str == NULL) { /* failed to realloc it to actual size */ - free(h.base); - return (-1); + /* + * At this point, we have a non-null terminated string in a + * buffer. There may not be enough room to null-terminate it + * (h.left == 0) - if realloc failes to expand it, it's fatal. + * If we were merely trying to shrink the buffer, a realloc failure + * is not [yet] fatal. Note that when realloc returns NULL, + * the original buffer is left allocated and valid. + */ + if (h.left == 1) /* exact fit, do not realloc */ + *str = h.base; + else { + *str = realloc(h.base, (size_t)(h.size - h.left + 1)); + if (*str == NULL) { + /* failed to expand? - fatal */ + if (h.left == 0) { + free(h.base); + return (-1); + } + *str = h.base; /* use oversize original buffer */ + } } (*str)[h.size - h.left] = '\0'; return (ret); |