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:
parent
3db34bf64a
commit
0ff0fad23d
88
qemu-char.c
88
qemu-char.c
@ -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) {
|
||||||
|
Loading…
Reference in New Issue
Block a user