char: remove fixed length filename allocation

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 <berrange@redhat.com>
Message-Id: <1453202071-10289-2-git-send-email-berrange@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
This commit is contained in:
Daniel P. Berrange 2016-01-19 11:14:28 +00:00 committed by Paolo Bonzini
parent 3db34bf64a
commit 0ff0fad23d

View File

@ -88,39 +88,37 @@
#define READ_BUF_LEN 4096 #define READ_BUF_LEN 4096
#define READ_RETRIES 10 #define READ_RETRIES 10
#define CHR_MAX_FILENAME_SIZE 256
#define TCP_MAX_FDS 16 #define TCP_MAX_FDS 16
/***********************************************************/ /***********************************************************/
/* Socket address helpers */ /* Socket address helpers */
static int SocketAddress_to_str(char *dest, int max_len, static char *SocketAddress_to_str(const char *prefix, SocketAddress *addr,
const char *prefix, SocketAddress *addr, bool is_listen, bool is_telnet)
bool is_listen, bool is_telnet)
{ {
switch (addr->type) { switch (addr->type) {
case SOCKET_ADDRESS_KIND_INET: case SOCKET_ADDRESS_KIND_INET:
return snprintf(dest, max_len, "%s%s:%s:%s%s", prefix, return g_strdup_printf("%s%s:%s:%s%s", prefix,
is_telnet ? "telnet" : "tcp", addr->u.inet->host, is_telnet ? "telnet" : "tcp", addr->u.inet->host,
addr->u.inet->port, is_listen ? ",server" : ""); addr->u.inet->port, is_listen ? ",server" : "");
break; break;
case SOCKET_ADDRESS_KIND_UNIX: case SOCKET_ADDRESS_KIND_UNIX:
return snprintf(dest, max_len, "%sunix:%s%s", prefix, return g_strdup_printf("%sunix:%s%s", prefix,
addr->u.q_unix->path, is_listen ? ",server" : ""); addr->u.q_unix->path,
is_listen ? ",server" : "");
break; break;
case SOCKET_ADDRESS_KIND_FD: case SOCKET_ADDRESS_KIND_FD:
return snprintf(dest, max_len, "%sfd:%s%s", prefix, addr->u.fd->str, return g_strdup_printf("%sfd:%s%s", prefix, addr->u.fd->str,
is_listen ? ",server" : ""); is_listen ? ",server" : "");
break; break;
default: default:
abort(); abort();
} }
} }
static int sockaddr_to_str(char *dest, int max_len, static char *sockaddr_to_str(struct sockaddr_storage *ss, socklen_t ss_len,
struct sockaddr_storage *ss, socklen_t ss_len, struct sockaddr_storage *ps, socklen_t ps_len,
struct sockaddr_storage *ps, socklen_t ps_len, bool is_listen, bool is_telnet)
bool is_listen, bool is_telnet)
{ {
char shost[NI_MAXHOST], sserv[NI_MAXSERV]; char shost[NI_MAXHOST], sserv[NI_MAXSERV];
char phost[NI_MAXHOST], pserv[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) { switch (ss->ss_family) {
#ifndef _WIN32 #ifndef _WIN32
case AF_UNIX: case AF_UNIX:
return snprintf(dest, max_len, "unix:%s%s", return g_strdup_printf("unix:%s%s",
((struct sockaddr_un *)(ss))->sun_path, ((struct sockaddr_un *)(ss))->sun_path,
is_listen ? ",server" : ""); is_listen ? ",server" : "");
#endif #endif
case AF_INET6: case AF_INET6:
left = "["; left = "[";
@ -142,14 +140,14 @@ static int sockaddr_to_str(char *dest, int max_len,
sserv, sizeof(sserv), NI_NUMERICHOST | NI_NUMERICSERV); sserv, sizeof(sserv), NI_NUMERICHOST | NI_NUMERICSERV);
getnameinfo((struct sockaddr *) ps, ps_len, phost, sizeof(phost), getnameinfo((struct sockaddr *) ps, ps_len, phost, sizeof(phost),
pserv, sizeof(pserv), NI_NUMERICHOST | NI_NUMERICSERV); pserv, sizeof(pserv), NI_NUMERICHOST | NI_NUMERICSERV);
return snprintf(dest, max_len, "%s:%s%s%s:%s%s <-> %s%s%s:%s", return g_strdup_printf("%s:%s%s%s:%s%s <-> %s%s%s:%s",
is_telnet ? "telnet" : "tcp", is_telnet ? "telnet" : "tcp",
left, shost, right, sserv, left, shost, right, sserv,
is_listen ? ",server" : "", is_listen ? ",server" : "",
left, phost, right, pserv); left, phost, right, pserv);
default: default:
return snprintf(dest, max_len, "unknown"); return g_strdup_printf("unknown");
} }
} }
@ -923,6 +921,7 @@ static GIOChannel *io_channel_from_socket(int fd)
return chan; return chan;
} }
#ifndef _WIN32
static int io_channel_send(GIOChannel *fd, const void *buf, size_t len) static int io_channel_send(GIOChannel *fd, const void *buf, size_t len)
{ {
size_t offset = 0; size_t offset = 0;
@ -953,7 +952,6 @@ static int io_channel_send(GIOChannel *fd, const void *buf, size_t len)
return -1; return -1;
} }
#ifndef _WIN32
typedef struct FDCharDriver { typedef struct FDCharDriver {
CharDriverState *chr; CharDriverState *chr;
@ -1074,15 +1072,18 @@ static CharDriverState *qemu_chr_open_pipe(const char *id,
{ {
ChardevHostdev *opts = backend->u.pipe; ChardevHostdev *opts = backend->u.pipe;
int fd_in, fd_out; int fd_in, fd_out;
char filename_in[CHR_MAX_FILENAME_SIZE]; char *filename_in;
char filename_out[CHR_MAX_FILENAME_SIZE]; char *filename_out;
const char *filename = opts->device; const char *filename = opts->device;
ChardevCommon *common = qapi_ChardevHostdev_base(backend->u.pipe); 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_in = qemu_open(filename_in, O_RDWR | O_BINARY));
TFR(fd_out = qemu_open(filename_out, 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 || fd_out < 0) {
if (fd_in >= 0) if (fd_in >= 0)
close(fd_in); close(fd_in);
@ -2115,7 +2116,7 @@ static int win_chr_pipe_init(CharDriverState *chr, const char *filename,
OVERLAPPED ov; OVERLAPPED ov;
int ret; int ret;
DWORD size; DWORD size;
char openname[CHR_MAX_FILENAME_SIZE]; char *openname;
s->fpipe = TRUE; s->fpipe = TRUE;
@ -2130,11 +2131,12 @@ static int win_chr_pipe_init(CharDriverState *chr, const char *filename,
goto fail; 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, s->hcom = CreateNamedPipe(openname, PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED,
PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_TYPE_BYTE | PIPE_READMODE_BYTE |
PIPE_WAIT, PIPE_WAIT,
MAXCONNECT, NSENDBUF, NRECVBUF, NTIMEOUT, NULL); MAXCONNECT, NSENDBUF, NRECVBUF, NTIMEOUT, NULL);
g_free(openname);
if (s->hcom == INVALID_HANDLE_VALUE) { if (s->hcom == INVALID_HANDLE_VALUE) {
error_setg(errp, "Failed CreateNamedPipe (%lu)", GetLastError()); error_setg(errp, "Failed CreateNamedPipe (%lu)", GetLastError());
s->hcom = NULL; s->hcom = NULL;
@ -2913,8 +2915,9 @@ static void tcp_chr_disconnect(CharDriverState *chr)
s->chan = NULL; s->chan = NULL;
closesocket(s->fd); closesocket(s->fd);
s->fd = -1; s->fd = -1;
SocketAddress_to_str(chr->filename, CHR_MAX_FILENAME_SIZE, g_free(chr->filename);
"disconnected:", s->addr, s->is_listen, s->is_telnet); chr->filename = SocketAddress_to_str("disconnected:", s->addr,
s->is_listen, s->is_telnet);
qemu_chr_be_event(chr, CHR_EVENT_CLOSED); qemu_chr_be_event(chr, CHR_EVENT_CLOSED);
if (s->reconnect_time) { if (s->reconnect_time) {
qemu_chr_socket_restart_timer(chr); 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); socklen_t ss_len = sizeof(ss), ps_len = sizeof(ps);
memset(&ss, 0, ss_len); memset(&ss, 0, ss_len);
g_free(chr->filename);
if (getsockname(s->fd, (struct sockaddr *) &ss, &ss_len) != 0) { if (getsockname(s->fd, (struct sockaddr *) &ss, &ss_len) != 0) {
snprintf(chr->filename, CHR_MAX_FILENAME_SIZE, chr->filename = g_strdup_printf("Error in getsockname: %s\n",
"Error in getsockname: %s\n", strerror(errno)); strerror(errno));
} else if (getpeername(s->fd, (struct sockaddr *) &ps, &ps_len) != 0) { } else if (getpeername(s->fd, (struct sockaddr *) &ps, &ps_len) != 0) {
snprintf(chr->filename, CHR_MAX_FILENAME_SIZE, chr->filename = g_strdup_printf("Error in getpeername: %s\n",
"Error in getpeername: %s\n", strerror(errno)); strerror(errno));
} else { } else {
sockaddr_to_str(chr->filename, CHR_MAX_FILENAME_SIZE, chr->filename = sockaddr_to_str(&ss, ss_len, &ps, ps_len,
&ss, ss_len, &ps, ps_len, s->is_listen, s->is_telnet);
s->is_listen, s->is_telnet);
} }
s->connected = 1; 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 */ /* be isn't opened until we get a connection */
chr->explicit_be_open = true; chr->explicit_be_open = true;
chr->filename = g_malloc(CHR_MAX_FILENAME_SIZE); chr->filename = SocketAddress_to_str("disconnected:",
SocketAddress_to_str(chr->filename, CHR_MAX_FILENAME_SIZE, "disconnected:", addr, is_listen, is_telnet);
addr, is_listen, is_telnet);
if (is_listen) { if (is_listen) {
if (is_telnet) { if (is_telnet) {