summaryrefslogtreecommitdiffstats
path: root/usr.bin/tar/util.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr.bin/tar/util.c')
-rw-r--r--usr.bin/tar/util.c36
1 files changed, 21 insertions, 15 deletions
diff --git a/usr.bin/tar/util.c b/usr.bin/tar/util.c
index 66e356d..441fab2 100644
--- a/usr.bin/tar/util.c
+++ b/usr.bin/tar/util.c
@@ -45,27 +45,33 @@ void
safe_fprintf(FILE *f, const char *fmt, ...)
{
char *buff;
- char *buffheap;
- char buffstack[256];
- int bufflength;
+ char *buff_heap;
+ int buff_length;
int length;
va_list ap;
char *p;
+ char buff_stack[256];
- /* Use a stack-allocated buffer if we can. */
- buffheap = NULL;
- bufflength = 256;
- buff = buffstack;
+ /* Use a stack-allocated buffer if we can, for speed and safety. */
+ buff_heap = NULL;
+ buff_length = sizeof(buff_stack);
+ buff = buff_stack;
va_start(ap, fmt);
- length = vsnprintf(buff, bufflength, fmt, ap);
+ length = vsnprintf(buff, buff_length, fmt, ap);
+ va_end(ap);
/* If the result is too large, allocate a buffer on the heap. */
- if (length >= bufflength) {
- bufflength = length+1;
- buff = buffheap = malloc(bufflength);
- length = vsnprintf(buff, bufflength, fmt, ap);
+ if (length >= buff_length) {
+ buff_length = length+1;
+ buff_heap = malloc(buff_length);
+ /* Failsafe: use the truncated string if malloc fails. */
+ if (buff_heap != NULL) {
+ buff = buff_heap;
+ va_start(ap, fmt);
+ length = vsnprintf(buff, buff_length, fmt, ap);
+ va_end(ap);
+ }
}
- va_end(ap);
for (p=buff; *p != '\0'; p++) {
unsigned char c = *p;
@@ -89,8 +95,8 @@ safe_fprintf(FILE *f, const char *fmt, ...)
}
}
/* If we allocated a heap-based buffer, free it now. */
- if (buffheap != NULL)
- free(buffheap);
+ if (buff_heap != NULL)
+ free(buff_heap);
}
static void
OpenPOWER on IntegriCloud