aboutsummaryrefslogtreecommitdiff
path: root/tests/libqtest.c
diff options
context:
space:
mode:
authorPaolo Bonzini <pbonzini@redhat.com>2014-06-13 09:35:18 +0200
committerPaolo Bonzini <pbonzini@redhat.com>2014-07-01 10:20:41 +0200
commit563890c7c7e977842e2a35afe7a24d06d2103242 (patch)
tree284a26ca2bcd81b2e0abada9e9838c2be325086c /tests/libqtest.c
parent8ffad850ef5ae14287d0e185d478c9a35820482c (diff)
libqtest: escape strings in QMP commands, fix leak
libqtest is using g_strdup_printf to format QMP commands, but this does not work if the argument strings need to be escaped. Instead, use the fancy %-formatting functionality of QObject. The only change required in tests is that strings have to be formatted as %s, not '%s' or \"%s\". Luckily this usage of parameterized QMP commands is not that frequent. The leak is in socket_sendf. Since we are extracting the send loop to a new function, fix it now. Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Diffstat (limited to 'tests/libqtest.c')
-rw-r--r--tests/libqtest.c47
1 files changed, 37 insertions, 10 deletions
diff --git a/tests/libqtest.c b/tests/libqtest.c
index 71468ac9c7..98e8f4b648 100644
--- a/tests/libqtest.c
+++ b/tests/libqtest.c
@@ -30,8 +30,9 @@
#include "qemu/compiler.h"
#include "qemu/osdep.h"
-#include "qapi/qmp/json-streamer.h"
#include "qapi/qmp/json-parser.h"
+#include "qapi/qmp/json-streamer.h"
+#include "qapi/qmp/qjson.h"
#define MAX_IRQ 256
#define SOCKET_TIMEOUT 5
@@ -220,19 +221,15 @@ void qtest_quit(QTestState *s)
g_free(s);
}
-static void socket_sendf(int fd, const char *fmt, va_list ap)
+static void socket_send(int fd, const char *buf, size_t size)
{
- gchar *str;
- size_t size, offset;
-
- str = g_strdup_vprintf(fmt, ap);
- size = strlen(str);
+ size_t offset;
offset = 0;
while (offset < size) {
ssize_t len;
- len = write(fd, str + offset, size - offset);
+ len = write(fd, buf + offset, size - offset);
if (len == -1 && errno == EINTR) {
continue;
}
@@ -244,6 +241,15 @@ static void socket_sendf(int fd, const char *fmt, va_list ap)
}
}
+static void socket_sendf(int fd, const char *fmt, va_list ap)
+{
+ gchar *str = g_strdup_vprintf(fmt, ap);
+ size_t size = strlen(str);
+
+ socket_send(fd, str, size);
+ g_free(str);
+}
+
static void GCC_FMT_ATTR(2, 3) qtest_sendf(QTestState *s, const char *fmt, ...)
{
va_list ap;
@@ -378,8 +384,29 @@ QDict *qtest_qmp_receive(QTestState *s)
QDict *qtest_qmpv(QTestState *s, const char *fmt, va_list ap)
{
- /* Send QMP request */
- socket_sendf(s->qmp_fd, fmt, ap);
+ va_list ap_copy;
+ QObject *qobj;
+
+ /* Going through qobject ensures we escape strings properly.
+ * This seemingly unnecessary copy is required in case va_list
+ * is an array type.
+ */
+ va_copy(ap_copy, ap);
+ qobj = qobject_from_jsonv(fmt, &ap_copy);
+ va_end(ap_copy);
+
+ /* No need to send anything for an empty QObject. */
+ if (qobj) {
+ QString *qstr = qobject_to_json(qobj);
+ const char *str = qstring_get_str(qstr);
+ size_t size = qstring_get_length(qstr);
+
+ /* Send QMP request */
+ socket_send(s->qmp_fd, str, size);
+
+ QDECREF(qstr);
+ qobject_decref(qobj);
+ }
/* Receive reply */
return qtest_qmp_receive(s);