mirror of https://gitlab.com/qemu-project/qemu
QAPI patches 2016-06-30
-----BEGIN PGP SIGNATURE----- Version: GnuPG v1 iQIcBAABAgAGBQJXdR7HAAoJEDhwtADrkYZTZ1sQAIWJjTpu0OT9j6qsb7fHBhKk TtqVb0zmBa11bjBC090wRfr/Z2dwFDEQrvKKT2CsDDTndD0yMZcbZt49jO8p2q3b LOgZqx+vHWfaMqljy8U0fcCRX6XJvAEp5rD6MsuWsEMzmNRcl79HbQ4spyWlDsot MmYKiRiQYFg/m8eLxC3guX+5ShtkxE6z4ZwVHaMaGR0Bm65N2eTpm/caWellD3qk PXWmTjBEnCy0A68WEnsiEJyX8hLh6WGnW/FHuomAYdHXotAr2iEvEm995bKLhq+L tI0uSOGlljCUgw5rAQJUxknMKe+2ERDfulESqnovp62ZsqDXQBr1omxyWNOyanTq +XQNN4BJlt197DLJ2S94Sc8BorhrjgYAo8EMKYCQNZ++ANvbryg6I1bA5qy0jA1M LeL8M10swsB36SNGAz4VM5d3Mk8gdvSBVrEdG6SKzeO1on6tf6B07TuoJVxouCnw KiXoZHrRhmnGTqbSINB7e5jAdVPtia5oHqboYd6AHM+Zbi/qx0Y5pv6obs3RPdJP G9WxKZeWSBkaO0HIc1zORw/0YVNj8liDnc/tE5+LUod62yGmyYHPwT9c0/BpaxW6 W3/u3IveSuLS4Dy4r/2LoR+AuBw1kdFCAw/QAI36WxqruhBr3pQGSW9zc/Sz7qSI n5y+PeVbhhFm9ZtQ7xRM =V6RA -----END PGP SIGNATURE----- Merge remote-tracking branch 'remotes/armbru/tags/pull-qapi-2016-06-30' into staging QAPI patches 2016-06-30 # gpg: Signature made Thu 30 Jun 2016 14:29:43 BST # gpg: using RSA key 0x3870B400EB918653 # gpg: Good signature from "Markus Armbruster <armbru@redhat.com>" # gpg: aka "Markus Armbruster <armbru@pond.sub.org>" # Primary key fingerprint: 354B C8B3 D7EB 2A6B 6867 4E5F 3870 B400 EB91 8653 * remotes/armbru/tags/pull-qapi-2016-06-30: qapi: Fix memleak in string visitors on int lists qapi: Simplify use of range.h range: Create range.c for code that should not be inline qapi: Fix crash on missing alternate member of QAPI struct checkpatch: There is no qemu_strtod() qobject: Correct JSON lexer grammar comments json-streamer: Don't leak tokens on incomplete parse Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
commit
1fb4c13e4f
|
@ -1,3 +1,23 @@
|
||||||
|
/*
|
||||||
|
* QEMU 64-bit address ranges
|
||||||
|
*
|
||||||
|
* Copyright (c) 2015-2016 Red Hat, Inc.
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public
|
||||||
|
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
#ifndef QEMU_RANGE_H
|
#ifndef QEMU_RANGE_H
|
||||||
#define QEMU_RANGE_H
|
#define QEMU_RANGE_H
|
||||||
|
|
||||||
|
@ -59,75 +79,6 @@ static inline int ranges_overlap(uint64_t first1, uint64_t len1,
|
||||||
return !(last2 < first1 || last1 < first2);
|
return !(last2 < first1 || last1 < first2);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 0,1 can merge with 1,2 but don't overlap */
|
GList *range_list_insert(GList *list, Range *data);
|
||||||
static inline bool ranges_can_merge(Range *range1, Range *range2)
|
|
||||||
{
|
|
||||||
return !(range1->end < range2->begin || range2->end < range1->begin);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline int range_merge(Range *range1, Range *range2)
|
|
||||||
{
|
|
||||||
if (ranges_can_merge(range1, range2)) {
|
|
||||||
if (range1->end < range2->end) {
|
|
||||||
range1->end = range2->end;
|
|
||||||
}
|
|
||||||
if (range1->begin > range2->begin) {
|
|
||||||
range1->begin = range2->begin;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline GList *g_list_insert_sorted_merged(GList *list,
|
|
||||||
gpointer data,
|
|
||||||
GCompareFunc func)
|
|
||||||
{
|
|
||||||
GList *l, *next = NULL;
|
|
||||||
Range *r, *nextr;
|
|
||||||
|
|
||||||
if (!list) {
|
|
||||||
list = g_list_insert_sorted(list, data, func);
|
|
||||||
return list;
|
|
||||||
}
|
|
||||||
|
|
||||||
nextr = data;
|
|
||||||
l = list;
|
|
||||||
while (l && l != next && nextr) {
|
|
||||||
r = l->data;
|
|
||||||
if (ranges_can_merge(r, nextr)) {
|
|
||||||
range_merge(r, nextr);
|
|
||||||
l = g_list_remove_link(l, next);
|
|
||||||
next = g_list_next(l);
|
|
||||||
if (next) {
|
|
||||||
nextr = next->data;
|
|
||||||
} else {
|
|
||||||
nextr = NULL;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
l = g_list_next(l);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!l) {
|
|
||||||
list = g_list_insert_sorted(list, data, func);
|
|
||||||
}
|
|
||||||
|
|
||||||
return list;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline gint range_compare(gconstpointer a, gconstpointer b)
|
|
||||||
{
|
|
||||||
Range *ra = (Range *)a, *rb = (Range *)b;
|
|
||||||
if (ra->begin == rb->begin && ra->end == rb->end) {
|
|
||||||
return 0;
|
|
||||||
} else if (range_get_last(ra->begin, ra->end) <
|
|
||||||
range_get_last(rb->begin, rb->end)) {
|
|
||||||
return -1;
|
|
||||||
} else {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -61,8 +61,7 @@ static int parse_str(StringInputVisitor *siv, const char *name, Error **errp)
|
||||||
cur = g_malloc0(sizeof(*cur));
|
cur = g_malloc0(sizeof(*cur));
|
||||||
cur->begin = start;
|
cur->begin = start;
|
||||||
cur->end = start + 1;
|
cur->end = start + 1;
|
||||||
siv->ranges = g_list_insert_sorted_merged(siv->ranges, cur,
|
siv->ranges = range_list_insert(siv->ranges, cur);
|
||||||
range_compare);
|
|
||||||
cur = NULL;
|
cur = NULL;
|
||||||
str = NULL;
|
str = NULL;
|
||||||
} else if (*endptr == '-') {
|
} else if (*endptr == '-') {
|
||||||
|
@ -76,10 +75,7 @@ static int parse_str(StringInputVisitor *siv, const char *name, Error **errp)
|
||||||
cur = g_malloc0(sizeof(*cur));
|
cur = g_malloc0(sizeof(*cur));
|
||||||
cur->begin = start;
|
cur->begin = start;
|
||||||
cur->end = end + 1;
|
cur->end = end + 1;
|
||||||
siv->ranges =
|
siv->ranges = range_list_insert(siv->ranges, cur);
|
||||||
g_list_insert_sorted_merged(siv->ranges,
|
|
||||||
cur,
|
|
||||||
range_compare);
|
|
||||||
cur = NULL;
|
cur = NULL;
|
||||||
str = NULL;
|
str = NULL;
|
||||||
} else if (*endptr == ',') {
|
} else if (*endptr == ',') {
|
||||||
|
@ -87,10 +83,7 @@ static int parse_str(StringInputVisitor *siv, const char *name, Error **errp)
|
||||||
cur = g_malloc0(sizeof(*cur));
|
cur = g_malloc0(sizeof(*cur));
|
||||||
cur->begin = start;
|
cur->begin = start;
|
||||||
cur->end = end + 1;
|
cur->end = end + 1;
|
||||||
siv->ranges =
|
siv->ranges = range_list_insert(siv->ranges, cur);
|
||||||
g_list_insert_sorted_merged(siv->ranges,
|
|
||||||
cur,
|
|
||||||
range_compare);
|
|
||||||
cur = NULL;
|
cur = NULL;
|
||||||
} else {
|
} else {
|
||||||
goto error;
|
goto error;
|
||||||
|
@ -103,9 +96,7 @@ static int parse_str(StringInputVisitor *siv, const char *name, Error **errp)
|
||||||
cur = g_malloc0(sizeof(*cur));
|
cur = g_malloc0(sizeof(*cur));
|
||||||
cur->begin = start;
|
cur->begin = start;
|
||||||
cur->end = start + 1;
|
cur->end = start + 1;
|
||||||
siv->ranges = g_list_insert_sorted_merged(siv->ranges,
|
siv->ranges = range_list_insert(siv->ranges, cur);
|
||||||
cur,
|
|
||||||
range_compare);
|
|
||||||
cur = NULL;
|
cur = NULL;
|
||||||
} else {
|
} else {
|
||||||
goto error;
|
goto error;
|
||||||
|
|
|
@ -85,7 +85,7 @@ static void string_output_append(StringOutputVisitor *sov, int64_t a)
|
||||||
Range *r = g_malloc0(sizeof(*r));
|
Range *r = g_malloc0(sizeof(*r));
|
||||||
r->begin = a;
|
r->begin = a;
|
||||||
r->end = a + 1;
|
r->end = a + 1;
|
||||||
sov->ranges = g_list_insert_sorted_merged(sov->ranges, r, range_compare);
|
sov->ranges = range_list_insert(sov->ranges, r);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void string_output_append_range(StringOutputVisitor *sov,
|
static void string_output_append_range(StringOutputVisitor *sov,
|
||||||
|
@ -94,7 +94,7 @@ static void string_output_append_range(StringOutputVisitor *sov,
|
||||||
Range *r = g_malloc0(sizeof(*r));
|
Range *r = g_malloc0(sizeof(*r));
|
||||||
r->begin = s;
|
r->begin = s;
|
||||||
r->end = e + 1;
|
r->end = e + 1;
|
||||||
sov->ranges = g_list_insert_sorted_merged(sov->ranges, r, range_compare);
|
sov->ranges = range_list_insert(sov->ranges, r);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void format_string(StringOutputVisitor *sov, Range *r, bool next,
|
static void format_string(StringOutputVisitor *sov, Range *r, bool next,
|
||||||
|
|
|
@ -18,11 +18,20 @@
|
||||||
#define MAX_TOKEN_SIZE (64ULL << 20)
|
#define MAX_TOKEN_SIZE (64ULL << 20)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* \"([^\\\"]|(\\\"\\'\\\\\\/\\b\\f\\n\\r\\t\\u[0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F]))*\"
|
* Required by JSON (RFC 7159):
|
||||||
* '([^\\']|(\\\"\\'\\\\\\/\\b\\f\\n\\r\\t\\u[0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F]))*'
|
*
|
||||||
* 0|([1-9][0-9]*(.[0-9]+)?([eE]([-+])?[0-9]+))
|
* \"([^\\\"]|\\[\"'\\/bfnrt]|\\u[0-9a-fA-F]{4})*\"
|
||||||
|
* -?(0|[1-9][0-9]*)(.[0-9]+)?([eE][-+]?[0-9]+)?
|
||||||
* [{}\[\],:]
|
* [{}\[\],:]
|
||||||
* [a-z]+
|
* [a-z]+ # covers null, true, false
|
||||||
|
*
|
||||||
|
* Extension of '' strings:
|
||||||
|
*
|
||||||
|
* '([^\\']|\\[\"'\\/bfnrt]|\\u[0-9a-fA-F]{4})*'
|
||||||
|
*
|
||||||
|
* Extension for vararg handling in JSON construction:
|
||||||
|
*
|
||||||
|
* %((l|ll|I64)?d|[ipsf])
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -213,7 +222,7 @@ static const uint8_t json_lexer[][256] = {
|
||||||
['\t'] = IN_WHITESPACE,
|
['\t'] = IN_WHITESPACE,
|
||||||
['\r'] = IN_WHITESPACE,
|
['\r'] = IN_WHITESPACE,
|
||||||
['\n'] = IN_WHITESPACE,
|
['\n'] = IN_WHITESPACE,
|
||||||
},
|
},
|
||||||
|
|
||||||
/* escape */
|
/* escape */
|
||||||
[IN_ESCAPE_LL] = {
|
[IN_ESCAPE_LL] = {
|
||||||
|
|
|
@ -20,9 +20,15 @@
|
||||||
#define MAX_TOKEN_COUNT (2ULL << 20)
|
#define MAX_TOKEN_COUNT (2ULL << 20)
|
||||||
#define MAX_NESTING (1ULL << 10)
|
#define MAX_NESTING (1ULL << 10)
|
||||||
|
|
||||||
|
static void json_message_free_token(void *token, void *opaque)
|
||||||
|
{
|
||||||
|
g_free(token);
|
||||||
|
}
|
||||||
|
|
||||||
static void json_message_free_tokens(JSONMessageParser *parser)
|
static void json_message_free_tokens(JSONMessageParser *parser)
|
||||||
{
|
{
|
||||||
if (parser->tokens) {
|
if (parser->tokens) {
|
||||||
|
g_queue_foreach(parser->tokens, json_message_free_token, NULL);
|
||||||
g_queue_free(parser->tokens);
|
g_queue_free(parser->tokens);
|
||||||
parser->tokens = NULL;
|
parser->tokens = NULL;
|
||||||
}
|
}
|
||||||
|
|
|
@ -2453,7 +2453,7 @@ sub process {
|
||||||
}
|
}
|
||||||
|
|
||||||
# recommend qemu_strto* over strto* for numeric conversions
|
# recommend qemu_strto* over strto* for numeric conversions
|
||||||
if ($line =~ /\b(strto[^k].*?)\s*\(/) {
|
if ($line =~ /\b(strto[^kd].*?)\s*\(/) {
|
||||||
WARN("consider using qemu_$1 in preference to $1\n" . $herecurr);
|
WARN("consider using qemu_$1 in preference to $1\n" . $herecurr);
|
||||||
}
|
}
|
||||||
# check for module_init(), use category-specific init macros explicitly please
|
# check for module_init(), use category-specific init macros explicitly please
|
||||||
|
|
|
@ -172,6 +172,9 @@ void visit_type_%(c_name)s(Visitor *v, const char *name, %(c_name)s **obj, Error
|
||||||
if (err) {
|
if (err) {
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
if (!*obj) {
|
||||||
|
goto out_obj;
|
||||||
|
}
|
||||||
switch ((*obj)->type) {
|
switch ((*obj)->type) {
|
||||||
''',
|
''',
|
||||||
c_name=c_name(name), promote_int=promote_int)
|
c_name=c_name(name), promote_int=promote_int)
|
||||||
|
@ -206,10 +209,13 @@ void visit_type_%(c_name)s(Visitor *v, const char *name, %(c_name)s **obj, Error
|
||||||
''')
|
''')
|
||||||
|
|
||||||
ret += mcgen('''
|
ret += mcgen('''
|
||||||
|
case QTYPE_NONE:
|
||||||
|
abort();
|
||||||
default:
|
default:
|
||||||
error_setg(&err, QERR_INVALID_PARAMETER_TYPE, name ? name : "null",
|
error_setg(&err, QERR_INVALID_PARAMETER_TYPE, name ? name : "null",
|
||||||
"%(name)s");
|
"%(name)s");
|
||||||
}
|
}
|
||||||
|
out_obj:
|
||||||
visit_end_alternate(v);
|
visit_end_alternate(v);
|
||||||
if (err && visit_is_input(v)) {
|
if (err && visit_is_input(v)) {
|
||||||
qapi_free_%(c_name)s(*obj);
|
qapi_free_%(c_name)s(*obj);
|
||||||
|
|
|
@ -766,6 +766,8 @@ static void test_visitor_in_errors(TestInputVisitorData *data,
|
||||||
Error *err = NULL;
|
Error *err = NULL;
|
||||||
Visitor *v;
|
Visitor *v;
|
||||||
strList *q = NULL;
|
strList *q = NULL;
|
||||||
|
UserDefTwo *r = NULL;
|
||||||
|
WrapAlternate *s = NULL;
|
||||||
|
|
||||||
v = visitor_input_test_init(data, "{ 'integer': false, 'boolean': 'foo', "
|
v = visitor_input_test_init(data, "{ 'integer': false, 'boolean': 'foo', "
|
||||||
"'string': -42 }");
|
"'string': -42 }");
|
||||||
|
@ -778,6 +780,16 @@ static void test_visitor_in_errors(TestInputVisitorData *data,
|
||||||
visit_type_strList(v, NULL, &q, &err);
|
visit_type_strList(v, NULL, &q, &err);
|
||||||
error_free_or_abort(&err);
|
error_free_or_abort(&err);
|
||||||
assert(!q);
|
assert(!q);
|
||||||
|
|
||||||
|
v = visitor_input_test_init(data, "{ 'str':'hi' }");
|
||||||
|
visit_type_UserDefTwo(v, NULL, &r, &err);
|
||||||
|
error_free_or_abort(&err);
|
||||||
|
assert(!r);
|
||||||
|
|
||||||
|
v = visitor_input_test_init(data, "{ }");
|
||||||
|
visit_type_WrapAlternate(v, NULL, &s, &err);
|
||||||
|
error_free_or_abort(&err);
|
||||||
|
assert(!s);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void test_visitor_in_wrong_type(TestInputVisitorData *data,
|
static void test_visitor_in_wrong_type(TestInputVisitorData *data,
|
||||||
|
|
|
@ -34,3 +34,4 @@ util-obj-y += base64.o
|
||||||
util-obj-y += log.o
|
util-obj-y += log.o
|
||||||
util-obj-y += qdist.o
|
util-obj-y += qdist.o
|
||||||
util-obj-y += qht.o
|
util-obj-y += qht.o
|
||||||
|
util-obj-y += range.o
|
||||||
|
|
|
@ -0,0 +1,76 @@
|
||||||
|
/*
|
||||||
|
* QEMU 64-bit address ranges
|
||||||
|
*
|
||||||
|
* Copyright (c) 2015-2016 Red Hat, Inc.
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public
|
||||||
|
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "qemu/osdep.h"
|
||||||
|
#include "qemu/range.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Operations on 64 bit address ranges.
|
||||||
|
* Notes:
|
||||||
|
* - ranges must not wrap around 0, but can include the last byte ~0x0LL.
|
||||||
|
* - this can not represent a full 0 to ~0x0LL range.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Return -1 if @a < @b, 1 if greater, and 0 if they touch or overlap. */
|
||||||
|
static inline int range_compare(Range *a, Range *b)
|
||||||
|
{
|
||||||
|
/* Zero a->end is 2**64, and therefore not less than any b->begin */
|
||||||
|
if (a->end && a->end < b->begin) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (b->end && a->begin > b->end) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Insert @data into @list of ranges; caller no longer owns @data */
|
||||||
|
GList *range_list_insert(GList *list, Range *data)
|
||||||
|
{
|
||||||
|
GList *l;
|
||||||
|
|
||||||
|
/* Range lists require no empty ranges */
|
||||||
|
assert(data->begin < data->end || (data->begin && !data->end));
|
||||||
|
|
||||||
|
/* Skip all list elements strictly less than data */
|
||||||
|
for (l = list; l && range_compare(l->data, data) < 0; l = l->next) {
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!l || range_compare(l->data, data) > 0) {
|
||||||
|
/* Rest of the list (if any) is strictly greater than @data */
|
||||||
|
return g_list_insert_before(list, l, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Current list element overlaps @data, merge the two */
|
||||||
|
range_extend(l->data, data);
|
||||||
|
g_free(data);
|
||||||
|
|
||||||
|
/* Merge any subsequent list elements that now also overlap */
|
||||||
|
while (l->next && range_compare(l->data, l->next->data) == 0) {
|
||||||
|
GList *new_l;
|
||||||
|
|
||||||
|
range_extend(l->data, l->next->data);
|
||||||
|
g_free(l->next->data);
|
||||||
|
new_l = g_list_delete_link(list, l->next);
|
||||||
|
assert(new_l == list);
|
||||||
|
}
|
||||||
|
|
||||||
|
return list;
|
||||||
|
}
|
Loading…
Reference in New Issue