Fix broken IoVprintf().

You can't call vsnprintf() on the same va_list more than once! I learned
this the hard way with StreamVprintf().
This commit is contained in:
Jordan Bancino 2023-03-18 14:55:04 +00:00
parent 5289c16e2b
commit 6c9e939b9f
2 changed files with 14 additions and 33 deletions

View file

@ -12,8 +12,8 @@ Milestone: v0.3.0
----------------- -----------------
[~] Stream API [~] Stream API
[~] Implementation [x] Implementation
[ ] Convert all code that deals with I/O [x] Convert all code that deals with I/O
[!] Multi-output (proof of concept) [!] Multi-output (proof of concept)
[!] Memory streams (proof of concept) [!] Memory streams (proof of concept)
[ ] TLS [ ] TLS

View file

@ -25,8 +25,9 @@
#include <Memory.h> #include <Memory.h>
#include <errno.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <fcntl.h> #include <fcntl.h>
struct Io struct Io
@ -133,8 +134,9 @@ IoClose(Io * io)
int int
IoVprintf(Io * io, const char *fmt, va_list ap) IoVprintf(Io * io, const char *fmt, va_list ap)
{ {
char *buf; char *buf = NULL;
int write; size_t bufSize = 0;
FILE *fp;
int ret; int ret;
@ -143,42 +145,21 @@ IoVprintf(Io * io, const char *fmt, va_list ap)
return -1; return -1;
} }
buf = Malloc(IO_BUFFER); fp = open_memstream(&buf, &bufSize);
if (!buf) if (!fp)
{ {
return -1; return -1;
} }
write = vsnprintf(buf, IO_BUFFER, fmt, ap); ret = vfprintf(fp, fmt, ap);
fclose(fp);
if (write < 0) if (ret >= 0)
{ {
Free(buf); ret = IoWrite(io, buf, bufSize);
return write;
} }
/* Number of bytes to write exceeded buffer size; this should be free(buf); /* Allocated by stdlib, not Memory API */
* rare, but may occasionally happen. If it does, realloc to the
* correct size and try again. */
if (write >= IO_BUFFER)
{
char *new = Realloc(buf, write + 1);
if (!new)
{
Free(buf);
return -1;
}
buf = new;
/* This time we don't care about the return value */
vsnprintf(buf, write, fmt, ap);
}
ret = IoWrite(io, buf, write);
Free(buf);
return ret; return ret;
} }