From: "Daniel P. Berrange" <berra...@redhat.com> A variety of places were snprintf()ing into a fixed length filename buffer. Some of the buffers were stack allocated, while another was heap allocated with g_malloc(). Switch them all to heap allocated using g_strdup_printf() avoiding arbitrary length restrictions.
This also facilitates later patches which will want to populate the filename by calling external functions which do not support use of a pre-allocated buffer. Signed-off-by: Daniel P. Berrange <berra...@redhat.com> Message-Id: <1453202071-10289-2-git-send-email-berra...@redhat.com> Signed-off-by: Paolo Bonzini <pbonz...@redhat.com> --- qemu-char.c | 86 +++++++++++++++++++++++++++++++------------------------------ 1 file changed, 44 insertions(+), 42 deletions(-) diff --git a/qemu-char.c b/qemu-char.c index e133f4f..8e96f90 100644 --- a/qemu-char.c +++ b/qemu-char.c @@ -88,39 +88,37 @@ #define READ_BUF_LEN 4096 #define READ_RETRIES 10 -#define CHR_MAX_FILENAME_SIZE 256 #define TCP_MAX_FDS 16 /***********************************************************/ /* Socket address helpers */ -static int SocketAddress_to_str(char *dest, int max_len, - const char *prefix, SocketAddress *addr, - bool is_listen, bool is_telnet) +static char *SocketAddress_to_str(const char *prefix, SocketAddress *addr, + bool is_listen, bool is_telnet) { switch (addr->type) { case SOCKET_ADDRESS_KIND_INET: - return snprintf(dest, max_len, "%s%s:%s:%s%s", prefix, - is_telnet ? "telnet" : "tcp", addr->u.inet->host, - addr->u.inet->port, is_listen ? ",server" : ""); + return g_strdup_printf("%s%s:%s:%s%s", prefix, + is_telnet ? "telnet" : "tcp", addr->u.inet->host, + addr->u.inet->port, is_listen ? ",server" : ""); break; case SOCKET_ADDRESS_KIND_UNIX: - return snprintf(dest, max_len, "%sunix:%s%s", prefix, - addr->u.q_unix->path, is_listen ? ",server" : ""); + return g_strdup_printf("%sunix:%s%s", prefix, + addr->u.q_unix->path, + is_listen ? ",server" : ""); break; case SOCKET_ADDRESS_KIND_FD: - return snprintf(dest, max_len, "%sfd:%s%s", prefix, addr->u.fd->str, - is_listen ? ",server" : ""); + return g_strdup_printf("%sfd:%s%s", prefix, addr->u.fd->str, + is_listen ? ",server" : ""); break; default: abort(); } } -static int sockaddr_to_str(char *dest, int max_len, - struct sockaddr_storage *ss, socklen_t ss_len, - struct sockaddr_storage *ps, socklen_t ps_len, - bool is_listen, bool is_telnet) +static char *sockaddr_to_str(struct sockaddr_storage *ss, socklen_t ss_len, + struct sockaddr_storage *ps, socklen_t ps_len, + bool is_listen, bool is_telnet) { char shost[NI_MAXHOST], sserv[NI_MAXSERV]; char phost[NI_MAXHOST], pserv[NI_MAXSERV]; @@ -129,9 +127,9 @@ static int sockaddr_to_str(char *dest, int max_len, switch (ss->ss_family) { #ifndef _WIN32 case AF_UNIX: - return snprintf(dest, max_len, "unix:%s%s", - ((struct sockaddr_un *)(ss))->sun_path, - is_listen ? ",server" : ""); + return g_strdup_printf("unix:%s%s", + ((struct sockaddr_un *)(ss))->sun_path, + is_listen ? ",server" : ""); #endif case AF_INET6: left = "["; @@ -142,14 +140,14 @@ static int sockaddr_to_str(char *dest, int max_len, sserv, sizeof(sserv), NI_NUMERICHOST | NI_NUMERICSERV); getnameinfo((struct sockaddr *) ps, ps_len, phost, sizeof(phost), pserv, sizeof(pserv), NI_NUMERICHOST | NI_NUMERICSERV); - return snprintf(dest, max_len, "%s:%s%s%s:%s%s <-> %s%s%s:%s", - is_telnet ? "telnet" : "tcp", - left, shost, right, sserv, - is_listen ? ",server" : "", - left, phost, right, pserv); + return g_strdup_printf("%s:%s%s%s:%s%s <-> %s%s%s:%s", + is_telnet ? "telnet" : "tcp", + left, shost, right, sserv, + is_listen ? ",server" : "", + left, phost, right, pserv); default: - return snprintf(dest, max_len, "unknown"); + return g_strdup_printf("unknown"); } } @@ -1074,15 +1072,18 @@ static CharDriverState *qemu_chr_open_pipe(const char *id, { ChardevHostdev *opts = backend->u.pipe; int fd_in, fd_out; - char filename_in[CHR_MAX_FILENAME_SIZE]; - char filename_out[CHR_MAX_FILENAME_SIZE]; + char *filename_in; + char *filename_out; const char *filename = opts->device; ChardevCommon *common = qapi_ChardevHostdev_base(backend->u.pipe); - snprintf(filename_in, CHR_MAX_FILENAME_SIZE, "%s.in", filename); - snprintf(filename_out, CHR_MAX_FILENAME_SIZE, "%s.out", filename); + + filename_in = g_strdup_printf("%s.in", filename); + filename_out = g_strdup_printf("%s.out", filename); TFR(fd_in = qemu_open(filename_in, O_RDWR | O_BINARY)); TFR(fd_out = qemu_open(filename_out, O_RDWR | O_BINARY)); + g_free(filename_in); + g_free(filename_out); if (fd_in < 0 || fd_out < 0) { if (fd_in >= 0) close(fd_in); @@ -2115,7 +2116,7 @@ static int win_chr_pipe_init(CharDriverState *chr, const char *filename, OVERLAPPED ov; int ret; DWORD size; - char openname[CHR_MAX_FILENAME_SIZE]; + char *openname; s->fpipe = TRUE; @@ -2130,11 +2131,12 @@ static int win_chr_pipe_init(CharDriverState *chr, const char *filename, goto fail; } - snprintf(openname, sizeof(openname), "\\\\.\\pipe\\%s", filename); + openname = g_strdup_printf("\\\\.\\pipe\\%s", filename); s->hcom = CreateNamedPipe(openname, PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED, PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT, MAXCONNECT, NSENDBUF, NRECVBUF, NTIMEOUT, NULL); + g_free(openname); if (s->hcom == INVALID_HANDLE_VALUE) { error_setg(errp, "Failed CreateNamedPipe (%lu)", GetLastError()); s->hcom = NULL; @@ -2913,8 +2915,9 @@ static void tcp_chr_disconnect(CharDriverState *chr) s->chan = NULL; closesocket(s->fd); s->fd = -1; - SocketAddress_to_str(chr->filename, CHR_MAX_FILENAME_SIZE, - "disconnected:", s->addr, s->is_listen, s->is_telnet); + g_free(chr->filename); + chr->filename = SocketAddress_to_str("disconnected:", s->addr, + s->is_listen, s->is_telnet); qemu_chr_be_event(chr, CHR_EVENT_CLOSED); if (s->reconnect_time) { qemu_chr_socket_restart_timer(chr); @@ -2989,16 +2992,16 @@ static void tcp_chr_connect(void *opaque) socklen_t ss_len = sizeof(ss), ps_len = sizeof(ps); memset(&ss, 0, ss_len); + g_free(chr->filename); if (getsockname(s->fd, (struct sockaddr *) &ss, &ss_len) != 0) { - snprintf(chr->filename, CHR_MAX_FILENAME_SIZE, - "Error in getsockname: %s\n", strerror(errno)); + chr->filename = g_strdup_printf("Error in getsockname: %s\n", + strerror(errno)); } else if (getpeername(s->fd, (struct sockaddr *) &ps, &ps_len) != 0) { - snprintf(chr->filename, CHR_MAX_FILENAME_SIZE, - "Error in getpeername: %s\n", strerror(errno)); + chr->filename = g_strdup_printf("Error in getpeername: %s\n", + strerror(errno)); } else { - sockaddr_to_str(chr->filename, CHR_MAX_FILENAME_SIZE, - &ss, ss_len, &ps, ps_len, - s->is_listen, s->is_telnet); + chr->filename = sockaddr_to_str(&ss, ss_len, &ps, ps_len, + s->is_listen, s->is_telnet); } s->connected = 1; @@ -4335,9 +4338,8 @@ static CharDriverState *qmp_chardev_open_socket(const char *id, /* be isn't opened until we get a connection */ chr->explicit_be_open = true; - chr->filename = g_malloc(CHR_MAX_FILENAME_SIZE); - SocketAddress_to_str(chr->filename, CHR_MAX_FILENAME_SIZE, "disconnected:", - addr, is_listen, is_telnet); + chr->filename = SocketAddress_to_str("disconnected:", + addr, is_listen, is_telnet); if (is_listen) { if (is_telnet) { -- 1.8.3.1