|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [Xen-devel] [PATCH RFC V2 05/10] libxl_json: introduce parser functions for builtin types
On Tue, Apr 22, 2014 at 04:09:58PM +0100, Ian Campbell wrote:
> Please could you CC Anthony too, I think he wrote all this
> libxl__json_object stuff.
>
> On Thu, 2014-04-17 at 12:13 +0100, Wei Liu wrote:
> > @@ -396,6 +396,66 @@ out:
> > return s;
> > }
> >
> > +int libxl_cpuid_policy_list_parse_json(libxl_ctx *ctx,
> > + const libxl__json_object *o,
> > + libxl_cpuid_policy_list *p)
> > +{
> > + int i, size;
> > + libxl_cpuid_policy_list l;
> > +
> > + if (!libxl__json_object_is_array(o))
> > + return -1;
> > +
> > + if (!o->u.array->count)
> > + return 0;
> > +
> > + size = o->u.array->count;
> > + /* need one extra slot as setinel */
>
> "sentinel"
>
> > + l = *p = calloc(size + 1, sizeof(libxl_cpuid_policy));
>
> This function should GC_INIT and use the provided gc for allocations,
> shouldn't it?.
>
I see. You're right here.
> > +
> > + if (!l)
> > + return -1;
> > +
> > + memset(l, 0, sizeof(libxl_cpuid_policy) * (size + 1));
> > + l[size].input[0] = XEN_CPUID_INPUT_UNUSED;
> > + l[size].input[1] = XEN_CPUID_INPUT_UNUSED;
> > +
> > + for (i = 0; i < size; i++) {
> > + const libxl__json_object *t;
> > + int j;
> > +
> > + if (flexarray_get(o->u.array, i, (void**)&t) != 0)
> > + return -1; /* dispose_fn will clean up memory
> > + * allocation */
>
> You haven't done a gc allocation, so it won't. Looking closer I think
> this falls into case #1 of the comment in libxl.h, which means the
> allocation should have come from the heap, but that means you need to
> manually free it.
>
The aformentioned "calloc" falls into #1 but not this one.
My comment is a bit confusing. The comment here actually refers to all
the malloc'ed memory in the loop, which will be freed by
libxl_cpuid_dispose.
In any case I will check other occurences of this.
> (I see this comment about dispose_fn a lot, so I won't repeat it)
>
> > + for (j = 0; j < 4; j++) {
>
> This, and the code it is based on, really ought to use ARRAY_SIZE I
> think.
>
Ack.
> > + const libxl__json_object *r;
> > +
> > + r = libxl__json_map_get(policy_names[j], t, JSON_STRING);
> > + if (!r)
> > + l[i].policy[j] = NULL;
> > + else
> > + l[i].policy[j] = strdup(r->u.string);
> > + }
> > + }
> > +
> > + assert(i == size);
>
> Given a lack of break's in the for loop this seems overly defensive to
> me.
>
I will remove this.
> > +
> > + return 0;
> > +}
> > +
> > /*
> > * Local variables:
> > * mode: C
> > diff --git a/tools/libxl/libxl_json.c b/tools/libxl/libxl_json.c
> > index 6f1116f..e2d5dbe 100644
> > --- a/tools/libxl/libxl_json.c
> > +++ b/tools/libxl/libxl_json.c
> > @@ -100,6 +100,35 @@ yajl_gen_status libxl_defbool_gen_json(yajl_gen hand,
> > return libxl__yajl_gen_asciiz(hand, libxl_defbool_to_string(*db));
> > }
> >
> > +int libxl_defbool_parse_json(libxl_ctx *ctx, const libxl__json_object *o,
> > + libxl_defbool *p)
> > +{
> > + if (!libxl__json_object_is_string(o))
> > + return -1;
> > +
> > + if (!strncmp(o->u.string, "<default>", strlen("<default>")))
> > + p->val = 0;
> > + else if (!strncmp(o->u.string, "True", strlen("True")))
> > + p->val = 1;
> > + else if (!strncmp(o->u.string, "False", strlen("False")))
>
> Should have some internal #defines for these strings and use in the
> generator too. Also you should use LIBXL__DEFBOOL_DEFAULT and friends.
>
Ack.
> > @@ -128,6 +166,34 @@ out:
> > return s;
> > }
> >
> > +int libxl_bitmap_parse_json(libxl_ctx *ctx, const libxl__json_object *o,
> > + libxl_bitmap *p)
> > +{
> > + int i;
> > + int size;
> > + const libxl__json_object *t;
> > +
> > + if (!libxl__json_object_is_array(o))
> > + return -1;
> > +
> > + if (!o->u.array->count)
> > + return 0;
> > +
> > + t = libxl__json_array_get(o, o->u.array->count - 1);
> > + size = t->u.i + 1;
>
> What is this doing? It's retrieving the last item in the array, assuming
> it is an integer and then inferring the length of the array from it?
>
Yes.
> Oh this is because a bitmask is represented as an array which contains a
> list of the bit indexes which are true.
>
> Is the json array guaranteed to be sorted? I guess it is if libxl
> generated it, but can we rely on that?
>
Yes. I basically reverse-engineer the process to generate the array and
find out that it's sorted.
> I wonder if it is too late to change the json representation of a
> bitmask that we are using. Thoughts?
>
Probably yes. It's a public function in libxl API so I wouldn't be
surprised if some high level tool depends on it.
> > +
> > + libxl_bitmap_alloc(ctx, p, size);
> > +
> > + for (i = 0; (t = libxl__json_array_get(o, i)); i++) {
> > + if (!libxl__json_object_is_integer(t))
> > + return -1; /* dispose_fn will clean up memory
> > + * allocation */
> > + libxl_bitmap_set(p, t->u.i);
> > + }
> > +
> > + return 0;
> > +}
> > +
> > yajl_gen_status libxl_key_value_list_gen_json(yajl_gen hand,
> > libxl_key_value_list *pkvl)
> > {
> > @@ -155,6 +221,43 @@ out:
> > return s;
> > }
> >
> > +int libxl_key_value_list_parse_json(libxl_ctx *ctx, const
> > libxl__json_object *o,
> > + libxl_key_value_list *p)
> > +{
> > + libxl__json_map_node *node = NULL;
> > + flexarray_t *maps = NULL;
> > + int i, size;
> > + libxl_key_value_list kvl;
> > +
> > + if (!libxl__json_object_is_map(o))
> > + return -1;
> > +
> > + maps = o->u.map;
> > + size = maps->count * 2;
> > + kvl = *p = calloc(size, sizeof(char *));
> > + if (!kvl)
> > + return -1;
> > +
> > + memset(kvl, 0, sizeof(char *) * size);
> > +
> > + for (i = 0; i < maps->count; i++) {
> > + int idx = i * 2;
> > + if (flexarray_get(maps, i, (void**)&node) != 0)
> > + return -1;
> > + assert(libxl__json_object_is_string(node->obj) ||
> > + libxl__json_object_is_null(node->obj));
>
> I think we may need to be mindful of potentially malicious json code
> which a toolstack is feeding to these parser functions, don't we?
>
> IOW asserting and crashing the entire daemon would be unfortunate.
>
I think "return -1" will be more appropriate in this case.
> > + kvl[idx] = strdup(node->map_key);
> > + if (libxl__json_object_is_string(node->obj))
> > + kvl[idx+1] = strdup(node->obj->u.string);
> > + else
> > + kvl[idx+1] = NULL;
> > + }
> > +
> > + assert(i == maps->count);
>
> Too defensive again.
>
Ack.
> > +
> > + return 0;
> > +}
> > +
> > yajl_gen_status libxl_string_list_gen_json(yajl_gen hand,
> > libxl_string_list *pl)
> > {
> > libxl_string_list l = *pl;
> > @@ -201,6 +343,27 @@ out:
> > return s;
> > }
> >
> > +int libxl_hwcap_parse_json(libxl_ctx *ctx, const libxl__json_object *o,
> > + libxl_hwcap *p)
> > +{
> > + int i;
> > +
> > + if (!libxl__json_object_is_array(o))
> > + return -1;
>
> I jut noticed the error handling here, but I'm sure it was the same for
> all the preceding. libxl functions should return an ERROR_* code and not
> -1 unless you have a good reason not to.
>
OK. Will change to that.
Wei.
> Ian.
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
http://lists.xen.org/xen-devel
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |