Commit Graph

142 Commits

Author SHA1 Message Date
Frediano Ziglio
bac2aa4e2d codegen: Make input structures for marshaller constant
Add const specifier to passed structure.
Make code a bit more "safe" as compiler can check if code is
trying to change some passed data.
Also allows to declare data passed as constant.

Signed-off-by: Frediano Ziglio <freddy77@gmail.com>
Acked-by: Victor Toso <victortoso@redhat.com>
2021-05-24 08:08:37 +01:00
Frediano Ziglio
6b662331f7 codegen: Handle zero_terminated attribute in demashaller
Make sure the output array is zero terminated to simplify
code using the output structures.

Changed in generated code:

    diff -ru gen/generated_client_demarshallers.c common/generated_client_demarshallers.c
    --- gen/generated_client_demarshallers.c	2021-02-21 15:13:42.004307087 +0000
    +++ common/generated_client_demarshallers.c	2021-02-21 15:13:58.916513426 +0000
    @@ -565,15 +565,24 @@
         return NULL;
     }

    -static uint8_t * parse_array_uint8(uint8_t *message_start, SPICE_GNUC_UNUSED uint8_t *message_end, uint8_t *struct_data, PointerInfo *this_ptr_info)
    +static uint8_t * parse_array_uint8_terminated(uint8_t *message_start, SPICE_GNUC_UNUSED uint8_t *message_end, uint8_t *struct_data, PointerInfo *this_ptr_info)
     {
         uint8_t *in = message_start + this_ptr_info->offset;
         uint8_t *end;

         end = struct_data;
         memcpy(end, in, this_ptr_info->nelements);
    +#if defined(__GNUC__)
    +#pragma GCC diagnostic push
    +#pragma GCC diagnostic ignored "-Wstringop-overflow"
    +#endif
    +    ((char *) (end))[this_ptr_info->nelements] = 0;
    +#if defined(__GNUC__)
    +#pragma GCC diagnostic pop
    +#endif
         in += this_ptr_info->nelements;
         end += this_ptr_info->nelements;
    +    end += 1;
         return end;
     }

    @@ -622,7 +631,8 @@
                 dst_info_host_data__array__nelements = host_size__value;

                 dst_info_host_data__array__nw_size = dst_info_host_data__array__nelements;
    -            dst_info_host_data__array__mem_size = sizeof(uint8_t) * dst_info_host_data__array__nelements;
    +            dst_info_host_data__array__mem_size = sizeof(uint8_t) * dst_info_host_data__array__nelements + sizeof(uint8_t);
    +            dst_info_host_data__array__mem_size = SPICE_ALIGN(dst_info_host_data__array__mem_size, 4);
                 if (SPICE_UNLIKELY(dst_info_host_data__array__nw_size > (uintptr_t) (message_end - message_start - host_data__value))) {
                     goto error;
                 }
    @@ -650,7 +660,8 @@
                 dst_info_cert_subject_data__array__nelements = cert_subject_size__value;

                 dst_info_cert_subject_data__array__nw_size = dst_info_cert_subject_data__array__nelements;
    -            dst_info_cert_subject_data__array__mem_size = sizeof(uint8_t) * dst_info_cert_subject_data__array__nelements;
    +            dst_info_cert_subject_data__array__mem_size = sizeof(uint8_t) * dst_info_cert_subject_data__array__nelements + sizeof(uint8_t);
    +            dst_info_cert_subject_data__array__mem_size = SPICE_ALIGN(dst_info_cert_subject_data__array__mem_size, 4);
                 if (SPICE_UNLIKELY(dst_info_cert_subject_data__array__nw_size > (uintptr_t) (message_end - message_start - cert_subject_data__value))) {
                     goto error;
                 }
    @@ -685,14 +696,14 @@
             out->dst_info.sport = consume_uint16(&in);
             out->dst_info.host_size = consume_uint32(&in);
             ptr_info[n_ptr].offset = consume_uint32(&in);
    -        ptr_info[n_ptr].parse = parse_array_uint8;
    +        ptr_info[n_ptr].parse = parse_array_uint8_terminated;
             ptr_info[n_ptr].dest = (void **)&out->dst_info.host_data;
             host_data__array__nelements = out->dst_info.host_size;
             ptr_info[n_ptr].nelements = host_data__array__nelements;
             n_ptr++;
             out->dst_info.cert_subject_size = consume_uint32(&in);
             ptr_info[n_ptr].offset = consume_uint32(&in);
    -        ptr_info[n_ptr].parse = parse_array_uint8;
    +        ptr_info[n_ptr].parse = parse_array_uint8_terminated;
             ptr_info[n_ptr].dest = (void **)&out->dst_info.cert_subject_data;
             cert_subject_data__array__nelements = out->dst_info.cert_subject_size;
             ptr_info[n_ptr].nelements = cert_subject_data__array__nelements;
    @@ -1050,7 +1061,8 @@
             host_data__array__nelements = host_size__value;

             host_data__array__nw_size = host_data__array__nelements;
    -        host_data__array__mem_size = sizeof(uint8_t) * host_data__array__nelements;
    +        host_data__array__mem_size = sizeof(uint8_t) * host_data__array__nelements + sizeof(uint8_t);
    +        host_data__array__mem_size = SPICE_ALIGN(host_data__array__mem_size, 4);
             if (SPICE_UNLIKELY(host_data__array__nw_size > (uintptr_t) (message_end - message_start - host_data__value))) {
                 goto error;
             }
    @@ -1078,7 +1090,8 @@
             cert_subject_data__array__nelements = cert_subject_size__value;

             cert_subject_data__array__nw_size = cert_subject_data__array__nelements;
    -        cert_subject_data__array__mem_size = sizeof(uint8_t) * cert_subject_data__array__nelements;
    +        cert_subject_data__array__mem_size = sizeof(uint8_t) * cert_subject_data__array__nelements + sizeof(uint8_t);
    +        cert_subject_data__array__mem_size = SPICE_ALIGN(cert_subject_data__array__mem_size, 4);
             if (SPICE_UNLIKELY(cert_subject_data__array__nw_size > (uintptr_t) (message_end - message_start - cert_subject_data__value))) {
                 goto error;
             }
    @@ -1107,13 +1120,13 @@
         out->sport = consume_uint16(&in);
         out->host_size = consume_uint32(&in);
         ptr_info[n_ptr].offset = consume_uint32(&in);
    -    ptr_info[n_ptr].parse = parse_array_uint8;
    +    ptr_info[n_ptr].parse = parse_array_uint8_terminated;
         ptr_info[n_ptr].dest = (void **)&out->host_data;
         ptr_info[n_ptr].nelements = host_data__array__nelements;
         n_ptr++;
         out->cert_subject_size = consume_uint32(&in);
         ptr_info[n_ptr].offset = consume_uint32(&in);
    -    ptr_info[n_ptr].parse = parse_array_uint8;
    +    ptr_info[n_ptr].parse = parse_array_uint8_terminated;
         ptr_info[n_ptr].dest = (void **)&out->cert_subject_data;
         ptr_info[n_ptr].nelements = cert_subject_data__array__nelements;
         n_ptr++;
    @@ -1338,7 +1351,8 @@
                 dst_info_host_data__array__nelements = host_size__value;

                 dst_info_host_data__array__nw_size = dst_info_host_data__array__nelements;
    -            dst_info_host_data__array__mem_size = sizeof(uint8_t) * dst_info_host_data__array__nelements;
    +            dst_info_host_data__array__mem_size = sizeof(uint8_t) * dst_info_host_data__array__nelements + sizeof(uint8_t);
    +            dst_info_host_data__array__mem_size = SPICE_ALIGN(dst_info_host_data__array__mem_size, 4);
                 if (SPICE_UNLIKELY(dst_info_host_data__array__nw_size > (uintptr_t) (message_end - message_start - host_data__value))) {
                     goto error;
                 }
    @@ -1366,7 +1380,8 @@
                 dst_info_cert_subject_data__array__nelements = cert_subject_size__value;

                 dst_info_cert_subject_data__array__nw_size = dst_info_cert_subject_data__array__nelements;
    -            dst_info_cert_subject_data__array__mem_size = sizeof(uint8_t) * dst_info_cert_subject_data__array__nelements;
    +            dst_info_cert_subject_data__array__mem_size = sizeof(uint8_t) * dst_info_cert_subject_data__array__nelements + sizeof(uint8_t);
    +            dst_info_cert_subject_data__array__mem_size = SPICE_ALIGN(dst_info_cert_subject_data__array__mem_size, 4);
                 if (SPICE_UNLIKELY(dst_info_cert_subject_data__array__nw_size > (uintptr_t) (message_end - message_start - cert_subject_data__value))) {
                     goto error;
                 }
    @@ -1401,14 +1416,14 @@
             out->dst_info.sport = consume_uint16(&in);
             out->dst_info.host_size = consume_uint32(&in);
             ptr_info[n_ptr].offset = consume_uint32(&in);
    -        ptr_info[n_ptr].parse = parse_array_uint8;
    +        ptr_info[n_ptr].parse = parse_array_uint8_terminated;
             ptr_info[n_ptr].dest = (void **)&out->dst_info.host_data;
             host_data__array__nelements = out->dst_info.host_size;
             ptr_info[n_ptr].nelements = host_data__array__nelements;
             n_ptr++;
             out->dst_info.cert_subject_size = consume_uint32(&in);
             ptr_info[n_ptr].offset = consume_uint32(&in);
    -        ptr_info[n_ptr].parse = parse_array_uint8;
    +        ptr_info[n_ptr].parse = parse_array_uint8_terminated;
             ptr_info[n_ptr].dest = (void **)&out->dst_info.cert_subject_data;
             cert_subject_data__array__nelements = out->dst_info.cert_subject_size;
             ptr_info[n_ptr].nelements = cert_subject_data__array__nelements;
    @@ -7582,7 +7597,8 @@
             name__array__nelements = name_size__value;

             name__array__nw_size = name__array__nelements;
    -        name__array__mem_size = sizeof(uint8_t) * name__array__nelements;
    +        name__array__mem_size = sizeof(uint8_t) * name__array__nelements + sizeof(uint8_t);
    +        name__array__mem_size = SPICE_ALIGN(name__array__mem_size, 4);
             if (SPICE_UNLIKELY(name__array__nw_size > (uintptr_t) (message_end - message_start - name__value))) {
                 goto error;
             }
    @@ -7609,7 +7625,7 @@

         out->name_size = consume_uint32(&in);
         ptr_info[n_ptr].offset = consume_uint32(&in);
    -    ptr_info[n_ptr].parse = parse_array_uint8;
    +    ptr_info[n_ptr].parse = parse_array_uint8_terminated;
         ptr_info[n_ptr].dest = (void **)&out->name;
         ptr_info[n_ptr].nelements = name__array__nelements;
         n_ptr++;

Signed-off-by: Frediano Ziglio <freddy77@gmail.com>
Acked-by: Victor Toso <victortoso@redhat.com>
2021-02-22 09:11:35 +00:00
Frediano Ziglio
bd15c96f54 codegen: Propagate zero_terminated attribute
Currently the attribute is not used.
However we would like to make sure when present that the array
is always zero terminated to simplify usages after demarshalling.

Signed-off-by: Frediano Ziglio <freddy77@gmail.com>
Acked-by: Victor Toso <victortoso@redhat.com>
2021-02-22 09:11:33 +00:00
Frediano Ziglio
a627a14af0 codegen: Propagate attributes to element under pointers
Current propagated attributes are propagated only from member to
member type.
But for pointers you probably want to use propagated attribus to
underlying type (like an array for instance).

Signed-off-by: Frediano Ziglio <freddy77@gmail.com>
Acked-by: Victor Toso <victortoso@redhat.com>
2021-02-22 09:11:30 +00:00
Frediano Ziglio
6838f30079 codegen: Add a check to array type
If the size is not constant the array has to be allocated in some
way in the output and so there must be a specification for the
output (as default is write into the C structure all data).
The only exceptions are when the length is constant (in this case
a constant length array in the C structure is used) or a pointer
(in this case the pointer allocate the array).

Signed-off-by: Frediano Ziglio <freddy77@gmail.com>
Acked-by: Victor Toso <victortoso@redhat.com>
2021-02-22 09:11:28 +00:00
Frediano Ziglio
e49301ebd1 codegen: Make "output_attrs" variable global
Allows to reuse it.

Signed-off-by: Frediano Ziglio <freddy77@gmail.com>
Acked-by: Victor Toso <victortoso@redhat.com>
2021-02-22 09:11:22 +00:00
Frediano Ziglio
d8fe0cbb84 codegen: Remove bytes array length support
This syntax was only used in protocol 1 which has been removed
time ago.
Beside not being used it's confusing and prone to errors,
array size is specified using 2 identifiers, one reporting
bytes and the other number of items, one used for marshalling,
the other for demarshalling.

Signed-off-by: Frediano Ziglio <freddy77@gmail.com>
2020-10-06 13:09:56 +01:00
Haochen Tong
8e0e13881e marshal: fix clang "missing field initializer" warning on generated files
Signed-off-by: Haochen Tong <i@hexchain.org>
Acked-by: Frediano Ziglio <fziglio@redhat.com>
2020-07-11 08:17:20 +01:00
Frediano Ziglio
61ce54ef6c proto: Allows to specify @deprecated option for flags and enums
We want to obsolete from enumeration values, currently CELT.
The removal of check in has_attr is not an issue, as the attributes
are already checked by fix_attributes calls.

Signed-off-by: Frediano Ziglio <fziglio@redhat.com>
Acked-by: Victor Toso <victortoso@redhat.com>
2020-04-07 10:22:33 +01:00
Frediano Ziglio
b699221f00 codegen: Check unsafe values alone
This rule remove possible integer overflows.
Current code generated is not affected by these integer overflows
as the computations are done using 64 bit but better safe then sorry.

Signed-off-by: Frediano Ziglio <fziglio@redhat.com>
Acked-by: Julien Rope <jrope@redhat.com>
2020-02-07 16:14:53 +00:00
Frediano Ziglio
ead7790d47 codegen: Ignore path generating include guards
Make sure that guard do no change building out-of-tree or
with Meson.

Signed-off-by: Frediano Ziglio <fziglio@redhat.com>
Acked-by: Uri Lublin <uril@redhat.com>
2019-11-04 11:08:10 +00:00
Frediano Ziglio
99f6aa0028 codegen: Document "chunk" attribute
Signed-off-by: Frediano Ziglio <fziglio@redhat.com>
Acked-by: Victor Toso <victortoso@redhat.com>
2019-10-10 13:01:33 +01:00
Frediano Ziglio
d4248885e8 codegen: Check validity of array members
Check that combination of fields for an array does not
lead to unsafe code.
check_valid method came from generate_c_declaration with
some more check and it's use in demarshaller to validate
the array if the structure is not generated.

Signed-off-by: Frediano Ziglio <fziglio@redhat.com>
Acked-by: Victor Toso <victortoso@redhat.com>
2019-10-10 12:33:42 +01:00
Frediano Ziglio
a5a86a1caf codegen: Add 'chunk' to the output attributes
Output attributes are the attributes that specify how to store
that field in the C structure.
There can be only one output type specified.

Signed-off-by: Frediano Ziglio <fziglio@redhat.com>
Acked-by: Victor Toso <victortoso@redhat.com>
2019-10-10 11:11:36 +01:00
Frediano Ziglio
c392a7fee7 codegen: Add a check for C structure fields
This check make sure that output fields for member with @end (arrays)
are declared as empty arrays in output C structure.
This avoids output fields to be declared as pointer or other
invalid types.
The check is a compile time check so no code in object file
is generated.

Signed-off-by: Frediano Ziglio <fziglio@redhat.com>
Acked-by: Uri Lublin <uril@redhat.com>
2019-08-14 15:49:19 +01:00
Frediano Ziglio
7abd2b36d9 codegen: Use has_end_attr instead of has_attr("end")
Just style, they do the same thing, but is more coherent
with the rest of the code.

Signed-off-by: Frediano Ziglio <fziglio@redhat.com>
Acked-by: Uri Lublin <uril@redhat.com>
2019-08-13 18:10:56 +01:00
Uri Lublin
a52a0a0906 ptypes.py: remove useless condition member != None
member = None is set before the if/else condition.
In the else code, when member is set it is checked
and if not-None it breaks out of the loop.
If the code is still in the loop for sure member is None.

Found by covscan.

Signed-off-by: Uri Lublin <uril@redhat.com>
Acked-by: Frediano Ziglio <fziglio@redhat.com>
2019-08-12 17:00:42 +01:00
Frediano Ziglio
3cd3886b27 codegen: Allows to generate C declarations automatically
Allows to specify a @declare attribute for messages and structure
that can generate the needed C structures.

Signed-off-by: Frediano Ziglio <fziglio@redhat.com>
Acked-by: Christophe Fergeau <cfergeau@redhat.com>
2019-03-18 13:01:58 +00:00
Frediano Ziglio
cb00ccfaab codegen: Rename --prefix parameter to --suffix
The option is used to add a suffix to public functions, not a
prefix.
Currently the option is not used (it was used to generate protocol
1 code).

Signed-off-by: Frediano Ziglio <fziglio@redhat.com>
Acked-by: Christophe Fergeau <cfergeau@redhat.com>
2019-03-08 21:22:58 +00:00
Frediano Ziglio
302e30ff43 codegen: Remove support for --ptrsize
This option was used in protocol 1 to generate 64 bit pointers.
A pointer in the protocol is an offset in the current message.
This allows the possibility to have messages with pointers with more
than 4GB. This feature was removed and not used in protocol 2.
The reason this feature was correctly removed in protocol 2 is that
having 64 bit pointers in the protocol would require messages larger
than 4GB which would cause:
- huge latency as a single message would take more than 4 seconds
  to be send in a 10Gb connection;
- huge memory requirements.

Signed-off-by: Frediano Ziglio <fziglio@redhat.com>
Acked-by: Christophe Fergeau <cfergeau@redhat.com>
2019-03-08 11:09:02 +00:00
Frediano Ziglio
60883a0321 codegen: Add a test for attribute combination
Does not make sense to specify the same field to have 2
different C implementation at the same time.

Signed-off-by: Frediano Ziglio <fziglio@redhat.com>
Acked-by: Christophe Fergeau <cfergeau@redhat.com>
2019-02-21 09:05:03 +00:00
Frediano Ziglio
a5de31bc8a codegen: Check wrong attribute
@ptr_array is supposed to change the destination to an array
of pointer to items. This for a raw buffer does not make sense
but check if user specifies this combination.

Signed-off-by: Frediano Ziglio <fziglio@redhat.com>
Acked-by: Christophe Fergeau <cfergeau@redhat.com>
2019-02-20 17:45:29 +00:00
Frediano Ziglio
7462c171e1 codegen: Fix c_type result for TypeAlias
c_type() method is supposed to return the type to use for
C structure field. But the name is not a C type but a
protocol name.
Return the type name of the aliased type (for instance
uint32_t for a uint32 type).
This does not change the generated code.

Signed-off-by: Frediano Ziglio <fziglio@redhat.com>
Acked-by: Christophe Fergeau <cfergeau@redhat.com>
2019-02-20 17:42:59 +00:00
Frediano Ziglio
53c0c5a665 codegen: Reduce indentation
Signed-off-by: Frediano Ziglio <fziglio@redhat.com>
Acked-by: Christophe Fergeau <cfergeau@redhat.com>
2019-02-20 17:42:59 +00:00
Frediano Ziglio
7fa8bda275 codegen: Use a better type for pointer converted to integer
Although on the platform we support size_t and uintptr_t are
the same, on some platform the size_t can (in theory) be smaller
than the necessary integer to store a pointer.

Signed-off-by: Frediano Ziglio <fziglio@redhat.com>
Acked-by: Christophe Fergeau <cfergeau@redhat.com>
2019-02-20 17:42:59 +00:00
Frediano Ziglio
7f6c55790b codegen: Document ptr_array attribute
Signed-off-by: Frediano Ziglio <fziglio@redhat.com>
Acked-by: Christophe Fergeau <cfergeau@redhat.com>
2019-02-20 17:39:27 +00:00
Frediano Ziglio
2060672e81 Create common header for demarshallers declarations
Code generated for demarshallers define and declare some types and
functions.
However these types and functions are also declared separately in other
headers (currently spice-common/client_demarshallers.h and
spice/server/demarshallers.h) resulting in potential ABI mismatch if the
different declarations do not match.
Using a common header shared between generated code and code using
these functions prevent potentially multiple different declarations.

Signed-off-by: Frediano Ziglio <fziglio@redhat.com>
Acked-by: Christophe Fergeau <cfergeau@redhat.com>
2018-10-15 13:31:16 +01:00
Frediano Ziglio
ddfb8807c6 codegen: Remove minor attribute
The idea in version 1 of the protocol was to extend it using the minor
version. However this was replaced by the usage of capabilities and the
minor attribute (which was not much used in version 1) was abandoned in
version 2.
This patch create a big difference in the code generated but only because
the minor version was passed between all possible functions as argument.
Note that exported functions retain the minor argument for compatibility
reasons.
The demarshaller code export directly spice_get_client_channel_parser or
spice_get_server_channel_parser functions which returns internal module
functions which parse message of specific channels.

Signed-off-by: Frediano Ziglio <fziglio@redhat.com>
Acked-by: Christophe Fergeau <cfergeau@redhat.com>
2018-10-15 10:58:38 +01:00
Frediano Ziglio
8a68e67afa codegen: Remove fixedsize attribute
This attribute was used only in SPICE version 1.
The intention was use fixed size for switch type in the protocol.
However this does not bring any improvement, just increase network
bytes used.
Generated code does not change.

Signed-off-by: Frediano Ziglio <fziglio@redhat.com>
Acked-by: Christophe Fergeau <cfergeau@redhat.com>
2018-10-15 10:58:38 +01:00
Frediano Ziglio
979717350d codegen: Remove bytes_count attribute
This attribute was used only in SPICE version 1.
Its usage was confusing, and was replaced by the simple usage of
array size.
Generated code does not change.

Signed-off-by: Frediano Ziglio <fziglio@redhat.com>
Acked-by: Christophe Fergeau <cfergeau@redhat.com>
2018-10-15 10:58:38 +01:00
Frediano Ziglio
bb15d4815a Fix flexible array buffer overflow
This is kind of a DoS, possibly flexible array in the protocol
causes the network size check to be ignored due to integer overflows.

The size of flexible array is computed as (message_end - position),
then this size is added to the number of bytes before the array and
this number is used to check if we overflow initial message.

An example is:

    message {
        uint32 dummy[2];
        uint8 data[] @end;
    } LenMessage;

which generated this (simplified remove useless code) code:

    { /* data */
        data__nelements = message_end - (start + 8);

        data__nw_size = data__nelements;
    }

    nw_size = 8 + data__nw_size;

    /* Check if message fits in reported side */
    if (nw_size > (uintptr_t) (message_end - start)) {
        return NULL;
    }

Following code:
- data__nelements == message_end - (start + 8)
- data__nw_size == data__nelements == message_end - (start + 8)
- nw_size == 8 + data__nw_size == 8 + message_end - (start + 8) ==
  8 + message_end - start - 8 == message_end -start
- the check for overflow is (nw_size > (message_end - start)) but
  nw_size == message_end - start so the check is doing
  ((message_end - start) > (message_end - start)) which is always false.

If message_end - start < 8 then data__nelements (number of element
on the array above) computation generate an integer underflow that
later create a buffer overflow.

Add a check to make sure that the array starts before the message ends
to avoid the overflow.

Difference is:
    diff -u save/generated_client_demarshallers1.c common/generated_client_demarshallers1.c
    --- save/generated_client_demarshallers1.c	2018-06-22 22:13:48.626793919 +0100
    +++ common/generated_client_demarshallers1.c	2018-06-22 22:14:03.408163291 +0100
    @@ -225,6 +225,9 @@
         uint64_t data__nelements;

         { /* data */
    +        if (SPICE_UNLIKELY((start + 0) > message_end)) {
    +            goto error;
    +        }
             data__nelements = message_end - (start + 0);

             data__nw_size = data__nelements;
    @@ -243,6 +246,9 @@
         *free_message = nofree;
         return data;

    +   error:
    +    free(data);
    +    return NULL;
     }

     static uint8_t * parse_msg_set_ack(uint8_t *message_start, uint8_t *message_end, SPICE_GNUC_UNUSED int minor, size_t *size, message_destructor_t *free_message)
    @@ -301,6 +307,9 @@
         SpiceMsgPing *out;

         { /* data */
    +        if (SPICE_UNLIKELY((start + 12) > message_end)) {
    +            goto error;
    +        }
             data__nelements = message_end - (start + 12);

             data__nw_size = data__nelements;
    @@ -5226,6 +5235,9 @@
             uint64_t cursor_data__nw_size;
             uint64_t cursor_data__nelements;
             { /* data */
    +            if (SPICE_UNLIKELY((start2 + 22) > message_end)) {
    +                goto error;
    +            }
                 cursor_data__nelements = message_end - (start2 + 22);

                 cursor_data__nw_size = cursor_data__nelements;
    @@ -5305,6 +5317,9 @@
             uint64_t cursor_data__nw_size;
             uint64_t cursor_data__nelements;
             { /* data */
    +            if (SPICE_UNLIKELY((start2 + 22) > message_end)) {
    +                goto error;
    +            }
                 cursor_data__nelements = message_end - (start2 + 22);

                 cursor_data__nw_size = cursor_data__nelements;
    @@ -5540,6 +5555,9 @@
         SpiceMsgPlaybackPacket *out;

         { /* data */
    +        if (SPICE_UNLIKELY((start + 4) > message_end)) {
    +            goto error;
    +        }
             data__nelements = message_end - (start + 4);

             data__nw_size = data__nelements;
    @@ -5594,6 +5612,9 @@
         SpiceMsgPlaybackMode *out;

         { /* data */
    +        if (SPICE_UNLIKELY((start + 8) > message_end)) {
    +            goto error;
    +        }
             data__nelements = message_end - (start + 8);

             data__nw_size = data__nelements;
    diff -u save/generated_client_demarshallers.c common/generated_client_demarshallers.c
    --- save/generated_client_demarshallers.c	2018-06-22 22:13:48.626793919 +0100
    +++ common/generated_client_demarshallers.c	2018-06-22 22:14:03.004153195 +0100
    @@ -225,6 +225,9 @@
         uint64_t data__nelements;

         { /* data */
    +        if (SPICE_UNLIKELY((start + 0) > message_end)) {
    +            goto error;
    +        }
             data__nelements = message_end - (start + 0);

             data__nw_size = data__nelements;
    @@ -243,6 +246,9 @@
         *free_message = nofree;
         return data;

    +   error:
    +    free(data);
    +    return NULL;
     }

     static uint8_t * parse_msg_set_ack(uint8_t *message_start, uint8_t *message_end, SPICE_GNUC_UNUSED int minor, size_t *size, message_destructor_t *free_message)
    @@ -301,6 +307,9 @@
         SpiceMsgPing *out;

         { /* data */
    +        if (SPICE_UNLIKELY((start + 12) > message_end)) {
    +            goto error;
    +        }
             data__nelements = message_end - (start + 12);

             data__nw_size = data__nelements;
    @@ -6574,6 +6583,9 @@
             }

             { /* data */
    +            if (SPICE_UNLIKELY((start2 + 2 + cursor_u__nw_size) > message_end)) {
    +                goto error;
    +            }
                 cursor_data__nelements = message_end - (start2 + 2 + cursor_u__nw_size);

                 cursor_data__nw_size = cursor_data__nelements;
    @@ -6670,6 +6682,9 @@
             }

             { /* data */
    +            if (SPICE_UNLIKELY((start2 + 2 + cursor_u__nw_size) > message_end)) {
    +                goto error;
    +            }
                 cursor_data__nelements = message_end - (start2 + 2 + cursor_u__nw_size);

                 cursor_data__nw_size = cursor_data__nelements;
    @@ -6907,6 +6922,9 @@
         SpiceMsgPlaybackPacket *out;

         { /* data */
    +        if (SPICE_UNLIKELY((start + 4) > message_end)) {
    +            goto error;
    +        }
             data__nelements = message_end - (start + 4);

             data__nw_size = data__nelements;
    @@ -6961,6 +6979,9 @@
         SpiceMsgPlaybackMode *out;

         { /* data */
    +        if (SPICE_UNLIKELY((start + 6) > message_end)) {
    +            goto error;
    +        }
             data__nelements = message_end - (start + 6);

             data__nw_size = data__nelements;
    @@ -7559,6 +7580,9 @@
         SpiceMsgTunnelSocketData *out;

         { /* data */
    +        if (SPICE_UNLIKELY((start + 2) > message_end)) {
    +            goto error;
    +        }
             data__nelements = message_end - (start + 2);

             data__nw_size = data__nelements;
    @@ -7840,6 +7864,9 @@
         }

         { /* compressed_data */
    +        if (SPICE_UNLIKELY((start + 1 + u__nw_size) > message_end)) {
    +            goto error;
    +        }
             compressed_data__nelements = message_end - (start + 1 + u__nw_size);

             compressed_data__nw_size = compressed_data__nelements;
    diff -u save/generated_server_demarshallers.c common/generated_server_demarshallers.c
    --- save/generated_server_demarshallers.c	2018-06-22 22:13:48.627793944 +0100
    +++ common/generated_server_demarshallers.c	2018-06-22 22:14:05.231208847 +0100
    @@ -306,6 +306,9 @@
         uint64_t data__nelements;

         { /* data */
    +        if (SPICE_UNLIKELY((start + 0) > message_end)) {
    +            goto error;
    +        }
             data__nelements = message_end - (start + 0);

             data__nw_size = data__nelements;
    @@ -324,6 +327,9 @@
         *free_message = nofree;
         return data;

    +   error:
    +    free(data);
    +    return NULL;
     }

     static uint8_t * parse_msgc_disconnecting(uint8_t *message_start, uint8_t *message_end, SPICE_GNUC_UNUSED int minor, size_t *size, message_destructor_t *free_message)
    @@ -1259,6 +1265,9 @@
         SpiceMsgcRecordPacket *out;

         { /* data */
    +        if (SPICE_UNLIKELY((start + 4) > message_end)) {
    +            goto error;
    +        }
             data__nelements = message_end - (start + 4);

             data__nw_size = data__nelements;
    @@ -1313,6 +1322,9 @@
         SpiceMsgcRecordMode *out;

         { /* data */
    +        if (SPICE_UNLIKELY((start + 6) > message_end)) {
    +            goto error;
    +        }
             data__nelements = message_end - (start + 6);

             data__nw_size = data__nelements;
    @@ -1841,6 +1853,9 @@
         SpiceMsgcTunnelSocketData *out;

         { /* data */
    +        if (SPICE_UNLIKELY((start + 2) > message_end)) {
    +            goto error;
    +        }
             data__nelements = message_end - (start + 2);

             data__nw_size = data__nelements;
    @@ -2057,6 +2072,9 @@
         }

         { /* compressed_data */
    +        if (SPICE_UNLIKELY((start + 1 + u__nw_size) > message_end)) {
    +            goto error;
    +        }
             compressed_data__nelements = message_end - (start + 1 + u__nw_size);

             compressed_data__nw_size = compressed_data__nelements;

Signed-off-by: Frediano Ziglio <fziglio@redhat.com>
Signed-off-by: Christophe Fergeau <cfergeau@redhat.com>
2018-08-16 15:02:24 +01:00
Frediano Ziglio
252d1b61ed ptypes: Improve some attribute documentation
Signed-off-by: Frediano Ziglio <fziglio@redhat.com>
Acked-by: Jonathon Jongsma <jjongsma@redhat.com>
2018-06-27 21:51:42 +01:00
Frediano Ziglio
bc9df58162 marshal: Fix a bug with zero attribute
If this attribute was specified during marshaller the field was
marshalled twice.

Signed-off-by: Frediano Ziglio <fziglio@redhat.com>
Acked-by: Jonathon Jongsma <jjongsma@redhat.com>
2018-06-27 21:44:19 +01:00
Christophe Fergeau
32e2ed57b5 build: Add __pycache__/*.pyc to DISTCLEANFILES
Python 3 puts its .pyc files in a __pycache__ subdirectory, This commit
adds these to DISTCLEANFILES. My main motivation for doing this is so
that git.mk can then properly add them to .gitignore.

Acked-by: Victor Toso <victortoso@redhat.com>
2018-06-18 14:08:10 +01:00
Eduardo Lima (Etrunko)
55070333f6 Add support for building with meson/ninja
In a comparison with current autotools build system, meson/ninja
provides a huge improvement in build speed, while keeping the same
functionalities currently available and being considered more user
friendly.

The new system coexists within the same repository with the current one,
so we can do more extensive testing of its functionality before deciding
if the old system can be removed, or for some reason, has to stay for
good.

- Meson: https://mesonbuild.com

  This is the equivalent of autogen/configure step in autotools. It
  generates the files that will be used by ninja to actually build the
  source code.

  The project has received lots of traction recently, with many GNOME
  projects willing to move to this new build system. The following wiki
  page has more details of the status of the many projects being ported:

    https://wiki.gnome.org/Initiatives/GnomeGoals/MesonPorting

  Meson has a python-like syntax, easy to read, and the documentation
  on the project is very complete, with a dedicated page on how to port
  from autotools, explaining how most common use cases can be
  implemented using meson.

    http://mesonbuild.com/Porting-from-autotools.html

  Other important sources of information:

    http://mesonbuild.com/howtox.html
    http://mesonbuild.com/Syntax.html
    http://mesonbuild.com/Reference-manual.html

- Ninja: https://ninja-build.org

  Ninja is the equivalent of make in an autotools setup, which actually
  builds the source code. It has being used by large and complex
  projects such as Google Chrome, Android and LLVM. There is not much to
  say about ninja (other than it is much faster than make) because we
  won't interact directly with it as much, as meson does the middle man
  job here. The reasoning for creating ninja in the first place is
  explained on the following post:

    http://neugierig.org/software/chromium/notes/2011/02/ninja.html

  Also its manual provides more in-depth information about the design
  principles:

    https://ninja-build.org/manual.html

- Basic workflow:

  Meson package is available for most if not all distros, so, taking
  Fedora as an example, we only need to run:

    # dnf -y install meson ninja-build.

  With Meson, building in-tree is not possible at all, so we need to
  pass a directory as argument to meson where we want the build to be
  done. This has the advantage of creating builds with different options
  under the same parent directory, e.g.:

    $ meson ./build --prefix=/usr
    $ meson ./build-extra -Dextra-checks=true -Dalignment-checks=true

  After configuration is done, we call ninja to actually do the build.

    $ ninja -C ./build
    $ ninja -C ./build install

  Ninja defaults to parallel builds, and this can be changed with the -j
  flag.

    $ ninja -j 10 -C ./build

- Hacking:

  * meson.build: Mandatory for the project root and usually found under
                 each directory you want something to be built.

  * meson_options.txt: Options that can interfere with the result of the
                       build.

Signed-off-by: Eduardo Lima (Etrunko) <etrunko@redhat.com>
Acked-by: Frediano Ziglio <fziglio@redhat.com>
Acked-by: Jonathon Jongsma <jjongsma@redhat.com>
2018-06-01 21:27:04 +01:00
Frediano Ziglio
b17894e764 Check for messages with duplicate values inside a channel
Make sure there are not 2 messages with the same value in the
same channel.

Signed-off-by: Frediano Ziglio <fziglio@redhat.com>
Acked-by: Christophe Fergeau <cfergeau@redhat.com>
2018-05-23 10:33:05 +01:00
Frediano Ziglio
e2f7a9235f Check for messages with duplicate names inside a channel
Make sure there are not 2 messages with the same name in the
same channel.

Signed-off-by: Frediano Ziglio <fziglio@redhat.com>
Acked-by: Christophe Fergeau <cfergeau@redhat.com>
2018-05-23 10:31:30 +01:00
Frediano Ziglio
abdef4fd2a codegen: Remove duplicate client and server code from ChannelType::resolve
Code that handled client and server messages check was the same, just
changed some variable names.
Instead use a class to store same information and reuse the code.
This allows easier extension of the 2 path of code.

Signed-off-by: Frediano Ziglio <fziglio@redhat.com>
Acked-by: Lukáš Hrázký <lhrazky@redhat.com>
2018-05-23 10:30:44 +01:00
Eduardo Lima (Etrunko)
20bda4dba9 Fix demarshaller code generator
Even though commit df4ec5c318 commented
out most of smartcard code which triggered this error, it still might
happen if a new message is added with an array member.

The reason is a missing declaration of mem_size, which is fixed simply
by checking if the attribute 'nocopy' is present.

The error log follows:

generated_server_demarshallers.c: In function ‘parse_msgc_smartcard_reader_add’:
generated_server_demarshallers.c:1985:30: error: ‘mem_size’ undeclared (first use in this function); did you mean ‘nw_size’?
     data = (uint8_t *)malloc(mem_size);
                              ^~~~~~~~
                              nw_size

This patch also updates test-marshallers so that this bug is triggered.

The diff between generated demarshallers with the patch applied follows:

--- tests/generated_test_demarshallers.c.old    2018-05-17 14:35:29.234056487 -0300
+++ tests/generated_test_demarshallers.c        2018-05-17 14:35:40.554031295 -0300
@@ -286,6 +286,7 @@ static uint8_t * parse_msg_main_ArrayMes
     uint8_t *start = message_start;
     uint8_t *data = NULL;
     uint64_t nw_size;
+    uint64_t mem_size;
     uint8_t *in, *end;
     uint64_t name__nw_size;
     uint64_t name__nelements;
@@ -298,6 +299,7 @@ static uint8_t * parse_msg_main_ArrayMes
     }

     nw_size = 0 + name__nw_size;
+    mem_size = sizeof(SpiceMsgMainArrayMessage);

     /* Check if message fits in reported side */
     if (nw_size > (uintptr_t) (message_end - start)) {

Signed-off-by: Eduardo Lima (Etrunko) <etrunko@redhat.com>
Acked-by: Frediano Ziglio <fziglio@redhat.com>
2018-05-17 21:02:58 +01:00
Frediano Ziglio
617be0f74b Avoid integer overflow computing image sizes
Use always 64, sizes can be 32x32.

Signed-off-by: Frediano Ziglio <fziglio@redhat.com>
Acked-by: Jonathon Jongsma <jjongsma@redhat.com>
2018-05-11 17:00:26 +01:00
Frediano Ziglio
a69fb1ec34 Fix integer overflows computing sizes
Make code safe using both 32 and 64 bit machine.
Consider that this code can be compiled for machines with 32 bit.
There are some arrays length which are 32 bit.

If size_t this can cause easily an overflow. For instance message_len
sending SPICE_MSG_NOTIFY messages are 32 bit and code add a small
constant (currently 24) before doing the test for size. Now passing
(uint32_t) -20 as message_len would lead to a size of 4 after the
addition. This overflow does not happen on 64 bit machine as the length
is converted to size_t.

There are also some array length where some item are bigger than 1 byte.
For instance SPICE_MAIN_CHANNELS_LIST message have a number of channels
and each channel is composed by 2 bytes. Now the code generated try to do
length * 2 where length is still a 32 bit so if we put a value like
0x80000002u we get 4 as length. This will cause an overflow as code will
allocate very few bytes but try to fill with a huge number of elements.
This overflow happen in both 32 and 64 bit machine.

To avoid all these possible overflows this patch use only 64 bit for
nelements (number of elements), nw_size (network size) and mem_size
(memory size needed) checking the sizes to avoid other overflows
(like pointers conversions under 32 bit machines).

Signed-off-by: Frediano Ziglio <fziglio@redhat.com>
Acked-by: Christophe de Dinechin <dinechin@redhat.com>
2018-05-11 08:41:36 +01:00
Frediano Ziglio
754cd54e1a codegen: Removed unused get_type methods
Signed-off-by: Frediano Ziglio <fziglio@redhat.com>
Acked-by: Lukáš Hrázký <lhrazky@redhat.com>
2018-05-09 11:59:33 +01:00
Frediano Ziglio
46fa9d5efb codegen: Add some comments
Signed-off-by: Frediano Ziglio <fziglio@redhat.com>
Acked-by: Lukáš Hrázký <lhrazky@redhat.com>
2018-05-09 11:59:33 +01:00
Jonathon Jongsma
885b1a6bb9 Remove extra self parameter from member function
When testing out some experimental protocol changes, I managed to
trigger the following error:

  GEN      generated_client_demarshallers.c
Traceback (most recent call last):
  File "../../../spice-common/spice_codegen.py", line 267, in <module>
    demarshal.write_protocol_parser(writer, proto, True)
  File "/home/jjongsma/work/spice/spice-common/python_modules/demarshal.py", line 1270, in write_protocol_parser
    parsers[channel.value] = (channel.channel_type, write_channel_parser(writer, channel.channel_type, is_server))
  File "/home/jjongsma/work/spice/spice-common/python_modules/demarshal.py", line 1163, in write_channel_parser
    func = write_msg_parser(helpers, ids[i].message_type)
  File "/home/jjongsma/work/spice/spice-common/python_modules/demarshal.py", line 1061, in write_msg_parser
    num_pointers = message.get_num_pointers()
  File "/home/jjongsma/work/spice/spice-common/python_modules/ptypes.py", line 855, in get_num_pointers
    count = count + m.get_num_pointers()
  File "/home/jjongsma/work/spice/spice-common/python_modules/ptypes.py", line 662, in get_num_pointers
    return self.member_type.get_num_pointers()
  File "/home/jjongsma/work/spice/spice-common/python_modules/ptypes.py", line 507, in get_num_pointers
    if self.is_constant_length(self):
TypeError: is_constant_length() takes exactly 1 argument (2 given)

Calling a member function will implicitly pass 'self' as the first
argument, but we were also explicitly passing it as an argument
(self.is_constant_length(self)). This resulted in the above error.

Acked-by: Lukáš Hrázký <lhrazky@redhat.com>
2018-04-17 14:14:22 +01:00
Frediano Ziglio
74e50b57ae Make the compiler work out better way to write unaligned memory
Instead of assuming that the system can safely do unaligned access
to memory use packed structures to allow the compiler generate
best code possible.
A packed structure tells the compiler to not leave padding inside it
and that the structure can be unaligned so any field can be unaligned
having to generate proper access code based on architecture.
For instance ARM7 can use unaligned access but not for 64 bit
numbers (currently these accesses are emulated by Linux kernel
with obvious performance consequences).

This changes the current methods from:

#ifdef WORDS_BIGENDIAN
#define read_uint32(ptr) ((uint32_t)SPICE_BYTESWAP32(*((uint32_t *)(ptr))))
#define write_uint32(ptr, val) *(uint32_t *)(ptr) = SPICE_BYTESWAP32((uint32_t)val)
#else
#define read_uint32(ptr) (*((uint32_t *)(ptr)))
#define write_uint32(ptr, val) (*((uint32_t *)(ptr))) = val
#endif

to:

#include <spice/start-packed.h>
typedef struct SPICE_ATTR_PACKED {
    uint32_t v;
} uint32_unaligned_t;
#include <spice/end-packed.h>

#ifdef WORDS_BIGENDIAN
#define read_uint32(ptr) ((uint32_t)SPICE_BYTESWAP32(((uint32_unaligned_t *)(ptr))->v))
#define write_uint32(ptr, val) ((uint32_unaligned_t *)(ptr))->v = SPICE_BYTESWAP32((uint32_t)val)
#else
#define read_uint32(ptr) (((uint32_unaligned_t *)(ptr))->v)
#define write_uint32(ptr, val) (((uint32_unaligned_t *)(ptr))->v) = val
#endif

Signed-off-by: Frediano Ziglio <fziglio@redhat.com>
Acked-by: Christophe Fergeau <cfergeau@redhat.com>
2017-09-25 16:12:45 +01:00
Pavel Grunt
63e575d5fc silence -Wunused-parameter 2016-11-01 15:26:43 +01:00
Francois Gouget
38047fb46f codegen: Fix compatibility with Python 2.6
Python 2.6 does not have a flags parameter.
This is needed for RHEL 6.8.

Signed-off-by: Francois Gouget <fgouget@codeweavers.com>
Acked-by: Frediano Ziglio <fziglio@redhat.com>
2016-07-30 08:57:05 +01:00
Pavel Grunt
22f8dd18f0 codegen: Do not generate extra null check
Spotted by coverity

Acked-by: Fabiano Fidêncio <fidencio@redhat.com>
2016-07-26 10:16:31 +01:00
Christophe Fergeau
073d064b86 codegen: Autogenerate client_marshallers.h
This commit adds autogeneration of a generated_client_marshallers.h
header, which is then included in client_marshallers.h

This allows to remove the SpiceMessageMarshallers struct from this file,
which has to match what the generated code expects.

Acked-by: Frediano Ziglio <fziglio@redhat.com>
2016-06-24 10:02:58 +01:00
Frediano Ziglio
0eb567e6fb codegen: Improve header guard generation
Until now, the same header guard was used for all generated .h files.
Now the header guard name is based on the name of the file being
generated so that it's different for each .h file.

Signed-off-by: Frediano Ziglio <fziglio@redhat.com>
Signed-off-by: Christophe Fergeau <cfergeau@redhat.com>
Acked-by: Frediano Ziglio <fziglio@redhat.com>
Acked-by: Christophe Fergeau <cfergeau@redhat.com>
2016-06-24 10:02:06 +01:00