1 /* this is a file autogenerated by spice_codegen.py */
2 /*
3   Copyright (C) 2013 Red Hat, Inc.
4 
5   This library is free software; you can redistribute it and/or
6   modify it under the terms of the GNU Lesser General Public
7   License as published by the Free Software Foundation; either
8   version 2.1 of the License, or (at your option) any later version.
9 
10   This library is distributed in the hope that it will be useful,
11   but WITHOUT ANY WARRANTY; without even the implied warranty of
12   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13   Lesser General Public License for more details.
14 
15   You should have received a copy of the GNU Lesser General Public
16   License along with this library; if not, see <http://www.gnu.org/licenses/>.
17 */
18 
19 #ifdef HAVE_CONFIG_H
20 #include <config.h>
21 #endif
22 #include "common/messages.h"
23 #include <string.h>
24 #include <assert.h>
25 #include <stdlib.h>
26 #include <stdio.h>
27 #include <spice/protocol.h>
28 #include <spice/macros.h>
29 #include <common/mem.h>
30 #include <common/demarshallers.h>
31 
32 #ifdef _MSC_VER
33 #pragma warning(disable:4101)
34 #endif
35 
36 
37 
38 #include <spice/start-packed.h>
39 typedef struct SPICE_ATTR_PACKED {
40     int16_t v;
41 } int16_unaligned_t;
42 typedef struct SPICE_ATTR_PACKED {
43     uint16_t v;
44 } uint16_unaligned_t;
45 typedef struct SPICE_ATTR_PACKED {
46     int32_t v;
47 } int32_unaligned_t;
48 typedef struct SPICE_ATTR_PACKED {
49     uint32_t v;
50 } uint32_unaligned_t;
51 typedef struct SPICE_ATTR_PACKED {
52     int64_t v;
53 } int64_unaligned_t;
54 typedef struct SPICE_ATTR_PACKED {
55     uint64_t v;
56 } uint64_unaligned_t;
57 #include <spice/end-packed.h>
58 
59 #define read_int8(ptr) (*((int8_t *)(ptr)))
60 #define write_int8(ptr, val) *(int8_t *)(ptr) = val
61 #define read_uint8(ptr) (*((uint8_t *)(ptr)))
62 #define write_uint8(ptr, val) *(uint8_t *)(ptr) = val
63 
64 #ifdef WORDS_BIGENDIAN
65 #define read_int16(ptr) ((int16_t)SPICE_BYTESWAP16(((uint16_unaligned_t *)(ptr))->v))
66 #define write_int16(ptr, val) ((uint16_unaligned_t *)(ptr))->v = SPICE_BYTESWAP16((uint16_t)val)
67 #define read_uint16(ptr) ((uint16_t)SPICE_BYTESWAP16(((uint16_unaligned_t *)(ptr))->v))
68 #define write_uint16(ptr, val) ((uint16_unaligned_t *)(ptr))->v = SPICE_BYTESWAP16((uint16_t)val)
69 #define read_int32(ptr) ((int32_t)SPICE_BYTESWAP32(((uint32_unaligned_t *)(ptr))->v))
70 #define write_int32(ptr, val) ((uint32_unaligned_t *)(ptr))->v = SPICE_BYTESWAP32((uint32_t)val)
71 #define read_uint32(ptr) ((uint32_t)SPICE_BYTESWAP32(((uint32_unaligned_t *)(ptr))->v))
72 #define write_uint32(ptr, val) ((uint32_unaligned_t *)(ptr))->v = SPICE_BYTESWAP32((uint32_t)val)
73 #define read_int64(ptr) ((int64_t)SPICE_BYTESWAP64(((uint64_unaligned_t *)(ptr))->v))
74 #define write_int64(ptr, val) ((uint64_unaligned_t *)(ptr))->v = SPICE_BYTESWAP64((uint64_t)val)
75 #define read_uint64(ptr) ((uint64_t)SPICE_BYTESWAP64(((uint64_unaligned_t *)(ptr))->v))
76 #define write_uint64(ptr, val) ((uint64_unaligned_t *)(ptr))->v = SPICE_BYTESWAP64((uint64_t)val)
77 #else
78 #define read_int16(ptr) (((int16_unaligned_t *)(ptr))->v)
79 #define write_int16(ptr, val) (((int16_unaligned_t *)(ptr))->v) = val
80 #define read_uint16(ptr) (((uint16_unaligned_t *)(ptr))->v)
81 #define write_uint16(ptr, val) (((uint16_unaligned_t *)(ptr))->v) = val
82 #define read_int32(ptr) (((int32_unaligned_t *)(ptr))->v)
83 #define write_int32(ptr, val) (((int32_unaligned_t *)(ptr))->v) = val
84 #define read_uint32(ptr) (((uint32_unaligned_t *)(ptr))->v)
85 #define write_uint32(ptr, val) (((uint32_unaligned_t *)(ptr))->v) = val
86 #define read_int64(ptr) (((int64_unaligned_t *)(ptr))->v)
87 #define write_int64(ptr, val) (((int64_unaligned_t *)(ptr))->v) = val
88 #define read_uint64(ptr) (((uint64_unaligned_t *)(ptr))->v)
89 #define write_uint64(ptr, val) (((uint64_unaligned_t *)(ptr))->v) = val
90 #endif
91 
consume_int8(uint8_t ** ptr)92 static int8_t SPICE_GNUC_UNUSED consume_int8(uint8_t **ptr)
93 {
94     int8_t val;
95     val = read_int8(*ptr);
96     *ptr += 1;
97     return val;
98 }
99 
consume_uint8(uint8_t ** ptr)100 static uint8_t SPICE_GNUC_UNUSED consume_uint8(uint8_t **ptr)
101 {
102     uint8_t val;
103     val = read_uint8(*ptr);
104     *ptr += 1;
105     return val;
106 }
107 
consume_int16(uint8_t ** ptr)108 static int16_t SPICE_GNUC_UNUSED consume_int16(uint8_t **ptr)
109 {
110     int16_t val;
111     val = read_int16(*ptr);
112     *ptr += 2;
113     return val;
114 }
115 
consume_uint16(uint8_t ** ptr)116 static uint16_t SPICE_GNUC_UNUSED consume_uint16(uint8_t **ptr)
117 {
118     uint16_t val;
119     val = read_uint16(*ptr);
120     *ptr += 2;
121     return val;
122 }
123 
consume_int32(uint8_t ** ptr)124 static int32_t SPICE_GNUC_UNUSED consume_int32(uint8_t **ptr)
125 {
126     int32_t val;
127     val = read_int32(*ptr);
128     *ptr += 4;
129     return val;
130 }
131 
consume_uint32(uint8_t ** ptr)132 static uint32_t SPICE_GNUC_UNUSED consume_uint32(uint8_t **ptr)
133 {
134     uint32_t val;
135     val = read_uint32(*ptr);
136     *ptr += 4;
137     return val;
138 }
139 
consume_int64(uint8_t ** ptr)140 static int64_t SPICE_GNUC_UNUSED consume_int64(uint8_t **ptr)
141 {
142     int64_t val;
143     val = read_int64(*ptr);
144     *ptr += 8;
145     return val;
146 }
147 
consume_uint64(uint8_t ** ptr)148 static uint64_t SPICE_GNUC_UNUSED consume_uint64(uint8_t **ptr)
149 {
150     uint64_t val;
151     val = read_uint64(*ptr);
152     *ptr += 8;
153     return val;
154 }
consume_fd(uint8_t ** ptr SPICE_GNUC_UNUSED)155 static int SPICE_GNUC_UNUSED consume_fd(uint8_t **ptr SPICE_GNUC_UNUSED)
156 {
157     return -1;
158 }
159 
160 typedef struct PointerInfo PointerInfo;
161 typedef void (*message_destructor_t)(uint8_t *message);
162 typedef uint8_t * (*parse_func_t)(uint8_t *message_start, uint8_t *message_end, uint8_t *struct_data, PointerInfo *ptr_info);
163 typedef uint8_t * (*parse_msg_func_t)(uint8_t *message_start, uint8_t *message_end, size_t *size_out, message_destructor_t *free_message);
164 typedef uint8_t * (*spice_parse_channel_func_t)(uint8_t *message_start, uint8_t *message_end, uint16_t message_type, int minor, size_t *size_out, message_destructor_t *free_message);
165 
166 struct PointerInfo {
167     uint64_t offset;
168     parse_func_t parse;
169     void * *dest;
170     uint64_t nelements;
171 };
172 
parse_msg_migrate(uint8_t * message_start,uint8_t * message_end,size_t * size,message_destructor_t * free_message)173 static uint8_t * parse_msg_migrate(uint8_t *message_start, uint8_t *message_end, size_t *size, message_destructor_t *free_message)
174 {
175     SPICE_GNUC_UNUSED uint8_t *pos;
176     uint8_t *start = message_start;
177     uint8_t *data = NULL;
178     uint64_t nw_size;
179     uint64_t mem_size;
180     uint8_t *in, *end;
181     SpiceMsgMigrate *out;
182 
183     nw_size = 4;
184     mem_size = sizeof(SpiceMsgMigrate);
185 
186     /* Check if message fits in reported side */
187     if (nw_size > (uintptr_t) (message_end - start)) {
188         return NULL;
189     }
190 
191     /* Validated extents and calculated size */
192     data = (uint8_t *)(mem_size > UINT32_MAX ? NULL : malloc(mem_size));
193     if (SPICE_UNLIKELY(data == NULL)) {
194         goto error;
195     }
196     end = data + sizeof(SpiceMsgMigrate);
197     in = start;
198 
199     out = (SpiceMsgMigrate *)data;
200 
201     out->flags = consume_uint32(&in);
202 
203     assert(in <= message_end);
204     assert(end <= data + mem_size);
205 
206     *size = end - data;
207     *free_message = (message_destructor_t) free;
208     return data;
209 
210    error:
211     free(data);
212     return NULL;
213 }
214 
nofree(SPICE_GNUC_UNUSED uint8_t * data)215 static void nofree(SPICE_GNUC_UNUSED uint8_t *data)
216 {
217 }
218 
parse_SpiceMsgData(uint8_t * message_start,uint8_t * message_end,size_t * size,message_destructor_t * free_message)219 static uint8_t * parse_SpiceMsgData(uint8_t *message_start, uint8_t *message_end, size_t *size, message_destructor_t *free_message)
220 {
221     SPICE_GNUC_UNUSED uint8_t *pos;
222     uint8_t *start = message_start;
223     uint8_t *data = NULL;
224     uint64_t nw_size;
225     uint64_t data__nw_size;
226     uint64_t data__nelements;
227 
228     { /* data */
229         if (SPICE_UNLIKELY((start + 0) > message_end)) {
230             goto error;
231         }
232         data__nelements = message_end - (start + 0);
233 
234         data__nw_size = data__nelements;
235     }
236 
237     nw_size = 0 + data__nw_size;
238 
239     /* Check if message fits in reported side */
240     if (nw_size > (uintptr_t) (message_end - start)) {
241         return NULL;
242     }
243 
244     /* Validated extents and calculated size */
245     data = message_start;
246     *size = message_end - message_start;
247     *free_message = nofree;
248     return data;
249 
250    error:
251     free(data);
252     return NULL;
253 }
254 
parse_msg_set_ack(uint8_t * message_start,uint8_t * message_end,size_t * size,message_destructor_t * free_message)255 static uint8_t * parse_msg_set_ack(uint8_t *message_start, uint8_t *message_end, size_t *size, message_destructor_t *free_message)
256 {
257     SPICE_GNUC_UNUSED uint8_t *pos;
258     uint8_t *start = message_start;
259     uint8_t *data = NULL;
260     uint64_t nw_size;
261     uint64_t mem_size;
262     uint8_t *in, *end;
263     SpiceMsgSetAck *out;
264 
265     nw_size = 8;
266     mem_size = sizeof(SpiceMsgSetAck);
267 
268     /* Check if message fits in reported side */
269     if (nw_size > (uintptr_t) (message_end - start)) {
270         return NULL;
271     }
272 
273     /* Validated extents and calculated size */
274     data = (uint8_t *)(mem_size > UINT32_MAX ? NULL : malloc(mem_size));
275     if (SPICE_UNLIKELY(data == NULL)) {
276         goto error;
277     }
278     end = data + sizeof(SpiceMsgSetAck);
279     in = start;
280 
281     out = (SpiceMsgSetAck *)data;
282 
283     out->generation = consume_uint32(&in);
284     out->window = consume_uint32(&in);
285 
286     assert(in <= message_end);
287     assert(end <= data + mem_size);
288 
289     *size = end - data;
290     *free_message = (message_destructor_t) free;
291     return data;
292 
293    error:
294     free(data);
295     return NULL;
296 }
297 
parse_msg_ping(uint8_t * message_start,uint8_t * message_end,size_t * size,message_destructor_t * free_message)298 static uint8_t * parse_msg_ping(uint8_t *message_start, uint8_t *message_end, size_t *size, message_destructor_t *free_message)
299 {
300     SPICE_GNUC_UNUSED uint8_t *pos;
301     uint8_t *start = message_start;
302     uint8_t *data = NULL;
303     uint64_t nw_size;
304     uint64_t mem_size;
305     uint8_t *in, *end;
306     uint64_t data__nw_size;
307     uint64_t data__nelements;
308     SpiceMsgPing *out;
309 
310     { /* data */
311         if (SPICE_UNLIKELY((start + 12) > message_end)) {
312             goto error;
313         }
314         data__nelements = message_end - (start + 12);
315 
316         data__nw_size = data__nelements;
317     }
318 
319     nw_size = 12 + data__nw_size;
320     mem_size = sizeof(SpiceMsgPing);
321 
322     /* Check if message fits in reported side */
323     if (nw_size > (uintptr_t) (message_end - start)) {
324         return NULL;
325     }
326 
327     /* Validated extents and calculated size */
328     data = (uint8_t *)(mem_size > UINT32_MAX ? NULL : malloc(mem_size));
329     if (SPICE_UNLIKELY(data == NULL)) {
330         goto error;
331     }
332     end = data + sizeof(SpiceMsgPing);
333     in = start;
334 
335     out = (SpiceMsgPing *)data;
336 
337     out->id = consume_uint32(&in);
338     out->timestamp = consume_uint64(&in);
339     /* use array as pointer */
340     out->data = (uint8_t *)in;
341     out->data_len = data__nelements;
342     in += data__nelements;
343 
344     assert(in <= message_end);
345     assert(end <= data + mem_size);
346 
347     *size = end - data;
348     *free_message = (message_destructor_t) free;
349     return data;
350 
351    error:
352     free(data);
353     return NULL;
354 }
355 
parse_msg_wait_for_channels(uint8_t * message_start,uint8_t * message_end,size_t * size,message_destructor_t * free_message)356 static uint8_t * parse_msg_wait_for_channels(uint8_t *message_start, uint8_t *message_end, size_t *size, message_destructor_t *free_message)
357 {
358     SPICE_GNUC_UNUSED uint8_t *pos;
359     uint8_t *start = message_start;
360     uint8_t *data = NULL;
361     uint64_t nw_size;
362     uint64_t mem_size;
363     uint8_t *in, *end;
364     uint64_t wait_list__nw_size, wait_list__mem_size;
365     uint64_t wait_list__nelements;
366     SpiceMsgWaitForChannels *out;
367     uint32_t i;
368 
369     { /* wait_list */
370         uint8_t wait_count__value;
371         pos = start + 0;
372         if (SPICE_UNLIKELY(pos + 1 > message_end)) {
373             goto error;
374         }
375         wait_count__value = read_uint8(pos);
376         wait_list__nelements = wait_count__value;
377 
378         wait_list__nw_size = (10) * wait_list__nelements;
379         wait_list__mem_size = sizeof(SpiceWaitForChannel) * wait_list__nelements;
380     }
381 
382     nw_size = 1 + wait_list__nw_size;
383     mem_size = sizeof(SpiceMsgWaitForChannels) + wait_list__mem_size;
384 
385     /* Check if message fits in reported side */
386     if (nw_size > (uintptr_t) (message_end - start)) {
387         return NULL;
388     }
389 
390     /* Validated extents and calculated size */
391     data = (uint8_t *)(mem_size > UINT32_MAX ? NULL : malloc(mem_size));
392     if (SPICE_UNLIKELY(data == NULL)) {
393         goto error;
394     }
395     end = data + sizeof(SpiceMsgWaitForChannels);
396     in = start;
397 
398     out = (SpiceMsgWaitForChannels *)data;
399 
400     out->wait_count = consume_uint8(&in);
401     for (i = 0; i < wait_list__nelements; i++) {
402         SpiceWaitForChannel *out2;
403         out2 = (SpiceWaitForChannel *)end;
404         end += sizeof(SpiceWaitForChannel);
405 
406         out2->channel_type = consume_uint8(&in);
407         out2->channel_id = consume_uint8(&in);
408         out2->message_serial = consume_uint64(&in);
409     }
410 
411     assert(in <= message_end);
412     assert(end <= data + mem_size);
413 
414     *size = end - data;
415     *free_message = (message_destructor_t) free;
416     return data;
417 
418    error:
419     free(data);
420     return NULL;
421 }
422 
parse_msg_disconnecting(uint8_t * message_start,uint8_t * message_end,size_t * size,message_destructor_t * free_message)423 static uint8_t * parse_msg_disconnecting(uint8_t *message_start, uint8_t *message_end, size_t *size, message_destructor_t *free_message)
424 {
425     SPICE_GNUC_UNUSED uint8_t *pos;
426     uint8_t *start = message_start;
427     uint8_t *data = NULL;
428     uint64_t nw_size;
429     uint64_t mem_size;
430     uint8_t *in, *end;
431     SpiceMsgDisconnect *out;
432 
433     nw_size = 12;
434     mem_size = sizeof(SpiceMsgDisconnect);
435 
436     /* Check if message fits in reported side */
437     if (nw_size > (uintptr_t) (message_end - start)) {
438         return NULL;
439     }
440 
441     /* Validated extents and calculated size */
442     data = (uint8_t *)(mem_size > UINT32_MAX ? NULL : malloc(mem_size));
443     if (SPICE_UNLIKELY(data == NULL)) {
444         goto error;
445     }
446     end = data + sizeof(SpiceMsgDisconnect);
447     in = start;
448 
449     out = (SpiceMsgDisconnect *)data;
450 
451     out->time_stamp = consume_uint64(&in);
452     out->reason = consume_uint32(&in);
453 
454     assert(in <= message_end);
455     assert(end <= data + mem_size);
456 
457     *size = end - data;
458     *free_message = (message_destructor_t) free;
459     return data;
460 
461    error:
462     free(data);
463     return NULL;
464 }
465 
parse_msg_notify(uint8_t * message_start,uint8_t * message_end,size_t * size,message_destructor_t * free_message)466 static uint8_t * parse_msg_notify(uint8_t *message_start, uint8_t *message_end, size_t *size, message_destructor_t *free_message)
467 {
468     SPICE_GNUC_UNUSED uint8_t *pos;
469     uint8_t *start = message_start;
470     uint8_t *data = NULL;
471     uint64_t nw_size;
472     uint64_t mem_size;
473     uint8_t *in, *end;
474     uint64_t message__nw_size, message__mem_size;
475     uint64_t message__nelements;
476     SpiceMsgNotify *out;
477 
478     { /* message */
479         uint32_t message_len__value;
480         pos = start + 20;
481         if (SPICE_UNLIKELY(pos + 4 > message_end)) {
482             goto error;
483         }
484         message_len__value = read_uint32(pos);
485         message__nelements = message_len__value;
486 
487         message__nw_size = message__nelements;
488         message__mem_size = sizeof(uint8_t) * message__nelements;
489     }
490 
491     nw_size = 24 + message__nw_size;
492     mem_size = sizeof(SpiceMsgNotify) + message__mem_size;
493 
494     /* Check if message fits in reported side */
495     if (nw_size > (uintptr_t) (message_end - start)) {
496         return NULL;
497     }
498 
499     /* Validated extents and calculated size */
500     data = (uint8_t *)(mem_size > UINT32_MAX ? NULL : malloc(mem_size));
501     if (SPICE_UNLIKELY(data == NULL)) {
502         goto error;
503     }
504     end = data + sizeof(SpiceMsgNotify);
505     in = start;
506 
507     out = (SpiceMsgNotify *)data;
508 
509     out->time_stamp = consume_uint64(&in);
510     out->severity = consume_uint32(&in);
511     out->visibilty = consume_uint32(&in);
512     out->what = consume_uint32(&in);
513     out->message_len = consume_uint32(&in);
514     memcpy(out->message, in, message__nelements);
515     in += message__nelements;
516     end += message__nelements;
517 
518     assert(in <= message_end);
519     assert(end <= data + mem_size);
520 
521     *size = end - data;
522     *free_message = (message_destructor_t) free;
523     return data;
524 
525    error:
526     free(data);
527     return NULL;
528 }
529 
parse_SpiceMsgEmpty(uint8_t * message_start,uint8_t * message_end,size_t * size,message_destructor_t * free_message)530 static uint8_t * parse_SpiceMsgEmpty(uint8_t *message_start, uint8_t *message_end, size_t *size, message_destructor_t *free_message)
531 {
532     SPICE_GNUC_UNUSED uint8_t *pos;
533     uint8_t *start = message_start;
534     uint8_t *data = NULL;
535     uint64_t nw_size;
536     uint64_t mem_size;
537     uint8_t *in, *end;
538 
539     nw_size = 0;
540     mem_size = sizeof(SpiceMsgEmpty);
541 
542     /* Check if message fits in reported side */
543     if (nw_size > (uintptr_t) (message_end - start)) {
544         return NULL;
545     }
546 
547     /* Validated extents and calculated size */
548     data = (uint8_t *)(mem_size > UINT32_MAX ? NULL : malloc(mem_size));
549     if (SPICE_UNLIKELY(data == NULL)) {
550         goto error;
551     }
552     end = data + sizeof(SpiceMsgEmpty);
553     in = start;
554 
555 
556     assert(in <= message_end);
557     assert(end <= data + mem_size);
558 
559     *size = end - data;
560     *free_message = (message_destructor_t) free;
561     return data;
562 
563    error:
564     free(data);
565     return NULL;
566 }
567 
parse_array_uint8(uint8_t * message_start,SPICE_GNUC_UNUSED uint8_t * message_end,uint8_t * struct_data,PointerInfo * this_ptr_info)568 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)
569 {
570     uint8_t *in = message_start + this_ptr_info->offset;
571     uint8_t *end;
572 
573     end = struct_data;
574     memcpy(end, in, this_ptr_info->nelements);
575     in += this_ptr_info->nelements;
576     end += this_ptr_info->nelements;
577     return end;
578 }
579 
parse_msg_main_migrate_begin(uint8_t * message_start,uint8_t * message_end,size_t * size,message_destructor_t * free_message)580 static uint8_t * parse_msg_main_migrate_begin(uint8_t *message_start, uint8_t *message_end, size_t *size, message_destructor_t *free_message)
581 {
582     SPICE_GNUC_UNUSED uint8_t *pos;
583     uint8_t *start = message_start;
584     uint8_t *data = NULL;
585     uint64_t nw_size;
586     uint64_t mem_size;
587     uint8_t *in, *end;
588     SPICE_GNUC_UNUSED intptr_t ptr_size;
589     uint32_t n_ptr=0;
590     PointerInfo ptr_info[2];
591     uint64_t dst_info__extra_size;
592     SpiceMsgMainMigrationBegin *out;
593     uint32_t i;
594 
595     { /* dst_info */
596         SPICE_GNUC_UNUSED uint8_t *start2 = (start + 0);
597         uint64_t dst_info_host_data__extra_size;
598         uint64_t dst_info_host_data__array__nelements;
599         uint64_t dst_info_cert_subject_data__extra_size;
600         uint64_t dst_info_cert_subject_data__array__nelements;
601         { /* host_data */
602             uint32_t host_data__value;
603             uint64_t dst_info_host_data__array__nw_size;
604             uint64_t dst_info_host_data__array__mem_size;
605             uint32_t host_size__value;
606             pos = (start2 + 8);
607             if (SPICE_UNLIKELY(pos + 4 > message_end)) {
608                 goto error;
609             }
610             host_data__value = read_uint32(pos);
611             if (SPICE_UNLIKELY(host_data__value == 0)) {
612                 goto error;
613             }
614             if (SPICE_UNLIKELY(host_data__value >= (uintptr_t) (message_end - message_start))) {
615                 goto error;
616             }
617             pos = start2 + 4;
618             if (SPICE_UNLIKELY(pos + 4 > message_end)) {
619                 goto error;
620             }
621             host_size__value = read_uint32(pos);
622             dst_info_host_data__array__nelements = host_size__value;
623 
624             dst_info_host_data__array__nw_size = dst_info_host_data__array__nelements;
625             dst_info_host_data__array__mem_size = sizeof(uint8_t) * dst_info_host_data__array__nelements;
626             if (SPICE_UNLIKELY(host_data__value + dst_info_host_data__array__nw_size > (uintptr_t) (message_end - message_start))) {
627                 goto error;
628             }
629             dst_info_host_data__extra_size = dst_info_host_data__array__mem_size + /* for alignment */ 3;
630         }
631 
632         { /* cert_subject_data */
633             uint32_t cert_subject_data__value;
634             uint64_t dst_info_cert_subject_data__array__nw_size;
635             uint64_t dst_info_cert_subject_data__array__mem_size;
636             uint32_t cert_subject_size__value;
637             pos = (start2 + 16);
638             if (SPICE_UNLIKELY(pos + 4 > message_end)) {
639                 goto error;
640             }
641             cert_subject_data__value = read_uint32(pos);
642             if (SPICE_UNLIKELY(cert_subject_data__value >= (uintptr_t) (message_end - message_start))) {
643                 goto error;
644             }
645             pos = start2 + 12;
646             if (SPICE_UNLIKELY(pos + 4 > message_end)) {
647                 goto error;
648             }
649             cert_subject_size__value = read_uint32(pos);
650             dst_info_cert_subject_data__array__nelements = cert_subject_size__value;
651 
652             dst_info_cert_subject_data__array__nw_size = dst_info_cert_subject_data__array__nelements;
653             dst_info_cert_subject_data__array__mem_size = sizeof(uint8_t) * dst_info_cert_subject_data__array__nelements;
654             if (SPICE_UNLIKELY(cert_subject_data__value + dst_info_cert_subject_data__array__nw_size > (uintptr_t) (message_end - message_start))) {
655                 goto error;
656             }
657             dst_info_cert_subject_data__extra_size = dst_info_cert_subject_data__array__mem_size + /* for alignment */ 3;
658         }
659 
660         dst_info__extra_size = dst_info_host_data__extra_size + dst_info_cert_subject_data__extra_size;
661     }
662 
663     nw_size = 20;
664     mem_size = sizeof(SpiceMsgMainMigrationBegin) + dst_info__extra_size;
665 
666     /* Check if message fits in reported side */
667     if (nw_size > (uintptr_t) (message_end - start)) {
668         return NULL;
669     }
670 
671     /* Validated extents and calculated size */
672     data = (uint8_t *)(mem_size > UINT32_MAX ? NULL : malloc(mem_size));
673     if (SPICE_UNLIKELY(data == NULL)) {
674         goto error;
675     }
676     end = data + sizeof(SpiceMsgMainMigrationBegin);
677     in = start;
678 
679     out = (SpiceMsgMainMigrationBegin *)data;
680 
681     /* dst_info */ {
682         uint64_t host_data__array__nelements;
683         uint64_t cert_subject_data__array__nelements;
684         out->dst_info.port = consume_uint16(&in);
685         out->dst_info.sport = consume_uint16(&in);
686         out->dst_info.host_size = consume_uint32(&in);
687         ptr_info[n_ptr].offset = consume_uint32(&in);
688         ptr_info[n_ptr].parse = parse_array_uint8;
689         ptr_info[n_ptr].dest = (void **)&out->dst_info.host_data;
690         host_data__array__nelements = out->dst_info.host_size;
691         ptr_info[n_ptr].nelements = host_data__array__nelements;
692         n_ptr++;
693         out->dst_info.cert_subject_size = consume_uint32(&in);
694         ptr_info[n_ptr].offset = consume_uint32(&in);
695         ptr_info[n_ptr].parse = parse_array_uint8;
696         ptr_info[n_ptr].dest = (void **)&out->dst_info.cert_subject_data;
697         cert_subject_data__array__nelements = out->dst_info.cert_subject_size;
698         ptr_info[n_ptr].nelements = cert_subject_data__array__nelements;
699         n_ptr++;
700     }
701 
702     assert(in <= message_end);
703 
704     for (i = 0; i < n_ptr; i++) {
705         if (ptr_info[i].offset == 0) {
706             *ptr_info[i].dest = NULL;
707         } else {
708             /* Align to 32 bit */
709             end = (uint8_t *)SPICE_ALIGN((uintptr_t)end, 4);
710             *ptr_info[i].dest = (void *)end;
711             end = ptr_info[i].parse(message_start, message_end, end, &ptr_info[i]);
712             if (SPICE_UNLIKELY(end == NULL)) {
713                 goto error;
714             }
715         }
716     }
717 
718     assert(end <= data + mem_size);
719 
720     *size = end - data;
721     *free_message = (message_destructor_t) free;
722     return data;
723 
724    error:
725     free(data);
726     return NULL;
727 }
728 
parse_msg_main_init(uint8_t * message_start,uint8_t * message_end,size_t * size,message_destructor_t * free_message)729 static uint8_t * parse_msg_main_init(uint8_t *message_start, uint8_t *message_end, size_t *size, message_destructor_t *free_message)
730 {
731     SPICE_GNUC_UNUSED uint8_t *pos;
732     uint8_t *start = message_start;
733     uint8_t *data = NULL;
734     uint64_t nw_size;
735     uint64_t mem_size;
736     uint8_t *in, *end;
737     SpiceMsgMainInit *out;
738 
739     nw_size = 32;
740     mem_size = sizeof(SpiceMsgMainInit);
741 
742     /* Check if message fits in reported side */
743     if (nw_size > (uintptr_t) (message_end - start)) {
744         return NULL;
745     }
746 
747     /* Validated extents and calculated size */
748     data = (uint8_t *)(mem_size > UINT32_MAX ? NULL : malloc(mem_size));
749     if (SPICE_UNLIKELY(data == NULL)) {
750         goto error;
751     }
752     end = data + sizeof(SpiceMsgMainInit);
753     in = start;
754 
755     out = (SpiceMsgMainInit *)data;
756 
757     out->session_id = consume_uint32(&in);
758     out->display_channels_hint = consume_uint32(&in);
759     out->supported_mouse_modes = consume_uint32(&in);
760     out->current_mouse_mode = consume_uint32(&in);
761     out->agent_connected = consume_uint32(&in);
762     out->agent_tokens = consume_uint32(&in);
763     out->multi_media_time = consume_uint32(&in);
764     out->ram_hint = consume_uint32(&in);
765 
766     assert(in <= message_end);
767     assert(end <= data + mem_size);
768 
769     *size = end - data;
770     *free_message = (message_destructor_t) free;
771     return data;
772 
773    error:
774     free(data);
775     return NULL;
776 }
777 
parse_msg_main_channels_list(uint8_t * message_start,uint8_t * message_end,size_t * size,message_destructor_t * free_message)778 static uint8_t * parse_msg_main_channels_list(uint8_t *message_start, uint8_t *message_end, size_t *size, message_destructor_t *free_message)
779 {
780     SPICE_GNUC_UNUSED uint8_t *pos;
781     uint8_t *start = message_start;
782     uint8_t *data = NULL;
783     uint64_t nw_size;
784     uint64_t mem_size;
785     uint8_t *in, *end;
786     uint64_t channels__nw_size, channels__mem_size;
787     uint64_t channels__nelements;
788     SpiceMsgChannels *out;
789     uint32_t i;
790 
791     { /* channels */
792         uint32_t num_of_channels__value;
793         pos = start + 0;
794         if (SPICE_UNLIKELY(pos + 4 > message_end)) {
795             goto error;
796         }
797         num_of_channels__value = read_uint32(pos);
798         channels__nelements = num_of_channels__value;
799 
800         channels__nw_size = (2) * channels__nelements;
801         channels__mem_size = sizeof(SpiceChannelId) * channels__nelements;
802     }
803 
804     nw_size = 4 + channels__nw_size;
805     mem_size = sizeof(SpiceMsgChannels) + channels__mem_size;
806 
807     /* Check if message fits in reported side */
808     if (nw_size > (uintptr_t) (message_end - start)) {
809         return NULL;
810     }
811 
812     /* Validated extents and calculated size */
813     data = (uint8_t *)(mem_size > UINT32_MAX ? NULL : malloc(mem_size));
814     if (SPICE_UNLIKELY(data == NULL)) {
815         goto error;
816     }
817     end = data + sizeof(SpiceMsgChannels);
818     in = start;
819 
820     out = (SpiceMsgChannels *)data;
821 
822     out->num_of_channels = consume_uint32(&in);
823     for (i = 0; i < channels__nelements; i++) {
824         SpiceChannelId *out2;
825         out2 = (SpiceChannelId *)end;
826         end += sizeof(SpiceChannelId);
827 
828         out2->type = consume_uint8(&in);
829         out2->id = consume_uint8(&in);
830     }
831 
832     assert(in <= message_end);
833     assert(end <= data + mem_size);
834 
835     *size = end - data;
836     *free_message = (message_destructor_t) free;
837     return data;
838 
839    error:
840     free(data);
841     return NULL;
842 }
843 
parse_msg_main_mouse_mode(uint8_t * message_start,uint8_t * message_end,size_t * size,message_destructor_t * free_message)844 static uint8_t * parse_msg_main_mouse_mode(uint8_t *message_start, uint8_t *message_end, size_t *size, message_destructor_t *free_message)
845 {
846     SPICE_GNUC_UNUSED uint8_t *pos;
847     uint8_t *start = message_start;
848     uint8_t *data = NULL;
849     uint64_t nw_size;
850     uint64_t mem_size;
851     uint8_t *in, *end;
852     SpiceMsgMainMouseMode *out;
853 
854     nw_size = 4;
855     mem_size = sizeof(SpiceMsgMainMouseMode);
856 
857     /* Check if message fits in reported side */
858     if (nw_size > (uintptr_t) (message_end - start)) {
859         return NULL;
860     }
861 
862     /* Validated extents and calculated size */
863     data = (uint8_t *)(mem_size > UINT32_MAX ? NULL : malloc(mem_size));
864     if (SPICE_UNLIKELY(data == NULL)) {
865         goto error;
866     }
867     end = data + sizeof(SpiceMsgMainMouseMode);
868     in = start;
869 
870     out = (SpiceMsgMainMouseMode *)data;
871 
872     out->supported_modes = consume_uint16(&in);
873     out->current_mode = consume_uint16(&in);
874 
875     assert(in <= message_end);
876     assert(end <= data + mem_size);
877 
878     *size = end - data;
879     *free_message = (message_destructor_t) free;
880     return data;
881 
882    error:
883     free(data);
884     return NULL;
885 }
886 
parse_msg_main_multi_media_time(uint8_t * message_start,uint8_t * message_end,size_t * size,message_destructor_t * free_message)887 static uint8_t * parse_msg_main_multi_media_time(uint8_t *message_start, uint8_t *message_end, size_t *size, message_destructor_t *free_message)
888 {
889     SPICE_GNUC_UNUSED uint8_t *pos;
890     uint8_t *start = message_start;
891     uint8_t *data = NULL;
892     uint64_t nw_size;
893     uint64_t mem_size;
894     uint8_t *in, *end;
895     SpiceMsgMainMultiMediaTime *out;
896 
897     nw_size = 4;
898     mem_size = sizeof(SpiceMsgMainMultiMediaTime);
899 
900     /* Check if message fits in reported side */
901     if (nw_size > (uintptr_t) (message_end - start)) {
902         return NULL;
903     }
904 
905     /* Validated extents and calculated size */
906     data = (uint8_t *)(mem_size > UINT32_MAX ? NULL : malloc(mem_size));
907     if (SPICE_UNLIKELY(data == NULL)) {
908         goto error;
909     }
910     end = data + sizeof(SpiceMsgMainMultiMediaTime);
911     in = start;
912 
913     out = (SpiceMsgMainMultiMediaTime *)data;
914 
915     out->time = consume_uint32(&in);
916 
917     assert(in <= message_end);
918     assert(end <= data + mem_size);
919 
920     *size = end - data;
921     *free_message = (message_destructor_t) free;
922     return data;
923 
924    error:
925     free(data);
926     return NULL;
927 }
928 
parse_msg_main_agent_disconnected(uint8_t * message_start,uint8_t * message_end,size_t * size,message_destructor_t * free_message)929 static uint8_t * parse_msg_main_agent_disconnected(uint8_t *message_start, uint8_t *message_end, size_t *size, message_destructor_t *free_message)
930 {
931     SPICE_GNUC_UNUSED uint8_t *pos;
932     uint8_t *start = message_start;
933     uint8_t *data = NULL;
934     uint64_t nw_size;
935     uint64_t mem_size;
936     uint8_t *in, *end;
937     SpiceMsgMainAgentDisconnect *out;
938 
939     nw_size = 4;
940     mem_size = sizeof(SpiceMsgMainAgentDisconnect);
941 
942     /* Check if message fits in reported side */
943     if (nw_size > (uintptr_t) (message_end - start)) {
944         return NULL;
945     }
946 
947     /* Validated extents and calculated size */
948     data = (uint8_t *)(mem_size > UINT32_MAX ? NULL : malloc(mem_size));
949     if (SPICE_UNLIKELY(data == NULL)) {
950         goto error;
951     }
952     end = data + sizeof(SpiceMsgMainAgentDisconnect);
953     in = start;
954 
955     out = (SpiceMsgMainAgentDisconnect *)data;
956 
957     out->error_code = consume_uint32(&in);
958 
959     assert(in <= message_end);
960     assert(end <= data + mem_size);
961 
962     *size = end - data;
963     *free_message = (message_destructor_t) free;
964     return data;
965 
966    error:
967     free(data);
968     return NULL;
969 }
970 
parse_msg_main_agent_token(uint8_t * message_start,uint8_t * message_end,size_t * size,message_destructor_t * free_message)971 static uint8_t * parse_msg_main_agent_token(uint8_t *message_start, uint8_t *message_end, size_t *size, message_destructor_t *free_message)
972 {
973     SPICE_GNUC_UNUSED uint8_t *pos;
974     uint8_t *start = message_start;
975     uint8_t *data = NULL;
976     uint64_t nw_size;
977     uint64_t mem_size;
978     uint8_t *in, *end;
979     SpiceMsgMainAgentTokens *out;
980 
981     nw_size = 4;
982     mem_size = sizeof(SpiceMsgMainAgentTokens);
983 
984     /* Check if message fits in reported side */
985     if (nw_size > (uintptr_t) (message_end - start)) {
986         return NULL;
987     }
988 
989     /* Validated extents and calculated size */
990     data = (uint8_t *)(mem_size > UINT32_MAX ? NULL : malloc(mem_size));
991     if (SPICE_UNLIKELY(data == NULL)) {
992         goto error;
993     }
994     end = data + sizeof(SpiceMsgMainAgentTokens);
995     in = start;
996 
997     out = (SpiceMsgMainAgentTokens *)data;
998 
999     out->num_tokens = consume_uint32(&in);
1000 
1001     assert(in <= message_end);
1002     assert(end <= data + mem_size);
1003 
1004     *size = end - data;
1005     *free_message = (message_destructor_t) free;
1006     return data;
1007 
1008    error:
1009     free(data);
1010     return NULL;
1011 }
1012 
parse_msg_main_migrate_switch_host(uint8_t * message_start,uint8_t * message_end,size_t * size,message_destructor_t * free_message)1013 static uint8_t * parse_msg_main_migrate_switch_host(uint8_t *message_start, uint8_t *message_end, size_t *size, message_destructor_t *free_message)
1014 {
1015     SPICE_GNUC_UNUSED uint8_t *pos;
1016     uint8_t *start = message_start;
1017     uint8_t *data = NULL;
1018     uint64_t nw_size;
1019     uint64_t mem_size;
1020     uint8_t *in, *end;
1021     SPICE_GNUC_UNUSED intptr_t ptr_size;
1022     uint32_t n_ptr=0;
1023     PointerInfo ptr_info[2];
1024     uint64_t host_data__extra_size;
1025     uint64_t host_data__array__nelements;
1026     uint64_t cert_subject_data__extra_size;
1027     uint64_t cert_subject_data__array__nelements;
1028     SpiceMsgMainMigrationSwitchHost *out;
1029     uint32_t i;
1030 
1031     { /* host_data */
1032         uint32_t host_data__value;
1033         uint64_t host_data__array__nw_size;
1034         uint64_t host_data__array__mem_size;
1035         uint32_t host_size__value;
1036         pos = (start + 8);
1037         if (SPICE_UNLIKELY(pos + 4 > message_end)) {
1038             goto error;
1039         }
1040         host_data__value = read_uint32(pos);
1041         if (SPICE_UNLIKELY(host_data__value >= (uintptr_t) (message_end - message_start))) {
1042             goto error;
1043         }
1044         pos = start + 4;
1045         if (SPICE_UNLIKELY(pos + 4 > message_end)) {
1046             goto error;
1047         }
1048         host_size__value = read_uint32(pos);
1049         host_data__array__nelements = host_size__value;
1050 
1051         host_data__array__nw_size = host_data__array__nelements;
1052         host_data__array__mem_size = sizeof(uint8_t) * host_data__array__nelements;
1053         if (SPICE_UNLIKELY(host_data__value + host_data__array__nw_size > (uintptr_t) (message_end - message_start))) {
1054             goto error;
1055         }
1056         host_data__extra_size = host_data__array__mem_size + /* for alignment */ 3;
1057     }
1058 
1059     { /* cert_subject_data */
1060         uint32_t cert_subject_data__value;
1061         uint64_t cert_subject_data__array__nw_size;
1062         uint64_t cert_subject_data__array__mem_size;
1063         uint32_t cert_subject_size__value;
1064         pos = (start + 16);
1065         if (SPICE_UNLIKELY(pos + 4 > message_end)) {
1066             goto error;
1067         }
1068         cert_subject_data__value = read_uint32(pos);
1069         if (SPICE_UNLIKELY(cert_subject_data__value >= (uintptr_t) (message_end - message_start))) {
1070             goto error;
1071         }
1072         pos = start + 12;
1073         if (SPICE_UNLIKELY(pos + 4 > message_end)) {
1074             goto error;
1075         }
1076         cert_subject_size__value = read_uint32(pos);
1077         cert_subject_data__array__nelements = cert_subject_size__value;
1078 
1079         cert_subject_data__array__nw_size = cert_subject_data__array__nelements;
1080         cert_subject_data__array__mem_size = sizeof(uint8_t) * cert_subject_data__array__nelements;
1081         if (SPICE_UNLIKELY(cert_subject_data__value + cert_subject_data__array__nw_size > (uintptr_t) (message_end - message_start))) {
1082             goto error;
1083         }
1084         cert_subject_data__extra_size = cert_subject_data__array__mem_size + /* for alignment */ 3;
1085     }
1086 
1087     nw_size = 20;
1088     mem_size = sizeof(SpiceMsgMainMigrationSwitchHost) + host_data__extra_size + cert_subject_data__extra_size;
1089 
1090     /* Check if message fits in reported side */
1091     if (nw_size > (uintptr_t) (message_end - start)) {
1092         return NULL;
1093     }
1094 
1095     /* Validated extents and calculated size */
1096     data = (uint8_t *)(mem_size > UINT32_MAX ? NULL : malloc(mem_size));
1097     if (SPICE_UNLIKELY(data == NULL)) {
1098         goto error;
1099     }
1100     end = data + sizeof(SpiceMsgMainMigrationSwitchHost);
1101     in = start;
1102 
1103     out = (SpiceMsgMainMigrationSwitchHost *)data;
1104 
1105     out->port = consume_uint16(&in);
1106     out->sport = consume_uint16(&in);
1107     out->host_size = consume_uint32(&in);
1108     ptr_info[n_ptr].offset = consume_uint32(&in);
1109     ptr_info[n_ptr].parse = parse_array_uint8;
1110     ptr_info[n_ptr].dest = (void **)&out->host_data;
1111     ptr_info[n_ptr].nelements = host_data__array__nelements;
1112     n_ptr++;
1113     out->cert_subject_size = consume_uint32(&in);
1114     ptr_info[n_ptr].offset = consume_uint32(&in);
1115     ptr_info[n_ptr].parse = parse_array_uint8;
1116     ptr_info[n_ptr].dest = (void **)&out->cert_subject_data;
1117     ptr_info[n_ptr].nelements = cert_subject_data__array__nelements;
1118     n_ptr++;
1119 
1120     assert(in <= message_end);
1121 
1122     for (i = 0; i < n_ptr; i++) {
1123         if (ptr_info[i].offset == 0) {
1124             *ptr_info[i].dest = NULL;
1125         } else {
1126             /* Align to 32 bit */
1127             end = (uint8_t *)SPICE_ALIGN((uintptr_t)end, 4);
1128             *ptr_info[i].dest = (void *)end;
1129             end = ptr_info[i].parse(message_start, message_end, end, &ptr_info[i]);
1130             if (SPICE_UNLIKELY(end == NULL)) {
1131                 goto error;
1132             }
1133         }
1134     }
1135 
1136     assert(end <= data + mem_size);
1137 
1138     *size = end - data;
1139     *free_message = (message_destructor_t) free;
1140     return data;
1141 
1142    error:
1143     free(data);
1144     return NULL;
1145 }
1146 
parse_msg_main_name(uint8_t * message_start,uint8_t * message_end,size_t * size,message_destructor_t * free_message)1147 static uint8_t * parse_msg_main_name(uint8_t *message_start, uint8_t *message_end, size_t *size, message_destructor_t *free_message)
1148 {
1149     SPICE_GNUC_UNUSED uint8_t *pos;
1150     uint8_t *start = message_start;
1151     uint8_t *data = NULL;
1152     uint64_t nw_size;
1153     uint64_t mem_size;
1154     uint8_t *in, *end;
1155     uint64_t name__nw_size, name__mem_size;
1156     uint64_t name__nelements;
1157     SpiceMsgMainName *out;
1158 
1159     { /* name */
1160         uint32_t name_len__value;
1161         pos = start + 0;
1162         if (SPICE_UNLIKELY(pos + 4 > message_end)) {
1163             goto error;
1164         }
1165         name_len__value = read_uint32(pos);
1166         name__nelements = name_len__value;
1167 
1168         name__nw_size = name__nelements;
1169         name__mem_size = sizeof(uint8_t) * name__nelements;
1170     }
1171 
1172     nw_size = 4 + name__nw_size;
1173     mem_size = sizeof(SpiceMsgMainName) + name__mem_size;
1174 
1175     /* Check if message fits in reported side */
1176     if (nw_size > (uintptr_t) (message_end - start)) {
1177         return NULL;
1178     }
1179 
1180     /* Validated extents and calculated size */
1181     data = (uint8_t *)(mem_size > UINT32_MAX ? NULL : malloc(mem_size));
1182     if (SPICE_UNLIKELY(data == NULL)) {
1183         goto error;
1184     }
1185     end = data + sizeof(SpiceMsgMainName);
1186     in = start;
1187 
1188     out = (SpiceMsgMainName *)data;
1189 
1190     out->name_len = consume_uint32(&in);
1191     memcpy(out->name, in, name__nelements);
1192     in += name__nelements;
1193     end += name__nelements;
1194 
1195     assert(in <= message_end);
1196     assert(end <= data + mem_size);
1197 
1198     *size = end - data;
1199     *free_message = (message_destructor_t) free;
1200     return data;
1201 
1202    error:
1203     free(data);
1204     return NULL;
1205 }
1206 
parse_msg_main_uuid(uint8_t * message_start,uint8_t * message_end,size_t * size,message_destructor_t * free_message)1207 static uint8_t * parse_msg_main_uuid(uint8_t *message_start, uint8_t *message_end, size_t *size, message_destructor_t *free_message)
1208 {
1209     SPICE_GNUC_UNUSED uint8_t *pos;
1210     uint8_t *start = message_start;
1211     uint8_t *data = NULL;
1212     uint64_t nw_size;
1213     uint64_t mem_size;
1214     uint8_t *in, *end;
1215     SpiceMsgMainUuid *out;
1216     uint64_t uuid__nelements;
1217 
1218     nw_size = 16;
1219     mem_size = sizeof(SpiceMsgMainUuid);
1220 
1221     /* Check if message fits in reported side */
1222     if (nw_size > (uintptr_t) (message_end - start)) {
1223         return NULL;
1224     }
1225 
1226     /* Validated extents and calculated size */
1227     data = (uint8_t *)(mem_size > UINT32_MAX ? NULL : malloc(mem_size));
1228     if (SPICE_UNLIKELY(data == NULL)) {
1229         goto error;
1230     }
1231     end = data + sizeof(SpiceMsgMainUuid);
1232     in = start;
1233 
1234     out = (SpiceMsgMainUuid *)data;
1235 
1236     uuid__nelements = 16;
1237     memcpy(out->uuid, in, uuid__nelements);
1238     in += uuid__nelements;
1239 
1240     assert(in <= message_end);
1241     assert(end <= data + mem_size);
1242 
1243     *size = end - data;
1244     *free_message = (message_destructor_t) free;
1245     return data;
1246 
1247    error:
1248     free(data);
1249     return NULL;
1250 }
1251 
parse_msg_main_agent_connected_tokens(uint8_t * message_start,uint8_t * message_end,size_t * size,message_destructor_t * free_message)1252 static uint8_t * parse_msg_main_agent_connected_tokens(uint8_t *message_start, uint8_t *message_end, size_t *size, message_destructor_t *free_message)
1253 {
1254     SPICE_GNUC_UNUSED uint8_t *pos;
1255     uint8_t *start = message_start;
1256     uint8_t *data = NULL;
1257     uint64_t nw_size;
1258     uint64_t mem_size;
1259     uint8_t *in, *end;
1260     SpiceMsgMainAgentConnectedTokens *out;
1261 
1262     nw_size = 4;
1263     mem_size = sizeof(SpiceMsgMainAgentConnectedTokens);
1264 
1265     /* Check if message fits in reported side */
1266     if (nw_size > (uintptr_t) (message_end - start)) {
1267         return NULL;
1268     }
1269 
1270     /* Validated extents and calculated size */
1271     data = (uint8_t *)(mem_size > UINT32_MAX ? NULL : malloc(mem_size));
1272     if (SPICE_UNLIKELY(data == NULL)) {
1273         goto error;
1274     }
1275     end = data + sizeof(SpiceMsgMainAgentConnectedTokens);
1276     in = start;
1277 
1278     out = (SpiceMsgMainAgentConnectedTokens *)data;
1279 
1280     out->num_tokens = consume_uint32(&in);
1281 
1282     assert(in <= message_end);
1283     assert(end <= data + mem_size);
1284 
1285     *size = end - data;
1286     *free_message = (message_destructor_t) free;
1287     return data;
1288 
1289    error:
1290     free(data);
1291     return NULL;
1292 }
1293 
parse_msg_main_migrate_begin_seamless(uint8_t * message_start,uint8_t * message_end,size_t * size,message_destructor_t * free_message)1294 static uint8_t * parse_msg_main_migrate_begin_seamless(uint8_t *message_start, uint8_t *message_end, size_t *size, message_destructor_t *free_message)
1295 {
1296     SPICE_GNUC_UNUSED uint8_t *pos;
1297     uint8_t *start = message_start;
1298     uint8_t *data = NULL;
1299     uint64_t nw_size;
1300     uint64_t mem_size;
1301     uint8_t *in, *end;
1302     SPICE_GNUC_UNUSED intptr_t ptr_size;
1303     uint32_t n_ptr=0;
1304     PointerInfo ptr_info[2];
1305     uint64_t dst_info__extra_size;
1306     SpiceMsgMainMigrateBeginSeamless *out;
1307     uint32_t i;
1308 
1309     { /* dst_info */
1310         SPICE_GNUC_UNUSED uint8_t *start2 = (start + 0);
1311         uint64_t dst_info_host_data__extra_size;
1312         uint64_t dst_info_host_data__array__nelements;
1313         uint64_t dst_info_cert_subject_data__extra_size;
1314         uint64_t dst_info_cert_subject_data__array__nelements;
1315         { /* host_data */
1316             uint32_t host_data__value;
1317             uint64_t dst_info_host_data__array__nw_size;
1318             uint64_t dst_info_host_data__array__mem_size;
1319             uint32_t host_size__value;
1320             pos = (start2 + 8);
1321             if (SPICE_UNLIKELY(pos + 4 > message_end)) {
1322                 goto error;
1323             }
1324             host_data__value = read_uint32(pos);
1325             if (SPICE_UNLIKELY(host_data__value == 0)) {
1326                 goto error;
1327             }
1328             if (SPICE_UNLIKELY(host_data__value >= (uintptr_t) (message_end - message_start))) {
1329                 goto error;
1330             }
1331             pos = start2 + 4;
1332             if (SPICE_UNLIKELY(pos + 4 > message_end)) {
1333                 goto error;
1334             }
1335             host_size__value = read_uint32(pos);
1336             dst_info_host_data__array__nelements = host_size__value;
1337 
1338             dst_info_host_data__array__nw_size = dst_info_host_data__array__nelements;
1339             dst_info_host_data__array__mem_size = sizeof(uint8_t) * dst_info_host_data__array__nelements;
1340             if (SPICE_UNLIKELY(host_data__value + dst_info_host_data__array__nw_size > (uintptr_t) (message_end - message_start))) {
1341                 goto error;
1342             }
1343             dst_info_host_data__extra_size = dst_info_host_data__array__mem_size + /* for alignment */ 3;
1344         }
1345 
1346         { /* cert_subject_data */
1347             uint32_t cert_subject_data__value;
1348             uint64_t dst_info_cert_subject_data__array__nw_size;
1349             uint64_t dst_info_cert_subject_data__array__mem_size;
1350             uint32_t cert_subject_size__value;
1351             pos = (start2 + 16);
1352             if (SPICE_UNLIKELY(pos + 4 > message_end)) {
1353                 goto error;
1354             }
1355             cert_subject_data__value = read_uint32(pos);
1356             if (SPICE_UNLIKELY(cert_subject_data__value >= (uintptr_t) (message_end - message_start))) {
1357                 goto error;
1358             }
1359             pos = start2 + 12;
1360             if (SPICE_UNLIKELY(pos + 4 > message_end)) {
1361                 goto error;
1362             }
1363             cert_subject_size__value = read_uint32(pos);
1364             dst_info_cert_subject_data__array__nelements = cert_subject_size__value;
1365 
1366             dst_info_cert_subject_data__array__nw_size = dst_info_cert_subject_data__array__nelements;
1367             dst_info_cert_subject_data__array__mem_size = sizeof(uint8_t) * dst_info_cert_subject_data__array__nelements;
1368             if (SPICE_UNLIKELY(cert_subject_data__value + dst_info_cert_subject_data__array__nw_size > (uintptr_t) (message_end - message_start))) {
1369                 goto error;
1370             }
1371             dst_info_cert_subject_data__extra_size = dst_info_cert_subject_data__array__mem_size + /* for alignment */ 3;
1372         }
1373 
1374         dst_info__extra_size = dst_info_host_data__extra_size + dst_info_cert_subject_data__extra_size;
1375     }
1376 
1377     nw_size = 24;
1378     mem_size = sizeof(SpiceMsgMainMigrateBeginSeamless) + dst_info__extra_size;
1379 
1380     /* Check if message fits in reported side */
1381     if (nw_size > (uintptr_t) (message_end - start)) {
1382         return NULL;
1383     }
1384 
1385     /* Validated extents and calculated size */
1386     data = (uint8_t *)(mem_size > UINT32_MAX ? NULL : malloc(mem_size));
1387     if (SPICE_UNLIKELY(data == NULL)) {
1388         goto error;
1389     }
1390     end = data + sizeof(SpiceMsgMainMigrateBeginSeamless);
1391     in = start;
1392 
1393     out = (SpiceMsgMainMigrateBeginSeamless *)data;
1394 
1395     /* dst_info */ {
1396         uint64_t host_data__array__nelements;
1397         uint64_t cert_subject_data__array__nelements;
1398         out->dst_info.port = consume_uint16(&in);
1399         out->dst_info.sport = consume_uint16(&in);
1400         out->dst_info.host_size = consume_uint32(&in);
1401         ptr_info[n_ptr].offset = consume_uint32(&in);
1402         ptr_info[n_ptr].parse = parse_array_uint8;
1403         ptr_info[n_ptr].dest = (void **)&out->dst_info.host_data;
1404         host_data__array__nelements = out->dst_info.host_size;
1405         ptr_info[n_ptr].nelements = host_data__array__nelements;
1406         n_ptr++;
1407         out->dst_info.cert_subject_size = consume_uint32(&in);
1408         ptr_info[n_ptr].offset = consume_uint32(&in);
1409         ptr_info[n_ptr].parse = parse_array_uint8;
1410         ptr_info[n_ptr].dest = (void **)&out->dst_info.cert_subject_data;
1411         cert_subject_data__array__nelements = out->dst_info.cert_subject_size;
1412         ptr_info[n_ptr].nelements = cert_subject_data__array__nelements;
1413         n_ptr++;
1414     }
1415     out->src_mig_version = consume_uint32(&in);
1416 
1417     assert(in <= message_end);
1418 
1419     for (i = 0; i < n_ptr; i++) {
1420         if (ptr_info[i].offset == 0) {
1421             *ptr_info[i].dest = NULL;
1422         } else {
1423             /* Align to 32 bit */
1424             end = (uint8_t *)SPICE_ALIGN((uintptr_t)end, 4);
1425             *ptr_info[i].dest = (void *)end;
1426             end = ptr_info[i].parse(message_start, message_end, end, &ptr_info[i]);
1427             if (SPICE_UNLIKELY(end == NULL)) {
1428                 goto error;
1429             }
1430         }
1431     }
1432 
1433     assert(end <= data + mem_size);
1434 
1435     *size = end - data;
1436     *free_message = (message_destructor_t) free;
1437     return data;
1438 
1439    error:
1440     free(data);
1441     return NULL;
1442 }
1443 
parse_MainChannel_msg(uint8_t * message_start,uint8_t * message_end,uint16_t message_type,SPICE_GNUC_UNUSED int minor,size_t * size_out,message_destructor_t * free_message)1444 static uint8_t * parse_MainChannel_msg(uint8_t *message_start, uint8_t *message_end, uint16_t message_type, SPICE_GNUC_UNUSED int minor, size_t *size_out, message_destructor_t *free_message)
1445 {
1446     static parse_msg_func_t funcs1[8] =  {
1447         parse_msg_migrate,
1448         parse_SpiceMsgData,
1449         parse_msg_set_ack,
1450         parse_msg_ping,
1451         parse_msg_wait_for_channels,
1452         parse_msg_disconnecting,
1453         parse_msg_notify,
1454         parse_SpiceMsgData
1455     };
1456     static parse_msg_func_t funcs2[19] =  {
1457         parse_SpiceMsgEmpty,
1458         parse_msg_main_migrate_begin,
1459         parse_SpiceMsgEmpty,
1460         parse_msg_main_init,
1461         parse_msg_main_channels_list,
1462         parse_msg_main_mouse_mode,
1463         parse_msg_main_multi_media_time,
1464         parse_SpiceMsgEmpty,
1465         parse_msg_main_agent_disconnected,
1466         parse_SpiceMsgData,
1467         parse_msg_main_agent_token,
1468         parse_msg_main_migrate_switch_host,
1469         parse_SpiceMsgEmpty,
1470         parse_msg_main_name,
1471         parse_msg_main_uuid,
1472         parse_msg_main_agent_connected_tokens,
1473         parse_msg_main_migrate_begin_seamless,
1474         parse_SpiceMsgEmpty,
1475         parse_SpiceMsgEmpty
1476     };
1477     if (message_type >= 1 && message_type < 9) {
1478         return funcs1[message_type-1](message_start, message_end, size_out, free_message);
1479     } else if (message_type >= 100 && message_type < 119) {
1480         return funcs2[message_type-100](message_start, message_end, size_out, free_message);
1481     }
1482     return NULL;
1483 }
1484 
1485 
1486 
parse_msg_display_mode(uint8_t * message_start,uint8_t * message_end,size_t * size,message_destructor_t * free_message)1487 static uint8_t * parse_msg_display_mode(uint8_t *message_start, uint8_t *message_end, size_t *size, message_destructor_t *free_message)
1488 {
1489     SPICE_GNUC_UNUSED uint8_t *pos;
1490     uint8_t *start = message_start;
1491     uint8_t *data = NULL;
1492     uint64_t nw_size;
1493     uint64_t mem_size;
1494     uint8_t *in, *end;
1495     SpiceMsgDisplayMode *out;
1496 
1497     nw_size = 12;
1498     mem_size = sizeof(SpiceMsgDisplayMode);
1499 
1500     /* Check if message fits in reported side */
1501     if (nw_size > (uintptr_t) (message_end - start)) {
1502         return NULL;
1503     }
1504 
1505     /* Validated extents and calculated size */
1506     data = (uint8_t *)(mem_size > UINT32_MAX ? NULL : malloc(mem_size));
1507     if (SPICE_UNLIKELY(data == NULL)) {
1508         goto error;
1509     }
1510     end = data + sizeof(SpiceMsgDisplayMode);
1511     in = start;
1512 
1513     out = (SpiceMsgDisplayMode *)data;
1514 
1515     out->x_res = consume_uint32(&in);
1516     out->y_res = consume_uint32(&in);
1517     out->bits = consume_uint32(&in);
1518 
1519     assert(in <= message_end);
1520     assert(end <= data + mem_size);
1521 
1522     *size = end - data;
1523     *free_message = (message_destructor_t) free;
1524     return data;
1525 
1526    error:
1527     free(data);
1528     return NULL;
1529 }
1530 
parse_struct_SpiceClipRects(uint8_t * message_start,SPICE_GNUC_UNUSED uint8_t * message_end,uint8_t * struct_data,PointerInfo * this_ptr_info)1531 static uint8_t * parse_struct_SpiceClipRects(uint8_t *message_start, SPICE_GNUC_UNUSED uint8_t *message_end, uint8_t *struct_data, PointerInfo *this_ptr_info)
1532 {
1533     uint8_t *in = message_start + this_ptr_info->offset;
1534     uint8_t *end;
1535     SpiceClipRects *out;
1536     uint64_t rects__nelements;
1537     uint32_t i;
1538 
1539     end = struct_data + sizeof(SpiceClipRects);
1540     out = (SpiceClipRects *)struct_data;
1541 
1542     out->num_rects = consume_uint32(&in);
1543     rects__nelements = out->num_rects;
1544     for (i = 0; i < rects__nelements; i++) {
1545         SpiceRect *out2;
1546         out2 = (SpiceRect *)end;
1547         end += sizeof(SpiceRect);
1548 
1549         out2->top = consume_int32(&in);
1550         out2->left = consume_int32(&in);
1551         out2->bottom = consume_int32(&in);
1552         out2->right = consume_int32(&in);
1553     }
1554     return end;
1555 }
1556 
parse_msg_display_copy_bits(uint8_t * message_start,uint8_t * message_end,size_t * size,message_destructor_t * free_message)1557 static uint8_t * parse_msg_display_copy_bits(uint8_t *message_start, uint8_t *message_end, size_t *size, message_destructor_t *free_message)
1558 {
1559     SPICE_GNUC_UNUSED uint8_t *pos;
1560     uint8_t *start = message_start;
1561     uint8_t *data = NULL;
1562     uint64_t nw_size;
1563     uint64_t mem_size;
1564     uint8_t *in, *end;
1565     SPICE_GNUC_UNUSED intptr_t ptr_size;
1566     uint32_t n_ptr=0;
1567     PointerInfo ptr_info[1];
1568     uint64_t base__nw_size, base__extra_size;
1569     uint32_t rects__saved_size = 0;
1570     SpiceMsgDisplayCopyBits *out;
1571     uint32_t i;
1572 
1573     { /* base */
1574         SPICE_GNUC_UNUSED uint8_t *start2 = (start + 0);
1575         uint64_t base_clip__nw_size, base_clip__extra_size;
1576         { /* clip */
1577             SPICE_GNUC_UNUSED uint8_t *start3 = (start2 + 20);
1578             uint64_t base_clip_u__nw_size, base_clip_u__extra_size;
1579             uint8_t type__value;
1580             { /* u */
1581                 uint64_t base_clip_u__mem_size;
1582                 pos = start3 + 0;
1583                 if (SPICE_UNLIKELY(pos + 1 > message_end)) {
1584                     goto error;
1585                 }
1586                 type__value = read_uint8(pos);
1587                 if (type__value == SPICE_CLIP_TYPE_RECTS) {
1588                     SPICE_GNUC_UNUSED uint8_t *start4 = (start3 + 1);
1589                     uint64_t base_clip_u_rects__nw_size, base_clip_u_rects__mem_size;
1590                     uint64_t base_clip_u_rects__nelements;
1591                     { /* rects */
1592                         uint32_t num_rects__value;
1593                         pos = start4 + 0;
1594                         if (SPICE_UNLIKELY(pos + 4 > message_end)) {
1595                             goto error;
1596                         }
1597                         num_rects__value = read_uint32(pos);
1598                         base_clip_u_rects__nelements = num_rects__value;
1599 
1600                         base_clip_u_rects__nw_size = (16) * base_clip_u_rects__nelements;
1601                         base_clip_u_rects__mem_size = sizeof(SpiceRect) * base_clip_u_rects__nelements;
1602                     }
1603 
1604                     base_clip_u__nw_size = 4 + base_clip_u_rects__nw_size;
1605                     base_clip_u__mem_size = sizeof(SpiceClipRects) + base_clip_u_rects__mem_size;
1606                     rects__saved_size = base_clip_u__nw_size;
1607                     base_clip_u__extra_size = base_clip_u__mem_size;
1608                 } else {
1609                     base_clip_u__nw_size = 0;
1610                     base_clip_u__extra_size = 0;
1611                 }
1612 
1613             }
1614 
1615             base_clip__nw_size = 1 + base_clip_u__nw_size;
1616             base_clip__extra_size = base_clip_u__extra_size;
1617         }
1618 
1619         base__nw_size = 20 + base_clip__nw_size;
1620         base__extra_size = base_clip__extra_size;
1621     }
1622 
1623     nw_size = 8 + base__nw_size;
1624     mem_size = sizeof(SpiceMsgDisplayCopyBits) + base__extra_size;
1625 
1626     /* Check if message fits in reported side */
1627     if (nw_size > (uintptr_t) (message_end - start)) {
1628         return NULL;
1629     }
1630 
1631     /* Validated extents and calculated size */
1632     data = (uint8_t *)(mem_size > UINT32_MAX ? NULL : malloc(mem_size));
1633     if (SPICE_UNLIKELY(data == NULL)) {
1634         goto error;
1635     }
1636     end = data + sizeof(SpiceMsgDisplayCopyBits);
1637     in = start;
1638 
1639     out = (SpiceMsgDisplayCopyBits *)data;
1640 
1641     /* base */ {
1642         out->base.surface_id = consume_uint32(&in);
1643         /* box */ {
1644             out->base.box.top = consume_int32(&in);
1645             out->base.box.left = consume_int32(&in);
1646             out->base.box.bottom = consume_int32(&in);
1647             out->base.box.right = consume_int32(&in);
1648         }
1649         /* clip */ {
1650             out->base.clip.type = consume_uint8(&in);
1651             if (out->base.clip.type == SPICE_CLIP_TYPE_RECTS) {
1652                 ptr_info[n_ptr].offset = in - start;
1653                 ptr_info[n_ptr].parse = parse_struct_SpiceClipRects;
1654                 ptr_info[n_ptr].dest = (void **)&out->base.clip.rects;
1655                 n_ptr++;
1656                 in += rects__saved_size;
1657             }
1658         }
1659     }
1660     /* src_pos */ {
1661         out->src_pos.x = consume_int32(&in);
1662         out->src_pos.y = consume_int32(&in);
1663     }
1664 
1665     assert(in <= message_end);
1666 
1667     for (i = 0; i < n_ptr; i++) {
1668         if (ptr_info[i].offset == 0) {
1669             *ptr_info[i].dest = NULL;
1670         } else {
1671             /* Align to 32 bit */
1672             end = (uint8_t *)SPICE_ALIGN((uintptr_t)end, 4);
1673             *ptr_info[i].dest = (void *)end;
1674             end = ptr_info[i].parse(message_start, message_end, end, &ptr_info[i]);
1675             if (SPICE_UNLIKELY(end == NULL)) {
1676                 goto error;
1677             }
1678         }
1679     }
1680 
1681     assert(end <= data + mem_size);
1682 
1683     *size = end - data;
1684     *free_message = (message_destructor_t) free;
1685     return data;
1686 
1687    error:
1688     free(data);
1689     return NULL;
1690 }
1691 
parse_msg_display_inval_list(uint8_t * message_start,uint8_t * message_end,size_t * size,message_destructor_t * free_message)1692 static uint8_t * parse_msg_display_inval_list(uint8_t *message_start, uint8_t *message_end, size_t *size, message_destructor_t *free_message)
1693 {
1694     SPICE_GNUC_UNUSED uint8_t *pos;
1695     uint8_t *start = message_start;
1696     uint8_t *data = NULL;
1697     uint64_t nw_size;
1698     uint64_t mem_size;
1699     uint8_t *in, *end;
1700     uint64_t resources__nw_size, resources__mem_size;
1701     uint64_t resources__nelements;
1702     SpiceResourceList *out;
1703     uint32_t i;
1704 
1705     { /* resources */
1706         uint16_t count__value;
1707         pos = start + 0;
1708         if (SPICE_UNLIKELY(pos + 2 > message_end)) {
1709             goto error;
1710         }
1711         count__value = read_uint16(pos);
1712         resources__nelements = count__value;
1713 
1714         resources__nw_size = (9) * resources__nelements;
1715         resources__mem_size = sizeof(SpiceResourceID) * resources__nelements;
1716     }
1717 
1718     nw_size = 2 + resources__nw_size;
1719     mem_size = sizeof(SpiceResourceList) + resources__mem_size;
1720 
1721     /* Check if message fits in reported side */
1722     if (nw_size > (uintptr_t) (message_end - start)) {
1723         return NULL;
1724     }
1725 
1726     /* Validated extents and calculated size */
1727     data = (uint8_t *)(mem_size > UINT32_MAX ? NULL : malloc(mem_size));
1728     if (SPICE_UNLIKELY(data == NULL)) {
1729         goto error;
1730     }
1731     end = data + sizeof(SpiceResourceList);
1732     in = start;
1733 
1734     out = (SpiceResourceList *)data;
1735 
1736     out->count = consume_uint16(&in);
1737     for (i = 0; i < resources__nelements; i++) {
1738         SpiceResourceID *out2;
1739         out2 = (SpiceResourceID *)end;
1740         end += sizeof(SpiceResourceID);
1741 
1742         out2->type = consume_uint8(&in);
1743         out2->id = consume_uint64(&in);
1744     }
1745 
1746     assert(in <= message_end);
1747     assert(end <= data + mem_size);
1748 
1749     *size = end - data;
1750     *free_message = (message_destructor_t) free;
1751     return data;
1752 
1753    error:
1754     free(data);
1755     return NULL;
1756 }
1757 
parse_msg_display_inval_all_pixmaps(uint8_t * message_start,uint8_t * message_end,size_t * size,message_destructor_t * free_message)1758 static uint8_t * parse_msg_display_inval_all_pixmaps(uint8_t *message_start, uint8_t *message_end, size_t *size, message_destructor_t *free_message)
1759 {
1760     SPICE_GNUC_UNUSED uint8_t *pos;
1761     uint8_t *start = message_start;
1762     uint8_t *data = NULL;
1763     uint64_t nw_size;
1764     uint64_t mem_size;
1765     uint8_t *in, *end;
1766     uint64_t wait_list__nw_size, wait_list__mem_size;
1767     uint64_t wait_list__nelements;
1768     SpiceMsgWaitForChannels *out;
1769     uint32_t i;
1770 
1771     { /* wait_list */
1772         uint8_t wait_count__value;
1773         pos = start + 0;
1774         if (SPICE_UNLIKELY(pos + 1 > message_end)) {
1775             goto error;
1776         }
1777         wait_count__value = read_uint8(pos);
1778         wait_list__nelements = wait_count__value;
1779 
1780         wait_list__nw_size = (10) * wait_list__nelements;
1781         wait_list__mem_size = sizeof(SpiceWaitForChannel) * wait_list__nelements;
1782     }
1783 
1784     nw_size = 1 + wait_list__nw_size;
1785     mem_size = sizeof(SpiceMsgWaitForChannels) + wait_list__mem_size;
1786 
1787     /* Check if message fits in reported side */
1788     if (nw_size > (uintptr_t) (message_end - start)) {
1789         return NULL;
1790     }
1791 
1792     /* Validated extents and calculated size */
1793     data = (uint8_t *)(mem_size > UINT32_MAX ? NULL : malloc(mem_size));
1794     if (SPICE_UNLIKELY(data == NULL)) {
1795         goto error;
1796     }
1797     end = data + sizeof(SpiceMsgWaitForChannels);
1798     in = start;
1799 
1800     out = (SpiceMsgWaitForChannels *)data;
1801 
1802     out->wait_count = consume_uint8(&in);
1803     for (i = 0; i < wait_list__nelements; i++) {
1804         SpiceWaitForChannel *out2;
1805         out2 = (SpiceWaitForChannel *)end;
1806         end += sizeof(SpiceWaitForChannel);
1807 
1808         out2->channel_type = consume_uint8(&in);
1809         out2->channel_id = consume_uint8(&in);
1810         out2->message_serial = consume_uint64(&in);
1811     }
1812 
1813     assert(in <= message_end);
1814     assert(end <= data + mem_size);
1815 
1816     *size = end - data;
1817     *free_message = (message_destructor_t) free;
1818     return data;
1819 
1820    error:
1821     free(data);
1822     return NULL;
1823 }
1824 
parse_msg_display_inval_palette(uint8_t * message_start,uint8_t * message_end,size_t * size,message_destructor_t * free_message)1825 static uint8_t * parse_msg_display_inval_palette(uint8_t *message_start, uint8_t *message_end, size_t *size, message_destructor_t *free_message)
1826 {
1827     SPICE_GNUC_UNUSED uint8_t *pos;
1828     uint8_t *start = message_start;
1829     uint8_t *data = NULL;
1830     uint64_t nw_size;
1831     uint64_t mem_size;
1832     uint8_t *in, *end;
1833     SpiceMsgDisplayInvalOne *out;
1834 
1835     nw_size = 8;
1836     mem_size = sizeof(SpiceMsgDisplayInvalOne);
1837 
1838     /* Check if message fits in reported side */
1839     if (nw_size > (uintptr_t) (message_end - start)) {
1840         return NULL;
1841     }
1842 
1843     /* Validated extents and calculated size */
1844     data = (uint8_t *)(mem_size > UINT32_MAX ? NULL : malloc(mem_size));
1845     if (SPICE_UNLIKELY(data == NULL)) {
1846         goto error;
1847     }
1848     end = data + sizeof(SpiceMsgDisplayInvalOne);
1849     in = start;
1850 
1851     out = (SpiceMsgDisplayInvalOne *)data;
1852 
1853     out->id = consume_uint64(&in);
1854 
1855     assert(in <= message_end);
1856     assert(end <= data + mem_size);
1857 
1858     *size = end - data;
1859     *free_message = (message_destructor_t) free;
1860     return data;
1861 
1862    error:
1863     free(data);
1864     return NULL;
1865 }
1866 
parse_msg_display_stream_create(uint8_t * message_start,uint8_t * message_end,size_t * size,message_destructor_t * free_message)1867 static uint8_t * parse_msg_display_stream_create(uint8_t *message_start, uint8_t *message_end, size_t *size, message_destructor_t *free_message)
1868 {
1869     SPICE_GNUC_UNUSED uint8_t *pos;
1870     uint8_t *start = message_start;
1871     uint8_t *data = NULL;
1872     uint64_t nw_size;
1873     uint64_t mem_size;
1874     uint8_t *in, *end;
1875     SPICE_GNUC_UNUSED intptr_t ptr_size;
1876     uint32_t n_ptr=0;
1877     PointerInfo ptr_info[1];
1878     uint64_t clip__nw_size, clip__extra_size;
1879     uint32_t rects__saved_size = 0;
1880     SpiceMsgDisplayStreamCreate *out;
1881     uint32_t i;
1882 
1883     { /* clip */
1884         SPICE_GNUC_UNUSED uint8_t *start2 = (start + 50);
1885         uint64_t clip_u__nw_size, clip_u__extra_size;
1886         uint8_t type__value;
1887         { /* u */
1888             uint64_t clip_u__mem_size;
1889             pos = start2 + 0;
1890             if (SPICE_UNLIKELY(pos + 1 > message_end)) {
1891                 goto error;
1892             }
1893             type__value = read_uint8(pos);
1894             if (type__value == SPICE_CLIP_TYPE_RECTS) {
1895                 SPICE_GNUC_UNUSED uint8_t *start3 = (start2 + 1);
1896                 uint64_t clip_u_rects__nw_size, clip_u_rects__mem_size;
1897                 uint64_t clip_u_rects__nelements;
1898                 { /* rects */
1899                     uint32_t num_rects__value;
1900                     pos = start3 + 0;
1901                     if (SPICE_UNLIKELY(pos + 4 > message_end)) {
1902                         goto error;
1903                     }
1904                     num_rects__value = read_uint32(pos);
1905                     clip_u_rects__nelements = num_rects__value;
1906 
1907                     clip_u_rects__nw_size = (16) * clip_u_rects__nelements;
1908                     clip_u_rects__mem_size = sizeof(SpiceRect) * clip_u_rects__nelements;
1909                 }
1910 
1911                 clip_u__nw_size = 4 + clip_u_rects__nw_size;
1912                 clip_u__mem_size = sizeof(SpiceClipRects) + clip_u_rects__mem_size;
1913                 rects__saved_size = clip_u__nw_size;
1914                 clip_u__extra_size = clip_u__mem_size;
1915             } else {
1916                 clip_u__nw_size = 0;
1917                 clip_u__extra_size = 0;
1918             }
1919 
1920         }
1921 
1922         clip__nw_size = 1 + clip_u__nw_size;
1923         clip__extra_size = clip_u__extra_size;
1924     }
1925 
1926     nw_size = 50 + clip__nw_size;
1927     mem_size = sizeof(SpiceMsgDisplayStreamCreate) + clip__extra_size;
1928 
1929     /* Check if message fits in reported side */
1930     if (nw_size > (uintptr_t) (message_end - start)) {
1931         return NULL;
1932     }
1933 
1934     /* Validated extents and calculated size */
1935     data = (uint8_t *)(mem_size > UINT32_MAX ? NULL : malloc(mem_size));
1936     if (SPICE_UNLIKELY(data == NULL)) {
1937         goto error;
1938     }
1939     end = data + sizeof(SpiceMsgDisplayStreamCreate);
1940     in = start;
1941 
1942     out = (SpiceMsgDisplayStreamCreate *)data;
1943 
1944     out->surface_id = consume_uint32(&in);
1945     out->id = consume_uint32(&in);
1946     out->flags = consume_uint8(&in);
1947     out->codec_type = consume_uint8(&in);
1948     out->stamp = consume_uint64(&in);
1949     out->stream_width = consume_uint32(&in);
1950     out->stream_height = consume_uint32(&in);
1951     out->src_width = consume_uint32(&in);
1952     out->src_height = consume_uint32(&in);
1953     /* dest */ {
1954         out->dest.top = consume_int32(&in);
1955         out->dest.left = consume_int32(&in);
1956         out->dest.bottom = consume_int32(&in);
1957         out->dest.right = consume_int32(&in);
1958     }
1959     /* clip */ {
1960         out->clip.type = consume_uint8(&in);
1961         if (out->clip.type == SPICE_CLIP_TYPE_RECTS) {
1962             ptr_info[n_ptr].offset = in - start;
1963             ptr_info[n_ptr].parse = parse_struct_SpiceClipRects;
1964             ptr_info[n_ptr].dest = (void **)&out->clip.rects;
1965             n_ptr++;
1966             in += rects__saved_size;
1967         }
1968     }
1969 
1970     assert(in <= message_end);
1971 
1972     for (i = 0; i < n_ptr; i++) {
1973         if (ptr_info[i].offset == 0) {
1974             *ptr_info[i].dest = NULL;
1975         } else {
1976             /* Align to 32 bit */
1977             end = (uint8_t *)SPICE_ALIGN((uintptr_t)end, 4);
1978             *ptr_info[i].dest = (void *)end;
1979             end = ptr_info[i].parse(message_start, message_end, end, &ptr_info[i]);
1980             if (SPICE_UNLIKELY(end == NULL)) {
1981                 goto error;
1982             }
1983         }
1984     }
1985 
1986     assert(end <= data + mem_size);
1987 
1988     *size = end - data;
1989     *free_message = (message_destructor_t) free;
1990     return data;
1991 
1992    error:
1993     free(data);
1994     return NULL;
1995 }
1996 
parse_msg_display_stream_data(uint8_t * message_start,uint8_t * message_end,size_t * size,message_destructor_t * free_message)1997 static uint8_t * parse_msg_display_stream_data(uint8_t *message_start, uint8_t *message_end, size_t *size, message_destructor_t *free_message)
1998 {
1999     SPICE_GNUC_UNUSED uint8_t *pos;
2000     uint8_t *start = message_start;
2001     uint8_t *data = NULL;
2002     uint64_t nw_size;
2003     uint64_t mem_size;
2004     uint8_t *in, *end;
2005     uint64_t data__nw_size, data__mem_size;
2006     uint64_t data__nelements;
2007     SpiceMsgDisplayStreamData *out;
2008 
2009     { /* data */
2010         uint32_t data_size__value;
2011         pos = start + 8;
2012         if (SPICE_UNLIKELY(pos + 4 > message_end)) {
2013             goto error;
2014         }
2015         data_size__value = read_uint32(pos);
2016         data__nelements = data_size__value;
2017 
2018         data__nw_size = data__nelements;
2019         data__mem_size = sizeof(uint8_t) * data__nelements;
2020     }
2021 
2022     nw_size = 12 + data__nw_size;
2023     mem_size = sizeof(SpiceMsgDisplayStreamData) + data__mem_size;
2024 
2025     /* Check if message fits in reported side */
2026     if (nw_size > (uintptr_t) (message_end - start)) {
2027         return NULL;
2028     }
2029 
2030     /* Validated extents and calculated size */
2031     data = (uint8_t *)(mem_size > UINT32_MAX ? NULL : malloc(mem_size));
2032     if (SPICE_UNLIKELY(data == NULL)) {
2033         goto error;
2034     }
2035     end = data + sizeof(SpiceMsgDisplayStreamData);
2036     in = start;
2037 
2038     out = (SpiceMsgDisplayStreamData *)data;
2039 
2040     /* base */ {
2041         out->base.id = consume_uint32(&in);
2042         out->base.multi_media_time = consume_uint32(&in);
2043     }
2044     out->data_size = consume_uint32(&in);
2045     memcpy(out->data, in, data__nelements);
2046     in += data__nelements;
2047     end += data__nelements;
2048 
2049     assert(in <= message_end);
2050     assert(end <= data + mem_size);
2051 
2052     *size = end - data;
2053     *free_message = (message_destructor_t) free;
2054     return data;
2055 
2056    error:
2057     free(data);
2058     return NULL;
2059 }
2060 
parse_msg_display_stream_clip(uint8_t * message_start,uint8_t * message_end,size_t * size,message_destructor_t * free_message)2061 static uint8_t * parse_msg_display_stream_clip(uint8_t *message_start, uint8_t *message_end, size_t *size, message_destructor_t *free_message)
2062 {
2063     SPICE_GNUC_UNUSED uint8_t *pos;
2064     uint8_t *start = message_start;
2065     uint8_t *data = NULL;
2066     uint64_t nw_size;
2067     uint64_t mem_size;
2068     uint8_t *in, *end;
2069     SPICE_GNUC_UNUSED intptr_t ptr_size;
2070     uint32_t n_ptr=0;
2071     PointerInfo ptr_info[1];
2072     uint64_t clip__nw_size, clip__extra_size;
2073     uint32_t rects__saved_size = 0;
2074     SpiceMsgDisplayStreamClip *out;
2075     uint32_t i;
2076 
2077     { /* clip */
2078         SPICE_GNUC_UNUSED uint8_t *start2 = (start + 4);
2079         uint64_t clip_u__nw_size, clip_u__extra_size;
2080         uint8_t type__value;
2081         { /* u */
2082             uint64_t clip_u__mem_size;
2083             pos = start2 + 0;
2084             if (SPICE_UNLIKELY(pos + 1 > message_end)) {
2085                 goto error;
2086             }
2087             type__value = read_uint8(pos);
2088             if (type__value == SPICE_CLIP_TYPE_RECTS) {
2089                 SPICE_GNUC_UNUSED uint8_t *start3 = (start2 + 1);
2090                 uint64_t clip_u_rects__nw_size, clip_u_rects__mem_size;
2091                 uint64_t clip_u_rects__nelements;
2092                 { /* rects */
2093                     uint32_t num_rects__value;
2094                     pos = start3 + 0;
2095                     if (SPICE_UNLIKELY(pos + 4 > message_end)) {
2096                         goto error;
2097                     }
2098                     num_rects__value = read_uint32(pos);
2099                     clip_u_rects__nelements = num_rects__value;
2100 
2101                     clip_u_rects__nw_size = (16) * clip_u_rects__nelements;
2102                     clip_u_rects__mem_size = sizeof(SpiceRect) * clip_u_rects__nelements;
2103                 }
2104 
2105                 clip_u__nw_size = 4 + clip_u_rects__nw_size;
2106                 clip_u__mem_size = sizeof(SpiceClipRects) + clip_u_rects__mem_size;
2107                 rects__saved_size = clip_u__nw_size;
2108                 clip_u__extra_size = clip_u__mem_size;
2109             } else {
2110                 clip_u__nw_size = 0;
2111                 clip_u__extra_size = 0;
2112             }
2113 
2114         }
2115 
2116         clip__nw_size = 1 + clip_u__nw_size;
2117         clip__extra_size = clip_u__extra_size;
2118     }
2119 
2120     nw_size = 4 + clip__nw_size;
2121     mem_size = sizeof(SpiceMsgDisplayStreamClip) + clip__extra_size;
2122 
2123     /* Check if message fits in reported side */
2124     if (nw_size > (uintptr_t) (message_end - start)) {
2125         return NULL;
2126     }
2127 
2128     /* Validated extents and calculated size */
2129     data = (uint8_t *)(mem_size > UINT32_MAX ? NULL : malloc(mem_size));
2130     if (SPICE_UNLIKELY(data == NULL)) {
2131         goto error;
2132     }
2133     end = data + sizeof(SpiceMsgDisplayStreamClip);
2134     in = start;
2135 
2136     out = (SpiceMsgDisplayStreamClip *)data;
2137 
2138     out->id = consume_uint32(&in);
2139     /* clip */ {
2140         out->clip.type = consume_uint8(&in);
2141         if (out->clip.type == SPICE_CLIP_TYPE_RECTS) {
2142             ptr_info[n_ptr].offset = in - start;
2143             ptr_info[n_ptr].parse = parse_struct_SpiceClipRects;
2144             ptr_info[n_ptr].dest = (void **)&out->clip.rects;
2145             n_ptr++;
2146             in += rects__saved_size;
2147         }
2148     }
2149 
2150     assert(in <= message_end);
2151 
2152     for (i = 0; i < n_ptr; i++) {
2153         if (ptr_info[i].offset == 0) {
2154             *ptr_info[i].dest = NULL;
2155         } else {
2156             /* Align to 32 bit */
2157             end = (uint8_t *)SPICE_ALIGN((uintptr_t)end, 4);
2158             *ptr_info[i].dest = (void *)end;
2159             end = ptr_info[i].parse(message_start, message_end, end, &ptr_info[i]);
2160             if (SPICE_UNLIKELY(end == NULL)) {
2161                 goto error;
2162             }
2163         }
2164     }
2165 
2166     assert(end <= data + mem_size);
2167 
2168     *size = end - data;
2169     *free_message = (message_destructor_t) free;
2170     return data;
2171 
2172    error:
2173     free(data);
2174     return NULL;
2175 }
2176 
parse_msg_display_stream_destroy(uint8_t * message_start,uint8_t * message_end,size_t * size,message_destructor_t * free_message)2177 static uint8_t * parse_msg_display_stream_destroy(uint8_t *message_start, uint8_t *message_end, size_t *size, message_destructor_t *free_message)
2178 {
2179     SPICE_GNUC_UNUSED uint8_t *pos;
2180     uint8_t *start = message_start;
2181     uint8_t *data = NULL;
2182     uint64_t nw_size;
2183     uint64_t mem_size;
2184     uint8_t *in, *end;
2185     SpiceMsgDisplayStreamDestroy *out;
2186 
2187     nw_size = 4;
2188     mem_size = sizeof(SpiceMsgDisplayStreamDestroy);
2189 
2190     /* Check if message fits in reported side */
2191     if (nw_size > (uintptr_t) (message_end - start)) {
2192         return NULL;
2193     }
2194 
2195     /* Validated extents and calculated size */
2196     data = (uint8_t *)(mem_size > UINT32_MAX ? NULL : malloc(mem_size));
2197     if (SPICE_UNLIKELY(data == NULL)) {
2198         goto error;
2199     }
2200     end = data + sizeof(SpiceMsgDisplayStreamDestroy);
2201     in = start;
2202 
2203     out = (SpiceMsgDisplayStreamDestroy *)data;
2204 
2205     out->id = consume_uint32(&in);
2206 
2207     assert(in <= message_end);
2208     assert(end <= data + mem_size);
2209 
2210     *size = end - data;
2211     *free_message = (message_destructor_t) free;
2212     return data;
2213 
2214    error:
2215     free(data);
2216     return NULL;
2217 }
2218 
validate_SpicePalette(uint8_t * message_start,uint8_t * message_end,uint64_t offset)2219 static intptr_t validate_SpicePalette(uint8_t *message_start, uint8_t *message_end, uint64_t offset)
2220 {
2221     uint8_t *start = message_start + offset;
2222     SPICE_GNUC_UNUSED uint8_t *pos;
2223     uint64_t mem_size, nw_size;
2224     uint64_t ents__nw_size, ents__mem_size;
2225     uint64_t ents__nelements;
2226 
2227     if (offset == 0) {
2228         return 0;
2229     }
2230 
2231     if (SPICE_UNLIKELY(start >= message_end)) {
2232         goto error;
2233     }
2234 
2235     { /* ents */
2236         uint16_t num_ents__value;
2237         pos = start + 8;
2238         if (SPICE_UNLIKELY(pos + 2 > message_end)) {
2239             goto error;
2240         }
2241         num_ents__value = read_uint16(pos);
2242         ents__nelements = num_ents__value;
2243 
2244         ents__nw_size = (4) * ents__nelements;
2245         ents__mem_size = sizeof(uint32_t) * ents__nelements;
2246     }
2247 
2248     nw_size = 10 + ents__nw_size;
2249     mem_size = sizeof(SpicePalette) + ents__mem_size;
2250 
2251     /* Check if struct fits in reported side */
2252     if (SPICE_UNLIKELY(nw_size > (uintptr_t) (message_end - start))) {
2253         goto error;
2254     }
2255     return mem_size;
2256 
2257    error:
2258     return -1;
2259 }
2260 
validate_SpiceImage(uint8_t * message_start,uint8_t * message_end,uint64_t offset)2261 static intptr_t validate_SpiceImage(uint8_t *message_start, uint8_t *message_end, uint64_t offset)
2262 {
2263     uint8_t *start = message_start + offset;
2264     SPICE_GNUC_UNUSED uint8_t *pos;
2265     uint64_t mem_size, nw_size;
2266     SPICE_GNUC_UNUSED intptr_t ptr_size;
2267     uint64_t u__nw_size, u__extra_size;
2268     uint8_t descriptor_type__value;
2269 
2270     if (offset == 0) {
2271         return 0;
2272     }
2273 
2274     if (SPICE_UNLIKELY(start >= message_end)) {
2275         goto error;
2276     }
2277 
2278     { /* u */
2279         pos = start + 8;
2280         if (SPICE_UNLIKELY(pos + 1 > message_end)) {
2281             goto error;
2282         }
2283         descriptor_type__value = read_uint8(pos);
2284         if (descriptor_type__value == SPICE_IMAGE_TYPE_BITMAP) {
2285             SPICE_GNUC_UNUSED uint8_t *start2 = (start + 18);
2286             uint64_t u_pal__nw_size, u_pal__extra_size;
2287             uint8_t flags__value;
2288             uint64_t u_data__nw_size, u_data__extra_size;
2289             uint64_t u_data__nelements;
2290             { /* pal */
2291                 pos = start2 + 1;
2292                 if (SPICE_UNLIKELY(pos + 1 > message_end)) {
2293                     goto error;
2294                 }
2295                 flags__value = read_uint8(pos);
2296                 if ((flags__value & SPICE_BITMAP_FLAGS_PAL_FROM_CACHE)) {
2297                     u_pal__nw_size = 8;
2298                     u_pal__extra_size = 0;
2299                 } else if (1) {
2300                     uint32_t u_pal_palette__value;
2301                     u_pal__nw_size = 4;
2302                     pos = (start2 + 14);
2303                     if (SPICE_UNLIKELY(pos + 4 > message_end)) {
2304                         goto error;
2305                     }
2306                     u_pal_palette__value = read_uint32(pos);
2307                     ptr_size = validate_SpicePalette(message_start, message_end, u_pal_palette__value);
2308                     if (SPICE_UNLIKELY(ptr_size < 0)) {
2309                         goto error;
2310                     }
2311                     u_pal__extra_size = ptr_size + /* for alignment */ 3;
2312                 } else {
2313                     u_pal__nw_size = 0;
2314                     u_pal__extra_size = 0;
2315                 }
2316 
2317             }
2318 
2319             { /* data */
2320                 uint32_t stride__value;
2321                 uint32_t y__value;
2322                 pos = start2 + 10;
2323                 if (SPICE_UNLIKELY(pos + 4 > message_end)) {
2324                     goto error;
2325                 }
2326                 stride__value = read_uint32(pos);
2327                 pos = start2 + 6;
2328                 if (SPICE_UNLIKELY(pos + 4 > message_end)) {
2329                     goto error;
2330                 }
2331                 y__value = read_uint32(pos);
2332                 u_data__nelements = (uint64_t) stride__value * y__value;
2333 
2334                 u_data__nw_size = u_data__nelements;
2335                 u_data__extra_size = sizeof(SpiceChunks) + sizeof(SpiceChunk);
2336             }
2337 
2338             u__nw_size = 14 + u_pal__nw_size + u_data__nw_size;
2339             u__extra_size = u_pal__extra_size + u_data__extra_size;
2340         } else if (descriptor_type__value == SPICE_IMAGE_TYPE_QUIC) {
2341             SPICE_GNUC_UNUSED uint8_t *start2 = (start + 18);
2342             uint64_t u_data__nw_size, u_data__extra_size;
2343             uint64_t u_data__nelements;
2344             { /* data */
2345                 uint32_t data_size__value;
2346                 pos = start2 + 0;
2347                 if (SPICE_UNLIKELY(pos + 4 > message_end)) {
2348                     goto error;
2349                 }
2350                 data_size__value = read_uint32(pos);
2351                 u_data__nelements = data_size__value;
2352 
2353                 u_data__nw_size = u_data__nelements;
2354                 u_data__extra_size = sizeof(SpiceChunks) + sizeof(SpiceChunk);
2355             }
2356 
2357             u__nw_size = 4 + u_data__nw_size;
2358             u__extra_size = u_data__extra_size;
2359         } else if (descriptor_type__value == SPICE_IMAGE_TYPE_LZ_RGB || descriptor_type__value == SPICE_IMAGE_TYPE_GLZ_RGB) {
2360             SPICE_GNUC_UNUSED uint8_t *start2 = (start + 18);
2361             uint64_t u_data__nw_size, u_data__extra_size;
2362             uint64_t u_data__nelements;
2363             { /* data */
2364                 uint32_t data_size__value;
2365                 pos = start2 + 0;
2366                 if (SPICE_UNLIKELY(pos + 4 > message_end)) {
2367                     goto error;
2368                 }
2369                 data_size__value = read_uint32(pos);
2370                 u_data__nelements = data_size__value;
2371 
2372                 u_data__nw_size = u_data__nelements;
2373                 u_data__extra_size = sizeof(SpiceChunks) + sizeof(SpiceChunk);
2374             }
2375 
2376             u__nw_size = 4 + u_data__nw_size;
2377             u__extra_size = u_data__extra_size;
2378         } else if (descriptor_type__value == SPICE_IMAGE_TYPE_JPEG) {
2379             SPICE_GNUC_UNUSED uint8_t *start2 = (start + 18);
2380             uint64_t u_data__nw_size, u_data__extra_size;
2381             uint64_t u_data__nelements;
2382             { /* data */
2383                 uint32_t data_size__value;
2384                 pos = start2 + 0;
2385                 if (SPICE_UNLIKELY(pos + 4 > message_end)) {
2386                     goto error;
2387                 }
2388                 data_size__value = read_uint32(pos);
2389                 u_data__nelements = data_size__value;
2390 
2391                 u_data__nw_size = u_data__nelements;
2392                 u_data__extra_size = sizeof(SpiceChunks) + sizeof(SpiceChunk);
2393             }
2394 
2395             u__nw_size = 4 + u_data__nw_size;
2396             u__extra_size = u_data__extra_size;
2397         } else if (descriptor_type__value == SPICE_IMAGE_TYPE_LZ4) {
2398             SPICE_GNUC_UNUSED uint8_t *start2 = (start + 18);
2399             uint64_t u_data__nw_size, u_data__extra_size;
2400             uint64_t u_data__nelements;
2401             { /* data */
2402                 uint32_t data_size__value;
2403                 pos = start2 + 0;
2404                 if (SPICE_UNLIKELY(pos + 4 > message_end)) {
2405                     goto error;
2406                 }
2407                 data_size__value = read_uint32(pos);
2408                 u_data__nelements = data_size__value;
2409 
2410                 u_data__nw_size = u_data__nelements;
2411                 u_data__extra_size = sizeof(SpiceChunks) + sizeof(SpiceChunk);
2412             }
2413 
2414             u__nw_size = 4 + u_data__nw_size;
2415             u__extra_size = u_data__extra_size;
2416         } else if (descriptor_type__value == SPICE_IMAGE_TYPE_LZ_PLT) {
2417             SPICE_GNUC_UNUSED uint8_t *start2 = (start + 18);
2418             uint64_t u_pal__nw_size, u_pal__extra_size;
2419             uint8_t flags__value;
2420             uint64_t u_data__nw_size, u_data__extra_size;
2421             uint64_t u_data__nelements;
2422             { /* pal */
2423                 pos = start2 + 0;
2424                 if (SPICE_UNLIKELY(pos + 1 > message_end)) {
2425                     goto error;
2426                 }
2427                 flags__value = read_uint8(pos);
2428                 if ((flags__value & SPICE_BITMAP_FLAGS_PAL_FROM_CACHE)) {
2429                     u_pal__nw_size = 8;
2430                     u_pal__extra_size = 0;
2431                 } else if (1) {
2432                     uint32_t u_pal_palette__value;
2433                     u_pal__nw_size = 4;
2434                     pos = (start2 + 5);
2435                     if (SPICE_UNLIKELY(pos + 4 > message_end)) {
2436                         goto error;
2437                     }
2438                     u_pal_palette__value = read_uint32(pos);
2439                     if (SPICE_UNLIKELY(u_pal_palette__value == 0)) {
2440                         goto error;
2441                     }
2442                     ptr_size = validate_SpicePalette(message_start, message_end, u_pal_palette__value);
2443                     if (SPICE_UNLIKELY(ptr_size < 0)) {
2444                         goto error;
2445                     }
2446                     u_pal__extra_size = ptr_size + /* for alignment */ 3;
2447                 } else {
2448                     u_pal__nw_size = 0;
2449                     u_pal__extra_size = 0;
2450                 }
2451 
2452             }
2453 
2454             { /* data */
2455                 uint32_t data_size__value;
2456                 pos = start2 + 1;
2457                 if (SPICE_UNLIKELY(pos + 4 > message_end)) {
2458                     goto error;
2459                 }
2460                 data_size__value = read_uint32(pos);
2461                 u_data__nelements = data_size__value;
2462 
2463                 u_data__nw_size = u_data__nelements;
2464                 u_data__extra_size = sizeof(SpiceChunks) + sizeof(SpiceChunk);
2465             }
2466 
2467             u__nw_size = 5 + u_pal__nw_size + u_data__nw_size;
2468             u__extra_size = u_pal__extra_size + u_data__extra_size;
2469         } else if (descriptor_type__value == SPICE_IMAGE_TYPE_ZLIB_GLZ_RGB) {
2470             SPICE_GNUC_UNUSED uint8_t *start2 = (start + 18);
2471             uint64_t u_data__nw_size, u_data__extra_size;
2472             uint64_t u_data__nelements;
2473             { /* data */
2474                 uint32_t data_size__value;
2475                 pos = start2 + 4;
2476                 if (SPICE_UNLIKELY(pos + 4 > message_end)) {
2477                     goto error;
2478                 }
2479                 data_size__value = read_uint32(pos);
2480                 u_data__nelements = data_size__value;
2481 
2482                 u_data__nw_size = u_data__nelements;
2483                 u_data__extra_size = sizeof(SpiceChunks) + sizeof(SpiceChunk);
2484             }
2485 
2486             u__nw_size = 8 + u_data__nw_size;
2487             u__extra_size = u_data__extra_size;
2488         } else if (descriptor_type__value == SPICE_IMAGE_TYPE_JPEG_ALPHA) {
2489             SPICE_GNUC_UNUSED uint8_t *start2 = (start + 18);
2490             uint64_t u_data__nw_size, u_data__extra_size;
2491             uint64_t u_data__nelements;
2492             { /* data */
2493                 uint32_t data_size__value;
2494                 pos = start2 + 5;
2495                 if (SPICE_UNLIKELY(pos + 4 > message_end)) {
2496                     goto error;
2497                 }
2498                 data_size__value = read_uint32(pos);
2499                 u_data__nelements = data_size__value;
2500 
2501                 u_data__nw_size = u_data__nelements;
2502                 u_data__extra_size = sizeof(SpiceChunks) + sizeof(SpiceChunk);
2503             }
2504 
2505             u__nw_size = 9 + u_data__nw_size;
2506             u__extra_size = u_data__extra_size;
2507         } else if (descriptor_type__value == SPICE_IMAGE_TYPE_SURFACE) {
2508             SPICE_GNUC_UNUSED uint8_t *start2 = (start + 18);
2509             u__nw_size = 4;
2510             u__extra_size = 0;
2511         } else {
2512             u__nw_size = 0;
2513             u__extra_size = 0;
2514         }
2515 
2516     }
2517 
2518     nw_size = 18 + u__nw_size;
2519     mem_size = sizeof(SpiceImage) + u__extra_size;
2520 
2521     /* Check if struct fits in reported side */
2522     if (SPICE_UNLIKELY(nw_size > (uintptr_t) (message_end - start))) {
2523         goto error;
2524     }
2525     return mem_size;
2526 
2527    error:
2528     return -1;
2529 }
2530 
parse_struct_SpicePalette(uint8_t * message_start,SPICE_GNUC_UNUSED uint8_t * message_end,uint8_t * struct_data,PointerInfo * this_ptr_info)2531 static uint8_t * parse_struct_SpicePalette(uint8_t *message_start, SPICE_GNUC_UNUSED uint8_t *message_end, uint8_t *struct_data, PointerInfo *this_ptr_info)
2532 {
2533     uint8_t *in = message_start + this_ptr_info->offset;
2534     uint8_t *end;
2535     SpicePalette *out;
2536     uint64_t ents__nelements;
2537     uint32_t i;
2538 
2539     end = struct_data + sizeof(SpicePalette);
2540     out = (SpicePalette *)struct_data;
2541 
2542     out->unique = consume_uint64(&in);
2543     out->num_ents = consume_uint16(&in);
2544     ents__nelements = out->num_ents;
2545     for (i = 0; i < ents__nelements; i++) {
2546         out->ents[i] = consume_uint32(&in);
2547         end += sizeof(uint32_t);
2548     }
2549     return end;
2550 }
2551 
parse_struct_SpiceImage(uint8_t * message_start,SPICE_GNUC_UNUSED uint8_t * message_end,uint8_t * struct_data,PointerInfo * this_ptr_info)2552 static uint8_t * parse_struct_SpiceImage(uint8_t *message_start, SPICE_GNUC_UNUSED uint8_t *message_end, uint8_t *struct_data, PointerInfo *this_ptr_info)
2553 {
2554     uint8_t *in = message_start + this_ptr_info->offset;
2555     uint8_t *end;
2556     SPICE_GNUC_UNUSED intptr_t ptr_size;
2557     uint32_t n_ptr=0;
2558     PointerInfo ptr_info[1];
2559     SpiceImage *out;
2560     uint32_t i;
2561 
2562     end = struct_data + sizeof(SpiceImage);
2563     out = (SpiceImage *)struct_data;
2564 
2565     /* descriptor */ {
2566         out->descriptor.id = consume_uint64(&in);
2567         out->descriptor.type = consume_uint8(&in);
2568         out->descriptor.flags = consume_uint8(&in);
2569         out->descriptor.width = consume_uint32(&in);
2570         out->descriptor.height = consume_uint32(&in);
2571     }
2572     if (out->descriptor.type == SPICE_IMAGE_TYPE_BITMAP) {
2573         uint64_t data__nelements;
2574         SpiceChunks *chunks;
2575         out->u.bitmap.format = consume_uint8(&in);
2576         out->u.bitmap.flags = consume_uint8(&in);
2577         out->u.bitmap.x = consume_uint32(&in);
2578         out->u.bitmap.y = consume_uint32(&in);
2579         out->u.bitmap.stride = consume_uint32(&in);
2580         if ((out->u.bitmap.flags & SPICE_BITMAP_FLAGS_PAL_FROM_CACHE)) {
2581             out->u.bitmap.palette_id = consume_uint64(&in);
2582         } else if (1) {
2583             ptr_info[n_ptr].offset = consume_uint32(&in);
2584             ptr_info[n_ptr].parse = parse_struct_SpicePalette;
2585             ptr_info[n_ptr].dest = (void **)&out->u.bitmap.palette;
2586             n_ptr++;
2587         }
2588         data__nelements = ((uint64_t) out->u.bitmap.stride * out->u.bitmap.y);
2589         /* use array as chunk */
2590         chunks = (SpiceChunks *)end;
2591         end += sizeof(SpiceChunks) + sizeof(SpiceChunk);
2592         out->u.bitmap.data = chunks;
2593         chunks->data_size = data__nelements;
2594         chunks->flags = 0;
2595         chunks->num_chunks = 1;
2596         chunks->chunk[0].len = data__nelements;
2597         chunks->chunk[0].data = in;
2598         in += data__nelements;
2599     } else if (out->descriptor.type == SPICE_IMAGE_TYPE_QUIC) {
2600         uint64_t data__nelements;
2601         SpiceChunks *chunks;
2602         out->u.quic.data_size = consume_uint32(&in);
2603         data__nelements = out->u.quic.data_size;
2604         /* use array as chunk */
2605         chunks = (SpiceChunks *)end;
2606         end += sizeof(SpiceChunks) + sizeof(SpiceChunk);
2607         out->u.quic.data = chunks;
2608         chunks->data_size = data__nelements;
2609         chunks->flags = 0;
2610         chunks->num_chunks = 1;
2611         chunks->chunk[0].len = data__nelements;
2612         chunks->chunk[0].data = in;
2613         in += data__nelements;
2614     } else if (out->descriptor.type == SPICE_IMAGE_TYPE_LZ_RGB || out->descriptor.type == SPICE_IMAGE_TYPE_GLZ_RGB) {
2615         uint64_t data__nelements;
2616         SpiceChunks *chunks;
2617         out->u.lz_rgb.data_size = consume_uint32(&in);
2618         data__nelements = out->u.lz_rgb.data_size;
2619         /* use array as chunk */
2620         chunks = (SpiceChunks *)end;
2621         end += sizeof(SpiceChunks) + sizeof(SpiceChunk);
2622         out->u.lz_rgb.data = chunks;
2623         chunks->data_size = data__nelements;
2624         chunks->flags = 0;
2625         chunks->num_chunks = 1;
2626         chunks->chunk[0].len = data__nelements;
2627         chunks->chunk[0].data = in;
2628         in += data__nelements;
2629     } else if (out->descriptor.type == SPICE_IMAGE_TYPE_JPEG) {
2630         uint64_t data__nelements;
2631         SpiceChunks *chunks;
2632         out->u.jpeg.data_size = consume_uint32(&in);
2633         data__nelements = out->u.jpeg.data_size;
2634         /* use array as chunk */
2635         chunks = (SpiceChunks *)end;
2636         end += sizeof(SpiceChunks) + sizeof(SpiceChunk);
2637         out->u.jpeg.data = chunks;
2638         chunks->data_size = data__nelements;
2639         chunks->flags = 0;
2640         chunks->num_chunks = 1;
2641         chunks->chunk[0].len = data__nelements;
2642         chunks->chunk[0].data = in;
2643         in += data__nelements;
2644     } else if (out->descriptor.type == SPICE_IMAGE_TYPE_LZ4) {
2645         uint64_t data__nelements;
2646         SpiceChunks *chunks;
2647         out->u.lz4.data_size = consume_uint32(&in);
2648         data__nelements = out->u.lz4.data_size;
2649         /* use array as chunk */
2650         chunks = (SpiceChunks *)end;
2651         end += sizeof(SpiceChunks) + sizeof(SpiceChunk);
2652         out->u.lz4.data = chunks;
2653         chunks->data_size = data__nelements;
2654         chunks->flags = 0;
2655         chunks->num_chunks = 1;
2656         chunks->chunk[0].len = data__nelements;
2657         chunks->chunk[0].data = in;
2658         in += data__nelements;
2659     } else if (out->descriptor.type == SPICE_IMAGE_TYPE_LZ_PLT) {
2660         uint64_t data__nelements;
2661         SpiceChunks *chunks;
2662         out->u.lz_plt.flags = consume_uint8(&in);
2663         out->u.lz_plt.data_size = consume_uint32(&in);
2664         if ((out->u.lz_plt.flags & SPICE_BITMAP_FLAGS_PAL_FROM_CACHE)) {
2665             out->u.lz_plt.palette_id = consume_uint64(&in);
2666         } else if (1) {
2667             ptr_info[n_ptr].offset = consume_uint32(&in);
2668             ptr_info[n_ptr].parse = parse_struct_SpicePalette;
2669             ptr_info[n_ptr].dest = (void **)&out->u.lz_plt.palette;
2670             n_ptr++;
2671         }
2672         data__nelements = out->u.lz_plt.data_size;
2673         /* use array as chunk */
2674         chunks = (SpiceChunks *)end;
2675         end += sizeof(SpiceChunks) + sizeof(SpiceChunk);
2676         out->u.lz_plt.data = chunks;
2677         chunks->data_size = data__nelements;
2678         chunks->flags = 0;
2679         chunks->num_chunks = 1;
2680         chunks->chunk[0].len = data__nelements;
2681         chunks->chunk[0].data = in;
2682         in += data__nelements;
2683     } else if (out->descriptor.type == SPICE_IMAGE_TYPE_ZLIB_GLZ_RGB) {
2684         uint64_t data__nelements;
2685         SpiceChunks *chunks;
2686         out->u.zlib_glz.glz_data_size = consume_uint32(&in);
2687         out->u.zlib_glz.data_size = consume_uint32(&in);
2688         data__nelements = out->u.zlib_glz.data_size;
2689         /* use array as chunk */
2690         chunks = (SpiceChunks *)end;
2691         end += sizeof(SpiceChunks) + sizeof(SpiceChunk);
2692         out->u.zlib_glz.data = chunks;
2693         chunks->data_size = data__nelements;
2694         chunks->flags = 0;
2695         chunks->num_chunks = 1;
2696         chunks->chunk[0].len = data__nelements;
2697         chunks->chunk[0].data = in;
2698         in += data__nelements;
2699     } else if (out->descriptor.type == SPICE_IMAGE_TYPE_JPEG_ALPHA) {
2700         uint64_t data__nelements;
2701         SpiceChunks *chunks;
2702         out->u.jpeg_alpha.flags = consume_uint8(&in);
2703         out->u.jpeg_alpha.jpeg_size = consume_uint32(&in);
2704         out->u.jpeg_alpha.data_size = consume_uint32(&in);
2705         data__nelements = out->u.jpeg_alpha.data_size;
2706         /* use array as chunk */
2707         chunks = (SpiceChunks *)end;
2708         end += sizeof(SpiceChunks) + sizeof(SpiceChunk);
2709         out->u.jpeg_alpha.data = chunks;
2710         chunks->data_size = data__nelements;
2711         chunks->flags = 0;
2712         chunks->num_chunks = 1;
2713         chunks->chunk[0].len = data__nelements;
2714         chunks->chunk[0].data = in;
2715         in += data__nelements;
2716     } else if (out->descriptor.type == SPICE_IMAGE_TYPE_SURFACE) {
2717         out->u.surface.surface_id = consume_uint32(&in);
2718     }
2719 
2720     for (i = 0; i < n_ptr; i++) {
2721         if (ptr_info[i].offset == 0) {
2722             *ptr_info[i].dest = NULL;
2723         } else {
2724             /* Align to 32 bit */
2725             end = (uint8_t *)SPICE_ALIGN((uintptr_t)end, 4);
2726             *ptr_info[i].dest = (void *)end;
2727             end = ptr_info[i].parse(message_start, message_end, end, &ptr_info[i]);
2728             if (SPICE_UNLIKELY(end == NULL)) {
2729                 goto error;
2730             }
2731         }
2732     }
2733 
2734     return end;
2735 
2736    error:
2737     return NULL;
2738 }
2739 
parse_msg_display_draw_fill(uint8_t * message_start,uint8_t * message_end,size_t * size,message_destructor_t * free_message)2740 static uint8_t * parse_msg_display_draw_fill(uint8_t *message_start, uint8_t *message_end, size_t *size, message_destructor_t *free_message)
2741 {
2742     SPICE_GNUC_UNUSED uint8_t *pos;
2743     uint8_t *start = message_start;
2744     uint8_t *data = NULL;
2745     uint64_t nw_size;
2746     uint64_t mem_size;
2747     uint8_t *in, *end;
2748     SPICE_GNUC_UNUSED intptr_t ptr_size;
2749     uint32_t n_ptr=0;
2750     PointerInfo ptr_info[3];
2751     uint64_t base__nw_size, base__extra_size;
2752     uint32_t rects__saved_size = 0;
2753     uint64_t data__nw_size, data__extra_size;
2754     SpiceMsgDisplayDrawFill *out;
2755     uint32_t i;
2756 
2757     { /* base */
2758         SPICE_GNUC_UNUSED uint8_t *start2 = (start + 0);
2759         uint64_t base_clip__nw_size, base_clip__extra_size;
2760         { /* clip */
2761             SPICE_GNUC_UNUSED uint8_t *start3 = (start2 + 20);
2762             uint64_t base_clip_u__nw_size, base_clip_u__extra_size;
2763             uint8_t type__value;
2764             { /* u */
2765                 uint64_t base_clip_u__mem_size;
2766                 pos = start3 + 0;
2767                 if (SPICE_UNLIKELY(pos + 1 > message_end)) {
2768                     goto error;
2769                 }
2770                 type__value = read_uint8(pos);
2771                 if (type__value == SPICE_CLIP_TYPE_RECTS) {
2772                     SPICE_GNUC_UNUSED uint8_t *start4 = (start3 + 1);
2773                     uint64_t base_clip_u_rects__nw_size, base_clip_u_rects__mem_size;
2774                     uint64_t base_clip_u_rects__nelements;
2775                     { /* rects */
2776                         uint32_t num_rects__value;
2777                         pos = start4 + 0;
2778                         if (SPICE_UNLIKELY(pos + 4 > message_end)) {
2779                             goto error;
2780                         }
2781                         num_rects__value = read_uint32(pos);
2782                         base_clip_u_rects__nelements = num_rects__value;
2783 
2784                         base_clip_u_rects__nw_size = (16) * base_clip_u_rects__nelements;
2785                         base_clip_u_rects__mem_size = sizeof(SpiceRect) * base_clip_u_rects__nelements;
2786                     }
2787 
2788                     base_clip_u__nw_size = 4 + base_clip_u_rects__nw_size;
2789                     base_clip_u__mem_size = sizeof(SpiceClipRects) + base_clip_u_rects__mem_size;
2790                     rects__saved_size = base_clip_u__nw_size;
2791                     base_clip_u__extra_size = base_clip_u__mem_size;
2792                 } else {
2793                     base_clip_u__nw_size = 0;
2794                     base_clip_u__extra_size = 0;
2795                 }
2796 
2797             }
2798 
2799             base_clip__nw_size = 1 + base_clip_u__nw_size;
2800             base_clip__extra_size = base_clip_u__extra_size;
2801         }
2802 
2803         base__nw_size = 20 + base_clip__nw_size;
2804         base__extra_size = base_clip__extra_size;
2805     }
2806 
2807     { /* data */
2808         SPICE_GNUC_UNUSED uint8_t *start2 = (start + 0 + base__nw_size);
2809         uint64_t data_brush__nw_size, data_brush__extra_size;
2810         uint64_t data_mask__extra_size;
2811         { /* brush */
2812             SPICE_GNUC_UNUSED uint8_t *start3 = (start2 + 0);
2813             uint64_t data_brush_u__nw_size, data_brush_u__extra_size;
2814             uint8_t type__value;
2815             { /* u */
2816                 pos = start3 + 0;
2817                 if (SPICE_UNLIKELY(pos + 1 > message_end)) {
2818                     goto error;
2819                 }
2820                 type__value = read_uint8(pos);
2821                 if (type__value == SPICE_BRUSH_TYPE_SOLID) {
2822                     data_brush_u__nw_size = 4;
2823                     data_brush_u__extra_size = 0;
2824                 } else if (type__value == SPICE_BRUSH_TYPE_PATTERN) {
2825                     SPICE_GNUC_UNUSED uint8_t *start4 = (start3 + 1);
2826                     uint64_t data_brush_u_pat__extra_size;
2827                     { /* pat */
2828                         uint32_t pat__value;
2829                         pos = (start4 + 0);
2830                         if (SPICE_UNLIKELY(pos + 4 > message_end)) {
2831                             goto error;
2832                         }
2833                         pat__value = read_uint32(pos);
2834                         if (SPICE_UNLIKELY(pat__value == 0)) {
2835                             goto error;
2836                         }
2837                         ptr_size = validate_SpiceImage(message_start, message_end, pat__value);
2838                         if (SPICE_UNLIKELY(ptr_size < 0)) {
2839                             goto error;
2840                         }
2841                         data_brush_u_pat__extra_size = ptr_size + /* for alignment */ 3;
2842                     }
2843 
2844                     data_brush_u__nw_size = 12;
2845                     data_brush_u__extra_size = data_brush_u_pat__extra_size;
2846                 } else {
2847                     data_brush_u__nw_size = 0;
2848                     data_brush_u__extra_size = 0;
2849                 }
2850 
2851             }
2852 
2853             data_brush__nw_size = 1 + data_brush_u__nw_size;
2854             data_brush__extra_size = data_brush_u__extra_size;
2855         }
2856 
2857         { /* mask */
2858             SPICE_GNUC_UNUSED uint8_t *start3 = (start2 + 2 + data_brush__nw_size);
2859             uint64_t data_mask_bitmap__extra_size;
2860             { /* bitmap */
2861                 uint32_t bitmap__value;
2862                 pos = (start3 + 9);
2863                 if (SPICE_UNLIKELY(pos + 4 > message_end)) {
2864                     goto error;
2865                 }
2866                 bitmap__value = read_uint32(pos);
2867                 ptr_size = validate_SpiceImage(message_start, message_end, bitmap__value);
2868                 if (SPICE_UNLIKELY(ptr_size < 0)) {
2869                     goto error;
2870                 }
2871                 data_mask_bitmap__extra_size = ptr_size + /* for alignment */ 3;
2872             }
2873 
2874             data_mask__extra_size = data_mask_bitmap__extra_size;
2875         }
2876 
2877         data__nw_size = 15 + data_brush__nw_size;
2878         data__extra_size = data_brush__extra_size + data_mask__extra_size;
2879     }
2880 
2881     nw_size = 0 + base__nw_size + data__nw_size;
2882     mem_size = sizeof(SpiceMsgDisplayDrawFill) + base__extra_size + data__extra_size;
2883 
2884     /* Check if message fits in reported side */
2885     if (nw_size > (uintptr_t) (message_end - start)) {
2886         return NULL;
2887     }
2888 
2889     /* Validated extents and calculated size */
2890     data = (uint8_t *)(mem_size > UINT32_MAX ? NULL : malloc(mem_size));
2891     if (SPICE_UNLIKELY(data == NULL)) {
2892         goto error;
2893     }
2894     end = data + sizeof(SpiceMsgDisplayDrawFill);
2895     in = start;
2896 
2897     out = (SpiceMsgDisplayDrawFill *)data;
2898 
2899     /* base */ {
2900         out->base.surface_id = consume_uint32(&in);
2901         /* box */ {
2902             out->base.box.top = consume_int32(&in);
2903             out->base.box.left = consume_int32(&in);
2904             out->base.box.bottom = consume_int32(&in);
2905             out->base.box.right = consume_int32(&in);
2906         }
2907         /* clip */ {
2908             out->base.clip.type = consume_uint8(&in);
2909             if (out->base.clip.type == SPICE_CLIP_TYPE_RECTS) {
2910                 ptr_info[n_ptr].offset = in - start;
2911                 ptr_info[n_ptr].parse = parse_struct_SpiceClipRects;
2912                 ptr_info[n_ptr].dest = (void **)&out->base.clip.rects;
2913                 n_ptr++;
2914                 in += rects__saved_size;
2915             }
2916         }
2917     }
2918     /* data */ {
2919         /* brush */ {
2920             out->data.brush.type = consume_uint8(&in);
2921             if (out->data.brush.type == SPICE_BRUSH_TYPE_SOLID) {
2922                 out->data.brush.u.color = consume_uint32(&in);
2923             } else if (out->data.brush.type == SPICE_BRUSH_TYPE_PATTERN) {
2924                 ptr_info[n_ptr].offset = consume_uint32(&in);
2925                 ptr_info[n_ptr].parse = parse_struct_SpiceImage;
2926                 ptr_info[n_ptr].dest = (void **)&out->data.brush.u.pattern.pat;
2927                 n_ptr++;
2928                 /* pos */ {
2929                     out->data.brush.u.pattern.pos.x = consume_int32(&in);
2930                     out->data.brush.u.pattern.pos.y = consume_int32(&in);
2931                 }
2932             }
2933         }
2934         out->data.rop_descriptor = consume_uint16(&in);
2935         /* mask */ {
2936             out->data.mask.flags = consume_uint8(&in);
2937             /* pos */ {
2938                 out->data.mask.pos.x = consume_int32(&in);
2939                 out->data.mask.pos.y = consume_int32(&in);
2940             }
2941             ptr_info[n_ptr].offset = consume_uint32(&in);
2942             ptr_info[n_ptr].parse = parse_struct_SpiceImage;
2943             ptr_info[n_ptr].dest = (void **)&out->data.mask.bitmap;
2944             n_ptr++;
2945         }
2946     }
2947 
2948     assert(in <= message_end);
2949 
2950     for (i = 0; i < n_ptr; i++) {
2951         if (ptr_info[i].offset == 0) {
2952             *ptr_info[i].dest = NULL;
2953         } else {
2954             /* Align to 32 bit */
2955             end = (uint8_t *)SPICE_ALIGN((uintptr_t)end, 4);
2956             *ptr_info[i].dest = (void *)end;
2957             end = ptr_info[i].parse(message_start, message_end, end, &ptr_info[i]);
2958             if (SPICE_UNLIKELY(end == NULL)) {
2959                 goto error;
2960             }
2961         }
2962     }
2963 
2964     assert(end <= data + mem_size);
2965 
2966     *size = end - data;
2967     *free_message = (message_destructor_t) free;
2968     return data;
2969 
2970    error:
2971     free(data);
2972     return NULL;
2973 }
2974 
parse_msg_display_draw_opaque(uint8_t * message_start,uint8_t * message_end,size_t * size,message_destructor_t * free_message)2975 static uint8_t * parse_msg_display_draw_opaque(uint8_t *message_start, uint8_t *message_end, size_t *size, message_destructor_t *free_message)
2976 {
2977     SPICE_GNUC_UNUSED uint8_t *pos;
2978     uint8_t *start = message_start;
2979     uint8_t *data = NULL;
2980     uint64_t nw_size;
2981     uint64_t mem_size;
2982     uint8_t *in, *end;
2983     SPICE_GNUC_UNUSED intptr_t ptr_size;
2984     uint32_t n_ptr=0;
2985     PointerInfo ptr_info[4];
2986     uint64_t base__nw_size, base__extra_size;
2987     uint32_t rects__saved_size = 0;
2988     uint64_t data__nw_size, data__extra_size;
2989     SpiceMsgDisplayDrawOpaque *out;
2990     uint32_t i;
2991 
2992     { /* base */
2993         SPICE_GNUC_UNUSED uint8_t *start2 = (start + 0);
2994         uint64_t base_clip__nw_size, base_clip__extra_size;
2995         { /* clip */
2996             SPICE_GNUC_UNUSED uint8_t *start3 = (start2 + 20);
2997             uint64_t base_clip_u__nw_size, base_clip_u__extra_size;
2998             uint8_t type__value;
2999             { /* u */
3000                 uint64_t base_clip_u__mem_size;
3001                 pos = start3 + 0;
3002                 if (SPICE_UNLIKELY(pos + 1 > message_end)) {
3003                     goto error;
3004                 }
3005                 type__value = read_uint8(pos);
3006                 if (type__value == SPICE_CLIP_TYPE_RECTS) {
3007                     SPICE_GNUC_UNUSED uint8_t *start4 = (start3 + 1);
3008                     uint64_t base_clip_u_rects__nw_size, base_clip_u_rects__mem_size;
3009                     uint64_t base_clip_u_rects__nelements;
3010                     { /* rects */
3011                         uint32_t num_rects__value;
3012                         pos = start4 + 0;
3013                         if (SPICE_UNLIKELY(pos + 4 > message_end)) {
3014                             goto error;
3015                         }
3016                         num_rects__value = read_uint32(pos);
3017                         base_clip_u_rects__nelements = num_rects__value;
3018 
3019                         base_clip_u_rects__nw_size = (16) * base_clip_u_rects__nelements;
3020                         base_clip_u_rects__mem_size = sizeof(SpiceRect) * base_clip_u_rects__nelements;
3021                     }
3022 
3023                     base_clip_u__nw_size = 4 + base_clip_u_rects__nw_size;
3024                     base_clip_u__mem_size = sizeof(SpiceClipRects) + base_clip_u_rects__mem_size;
3025                     rects__saved_size = base_clip_u__nw_size;
3026                     base_clip_u__extra_size = base_clip_u__mem_size;
3027                 } else {
3028                     base_clip_u__nw_size = 0;
3029                     base_clip_u__extra_size = 0;
3030                 }
3031 
3032             }
3033 
3034             base_clip__nw_size = 1 + base_clip_u__nw_size;
3035             base_clip__extra_size = base_clip_u__extra_size;
3036         }
3037 
3038         base__nw_size = 20 + base_clip__nw_size;
3039         base__extra_size = base_clip__extra_size;
3040     }
3041 
3042     { /* data */
3043         SPICE_GNUC_UNUSED uint8_t *start2 = (start + 0 + base__nw_size);
3044         uint64_t data_src_bitmap__extra_size;
3045         uint64_t data_brush__nw_size, data_brush__extra_size;
3046         uint64_t data_mask__extra_size;
3047         { /* src_bitmap */
3048             uint32_t src_bitmap__value;
3049             pos = (start2 + 0);
3050             if (SPICE_UNLIKELY(pos + 4 > message_end)) {
3051                 goto error;
3052             }
3053             src_bitmap__value = read_uint32(pos);
3054             ptr_size = validate_SpiceImage(message_start, message_end, src_bitmap__value);
3055             if (SPICE_UNLIKELY(ptr_size < 0)) {
3056                 goto error;
3057             }
3058             data_src_bitmap__extra_size = ptr_size + /* for alignment */ 3;
3059         }
3060 
3061         { /* brush */
3062             SPICE_GNUC_UNUSED uint8_t *start3 = (start2 + 20);
3063             uint64_t data_brush_u__nw_size, data_brush_u__extra_size;
3064             uint8_t type__value;
3065             { /* u */
3066                 pos = start3 + 0;
3067                 if (SPICE_UNLIKELY(pos + 1 > message_end)) {
3068                     goto error;
3069                 }
3070                 type__value = read_uint8(pos);
3071                 if (type__value == SPICE_BRUSH_TYPE_SOLID) {
3072                     data_brush_u__nw_size = 4;
3073                     data_brush_u__extra_size = 0;
3074                 } else if (type__value == SPICE_BRUSH_TYPE_PATTERN) {
3075                     SPICE_GNUC_UNUSED uint8_t *start4 = (start3 + 1);
3076                     uint64_t data_brush_u_pat__extra_size;
3077                     { /* pat */
3078                         uint32_t pat__value;
3079                         pos = (start4 + 0);
3080                         if (SPICE_UNLIKELY(pos + 4 > message_end)) {
3081                             goto error;
3082                         }
3083                         pat__value = read_uint32(pos);
3084                         if (SPICE_UNLIKELY(pat__value == 0)) {
3085                             goto error;
3086                         }
3087                         ptr_size = validate_SpiceImage(message_start, message_end, pat__value);
3088                         if (SPICE_UNLIKELY(ptr_size < 0)) {
3089                             goto error;
3090                         }
3091                         data_brush_u_pat__extra_size = ptr_size + /* for alignment */ 3;
3092                     }
3093 
3094                     data_brush_u__nw_size = 12;
3095                     data_brush_u__extra_size = data_brush_u_pat__extra_size;
3096                 } else {
3097                     data_brush_u__nw_size = 0;
3098                     data_brush_u__extra_size = 0;
3099                 }
3100 
3101             }
3102 
3103             data_brush__nw_size = 1 + data_brush_u__nw_size;
3104             data_brush__extra_size = data_brush_u__extra_size;
3105         }
3106 
3107         { /* mask */
3108             SPICE_GNUC_UNUSED uint8_t *start3 = (start2 + 23 + data_brush__nw_size);
3109             uint64_t data_mask_bitmap__extra_size;
3110             { /* bitmap */
3111                 uint32_t bitmap__value;
3112                 pos = (start3 + 9);
3113                 if (SPICE_UNLIKELY(pos + 4 > message_end)) {
3114                     goto error;
3115                 }
3116                 bitmap__value = read_uint32(pos);
3117                 ptr_size = validate_SpiceImage(message_start, message_end, bitmap__value);
3118                 if (SPICE_UNLIKELY(ptr_size < 0)) {
3119                     goto error;
3120                 }
3121                 data_mask_bitmap__extra_size = ptr_size + /* for alignment */ 3;
3122             }
3123 
3124             data_mask__extra_size = data_mask_bitmap__extra_size;
3125         }
3126 
3127         data__nw_size = 36 + data_brush__nw_size;
3128         data__extra_size = data_src_bitmap__extra_size + data_brush__extra_size + data_mask__extra_size;
3129     }
3130 
3131     nw_size = 0 + base__nw_size + data__nw_size;
3132     mem_size = sizeof(SpiceMsgDisplayDrawOpaque) + base__extra_size + data__extra_size;
3133 
3134     /* Check if message fits in reported side */
3135     if (nw_size > (uintptr_t) (message_end - start)) {
3136         return NULL;
3137     }
3138 
3139     /* Validated extents and calculated size */
3140     data = (uint8_t *)(mem_size > UINT32_MAX ? NULL : malloc(mem_size));
3141     if (SPICE_UNLIKELY(data == NULL)) {
3142         goto error;
3143     }
3144     end = data + sizeof(SpiceMsgDisplayDrawOpaque);
3145     in = start;
3146 
3147     out = (SpiceMsgDisplayDrawOpaque *)data;
3148 
3149     /* base */ {
3150         out->base.surface_id = consume_uint32(&in);
3151         /* box */ {
3152             out->base.box.top = consume_int32(&in);
3153             out->base.box.left = consume_int32(&in);
3154             out->base.box.bottom = consume_int32(&in);
3155             out->base.box.right = consume_int32(&in);
3156         }
3157         /* clip */ {
3158             out->base.clip.type = consume_uint8(&in);
3159             if (out->base.clip.type == SPICE_CLIP_TYPE_RECTS) {
3160                 ptr_info[n_ptr].offset = in - start;
3161                 ptr_info[n_ptr].parse = parse_struct_SpiceClipRects;
3162                 ptr_info[n_ptr].dest = (void **)&out->base.clip.rects;
3163                 n_ptr++;
3164                 in += rects__saved_size;
3165             }
3166         }
3167     }
3168     /* data */ {
3169         ptr_info[n_ptr].offset = consume_uint32(&in);
3170         ptr_info[n_ptr].parse = parse_struct_SpiceImage;
3171         ptr_info[n_ptr].dest = (void **)&out->data.src_bitmap;
3172         n_ptr++;
3173         /* src_area */ {
3174             out->data.src_area.top = consume_int32(&in);
3175             out->data.src_area.left = consume_int32(&in);
3176             out->data.src_area.bottom = consume_int32(&in);
3177             out->data.src_area.right = consume_int32(&in);
3178         }
3179         /* brush */ {
3180             out->data.brush.type = consume_uint8(&in);
3181             if (out->data.brush.type == SPICE_BRUSH_TYPE_SOLID) {
3182                 out->data.brush.u.color = consume_uint32(&in);
3183             } else if (out->data.brush.type == SPICE_BRUSH_TYPE_PATTERN) {
3184                 ptr_info[n_ptr].offset = consume_uint32(&in);
3185                 ptr_info[n_ptr].parse = parse_struct_SpiceImage;
3186                 ptr_info[n_ptr].dest = (void **)&out->data.brush.u.pattern.pat;
3187                 n_ptr++;
3188                 /* pos */ {
3189                     out->data.brush.u.pattern.pos.x = consume_int32(&in);
3190                     out->data.brush.u.pattern.pos.y = consume_int32(&in);
3191                 }
3192             }
3193         }
3194         out->data.rop_descriptor = consume_uint16(&in);
3195         out->data.scale_mode = consume_uint8(&in);
3196         /* mask */ {
3197             out->data.mask.flags = consume_uint8(&in);
3198             /* pos */ {
3199                 out->data.mask.pos.x = consume_int32(&in);
3200                 out->data.mask.pos.y = consume_int32(&in);
3201             }
3202             ptr_info[n_ptr].offset = consume_uint32(&in);
3203             ptr_info[n_ptr].parse = parse_struct_SpiceImage;
3204             ptr_info[n_ptr].dest = (void **)&out->data.mask.bitmap;
3205             n_ptr++;
3206         }
3207     }
3208 
3209     assert(in <= message_end);
3210 
3211     for (i = 0; i < n_ptr; i++) {
3212         if (ptr_info[i].offset == 0) {
3213             *ptr_info[i].dest = NULL;
3214         } else {
3215             /* Align to 32 bit */
3216             end = (uint8_t *)SPICE_ALIGN((uintptr_t)end, 4);
3217             *ptr_info[i].dest = (void *)end;
3218             end = ptr_info[i].parse(message_start, message_end, end, &ptr_info[i]);
3219             if (SPICE_UNLIKELY(end == NULL)) {
3220                 goto error;
3221             }
3222         }
3223     }
3224 
3225     assert(end <= data + mem_size);
3226 
3227     *size = end - data;
3228     *free_message = (message_destructor_t) free;
3229     return data;
3230 
3231    error:
3232     free(data);
3233     return NULL;
3234 }
3235 
parse_msg_display_draw_copy(uint8_t * message_start,uint8_t * message_end,size_t * size,message_destructor_t * free_message)3236 static uint8_t * parse_msg_display_draw_copy(uint8_t *message_start, uint8_t *message_end, size_t *size, message_destructor_t *free_message)
3237 {
3238     SPICE_GNUC_UNUSED uint8_t *pos;
3239     uint8_t *start = message_start;
3240     uint8_t *data = NULL;
3241     uint64_t nw_size;
3242     uint64_t mem_size;
3243     uint8_t *in, *end;
3244     SPICE_GNUC_UNUSED intptr_t ptr_size;
3245     uint32_t n_ptr=0;
3246     PointerInfo ptr_info[3];
3247     uint64_t base__nw_size, base__extra_size;
3248     uint32_t rects__saved_size = 0;
3249     uint64_t data__extra_size;
3250     SpiceMsgDisplayDrawCopy *out;
3251     uint32_t i;
3252 
3253     { /* base */
3254         SPICE_GNUC_UNUSED uint8_t *start2 = (start + 0);
3255         uint64_t base_clip__nw_size, base_clip__extra_size;
3256         { /* clip */
3257             SPICE_GNUC_UNUSED uint8_t *start3 = (start2 + 20);
3258             uint64_t base_clip_u__nw_size, base_clip_u__extra_size;
3259             uint8_t type__value;
3260             { /* u */
3261                 uint64_t base_clip_u__mem_size;
3262                 pos = start3 + 0;
3263                 if (SPICE_UNLIKELY(pos + 1 > message_end)) {
3264                     goto error;
3265                 }
3266                 type__value = read_uint8(pos);
3267                 if (type__value == SPICE_CLIP_TYPE_RECTS) {
3268                     SPICE_GNUC_UNUSED uint8_t *start4 = (start3 + 1);
3269                     uint64_t base_clip_u_rects__nw_size, base_clip_u_rects__mem_size;
3270                     uint64_t base_clip_u_rects__nelements;
3271                     { /* rects */
3272                         uint32_t num_rects__value;
3273                         pos = start4 + 0;
3274                         if (SPICE_UNLIKELY(pos + 4 > message_end)) {
3275                             goto error;
3276                         }
3277                         num_rects__value = read_uint32(pos);
3278                         base_clip_u_rects__nelements = num_rects__value;
3279 
3280                         base_clip_u_rects__nw_size = (16) * base_clip_u_rects__nelements;
3281                         base_clip_u_rects__mem_size = sizeof(SpiceRect) * base_clip_u_rects__nelements;
3282                     }
3283 
3284                     base_clip_u__nw_size = 4 + base_clip_u_rects__nw_size;
3285                     base_clip_u__mem_size = sizeof(SpiceClipRects) + base_clip_u_rects__mem_size;
3286                     rects__saved_size = base_clip_u__nw_size;
3287                     base_clip_u__extra_size = base_clip_u__mem_size;
3288                 } else {
3289                     base_clip_u__nw_size = 0;
3290                     base_clip_u__extra_size = 0;
3291                 }
3292 
3293             }
3294 
3295             base_clip__nw_size = 1 + base_clip_u__nw_size;
3296             base_clip__extra_size = base_clip_u__extra_size;
3297         }
3298 
3299         base__nw_size = 20 + base_clip__nw_size;
3300         base__extra_size = base_clip__extra_size;
3301     }
3302 
3303     { /* data */
3304         SPICE_GNUC_UNUSED uint8_t *start2 = (start + 0 + base__nw_size);
3305         uint64_t data_src_bitmap__extra_size;
3306         uint64_t data_mask__extra_size;
3307         { /* src_bitmap */
3308             uint32_t src_bitmap__value;
3309             pos = (start2 + 0);
3310             if (SPICE_UNLIKELY(pos + 4 > message_end)) {
3311                 goto error;
3312             }
3313             src_bitmap__value = read_uint32(pos);
3314             ptr_size = validate_SpiceImage(message_start, message_end, src_bitmap__value);
3315             if (SPICE_UNLIKELY(ptr_size < 0)) {
3316                 goto error;
3317             }
3318             data_src_bitmap__extra_size = ptr_size + /* for alignment */ 3;
3319         }
3320 
3321         { /* mask */
3322             SPICE_GNUC_UNUSED uint8_t *start3 = (start2 + 23);
3323             uint64_t data_mask_bitmap__extra_size;
3324             { /* bitmap */
3325                 uint32_t bitmap__value;
3326                 pos = (start3 + 9);
3327                 if (SPICE_UNLIKELY(pos + 4 > message_end)) {
3328                     goto error;
3329                 }
3330                 bitmap__value = read_uint32(pos);
3331                 ptr_size = validate_SpiceImage(message_start, message_end, bitmap__value);
3332                 if (SPICE_UNLIKELY(ptr_size < 0)) {
3333                     goto error;
3334                 }
3335                 data_mask_bitmap__extra_size = ptr_size + /* for alignment */ 3;
3336             }
3337 
3338             data_mask__extra_size = data_mask_bitmap__extra_size;
3339         }
3340 
3341         data__extra_size = data_src_bitmap__extra_size + data_mask__extra_size;
3342     }
3343 
3344     nw_size = 36 + base__nw_size;
3345     mem_size = sizeof(SpiceMsgDisplayDrawCopy) + base__extra_size + data__extra_size;
3346 
3347     /* Check if message fits in reported side */
3348     if (nw_size > (uintptr_t) (message_end - start)) {
3349         return NULL;
3350     }
3351 
3352     /* Validated extents and calculated size */
3353     data = (uint8_t *)(mem_size > UINT32_MAX ? NULL : malloc(mem_size));
3354     if (SPICE_UNLIKELY(data == NULL)) {
3355         goto error;
3356     }
3357     end = data + sizeof(SpiceMsgDisplayDrawCopy);
3358     in = start;
3359 
3360     out = (SpiceMsgDisplayDrawCopy *)data;
3361 
3362     /* base */ {
3363         out->base.surface_id = consume_uint32(&in);
3364         /* box */ {
3365             out->base.box.top = consume_int32(&in);
3366             out->base.box.left = consume_int32(&in);
3367             out->base.box.bottom = consume_int32(&in);
3368             out->base.box.right = consume_int32(&in);
3369         }
3370         /* clip */ {
3371             out->base.clip.type = consume_uint8(&in);
3372             if (out->base.clip.type == SPICE_CLIP_TYPE_RECTS) {
3373                 ptr_info[n_ptr].offset = in - start;
3374                 ptr_info[n_ptr].parse = parse_struct_SpiceClipRects;
3375                 ptr_info[n_ptr].dest = (void **)&out->base.clip.rects;
3376                 n_ptr++;
3377                 in += rects__saved_size;
3378             }
3379         }
3380     }
3381     /* data */ {
3382         ptr_info[n_ptr].offset = consume_uint32(&in);
3383         ptr_info[n_ptr].parse = parse_struct_SpiceImage;
3384         ptr_info[n_ptr].dest = (void **)&out->data.src_bitmap;
3385         n_ptr++;
3386         /* src_area */ {
3387             out->data.src_area.top = consume_int32(&in);
3388             out->data.src_area.left = consume_int32(&in);
3389             out->data.src_area.bottom = consume_int32(&in);
3390             out->data.src_area.right = consume_int32(&in);
3391         }
3392         out->data.rop_descriptor = consume_uint16(&in);
3393         out->data.scale_mode = consume_uint8(&in);
3394         /* mask */ {
3395             out->data.mask.flags = consume_uint8(&in);
3396             /* pos */ {
3397                 out->data.mask.pos.x = consume_int32(&in);
3398                 out->data.mask.pos.y = consume_int32(&in);
3399             }
3400             ptr_info[n_ptr].offset = consume_uint32(&in);
3401             ptr_info[n_ptr].parse = parse_struct_SpiceImage;
3402             ptr_info[n_ptr].dest = (void **)&out->data.mask.bitmap;
3403             n_ptr++;
3404         }
3405     }
3406 
3407     assert(in <= message_end);
3408 
3409     for (i = 0; i < n_ptr; i++) {
3410         if (ptr_info[i].offset == 0) {
3411             *ptr_info[i].dest = NULL;
3412         } else {
3413             /* Align to 32 bit */
3414             end = (uint8_t *)SPICE_ALIGN((uintptr_t)end, 4);
3415             *ptr_info[i].dest = (void *)end;
3416             end = ptr_info[i].parse(message_start, message_end, end, &ptr_info[i]);
3417             if (SPICE_UNLIKELY(end == NULL)) {
3418                 goto error;
3419             }
3420         }
3421     }
3422 
3423     assert(end <= data + mem_size);
3424 
3425     *size = end - data;
3426     *free_message = (message_destructor_t) free;
3427     return data;
3428 
3429    error:
3430     free(data);
3431     return NULL;
3432 }
3433 
parse_msg_display_draw_blend(uint8_t * message_start,uint8_t * message_end,size_t * size,message_destructor_t * free_message)3434 static uint8_t * parse_msg_display_draw_blend(uint8_t *message_start, uint8_t *message_end, size_t *size, message_destructor_t *free_message)
3435 {
3436     SPICE_GNUC_UNUSED uint8_t *pos;
3437     uint8_t *start = message_start;
3438     uint8_t *data = NULL;
3439     uint64_t nw_size;
3440     uint64_t mem_size;
3441     uint8_t *in, *end;
3442     SPICE_GNUC_UNUSED intptr_t ptr_size;
3443     uint32_t n_ptr=0;
3444     PointerInfo ptr_info[3];
3445     uint64_t base__nw_size, base__extra_size;
3446     uint32_t rects__saved_size = 0;
3447     uint64_t data__extra_size;
3448     SpiceMsgDisplayDrawCopy *out;
3449     uint32_t i;
3450 
3451     { /* base */
3452         SPICE_GNUC_UNUSED uint8_t *start2 = (start + 0);
3453         uint64_t base_clip__nw_size, base_clip__extra_size;
3454         { /* clip */
3455             SPICE_GNUC_UNUSED uint8_t *start3 = (start2 + 20);
3456             uint64_t base_clip_u__nw_size, base_clip_u__extra_size;
3457             uint8_t type__value;
3458             { /* u */
3459                 uint64_t base_clip_u__mem_size;
3460                 pos = start3 + 0;
3461                 if (SPICE_UNLIKELY(pos + 1 > message_end)) {
3462                     goto error;
3463                 }
3464                 type__value = read_uint8(pos);
3465                 if (type__value == SPICE_CLIP_TYPE_RECTS) {
3466                     SPICE_GNUC_UNUSED uint8_t *start4 = (start3 + 1);
3467                     uint64_t base_clip_u_rects__nw_size, base_clip_u_rects__mem_size;
3468                     uint64_t base_clip_u_rects__nelements;
3469                     { /* rects */
3470                         uint32_t num_rects__value;
3471                         pos = start4 + 0;
3472                         if (SPICE_UNLIKELY(pos + 4 > message_end)) {
3473                             goto error;
3474                         }
3475                         num_rects__value = read_uint32(pos);
3476                         base_clip_u_rects__nelements = num_rects__value;
3477 
3478                         base_clip_u_rects__nw_size = (16) * base_clip_u_rects__nelements;
3479                         base_clip_u_rects__mem_size = sizeof(SpiceRect) * base_clip_u_rects__nelements;
3480                     }
3481 
3482                     base_clip_u__nw_size = 4 + base_clip_u_rects__nw_size;
3483                     base_clip_u__mem_size = sizeof(SpiceClipRects) + base_clip_u_rects__mem_size;
3484                     rects__saved_size = base_clip_u__nw_size;
3485                     base_clip_u__extra_size = base_clip_u__mem_size;
3486                 } else {
3487                     base_clip_u__nw_size = 0;
3488                     base_clip_u__extra_size = 0;
3489                 }
3490 
3491             }
3492 
3493             base_clip__nw_size = 1 + base_clip_u__nw_size;
3494             base_clip__extra_size = base_clip_u__extra_size;
3495         }
3496 
3497         base__nw_size = 20 + base_clip__nw_size;
3498         base__extra_size = base_clip__extra_size;
3499     }
3500 
3501     { /* data */
3502         SPICE_GNUC_UNUSED uint8_t *start2 = (start + 0 + base__nw_size);
3503         uint64_t data_src_bitmap__extra_size;
3504         uint64_t data_mask__extra_size;
3505         { /* src_bitmap */
3506             uint32_t src_bitmap__value;
3507             pos = (start2 + 0);
3508             if (SPICE_UNLIKELY(pos + 4 > message_end)) {
3509                 goto error;
3510             }
3511             src_bitmap__value = read_uint32(pos);
3512             ptr_size = validate_SpiceImage(message_start, message_end, src_bitmap__value);
3513             if (SPICE_UNLIKELY(ptr_size < 0)) {
3514                 goto error;
3515             }
3516             data_src_bitmap__extra_size = ptr_size + /* for alignment */ 3;
3517         }
3518 
3519         { /* mask */
3520             SPICE_GNUC_UNUSED uint8_t *start3 = (start2 + 23);
3521             uint64_t data_mask_bitmap__extra_size;
3522             { /* bitmap */
3523                 uint32_t bitmap__value;
3524                 pos = (start3 + 9);
3525                 if (SPICE_UNLIKELY(pos + 4 > message_end)) {
3526                     goto error;
3527                 }
3528                 bitmap__value = read_uint32(pos);
3529                 ptr_size = validate_SpiceImage(message_start, message_end, bitmap__value);
3530                 if (SPICE_UNLIKELY(ptr_size < 0)) {
3531                     goto error;
3532                 }
3533                 data_mask_bitmap__extra_size = ptr_size + /* for alignment */ 3;
3534             }
3535 
3536             data_mask__extra_size = data_mask_bitmap__extra_size;
3537         }
3538 
3539         data__extra_size = data_src_bitmap__extra_size + data_mask__extra_size;
3540     }
3541 
3542     nw_size = 36 + base__nw_size;
3543     mem_size = sizeof(SpiceMsgDisplayDrawCopy) + base__extra_size + data__extra_size;
3544 
3545     /* Check if message fits in reported side */
3546     if (nw_size > (uintptr_t) (message_end - start)) {
3547         return NULL;
3548     }
3549 
3550     /* Validated extents and calculated size */
3551     data = (uint8_t *)(mem_size > UINT32_MAX ? NULL : malloc(mem_size));
3552     if (SPICE_UNLIKELY(data == NULL)) {
3553         goto error;
3554     }
3555     end = data + sizeof(SpiceMsgDisplayDrawCopy);
3556     in = start;
3557 
3558     out = (SpiceMsgDisplayDrawCopy *)data;
3559 
3560     /* base */ {
3561         out->base.surface_id = consume_uint32(&in);
3562         /* box */ {
3563             out->base.box.top = consume_int32(&in);
3564             out->base.box.left = consume_int32(&in);
3565             out->base.box.bottom = consume_int32(&in);
3566             out->base.box.right = consume_int32(&in);
3567         }
3568         /* clip */ {
3569             out->base.clip.type = consume_uint8(&in);
3570             if (out->base.clip.type == SPICE_CLIP_TYPE_RECTS) {
3571                 ptr_info[n_ptr].offset = in - start;
3572                 ptr_info[n_ptr].parse = parse_struct_SpiceClipRects;
3573                 ptr_info[n_ptr].dest = (void **)&out->base.clip.rects;
3574                 n_ptr++;
3575                 in += rects__saved_size;
3576             }
3577         }
3578     }
3579     /* data */ {
3580         ptr_info[n_ptr].offset = consume_uint32(&in);
3581         ptr_info[n_ptr].parse = parse_struct_SpiceImage;
3582         ptr_info[n_ptr].dest = (void **)&out->data.src_bitmap;
3583         n_ptr++;
3584         /* src_area */ {
3585             out->data.src_area.top = consume_int32(&in);
3586             out->data.src_area.left = consume_int32(&in);
3587             out->data.src_area.bottom = consume_int32(&in);
3588             out->data.src_area.right = consume_int32(&in);
3589         }
3590         out->data.rop_descriptor = consume_uint16(&in);
3591         out->data.scale_mode = consume_uint8(&in);
3592         /* mask */ {
3593             out->data.mask.flags = consume_uint8(&in);
3594             /* pos */ {
3595                 out->data.mask.pos.x = consume_int32(&in);
3596                 out->data.mask.pos.y = consume_int32(&in);
3597             }
3598             ptr_info[n_ptr].offset = consume_uint32(&in);
3599             ptr_info[n_ptr].parse = parse_struct_SpiceImage;
3600             ptr_info[n_ptr].dest = (void **)&out->data.mask.bitmap;
3601             n_ptr++;
3602         }
3603     }
3604 
3605     assert(in <= message_end);
3606 
3607     for (i = 0; i < n_ptr; i++) {
3608         if (ptr_info[i].offset == 0) {
3609             *ptr_info[i].dest = NULL;
3610         } else {
3611             /* Align to 32 bit */
3612             end = (uint8_t *)SPICE_ALIGN((uintptr_t)end, 4);
3613             *ptr_info[i].dest = (void *)end;
3614             end = ptr_info[i].parse(message_start, message_end, end, &ptr_info[i]);
3615             if (SPICE_UNLIKELY(end == NULL)) {
3616                 goto error;
3617             }
3618         }
3619     }
3620 
3621     assert(end <= data + mem_size);
3622 
3623     *size = end - data;
3624     *free_message = (message_destructor_t) free;
3625     return data;
3626 
3627    error:
3628     free(data);
3629     return NULL;
3630 }
3631 
parse_msg_display_draw_blackness(uint8_t * message_start,uint8_t * message_end,size_t * size,message_destructor_t * free_message)3632 static uint8_t * parse_msg_display_draw_blackness(uint8_t *message_start, uint8_t *message_end, size_t *size, message_destructor_t *free_message)
3633 {
3634     SPICE_GNUC_UNUSED uint8_t *pos;
3635     uint8_t *start = message_start;
3636     uint8_t *data = NULL;
3637     uint64_t nw_size;
3638     uint64_t mem_size;
3639     uint8_t *in, *end;
3640     SPICE_GNUC_UNUSED intptr_t ptr_size;
3641     uint32_t n_ptr=0;
3642     PointerInfo ptr_info[2];
3643     uint64_t base__nw_size, base__extra_size;
3644     uint32_t rects__saved_size = 0;
3645     uint64_t data__extra_size;
3646     SpiceMsgDisplayDrawBlackness *out;
3647     uint32_t i;
3648 
3649     { /* base */
3650         SPICE_GNUC_UNUSED uint8_t *start2 = (start + 0);
3651         uint64_t base_clip__nw_size, base_clip__extra_size;
3652         { /* clip */
3653             SPICE_GNUC_UNUSED uint8_t *start3 = (start2 + 20);
3654             uint64_t base_clip_u__nw_size, base_clip_u__extra_size;
3655             uint8_t type__value;
3656             { /* u */
3657                 uint64_t base_clip_u__mem_size;
3658                 pos = start3 + 0;
3659                 if (SPICE_UNLIKELY(pos + 1 > message_end)) {
3660                     goto error;
3661                 }
3662                 type__value = read_uint8(pos);
3663                 if (type__value == SPICE_CLIP_TYPE_RECTS) {
3664                     SPICE_GNUC_UNUSED uint8_t *start4 = (start3 + 1);
3665                     uint64_t base_clip_u_rects__nw_size, base_clip_u_rects__mem_size;
3666                     uint64_t base_clip_u_rects__nelements;
3667                     { /* rects */
3668                         uint32_t num_rects__value;
3669                         pos = start4 + 0;
3670                         if (SPICE_UNLIKELY(pos + 4 > message_end)) {
3671                             goto error;
3672                         }
3673                         num_rects__value = read_uint32(pos);
3674                         base_clip_u_rects__nelements = num_rects__value;
3675 
3676                         base_clip_u_rects__nw_size = (16) * base_clip_u_rects__nelements;
3677                         base_clip_u_rects__mem_size = sizeof(SpiceRect) * base_clip_u_rects__nelements;
3678                     }
3679 
3680                     base_clip_u__nw_size = 4 + base_clip_u_rects__nw_size;
3681                     base_clip_u__mem_size = sizeof(SpiceClipRects) + base_clip_u_rects__mem_size;
3682                     rects__saved_size = base_clip_u__nw_size;
3683                     base_clip_u__extra_size = base_clip_u__mem_size;
3684                 } else {
3685                     base_clip_u__nw_size = 0;
3686                     base_clip_u__extra_size = 0;
3687                 }
3688 
3689             }
3690 
3691             base_clip__nw_size = 1 + base_clip_u__nw_size;
3692             base_clip__extra_size = base_clip_u__extra_size;
3693         }
3694 
3695         base__nw_size = 20 + base_clip__nw_size;
3696         base__extra_size = base_clip__extra_size;
3697     }
3698 
3699     { /* data */
3700         SPICE_GNUC_UNUSED uint8_t *start2 = (start + 0 + base__nw_size);
3701         uint64_t data_mask__extra_size;
3702         { /* mask */
3703             SPICE_GNUC_UNUSED uint8_t *start3 = (start2 + 0);
3704             uint64_t data_mask_bitmap__extra_size;
3705             { /* bitmap */
3706                 uint32_t bitmap__value;
3707                 pos = (start3 + 9);
3708                 if (SPICE_UNLIKELY(pos + 4 > message_end)) {
3709                     goto error;
3710                 }
3711                 bitmap__value = read_uint32(pos);
3712                 ptr_size = validate_SpiceImage(message_start, message_end, bitmap__value);
3713                 if (SPICE_UNLIKELY(ptr_size < 0)) {
3714                     goto error;
3715                 }
3716                 data_mask_bitmap__extra_size = ptr_size + /* for alignment */ 3;
3717             }
3718 
3719             data_mask__extra_size = data_mask_bitmap__extra_size;
3720         }
3721 
3722         data__extra_size = data_mask__extra_size;
3723     }
3724 
3725     nw_size = 13 + base__nw_size;
3726     mem_size = sizeof(SpiceMsgDisplayDrawBlackness) + base__extra_size + data__extra_size;
3727 
3728     /* Check if message fits in reported side */
3729     if (nw_size > (uintptr_t) (message_end - start)) {
3730         return NULL;
3731     }
3732 
3733     /* Validated extents and calculated size */
3734     data = (uint8_t *)(mem_size > UINT32_MAX ? NULL : malloc(mem_size));
3735     if (SPICE_UNLIKELY(data == NULL)) {
3736         goto error;
3737     }
3738     end = data + sizeof(SpiceMsgDisplayDrawBlackness);
3739     in = start;
3740 
3741     out = (SpiceMsgDisplayDrawBlackness *)data;
3742 
3743     /* base */ {
3744         out->base.surface_id = consume_uint32(&in);
3745         /* box */ {
3746             out->base.box.top = consume_int32(&in);
3747             out->base.box.left = consume_int32(&in);
3748             out->base.box.bottom = consume_int32(&in);
3749             out->base.box.right = consume_int32(&in);
3750         }
3751         /* clip */ {
3752             out->base.clip.type = consume_uint8(&in);
3753             if (out->base.clip.type == SPICE_CLIP_TYPE_RECTS) {
3754                 ptr_info[n_ptr].offset = in - start;
3755                 ptr_info[n_ptr].parse = parse_struct_SpiceClipRects;
3756                 ptr_info[n_ptr].dest = (void **)&out->base.clip.rects;
3757                 n_ptr++;
3758                 in += rects__saved_size;
3759             }
3760         }
3761     }
3762     /* data */ {
3763         /* mask */ {
3764             out->data.mask.flags = consume_uint8(&in);
3765             /* pos */ {
3766                 out->data.mask.pos.x = consume_int32(&in);
3767                 out->data.mask.pos.y = consume_int32(&in);
3768             }
3769             ptr_info[n_ptr].offset = consume_uint32(&in);
3770             ptr_info[n_ptr].parse = parse_struct_SpiceImage;
3771             ptr_info[n_ptr].dest = (void **)&out->data.mask.bitmap;
3772             n_ptr++;
3773         }
3774     }
3775 
3776     assert(in <= message_end);
3777 
3778     for (i = 0; i < n_ptr; i++) {
3779         if (ptr_info[i].offset == 0) {
3780             *ptr_info[i].dest = NULL;
3781         } else {
3782             /* Align to 32 bit */
3783             end = (uint8_t *)SPICE_ALIGN((uintptr_t)end, 4);
3784             *ptr_info[i].dest = (void *)end;
3785             end = ptr_info[i].parse(message_start, message_end, end, &ptr_info[i]);
3786             if (SPICE_UNLIKELY(end == NULL)) {
3787                 goto error;
3788             }
3789         }
3790     }
3791 
3792     assert(end <= data + mem_size);
3793 
3794     *size = end - data;
3795     *free_message = (message_destructor_t) free;
3796     return data;
3797 
3798    error:
3799     free(data);
3800     return NULL;
3801 }
3802 
parse_msg_display_draw_whiteness(uint8_t * message_start,uint8_t * message_end,size_t * size,message_destructor_t * free_message)3803 static uint8_t * parse_msg_display_draw_whiteness(uint8_t *message_start, uint8_t *message_end, size_t *size, message_destructor_t *free_message)
3804 {
3805     SPICE_GNUC_UNUSED uint8_t *pos;
3806     uint8_t *start = message_start;
3807     uint8_t *data = NULL;
3808     uint64_t nw_size;
3809     uint64_t mem_size;
3810     uint8_t *in, *end;
3811     SPICE_GNUC_UNUSED intptr_t ptr_size;
3812     uint32_t n_ptr=0;
3813     PointerInfo ptr_info[2];
3814     uint64_t base__nw_size, base__extra_size;
3815     uint32_t rects__saved_size = 0;
3816     uint64_t data__extra_size;
3817     SpiceMsgDisplayDrawWhiteness *out;
3818     uint32_t i;
3819 
3820     { /* base */
3821         SPICE_GNUC_UNUSED uint8_t *start2 = (start + 0);
3822         uint64_t base_clip__nw_size, base_clip__extra_size;
3823         { /* clip */
3824             SPICE_GNUC_UNUSED uint8_t *start3 = (start2 + 20);
3825             uint64_t base_clip_u__nw_size, base_clip_u__extra_size;
3826             uint8_t type__value;
3827             { /* u */
3828                 uint64_t base_clip_u__mem_size;
3829                 pos = start3 + 0;
3830                 if (SPICE_UNLIKELY(pos + 1 > message_end)) {
3831                     goto error;
3832                 }
3833                 type__value = read_uint8(pos);
3834                 if (type__value == SPICE_CLIP_TYPE_RECTS) {
3835                     SPICE_GNUC_UNUSED uint8_t *start4 = (start3 + 1);
3836                     uint64_t base_clip_u_rects__nw_size, base_clip_u_rects__mem_size;
3837                     uint64_t base_clip_u_rects__nelements;
3838                     { /* rects */
3839                         uint32_t num_rects__value;
3840                         pos = start4 + 0;
3841                         if (SPICE_UNLIKELY(pos + 4 > message_end)) {
3842                             goto error;
3843                         }
3844                         num_rects__value = read_uint32(pos);
3845                         base_clip_u_rects__nelements = num_rects__value;
3846 
3847                         base_clip_u_rects__nw_size = (16) * base_clip_u_rects__nelements;
3848                         base_clip_u_rects__mem_size = sizeof(SpiceRect) * base_clip_u_rects__nelements;
3849                     }
3850 
3851                     base_clip_u__nw_size = 4 + base_clip_u_rects__nw_size;
3852                     base_clip_u__mem_size = sizeof(SpiceClipRects) + base_clip_u_rects__mem_size;
3853                     rects__saved_size = base_clip_u__nw_size;
3854                     base_clip_u__extra_size = base_clip_u__mem_size;
3855                 } else {
3856                     base_clip_u__nw_size = 0;
3857                     base_clip_u__extra_size = 0;
3858                 }
3859 
3860             }
3861 
3862             base_clip__nw_size = 1 + base_clip_u__nw_size;
3863             base_clip__extra_size = base_clip_u__extra_size;
3864         }
3865 
3866         base__nw_size = 20 + base_clip__nw_size;
3867         base__extra_size = base_clip__extra_size;
3868     }
3869 
3870     { /* data */
3871         SPICE_GNUC_UNUSED uint8_t *start2 = (start + 0 + base__nw_size);
3872         uint64_t data_mask__extra_size;
3873         { /* mask */
3874             SPICE_GNUC_UNUSED uint8_t *start3 = (start2 + 0);
3875             uint64_t data_mask_bitmap__extra_size;
3876             { /* bitmap */
3877                 uint32_t bitmap__value;
3878                 pos = (start3 + 9);
3879                 if (SPICE_UNLIKELY(pos + 4 > message_end)) {
3880                     goto error;
3881                 }
3882                 bitmap__value = read_uint32(pos);
3883                 ptr_size = validate_SpiceImage(message_start, message_end, bitmap__value);
3884                 if (SPICE_UNLIKELY(ptr_size < 0)) {
3885                     goto error;
3886                 }
3887                 data_mask_bitmap__extra_size = ptr_size + /* for alignment */ 3;
3888             }
3889 
3890             data_mask__extra_size = data_mask_bitmap__extra_size;
3891         }
3892 
3893         data__extra_size = data_mask__extra_size;
3894     }
3895 
3896     nw_size = 13 + base__nw_size;
3897     mem_size = sizeof(SpiceMsgDisplayDrawWhiteness) + base__extra_size + data__extra_size;
3898 
3899     /* Check if message fits in reported side */
3900     if (nw_size > (uintptr_t) (message_end - start)) {
3901         return NULL;
3902     }
3903 
3904     /* Validated extents and calculated size */
3905     data = (uint8_t *)(mem_size > UINT32_MAX ? NULL : malloc(mem_size));
3906     if (SPICE_UNLIKELY(data == NULL)) {
3907         goto error;
3908     }
3909     end = data + sizeof(SpiceMsgDisplayDrawWhiteness);
3910     in = start;
3911 
3912     out = (SpiceMsgDisplayDrawWhiteness *)data;
3913 
3914     /* base */ {
3915         out->base.surface_id = consume_uint32(&in);
3916         /* box */ {
3917             out->base.box.top = consume_int32(&in);
3918             out->base.box.left = consume_int32(&in);
3919             out->base.box.bottom = consume_int32(&in);
3920             out->base.box.right = consume_int32(&in);
3921         }
3922         /* clip */ {
3923             out->base.clip.type = consume_uint8(&in);
3924             if (out->base.clip.type == SPICE_CLIP_TYPE_RECTS) {
3925                 ptr_info[n_ptr].offset = in - start;
3926                 ptr_info[n_ptr].parse = parse_struct_SpiceClipRects;
3927                 ptr_info[n_ptr].dest = (void **)&out->base.clip.rects;
3928                 n_ptr++;
3929                 in += rects__saved_size;
3930             }
3931         }
3932     }
3933     /* data */ {
3934         /* mask */ {
3935             out->data.mask.flags = consume_uint8(&in);
3936             /* pos */ {
3937                 out->data.mask.pos.x = consume_int32(&in);
3938                 out->data.mask.pos.y = consume_int32(&in);
3939             }
3940             ptr_info[n_ptr].offset = consume_uint32(&in);
3941             ptr_info[n_ptr].parse = parse_struct_SpiceImage;
3942             ptr_info[n_ptr].dest = (void **)&out->data.mask.bitmap;
3943             n_ptr++;
3944         }
3945     }
3946 
3947     assert(in <= message_end);
3948 
3949     for (i = 0; i < n_ptr; i++) {
3950         if (ptr_info[i].offset == 0) {
3951             *ptr_info[i].dest = NULL;
3952         } else {
3953             /* Align to 32 bit */
3954             end = (uint8_t *)SPICE_ALIGN((uintptr_t)end, 4);
3955             *ptr_info[i].dest = (void *)end;
3956             end = ptr_info[i].parse(message_start, message_end, end, &ptr_info[i]);
3957             if (SPICE_UNLIKELY(end == NULL)) {
3958                 goto error;
3959             }
3960         }
3961     }
3962 
3963     assert(end <= data + mem_size);
3964 
3965     *size = end - data;
3966     *free_message = (message_destructor_t) free;
3967     return data;
3968 
3969    error:
3970     free(data);
3971     return NULL;
3972 }
3973 
parse_msg_display_draw_invers(uint8_t * message_start,uint8_t * message_end,size_t * size,message_destructor_t * free_message)3974 static uint8_t * parse_msg_display_draw_invers(uint8_t *message_start, uint8_t *message_end, size_t *size, message_destructor_t *free_message)
3975 {
3976     SPICE_GNUC_UNUSED uint8_t *pos;
3977     uint8_t *start = message_start;
3978     uint8_t *data = NULL;
3979     uint64_t nw_size;
3980     uint64_t mem_size;
3981     uint8_t *in, *end;
3982     SPICE_GNUC_UNUSED intptr_t ptr_size;
3983     uint32_t n_ptr=0;
3984     PointerInfo ptr_info[2];
3985     uint64_t base__nw_size, base__extra_size;
3986     uint32_t rects__saved_size = 0;
3987     uint64_t data__extra_size;
3988     SpiceMsgDisplayDrawInvers *out;
3989     uint32_t i;
3990 
3991     { /* base */
3992         SPICE_GNUC_UNUSED uint8_t *start2 = (start + 0);
3993         uint64_t base_clip__nw_size, base_clip__extra_size;
3994         { /* clip */
3995             SPICE_GNUC_UNUSED uint8_t *start3 = (start2 + 20);
3996             uint64_t base_clip_u__nw_size, base_clip_u__extra_size;
3997             uint8_t type__value;
3998             { /* u */
3999                 uint64_t base_clip_u__mem_size;
4000                 pos = start3 + 0;
4001                 if (SPICE_UNLIKELY(pos + 1 > message_end)) {
4002                     goto error;
4003                 }
4004                 type__value = read_uint8(pos);
4005                 if (type__value == SPICE_CLIP_TYPE_RECTS) {
4006                     SPICE_GNUC_UNUSED uint8_t *start4 = (start3 + 1);
4007                     uint64_t base_clip_u_rects__nw_size, base_clip_u_rects__mem_size;
4008                     uint64_t base_clip_u_rects__nelements;
4009                     { /* rects */
4010                         uint32_t num_rects__value;
4011                         pos = start4 + 0;
4012                         if (SPICE_UNLIKELY(pos + 4 > message_end)) {
4013                             goto error;
4014                         }
4015                         num_rects__value = read_uint32(pos);
4016                         base_clip_u_rects__nelements = num_rects__value;
4017 
4018                         base_clip_u_rects__nw_size = (16) * base_clip_u_rects__nelements;
4019                         base_clip_u_rects__mem_size = sizeof(SpiceRect) * base_clip_u_rects__nelements;
4020                     }
4021 
4022                     base_clip_u__nw_size = 4 + base_clip_u_rects__nw_size;
4023                     base_clip_u__mem_size = sizeof(SpiceClipRects) + base_clip_u_rects__mem_size;
4024                     rects__saved_size = base_clip_u__nw_size;
4025                     base_clip_u__extra_size = base_clip_u__mem_size;
4026                 } else {
4027                     base_clip_u__nw_size = 0;
4028                     base_clip_u__extra_size = 0;
4029                 }
4030 
4031             }
4032 
4033             base_clip__nw_size = 1 + base_clip_u__nw_size;
4034             base_clip__extra_size = base_clip_u__extra_size;
4035         }
4036 
4037         base__nw_size = 20 + base_clip__nw_size;
4038         base__extra_size = base_clip__extra_size;
4039     }
4040 
4041     { /* data */
4042         SPICE_GNUC_UNUSED uint8_t *start2 = (start + 0 + base__nw_size);
4043         uint64_t data_mask__extra_size;
4044         { /* mask */
4045             SPICE_GNUC_UNUSED uint8_t *start3 = (start2 + 0);
4046             uint64_t data_mask_bitmap__extra_size;
4047             { /* bitmap */
4048                 uint32_t bitmap__value;
4049                 pos = (start3 + 9);
4050                 if (SPICE_UNLIKELY(pos + 4 > message_end)) {
4051                     goto error;
4052                 }
4053                 bitmap__value = read_uint32(pos);
4054                 ptr_size = validate_SpiceImage(message_start, message_end, bitmap__value);
4055                 if (SPICE_UNLIKELY(ptr_size < 0)) {
4056                     goto error;
4057                 }
4058                 data_mask_bitmap__extra_size = ptr_size + /* for alignment */ 3;
4059             }
4060 
4061             data_mask__extra_size = data_mask_bitmap__extra_size;
4062         }
4063 
4064         data__extra_size = data_mask__extra_size;
4065     }
4066 
4067     nw_size = 13 + base__nw_size;
4068     mem_size = sizeof(SpiceMsgDisplayDrawInvers) + base__extra_size + data__extra_size;
4069 
4070     /* Check if message fits in reported side */
4071     if (nw_size > (uintptr_t) (message_end - start)) {
4072         return NULL;
4073     }
4074 
4075     /* Validated extents and calculated size */
4076     data = (uint8_t *)(mem_size > UINT32_MAX ? NULL : malloc(mem_size));
4077     if (SPICE_UNLIKELY(data == NULL)) {
4078         goto error;
4079     }
4080     end = data + sizeof(SpiceMsgDisplayDrawInvers);
4081     in = start;
4082 
4083     out = (SpiceMsgDisplayDrawInvers *)data;
4084 
4085     /* base */ {
4086         out->base.surface_id = consume_uint32(&in);
4087         /* box */ {
4088             out->base.box.top = consume_int32(&in);
4089             out->base.box.left = consume_int32(&in);
4090             out->base.box.bottom = consume_int32(&in);
4091             out->base.box.right = consume_int32(&in);
4092         }
4093         /* clip */ {
4094             out->base.clip.type = consume_uint8(&in);
4095             if (out->base.clip.type == SPICE_CLIP_TYPE_RECTS) {
4096                 ptr_info[n_ptr].offset = in - start;
4097                 ptr_info[n_ptr].parse = parse_struct_SpiceClipRects;
4098                 ptr_info[n_ptr].dest = (void **)&out->base.clip.rects;
4099                 n_ptr++;
4100                 in += rects__saved_size;
4101             }
4102         }
4103     }
4104     /* data */ {
4105         /* mask */ {
4106             out->data.mask.flags = consume_uint8(&in);
4107             /* pos */ {
4108                 out->data.mask.pos.x = consume_int32(&in);
4109                 out->data.mask.pos.y = consume_int32(&in);
4110             }
4111             ptr_info[n_ptr].offset = consume_uint32(&in);
4112             ptr_info[n_ptr].parse = parse_struct_SpiceImage;
4113             ptr_info[n_ptr].dest = (void **)&out->data.mask.bitmap;
4114             n_ptr++;
4115         }
4116     }
4117 
4118     assert(in <= message_end);
4119 
4120     for (i = 0; i < n_ptr; i++) {
4121         if (ptr_info[i].offset == 0) {
4122             *ptr_info[i].dest = NULL;
4123         } else {
4124             /* Align to 32 bit */
4125             end = (uint8_t *)SPICE_ALIGN((uintptr_t)end, 4);
4126             *ptr_info[i].dest = (void *)end;
4127             end = ptr_info[i].parse(message_start, message_end, end, &ptr_info[i]);
4128             if (SPICE_UNLIKELY(end == NULL)) {
4129                 goto error;
4130             }
4131         }
4132     }
4133 
4134     assert(end <= data + mem_size);
4135 
4136     *size = end - data;
4137     *free_message = (message_destructor_t) free;
4138     return data;
4139 
4140    error:
4141     free(data);
4142     return NULL;
4143 }
4144 
parse_msg_display_draw_rop3(uint8_t * message_start,uint8_t * message_end,size_t * size,message_destructor_t * free_message)4145 static uint8_t * parse_msg_display_draw_rop3(uint8_t *message_start, uint8_t *message_end, size_t *size, message_destructor_t *free_message)
4146 {
4147     SPICE_GNUC_UNUSED uint8_t *pos;
4148     uint8_t *start = message_start;
4149     uint8_t *data = NULL;
4150     uint64_t nw_size;
4151     uint64_t mem_size;
4152     uint8_t *in, *end;
4153     SPICE_GNUC_UNUSED intptr_t ptr_size;
4154     uint32_t n_ptr=0;
4155     PointerInfo ptr_info[4];
4156     uint64_t base__nw_size, base__extra_size;
4157     uint32_t rects__saved_size = 0;
4158     uint64_t data__nw_size, data__extra_size;
4159     SpiceMsgDisplayDrawRop3 *out;
4160     uint32_t i;
4161 
4162     { /* base */
4163         SPICE_GNUC_UNUSED uint8_t *start2 = (start + 0);
4164         uint64_t base_clip__nw_size, base_clip__extra_size;
4165         { /* clip */
4166             SPICE_GNUC_UNUSED uint8_t *start3 = (start2 + 20);
4167             uint64_t base_clip_u__nw_size, base_clip_u__extra_size;
4168             uint8_t type__value;
4169             { /* u */
4170                 uint64_t base_clip_u__mem_size;
4171                 pos = start3 + 0;
4172                 if (SPICE_UNLIKELY(pos + 1 > message_end)) {
4173                     goto error;
4174                 }
4175                 type__value = read_uint8(pos);
4176                 if (type__value == SPICE_CLIP_TYPE_RECTS) {
4177                     SPICE_GNUC_UNUSED uint8_t *start4 = (start3 + 1);
4178                     uint64_t base_clip_u_rects__nw_size, base_clip_u_rects__mem_size;
4179                     uint64_t base_clip_u_rects__nelements;
4180                     { /* rects */
4181                         uint32_t num_rects__value;
4182                         pos = start4 + 0;
4183                         if (SPICE_UNLIKELY(pos + 4 > message_end)) {
4184                             goto error;
4185                         }
4186                         num_rects__value = read_uint32(pos);
4187                         base_clip_u_rects__nelements = num_rects__value;
4188 
4189                         base_clip_u_rects__nw_size = (16) * base_clip_u_rects__nelements;
4190                         base_clip_u_rects__mem_size = sizeof(SpiceRect) * base_clip_u_rects__nelements;
4191                     }
4192 
4193                     base_clip_u__nw_size = 4 + base_clip_u_rects__nw_size;
4194                     base_clip_u__mem_size = sizeof(SpiceClipRects) + base_clip_u_rects__mem_size;
4195                     rects__saved_size = base_clip_u__nw_size;
4196                     base_clip_u__extra_size = base_clip_u__mem_size;
4197                 } else {
4198                     base_clip_u__nw_size = 0;
4199                     base_clip_u__extra_size = 0;
4200                 }
4201 
4202             }
4203 
4204             base_clip__nw_size = 1 + base_clip_u__nw_size;
4205             base_clip__extra_size = base_clip_u__extra_size;
4206         }
4207 
4208         base__nw_size = 20 + base_clip__nw_size;
4209         base__extra_size = base_clip__extra_size;
4210     }
4211 
4212     { /* data */
4213         SPICE_GNUC_UNUSED uint8_t *start2 = (start + 0 + base__nw_size);
4214         uint64_t data_src_bitmap__extra_size;
4215         uint64_t data_brush__nw_size, data_brush__extra_size;
4216         uint64_t data_mask__extra_size;
4217         { /* src_bitmap */
4218             uint32_t src_bitmap__value;
4219             pos = (start2 + 0);
4220             if (SPICE_UNLIKELY(pos + 4 > message_end)) {
4221                 goto error;
4222             }
4223             src_bitmap__value = read_uint32(pos);
4224             ptr_size = validate_SpiceImage(message_start, message_end, src_bitmap__value);
4225             if (SPICE_UNLIKELY(ptr_size < 0)) {
4226                 goto error;
4227             }
4228             data_src_bitmap__extra_size = ptr_size + /* for alignment */ 3;
4229         }
4230 
4231         { /* brush */
4232             SPICE_GNUC_UNUSED uint8_t *start3 = (start2 + 20);
4233             uint64_t data_brush_u__nw_size, data_brush_u__extra_size;
4234             uint8_t type__value;
4235             { /* u */
4236                 pos = start3 + 0;
4237                 if (SPICE_UNLIKELY(pos + 1 > message_end)) {
4238                     goto error;
4239                 }
4240                 type__value = read_uint8(pos);
4241                 if (type__value == SPICE_BRUSH_TYPE_SOLID) {
4242                     data_brush_u__nw_size = 4;
4243                     data_brush_u__extra_size = 0;
4244                 } else if (type__value == SPICE_BRUSH_TYPE_PATTERN) {
4245                     SPICE_GNUC_UNUSED uint8_t *start4 = (start3 + 1);
4246                     uint64_t data_brush_u_pat__extra_size;
4247                     { /* pat */
4248                         uint32_t pat__value;
4249                         pos = (start4 + 0);
4250                         if (SPICE_UNLIKELY(pos + 4 > message_end)) {
4251                             goto error;
4252                         }
4253                         pat__value = read_uint32(pos);
4254                         if (SPICE_UNLIKELY(pat__value == 0)) {
4255                             goto error;
4256                         }
4257                         ptr_size = validate_SpiceImage(message_start, message_end, pat__value);
4258                         if (SPICE_UNLIKELY(ptr_size < 0)) {
4259                             goto error;
4260                         }
4261                         data_brush_u_pat__extra_size = ptr_size + /* for alignment */ 3;
4262                     }
4263 
4264                     data_brush_u__nw_size = 12;
4265                     data_brush_u__extra_size = data_brush_u_pat__extra_size;
4266                 } else {
4267                     data_brush_u__nw_size = 0;
4268                     data_brush_u__extra_size = 0;
4269                 }
4270 
4271             }
4272 
4273             data_brush__nw_size = 1 + data_brush_u__nw_size;
4274             data_brush__extra_size = data_brush_u__extra_size;
4275         }
4276 
4277         { /* mask */
4278             SPICE_GNUC_UNUSED uint8_t *start3 = (start2 + 22 + data_brush__nw_size);
4279             uint64_t data_mask_bitmap__extra_size;
4280             { /* bitmap */
4281                 uint32_t bitmap__value;
4282                 pos = (start3 + 9);
4283                 if (SPICE_UNLIKELY(pos + 4 > message_end)) {
4284                     goto error;
4285                 }
4286                 bitmap__value = read_uint32(pos);
4287                 ptr_size = validate_SpiceImage(message_start, message_end, bitmap__value);
4288                 if (SPICE_UNLIKELY(ptr_size < 0)) {
4289                     goto error;
4290                 }
4291                 data_mask_bitmap__extra_size = ptr_size + /* for alignment */ 3;
4292             }
4293 
4294             data_mask__extra_size = data_mask_bitmap__extra_size;
4295         }
4296 
4297         data__nw_size = 35 + data_brush__nw_size;
4298         data__extra_size = data_src_bitmap__extra_size + data_brush__extra_size + data_mask__extra_size;
4299     }
4300 
4301     nw_size = 0 + base__nw_size + data__nw_size;
4302     mem_size = sizeof(SpiceMsgDisplayDrawRop3) + base__extra_size + data__extra_size;
4303 
4304     /* Check if message fits in reported side */
4305     if (nw_size > (uintptr_t) (message_end - start)) {
4306         return NULL;
4307     }
4308 
4309     /* Validated extents and calculated size */
4310     data = (uint8_t *)(mem_size > UINT32_MAX ? NULL : malloc(mem_size));
4311     if (SPICE_UNLIKELY(data == NULL)) {
4312         goto error;
4313     }
4314     end = data + sizeof(SpiceMsgDisplayDrawRop3);
4315     in = start;
4316 
4317     out = (SpiceMsgDisplayDrawRop3 *)data;
4318 
4319     /* base */ {
4320         out->base.surface_id = consume_uint32(&in);
4321         /* box */ {
4322             out->base.box.top = consume_int32(&in);
4323             out->base.box.left = consume_int32(&in);
4324             out->base.box.bottom = consume_int32(&in);
4325             out->base.box.right = consume_int32(&in);
4326         }
4327         /* clip */ {
4328             out->base.clip.type = consume_uint8(&in);
4329             if (out->base.clip.type == SPICE_CLIP_TYPE_RECTS) {
4330                 ptr_info[n_ptr].offset = in - start;
4331                 ptr_info[n_ptr].parse = parse_struct_SpiceClipRects;
4332                 ptr_info[n_ptr].dest = (void **)&out->base.clip.rects;
4333                 n_ptr++;
4334                 in += rects__saved_size;
4335             }
4336         }
4337     }
4338     /* data */ {
4339         ptr_info[n_ptr].offset = consume_uint32(&in);
4340         ptr_info[n_ptr].parse = parse_struct_SpiceImage;
4341         ptr_info[n_ptr].dest = (void **)&out->data.src_bitmap;
4342         n_ptr++;
4343         /* src_area */ {
4344             out->data.src_area.top = consume_int32(&in);
4345             out->data.src_area.left = consume_int32(&in);
4346             out->data.src_area.bottom = consume_int32(&in);
4347             out->data.src_area.right = consume_int32(&in);
4348         }
4349         /* brush */ {
4350             out->data.brush.type = consume_uint8(&in);
4351             if (out->data.brush.type == SPICE_BRUSH_TYPE_SOLID) {
4352                 out->data.brush.u.color = consume_uint32(&in);
4353             } else if (out->data.brush.type == SPICE_BRUSH_TYPE_PATTERN) {
4354                 ptr_info[n_ptr].offset = consume_uint32(&in);
4355                 ptr_info[n_ptr].parse = parse_struct_SpiceImage;
4356                 ptr_info[n_ptr].dest = (void **)&out->data.brush.u.pattern.pat;
4357                 n_ptr++;
4358                 /* pos */ {
4359                     out->data.brush.u.pattern.pos.x = consume_int32(&in);
4360                     out->data.brush.u.pattern.pos.y = consume_int32(&in);
4361                 }
4362             }
4363         }
4364         out->data.rop3 = consume_uint8(&in);
4365         out->data.scale_mode = consume_uint8(&in);
4366         /* mask */ {
4367             out->data.mask.flags = consume_uint8(&in);
4368             /* pos */ {
4369                 out->data.mask.pos.x = consume_int32(&in);
4370                 out->data.mask.pos.y = consume_int32(&in);
4371             }
4372             ptr_info[n_ptr].offset = consume_uint32(&in);
4373             ptr_info[n_ptr].parse = parse_struct_SpiceImage;
4374             ptr_info[n_ptr].dest = (void **)&out->data.mask.bitmap;
4375             n_ptr++;
4376         }
4377     }
4378 
4379     assert(in <= message_end);
4380 
4381     for (i = 0; i < n_ptr; i++) {
4382         if (ptr_info[i].offset == 0) {
4383             *ptr_info[i].dest = NULL;
4384         } else {
4385             /* Align to 32 bit */
4386             end = (uint8_t *)SPICE_ALIGN((uintptr_t)end, 4);
4387             *ptr_info[i].dest = (void *)end;
4388             end = ptr_info[i].parse(message_start, message_end, end, &ptr_info[i]);
4389             if (SPICE_UNLIKELY(end == NULL)) {
4390                 goto error;
4391             }
4392         }
4393     }
4394 
4395     assert(end <= data + mem_size);
4396 
4397     *size = end - data;
4398     *free_message = (message_destructor_t) free;
4399     return data;
4400 
4401    error:
4402     free(data);
4403     return NULL;
4404 }
4405 
validate_SpicePath(uint8_t * message_start,uint8_t * message_end,uint64_t offset)4406 static intptr_t validate_SpicePath(uint8_t *message_start, uint8_t *message_end, uint64_t offset)
4407 {
4408     uint8_t *start = message_start + offset;
4409     SPICE_GNUC_UNUSED uint8_t *pos;
4410     uint64_t mem_size, nw_size;
4411     uint64_t segments__nw_size, segments__mem_size;
4412     uint64_t segments__nelements;
4413     uint32_t i;
4414 
4415     if (offset == 0) {
4416         return 0;
4417     }
4418 
4419     if (SPICE_UNLIKELY(start >= message_end)) {
4420         goto error;
4421     }
4422 
4423     { /* segments */
4424         uint32_t num_segments__value;
4425         uint8_t *start2 = (start + 4);
4426         uint64_t segments__element__nw_size;
4427         uint64_t segments__element__mem_size;
4428         pos = start + 0;
4429         if (SPICE_UNLIKELY(pos + 4 > message_end)) {
4430             goto error;
4431         }
4432         num_segments__value = read_uint32(pos);
4433         segments__nelements = num_segments__value;
4434 
4435         segments__nw_size = 0;
4436         segments__mem_size = 0;
4437         for (i = 0; i < segments__nelements; i++) {
4438             SPICE_GNUC_UNUSED uint8_t *start3 = start2;
4439             uint64_t segments__element_points__nw_size, segments__element_points__mem_size;
4440             uint64_t segments__element_points__nelements;
4441             { /* points */
4442                 uint32_t count__value;
4443                 pos = start3 + 1;
4444                 if (SPICE_UNLIKELY(pos + 4 > message_end)) {
4445                     goto error;
4446                 }
4447                 count__value = read_uint32(pos);
4448                 segments__element_points__nelements = count__value;
4449 
4450                 segments__element_points__nw_size = (8) * segments__element_points__nelements;
4451                 segments__element_points__mem_size = sizeof(SpicePointFix) * segments__element_points__nelements;
4452             }
4453 
4454             segments__element__nw_size = 5 + segments__element_points__nw_size;
4455             segments__element__mem_size = sizeof(SpicePathSeg) + segments__element_points__mem_size;
4456             segments__nw_size += segments__element__nw_size;
4457             segments__mem_size += sizeof(void *) + SPICE_ALIGN(segments__element__mem_size, 4);
4458             start2 += segments__element__nw_size;
4459         }
4460     }
4461 
4462     nw_size = 4 + segments__nw_size;
4463     mem_size = sizeof(SpicePath) + segments__mem_size;
4464 
4465     /* Check if struct fits in reported side */
4466     if (SPICE_UNLIKELY(nw_size > (uintptr_t) (message_end - start))) {
4467         goto error;
4468     }
4469     return mem_size;
4470 
4471    error:
4472     return -1;
4473 }
4474 
parse_struct_SpicePath(uint8_t * message_start,SPICE_GNUC_UNUSED uint8_t * message_end,uint8_t * struct_data,PointerInfo * this_ptr_info)4475 static uint8_t * parse_struct_SpicePath(uint8_t *message_start, SPICE_GNUC_UNUSED uint8_t *message_end, uint8_t *struct_data, PointerInfo *this_ptr_info)
4476 {
4477     uint8_t *in = message_start + this_ptr_info->offset;
4478     uint8_t *end;
4479     SpicePath *out;
4480     uint64_t segments__nelements;
4481     uint32_t i;
4482     void * *ptr_array;
4483     int ptr_array_index;
4484     uint32_t j;
4485 
4486     end = struct_data + sizeof(SpicePath);
4487     out = (SpicePath *)struct_data;
4488 
4489     out->num_segments = consume_uint32(&in);
4490     segments__nelements = out->num_segments;
4491     ptr_array_index = 0;
4492     ptr_array = (void **)out->segments;
4493     end += sizeof(void *) * segments__nelements;
4494     for (i = 0; i < segments__nelements; i++) {
4495         SpicePathSeg *out2;
4496         uint64_t points__nelements;
4497         ptr_array[ptr_array_index++] = end;
4498         out2 = (SpicePathSeg *)end;
4499         end += sizeof(SpicePathSeg);
4500 
4501         out2->flags = consume_uint8(&in);
4502         out2->count = consume_uint32(&in);
4503         points__nelements = out2->count;
4504         for (j = 0; j < points__nelements; j++) {
4505             SpicePointFix *out3;
4506             out3 = (SpicePointFix *)end;
4507             end += sizeof(SpicePointFix);
4508 
4509             out3->x = consume_int32(&in);
4510             out3->y = consume_int32(&in);
4511         }
4512         /* Align ptr_array element to 4 bytes */
4513         end = (uint8_t *)SPICE_ALIGN((uintptr_t)end, 4);
4514     }
4515     return end;
4516 }
4517 
parse_array_int32(uint8_t * message_start,SPICE_GNUC_UNUSED uint8_t * message_end,uint8_t * struct_data,PointerInfo * this_ptr_info)4518 static uint8_t * parse_array_int32(uint8_t *message_start, SPICE_GNUC_UNUSED uint8_t *message_end, uint8_t *struct_data, PointerInfo *this_ptr_info)
4519 {
4520     uint8_t *in = message_start + this_ptr_info->offset;
4521     uint8_t *end;
4522     uint32_t i;
4523 
4524     end = struct_data;
4525     for (i = 0; i < this_ptr_info->nelements; i++) {
4526         *(SPICE_FIXED28_4 *)end = consume_int32(&in);
4527         end += sizeof(SPICE_FIXED28_4);
4528     }
4529     return end;
4530 }
4531 
parse_msg_display_draw_stroke(uint8_t * message_start,uint8_t * message_end,size_t * size,message_destructor_t * free_message)4532 static uint8_t * parse_msg_display_draw_stroke(uint8_t *message_start, uint8_t *message_end, size_t *size, message_destructor_t *free_message)
4533 {
4534     SPICE_GNUC_UNUSED uint8_t *pos;
4535     uint8_t *start = message_start;
4536     uint8_t *data = NULL;
4537     uint64_t nw_size;
4538     uint64_t mem_size;
4539     uint8_t *in, *end;
4540     SPICE_GNUC_UNUSED intptr_t ptr_size;
4541     uint32_t n_ptr=0;
4542     PointerInfo ptr_info[4];
4543     uint64_t base__nw_size, base__extra_size;
4544     uint32_t rects__saved_size = 0;
4545     uint64_t data__nw_size, data__extra_size;
4546     SpiceMsgDisplayDrawStroke *out;
4547     uint32_t i;
4548 
4549     { /* base */
4550         SPICE_GNUC_UNUSED uint8_t *start2 = (start + 0);
4551         uint64_t base_clip__nw_size, base_clip__extra_size;
4552         { /* clip */
4553             SPICE_GNUC_UNUSED uint8_t *start3 = (start2 + 20);
4554             uint64_t base_clip_u__nw_size, base_clip_u__extra_size;
4555             uint8_t type__value;
4556             { /* u */
4557                 uint64_t base_clip_u__mem_size;
4558                 pos = start3 + 0;
4559                 if (SPICE_UNLIKELY(pos + 1 > message_end)) {
4560                     goto error;
4561                 }
4562                 type__value = read_uint8(pos);
4563                 if (type__value == SPICE_CLIP_TYPE_RECTS) {
4564                     SPICE_GNUC_UNUSED uint8_t *start4 = (start3 + 1);
4565                     uint64_t base_clip_u_rects__nw_size, base_clip_u_rects__mem_size;
4566                     uint64_t base_clip_u_rects__nelements;
4567                     { /* rects */
4568                         uint32_t num_rects__value;
4569                         pos = start4 + 0;
4570                         if (SPICE_UNLIKELY(pos + 4 > message_end)) {
4571                             goto error;
4572                         }
4573                         num_rects__value = read_uint32(pos);
4574                         base_clip_u_rects__nelements = num_rects__value;
4575 
4576                         base_clip_u_rects__nw_size = (16) * base_clip_u_rects__nelements;
4577                         base_clip_u_rects__mem_size = sizeof(SpiceRect) * base_clip_u_rects__nelements;
4578                     }
4579 
4580                     base_clip_u__nw_size = 4 + base_clip_u_rects__nw_size;
4581                     base_clip_u__mem_size = sizeof(SpiceClipRects) + base_clip_u_rects__mem_size;
4582                     rects__saved_size = base_clip_u__nw_size;
4583                     base_clip_u__extra_size = base_clip_u__mem_size;
4584                 } else {
4585                     base_clip_u__nw_size = 0;
4586                     base_clip_u__extra_size = 0;
4587                 }
4588 
4589             }
4590 
4591             base_clip__nw_size = 1 + base_clip_u__nw_size;
4592             base_clip__extra_size = base_clip_u__extra_size;
4593         }
4594 
4595         base__nw_size = 20 + base_clip__nw_size;
4596         base__extra_size = base_clip__extra_size;
4597     }
4598 
4599     { /* data */
4600         SPICE_GNUC_UNUSED uint8_t *start2 = (start + 0 + base__nw_size);
4601         uint64_t data_path__extra_size;
4602         uint64_t data_attr__nw_size, data_attr__extra_size;
4603         uint64_t data_brush__nw_size, data_brush__extra_size;
4604         { /* path */
4605             uint32_t path__value;
4606             pos = (start2 + 0);
4607             if (SPICE_UNLIKELY(pos + 4 > message_end)) {
4608                 goto error;
4609             }
4610             path__value = read_uint32(pos);
4611             if (SPICE_UNLIKELY(path__value == 0)) {
4612                 goto error;
4613             }
4614             ptr_size = validate_SpicePath(message_start, message_end, path__value);
4615             if (SPICE_UNLIKELY(ptr_size < 0)) {
4616                 goto error;
4617             }
4618             data_path__extra_size = ptr_size + /* for alignment */ 3;
4619         }
4620 
4621         { /* attr */
4622             SPICE_GNUC_UNUSED uint8_t *start3 = (start2 + 4);
4623             uint64_t data_attr_u1__nw_size;
4624             uint8_t flags__value;
4625             uint64_t data_attr_u2__nw_size, data_attr_u2__extra_size;
4626             { /* u1 */
4627                 pos = start3 + 0;
4628                 if (SPICE_UNLIKELY(pos + 1 > message_end)) {
4629                     goto error;
4630                 }
4631                 flags__value = read_uint8(pos);
4632                 if ((flags__value & SPICE_LINE_FLAGS_STYLED)) {
4633                     data_attr_u1__nw_size = 1;
4634                 } else {
4635                     data_attr_u1__nw_size = 0;
4636                 }
4637 
4638             }
4639 
4640             { /* u2 */
4641                 uint64_t data_attr_u2__array__nelements;
4642                 pos = start3 + 0;
4643                 if (SPICE_UNLIKELY(pos + 1 > message_end)) {
4644                     goto error;
4645                 }
4646                 flags__value = read_uint8(pos);
4647                 if ((flags__value & SPICE_LINE_FLAGS_STYLED)) {
4648                     uint32_t data_attr_u2_style__value;
4649                     uint64_t data_attr_u2__array__nw_size;
4650                     uint64_t data_attr_u2__array__mem_size;
4651                     uint8_t style_nseg__value;
4652                     data_attr_u2__nw_size = 4;
4653                     pos = (start3 + 1 + data_attr_u1__nw_size);
4654                     if (SPICE_UNLIKELY(pos + 4 > message_end)) {
4655                         goto error;
4656                     }
4657                     data_attr_u2_style__value = read_uint32(pos);
4658                     if (SPICE_UNLIKELY(data_attr_u2_style__value >= (uintptr_t) (message_end - message_start))) {
4659                         goto error;
4660                     }
4661                     pos = start3 + 1;
4662                     if (SPICE_UNLIKELY(pos + 1 > message_end)) {
4663                         goto error;
4664                     }
4665                     style_nseg__value = read_uint8(pos);
4666                     data_attr_u2__array__nelements = style_nseg__value;
4667 
4668                     data_attr_u2__array__nw_size = (4) * data_attr_u2__array__nelements;
4669                     data_attr_u2__array__mem_size = sizeof(SPICE_FIXED28_4) * data_attr_u2__array__nelements;
4670                     if (SPICE_UNLIKELY(data_attr_u2_style__value + data_attr_u2__array__nw_size > (uintptr_t) (message_end - message_start))) {
4671                         goto error;
4672                     }
4673                     data_attr_u2__extra_size = data_attr_u2__array__mem_size + /* for alignment */ 3;
4674                 } else {
4675                     data_attr_u2__nw_size = 0;
4676                     data_attr_u2__extra_size = 0;
4677                 }
4678 
4679             }
4680 
4681             data_attr__nw_size = 1 + data_attr_u1__nw_size + data_attr_u2__nw_size;
4682             data_attr__extra_size = data_attr_u2__extra_size;
4683         }
4684 
4685         { /* brush */
4686             SPICE_GNUC_UNUSED uint8_t *start3 = (start2 + 4 + data_attr__nw_size);
4687             uint64_t data_brush_u__nw_size, data_brush_u__extra_size;
4688             uint8_t type__value;
4689             { /* u */
4690                 pos = start3 + 0;
4691                 if (SPICE_UNLIKELY(pos + 1 > message_end)) {
4692                     goto error;
4693                 }
4694                 type__value = read_uint8(pos);
4695                 if (type__value == SPICE_BRUSH_TYPE_SOLID) {
4696                     data_brush_u__nw_size = 4;
4697                     data_brush_u__extra_size = 0;
4698                 } else if (type__value == SPICE_BRUSH_TYPE_PATTERN) {
4699                     SPICE_GNUC_UNUSED uint8_t *start4 = (start3 + 1);
4700                     uint64_t data_brush_u_pat__extra_size;
4701                     { /* pat */
4702                         uint32_t pat__value;
4703                         pos = (start4 + 0);
4704                         if (SPICE_UNLIKELY(pos + 4 > message_end)) {
4705                             goto error;
4706                         }
4707                         pat__value = read_uint32(pos);
4708                         if (SPICE_UNLIKELY(pat__value == 0)) {
4709                             goto error;
4710                         }
4711                         ptr_size = validate_SpiceImage(message_start, message_end, pat__value);
4712                         if (SPICE_UNLIKELY(ptr_size < 0)) {
4713                             goto error;
4714                         }
4715                         data_brush_u_pat__extra_size = ptr_size + /* for alignment */ 3;
4716                     }
4717 
4718                     data_brush_u__nw_size = 12;
4719                     data_brush_u__extra_size = data_brush_u_pat__extra_size;
4720                 } else {
4721                     data_brush_u__nw_size = 0;
4722                     data_brush_u__extra_size = 0;
4723                 }
4724 
4725             }
4726 
4727             data_brush__nw_size = 1 + data_brush_u__nw_size;
4728             data_brush__extra_size = data_brush_u__extra_size;
4729         }
4730 
4731         data__nw_size = 8 + data_attr__nw_size + data_brush__nw_size;
4732         data__extra_size = data_path__extra_size + data_attr__extra_size + data_brush__extra_size;
4733     }
4734 
4735     nw_size = 0 + base__nw_size + data__nw_size;
4736     mem_size = sizeof(SpiceMsgDisplayDrawStroke) + base__extra_size + data__extra_size;
4737 
4738     /* Check if message fits in reported side */
4739     if (nw_size > (uintptr_t) (message_end - start)) {
4740         return NULL;
4741     }
4742 
4743     /* Validated extents and calculated size */
4744     data = (uint8_t *)(mem_size > UINT32_MAX ? NULL : malloc(mem_size));
4745     if (SPICE_UNLIKELY(data == NULL)) {
4746         goto error;
4747     }
4748     end = data + sizeof(SpiceMsgDisplayDrawStroke);
4749     in = start;
4750 
4751     out = (SpiceMsgDisplayDrawStroke *)data;
4752 
4753     /* base */ {
4754         out->base.surface_id = consume_uint32(&in);
4755         /* box */ {
4756             out->base.box.top = consume_int32(&in);
4757             out->base.box.left = consume_int32(&in);
4758             out->base.box.bottom = consume_int32(&in);
4759             out->base.box.right = consume_int32(&in);
4760         }
4761         /* clip */ {
4762             out->base.clip.type = consume_uint8(&in);
4763             if (out->base.clip.type == SPICE_CLIP_TYPE_RECTS) {
4764                 ptr_info[n_ptr].offset = in - start;
4765                 ptr_info[n_ptr].parse = parse_struct_SpiceClipRects;
4766                 ptr_info[n_ptr].dest = (void **)&out->base.clip.rects;
4767                 n_ptr++;
4768                 in += rects__saved_size;
4769             }
4770         }
4771     }
4772     /* data */ {
4773         ptr_info[n_ptr].offset = consume_uint32(&in);
4774         ptr_info[n_ptr].parse = parse_struct_SpicePath;
4775         ptr_info[n_ptr].dest = (void **)&out->data.path;
4776         n_ptr++;
4777         /* attr */ {
4778             out->data.attr.flags = consume_uint8(&in);
4779             if ((out->data.attr.flags & SPICE_LINE_FLAGS_STYLED)) {
4780                 out->data.attr.style_nseg = consume_uint8(&in);
4781             }
4782             if ((out->data.attr.flags & SPICE_LINE_FLAGS_STYLED)) {
4783                 uint64_t style__array__nelements;
4784                 ptr_info[n_ptr].offset = consume_uint32(&in);
4785                 ptr_info[n_ptr].parse = parse_array_int32;
4786                 ptr_info[n_ptr].dest = (void **)&out->data.attr.style;
4787                 style__array__nelements = out->data.attr.style_nseg;
4788                 ptr_info[n_ptr].nelements = style__array__nelements;
4789                 n_ptr++;
4790             }
4791         }
4792         /* brush */ {
4793             out->data.brush.type = consume_uint8(&in);
4794             if (out->data.brush.type == SPICE_BRUSH_TYPE_SOLID) {
4795                 out->data.brush.u.color = consume_uint32(&in);
4796             } else if (out->data.brush.type == SPICE_BRUSH_TYPE_PATTERN) {
4797                 ptr_info[n_ptr].offset = consume_uint32(&in);
4798                 ptr_info[n_ptr].parse = parse_struct_SpiceImage;
4799                 ptr_info[n_ptr].dest = (void **)&out->data.brush.u.pattern.pat;
4800                 n_ptr++;
4801                 /* pos */ {
4802                     out->data.brush.u.pattern.pos.x = consume_int32(&in);
4803                     out->data.brush.u.pattern.pos.y = consume_int32(&in);
4804                 }
4805             }
4806         }
4807         out->data.fore_mode = consume_uint16(&in);
4808         out->data.back_mode = consume_uint16(&in);
4809     }
4810 
4811     assert(in <= message_end);
4812 
4813     for (i = 0; i < n_ptr; i++) {
4814         if (ptr_info[i].offset == 0) {
4815             *ptr_info[i].dest = NULL;
4816         } else {
4817             /* Align to 32 bit */
4818             end = (uint8_t *)SPICE_ALIGN((uintptr_t)end, 4);
4819             *ptr_info[i].dest = (void *)end;
4820             end = ptr_info[i].parse(message_start, message_end, end, &ptr_info[i]);
4821             if (SPICE_UNLIKELY(end == NULL)) {
4822                 goto error;
4823             }
4824         }
4825     }
4826 
4827     assert(end <= data + mem_size);
4828 
4829     *size = end - data;
4830     *free_message = (message_destructor_t) free;
4831     return data;
4832 
4833    error:
4834     free(data);
4835     return NULL;
4836 }
4837 
validate_SpiceString(uint8_t * message_start,uint8_t * message_end,uint64_t offset)4838 static intptr_t validate_SpiceString(uint8_t *message_start, uint8_t *message_end, uint64_t offset)
4839 {
4840     uint8_t *start = message_start + offset;
4841     SPICE_GNUC_UNUSED uint8_t *pos;
4842     uint64_t mem_size, nw_size;
4843     uint64_t u__nw_size, u__extra_size;
4844     uint8_t flags__value;
4845     uint32_t i;
4846 
4847     if (offset == 0) {
4848         return 0;
4849     }
4850 
4851     if (SPICE_UNLIKELY(start >= message_end)) {
4852         goto error;
4853     }
4854 
4855     { /* u */
4856         uint64_t u__mem_size;
4857         uint64_t u__nelements;
4858         pos = start + 2;
4859         if (SPICE_UNLIKELY(pos + 1 > message_end)) {
4860             goto error;
4861         }
4862         flags__value = read_uint8(pos);
4863         if ((flags__value & SPICE_STRING_FLAGS_RASTER_A1)) {
4864             uint16_t length__value;
4865             uint8_t *start2 = (start + 3);
4866             uint64_t u__element__nw_size;
4867             uint64_t u__element__mem_size;
4868             pos = start + 0;
4869             if (SPICE_UNLIKELY(pos + 2 > message_end)) {
4870                 goto error;
4871             }
4872             length__value = read_uint16(pos);
4873             u__nelements = length__value;
4874 
4875             u__nw_size = 0;
4876             u__mem_size = 0;
4877             for (i = 0; i < u__nelements; i++) {
4878                 SPICE_GNUC_UNUSED uint8_t *start3 = start2;
4879                 uint64_t u__element_data__nw_size, u__element_data__mem_size;
4880                 uint64_t u__element_data__nelements;
4881                 { /* data */
4882                     uint16_t width__value;
4883                     uint16_t height__value;
4884                     pos = start3 + 16;
4885                     if (SPICE_UNLIKELY(pos + 2 > message_end)) {
4886                         goto error;
4887                     }
4888                     width__value = read_uint16(pos);
4889                     pos = start3 + 18;
4890                     if (SPICE_UNLIKELY(pos + 2 > message_end)) {
4891                         goto error;
4892                     }
4893                     height__value = read_uint16(pos);
4894                     u__element_data__nelements = (((uint64_t) width__value + 7U) / 8U ) * height__value;
4895 
4896                     u__element_data__nw_size = u__element_data__nelements;
4897                     u__element_data__mem_size = sizeof(uint8_t) * u__element_data__nelements;
4898                 }
4899 
4900                 u__element__nw_size = 20 + u__element_data__nw_size;
4901                 u__element__mem_size = sizeof(SpiceRasterGlyph) + u__element_data__mem_size;
4902                 u__nw_size += u__element__nw_size;
4903                 u__mem_size += sizeof(void *) + SPICE_ALIGN(u__element__mem_size, 4);
4904                 start2 += u__element__nw_size;
4905             }
4906             u__extra_size = u__mem_size;
4907         } else if ((flags__value & SPICE_STRING_FLAGS_RASTER_A4)) {
4908             uint16_t length__value;
4909             uint8_t *start2 = (start + 3);
4910             uint64_t u__element__nw_size;
4911             uint64_t u__element__mem_size;
4912             pos = start + 0;
4913             if (SPICE_UNLIKELY(pos + 2 > message_end)) {
4914                 goto error;
4915             }
4916             length__value = read_uint16(pos);
4917             u__nelements = length__value;
4918 
4919             u__nw_size = 0;
4920             u__mem_size = 0;
4921             for (i = 0; i < u__nelements; i++) {
4922                 SPICE_GNUC_UNUSED uint8_t *start3 = start2;
4923                 uint64_t u__element_data__nw_size, u__element_data__mem_size;
4924                 uint64_t u__element_data__nelements;
4925                 { /* data */
4926                     uint16_t width__value;
4927                     uint16_t height__value;
4928                     pos = start3 + 16;
4929                     if (SPICE_UNLIKELY(pos + 2 > message_end)) {
4930                         goto error;
4931                     }
4932                     width__value = read_uint16(pos);
4933                     pos = start3 + 18;
4934                     if (SPICE_UNLIKELY(pos + 2 > message_end)) {
4935                         goto error;
4936                     }
4937                     height__value = read_uint16(pos);
4938                     u__element_data__nelements = ((4U * (uint64_t) width__value + 7U) / 8U ) * height__value;
4939 
4940                     u__element_data__nw_size = u__element_data__nelements;
4941                     u__element_data__mem_size = sizeof(uint8_t) * u__element_data__nelements;
4942                 }
4943 
4944                 u__element__nw_size = 20 + u__element_data__nw_size;
4945                 u__element__mem_size = sizeof(SpiceRasterGlyph) + u__element_data__mem_size;
4946                 u__nw_size += u__element__nw_size;
4947                 u__mem_size += sizeof(void *) + SPICE_ALIGN(u__element__mem_size, 4);
4948                 start2 += u__element__nw_size;
4949             }
4950             u__extra_size = u__mem_size;
4951         } else if ((flags__value & SPICE_STRING_FLAGS_RASTER_A8)) {
4952             uint16_t length__value;
4953             uint8_t *start2 = (start + 3);
4954             uint64_t u__element__nw_size;
4955             uint64_t u__element__mem_size;
4956             pos = start + 0;
4957             if (SPICE_UNLIKELY(pos + 2 > message_end)) {
4958                 goto error;
4959             }
4960             length__value = read_uint16(pos);
4961             u__nelements = length__value;
4962 
4963             u__nw_size = 0;
4964             u__mem_size = 0;
4965             for (i = 0; i < u__nelements; i++) {
4966                 SPICE_GNUC_UNUSED uint8_t *start3 = start2;
4967                 uint64_t u__element_data__nw_size, u__element_data__mem_size;
4968                 uint64_t u__element_data__nelements;
4969                 { /* data */
4970                     uint16_t width__value;
4971                     uint16_t height__value;
4972                     pos = start3 + 16;
4973                     if (SPICE_UNLIKELY(pos + 2 > message_end)) {
4974                         goto error;
4975                     }
4976                     width__value = read_uint16(pos);
4977                     pos = start3 + 18;
4978                     if (SPICE_UNLIKELY(pos + 2 > message_end)) {
4979                         goto error;
4980                     }
4981                     height__value = read_uint16(pos);
4982                     u__element_data__nelements = (uint64_t) width__value * height__value;
4983 
4984                     u__element_data__nw_size = u__element_data__nelements;
4985                     u__element_data__mem_size = sizeof(uint8_t) * u__element_data__nelements;
4986                 }
4987 
4988                 u__element__nw_size = 20 + u__element_data__nw_size;
4989                 u__element__mem_size = sizeof(SpiceRasterGlyph) + u__element_data__mem_size;
4990                 u__nw_size += u__element__nw_size;
4991                 u__mem_size += sizeof(void *) + SPICE_ALIGN(u__element__mem_size, 4);
4992                 start2 += u__element__nw_size;
4993             }
4994             u__extra_size = u__mem_size;
4995         } else {
4996             u__nw_size = 0;
4997             u__extra_size = 0;
4998         }
4999 
5000     }
5001 
5002     nw_size = 3 + u__nw_size;
5003     mem_size = sizeof(SpiceString) + u__extra_size;
5004 
5005     /* Check if struct fits in reported side */
5006     if (SPICE_UNLIKELY(nw_size > (uintptr_t) (message_end - start))) {
5007         goto error;
5008     }
5009     return mem_size;
5010 
5011    error:
5012     return -1;
5013 }
5014 
parse_struct_SpiceString(uint8_t * message_start,SPICE_GNUC_UNUSED uint8_t * message_end,uint8_t * struct_data,PointerInfo * this_ptr_info)5015 static uint8_t * parse_struct_SpiceString(uint8_t *message_start, SPICE_GNUC_UNUSED uint8_t *message_end, uint8_t *struct_data, PointerInfo *this_ptr_info)
5016 {
5017     uint8_t *in = message_start + this_ptr_info->offset;
5018     uint8_t *end;
5019     SpiceString *out;
5020     uint32_t i;
5021 
5022     end = struct_data + sizeof(SpiceString);
5023     out = (SpiceString *)struct_data;
5024 
5025     out->length = consume_uint16(&in);
5026     out->flags = consume_uint8(&in);
5027     if ((out->flags & SPICE_STRING_FLAGS_RASTER_A1)) {
5028         uint64_t glyphs__nelements;
5029         void * *ptr_array;
5030         int ptr_array_index;
5031         glyphs__nelements = out->length;
5032         ptr_array_index = 0;
5033         ptr_array = (void **)out->glyphs;
5034         end += sizeof(void *) * glyphs__nelements;
5035         for (i = 0; i < glyphs__nelements; i++) {
5036             SpiceRasterGlyph *out2;
5037             uint64_t data__nelements;
5038             ptr_array[ptr_array_index++] = end;
5039             out2 = (SpiceRasterGlyph *)end;
5040             end += sizeof(SpiceRasterGlyph);
5041 
5042             /* render_pos */ {
5043                 out2->render_pos.x = consume_int32(&in);
5044                 out2->render_pos.y = consume_int32(&in);
5045             }
5046             /* glyph_origin */ {
5047                 out2->glyph_origin.x = consume_int32(&in);
5048                 out2->glyph_origin.y = consume_int32(&in);
5049             }
5050             out2->width = consume_uint16(&in);
5051             out2->height = consume_uint16(&in);
5052             data__nelements = (((uint64_t) out2->width + 7U) / 8U ) * out2->height;
5053             memcpy(out2->data, in, data__nelements);
5054             in += data__nelements;
5055             end += data__nelements;
5056             /* Align ptr_array element to 4 bytes */
5057             end = (uint8_t *)SPICE_ALIGN((uintptr_t)end, 4);
5058         }
5059     } else if ((out->flags & SPICE_STRING_FLAGS_RASTER_A4)) {
5060         uint64_t glyphs__nelements;
5061         void * *ptr_array;
5062         int ptr_array_index;
5063         glyphs__nelements = out->length;
5064         ptr_array_index = 0;
5065         ptr_array = (void **)out->glyphs;
5066         end += sizeof(void *) * glyphs__nelements;
5067         for (i = 0; i < glyphs__nelements; i++) {
5068             SpiceRasterGlyph *out2;
5069             uint64_t data__nelements;
5070             ptr_array[ptr_array_index++] = end;
5071             out2 = (SpiceRasterGlyph *)end;
5072             end += sizeof(SpiceRasterGlyph);
5073 
5074             /* render_pos */ {
5075                 out2->render_pos.x = consume_int32(&in);
5076                 out2->render_pos.y = consume_int32(&in);
5077             }
5078             /* glyph_origin */ {
5079                 out2->glyph_origin.x = consume_int32(&in);
5080                 out2->glyph_origin.y = consume_int32(&in);
5081             }
5082             out2->width = consume_uint16(&in);
5083             out2->height = consume_uint16(&in);
5084             data__nelements = ((4U * (uint64_t) out2->width + 7U) / 8U ) * out2->height;
5085             memcpy(out2->data, in, data__nelements);
5086             in += data__nelements;
5087             end += data__nelements;
5088             /* Align ptr_array element to 4 bytes */
5089             end = (uint8_t *)SPICE_ALIGN((uintptr_t)end, 4);
5090         }
5091     } else if ((out->flags & SPICE_STRING_FLAGS_RASTER_A8)) {
5092         uint64_t glyphs__nelements;
5093         void * *ptr_array;
5094         int ptr_array_index;
5095         glyphs__nelements = out->length;
5096         ptr_array_index = 0;
5097         ptr_array = (void **)out->glyphs;
5098         end += sizeof(void *) * glyphs__nelements;
5099         for (i = 0; i < glyphs__nelements; i++) {
5100             SpiceRasterGlyph *out2;
5101             uint64_t data__nelements;
5102             ptr_array[ptr_array_index++] = end;
5103             out2 = (SpiceRasterGlyph *)end;
5104             end += sizeof(SpiceRasterGlyph);
5105 
5106             /* render_pos */ {
5107                 out2->render_pos.x = consume_int32(&in);
5108                 out2->render_pos.y = consume_int32(&in);
5109             }
5110             /* glyph_origin */ {
5111                 out2->glyph_origin.x = consume_int32(&in);
5112                 out2->glyph_origin.y = consume_int32(&in);
5113             }
5114             out2->width = consume_uint16(&in);
5115             out2->height = consume_uint16(&in);
5116             data__nelements = ((uint64_t) out2->width * out2->height);
5117             memcpy(out2->data, in, data__nelements);
5118             in += data__nelements;
5119             end += data__nelements;
5120             /* Align ptr_array element to 4 bytes */
5121             end = (uint8_t *)SPICE_ALIGN((uintptr_t)end, 4);
5122         }
5123     }
5124     return end;
5125 }
5126 
parse_msg_display_draw_text(uint8_t * message_start,uint8_t * message_end,size_t * size,message_destructor_t * free_message)5127 static uint8_t * parse_msg_display_draw_text(uint8_t *message_start, uint8_t *message_end, size_t *size, message_destructor_t *free_message)
5128 {
5129     SPICE_GNUC_UNUSED uint8_t *pos;
5130     uint8_t *start = message_start;
5131     uint8_t *data = NULL;
5132     uint64_t nw_size;
5133     uint64_t mem_size;
5134     uint8_t *in, *end;
5135     SPICE_GNUC_UNUSED intptr_t ptr_size;
5136     uint32_t n_ptr=0;
5137     PointerInfo ptr_info[4];
5138     uint64_t base__nw_size, base__extra_size;
5139     uint32_t rects__saved_size = 0;
5140     uint64_t data__nw_size, data__extra_size;
5141     SpiceMsgDisplayDrawText *out;
5142     uint32_t i;
5143 
5144     { /* base */
5145         SPICE_GNUC_UNUSED uint8_t *start2 = (start + 0);
5146         uint64_t base_clip__nw_size, base_clip__extra_size;
5147         { /* clip */
5148             SPICE_GNUC_UNUSED uint8_t *start3 = (start2 + 20);
5149             uint64_t base_clip_u__nw_size, base_clip_u__extra_size;
5150             uint8_t type__value;
5151             { /* u */
5152                 uint64_t base_clip_u__mem_size;
5153                 pos = start3 + 0;
5154                 if (SPICE_UNLIKELY(pos + 1 > message_end)) {
5155                     goto error;
5156                 }
5157                 type__value = read_uint8(pos);
5158                 if (type__value == SPICE_CLIP_TYPE_RECTS) {
5159                     SPICE_GNUC_UNUSED uint8_t *start4 = (start3 + 1);
5160                     uint64_t base_clip_u_rects__nw_size, base_clip_u_rects__mem_size;
5161                     uint64_t base_clip_u_rects__nelements;
5162                     { /* rects */
5163                         uint32_t num_rects__value;
5164                         pos = start4 + 0;
5165                         if (SPICE_UNLIKELY(pos + 4 > message_end)) {
5166                             goto error;
5167                         }
5168                         num_rects__value = read_uint32(pos);
5169                         base_clip_u_rects__nelements = num_rects__value;
5170 
5171                         base_clip_u_rects__nw_size = (16) * base_clip_u_rects__nelements;
5172                         base_clip_u_rects__mem_size = sizeof(SpiceRect) * base_clip_u_rects__nelements;
5173                     }
5174 
5175                     base_clip_u__nw_size = 4 + base_clip_u_rects__nw_size;
5176                     base_clip_u__mem_size = sizeof(SpiceClipRects) + base_clip_u_rects__mem_size;
5177                     rects__saved_size = base_clip_u__nw_size;
5178                     base_clip_u__extra_size = base_clip_u__mem_size;
5179                 } else {
5180                     base_clip_u__nw_size = 0;
5181                     base_clip_u__extra_size = 0;
5182                 }
5183 
5184             }
5185 
5186             base_clip__nw_size = 1 + base_clip_u__nw_size;
5187             base_clip__extra_size = base_clip_u__extra_size;
5188         }
5189 
5190         base__nw_size = 20 + base_clip__nw_size;
5191         base__extra_size = base_clip__extra_size;
5192     }
5193 
5194     { /* data */
5195         SPICE_GNUC_UNUSED uint8_t *start2 = (start + 0 + base__nw_size);
5196         uint64_t data_str__extra_size;
5197         uint64_t data_fore_brush__nw_size, data_fore_brush__extra_size;
5198         uint64_t data_back_brush__nw_size, data_back_brush__extra_size;
5199         { /* str */
5200             uint32_t str__value;
5201             pos = (start2 + 0);
5202             if (SPICE_UNLIKELY(pos + 4 > message_end)) {
5203                 goto error;
5204             }
5205             str__value = read_uint32(pos);
5206             if (SPICE_UNLIKELY(str__value == 0)) {
5207                 goto error;
5208             }
5209             ptr_size = validate_SpiceString(message_start, message_end, str__value);
5210             if (SPICE_UNLIKELY(ptr_size < 0)) {
5211                 goto error;
5212             }
5213             data_str__extra_size = ptr_size + /* for alignment */ 3;
5214         }
5215 
5216         { /* fore_brush */
5217             SPICE_GNUC_UNUSED uint8_t *start3 = (start2 + 20);
5218             uint64_t data_fore_brush_u__nw_size, data_fore_brush_u__extra_size;
5219             uint8_t type__value;
5220             { /* u */
5221                 pos = start3 + 0;
5222                 if (SPICE_UNLIKELY(pos + 1 > message_end)) {
5223                     goto error;
5224                 }
5225                 type__value = read_uint8(pos);
5226                 if (type__value == SPICE_BRUSH_TYPE_SOLID) {
5227                     data_fore_brush_u__nw_size = 4;
5228                     data_fore_brush_u__extra_size = 0;
5229                 } else if (type__value == SPICE_BRUSH_TYPE_PATTERN) {
5230                     SPICE_GNUC_UNUSED uint8_t *start4 = (start3 + 1);
5231                     uint64_t data_fore_brush_u_pat__extra_size;
5232                     { /* pat */
5233                         uint32_t pat__value;
5234                         pos = (start4 + 0);
5235                         if (SPICE_UNLIKELY(pos + 4 > message_end)) {
5236                             goto error;
5237                         }
5238                         pat__value = read_uint32(pos);
5239                         if (SPICE_UNLIKELY(pat__value == 0)) {
5240                             goto error;
5241                         }
5242                         ptr_size = validate_SpiceImage(message_start, message_end, pat__value);
5243                         if (SPICE_UNLIKELY(ptr_size < 0)) {
5244                             goto error;
5245                         }
5246                         data_fore_brush_u_pat__extra_size = ptr_size + /* for alignment */ 3;
5247                     }
5248 
5249                     data_fore_brush_u__nw_size = 12;
5250                     data_fore_brush_u__extra_size = data_fore_brush_u_pat__extra_size;
5251                 } else {
5252                     data_fore_brush_u__nw_size = 0;
5253                     data_fore_brush_u__extra_size = 0;
5254                 }
5255 
5256             }
5257 
5258             data_fore_brush__nw_size = 1 + data_fore_brush_u__nw_size;
5259             data_fore_brush__extra_size = data_fore_brush_u__extra_size;
5260         }
5261 
5262         { /* back_brush */
5263             SPICE_GNUC_UNUSED uint8_t *start3 = (start2 + 20 + data_fore_brush__nw_size);
5264             uint64_t data_back_brush_u__nw_size, data_back_brush_u__extra_size;
5265             uint8_t type__value;
5266             { /* u */
5267                 pos = start3 + 0;
5268                 if (SPICE_UNLIKELY(pos + 1 > message_end)) {
5269                     goto error;
5270                 }
5271                 type__value = read_uint8(pos);
5272                 if (type__value == SPICE_BRUSH_TYPE_SOLID) {
5273                     data_back_brush_u__nw_size = 4;
5274                     data_back_brush_u__extra_size = 0;
5275                 } else if (type__value == SPICE_BRUSH_TYPE_PATTERN) {
5276                     SPICE_GNUC_UNUSED uint8_t *start4 = (start3 + 1);
5277                     uint64_t data_back_brush_u_pat__extra_size;
5278                     { /* pat */
5279                         uint32_t pat__value;
5280                         pos = (start4 + 0);
5281                         if (SPICE_UNLIKELY(pos + 4 > message_end)) {
5282                             goto error;
5283                         }
5284                         pat__value = read_uint32(pos);
5285                         if (SPICE_UNLIKELY(pat__value == 0)) {
5286                             goto error;
5287                         }
5288                         ptr_size = validate_SpiceImage(message_start, message_end, pat__value);
5289                         if (SPICE_UNLIKELY(ptr_size < 0)) {
5290                             goto error;
5291                         }
5292                         data_back_brush_u_pat__extra_size = ptr_size + /* for alignment */ 3;
5293                     }
5294 
5295                     data_back_brush_u__nw_size = 12;
5296                     data_back_brush_u__extra_size = data_back_brush_u_pat__extra_size;
5297                 } else {
5298                     data_back_brush_u__nw_size = 0;
5299                     data_back_brush_u__extra_size = 0;
5300                 }
5301 
5302             }
5303 
5304             data_back_brush__nw_size = 1 + data_back_brush_u__nw_size;
5305             data_back_brush__extra_size = data_back_brush_u__extra_size;
5306         }
5307 
5308         data__nw_size = 24 + data_fore_brush__nw_size + data_back_brush__nw_size;
5309         data__extra_size = data_str__extra_size + data_fore_brush__extra_size + data_back_brush__extra_size;
5310     }
5311 
5312     nw_size = 0 + base__nw_size + data__nw_size;
5313     mem_size = sizeof(SpiceMsgDisplayDrawText) + base__extra_size + data__extra_size;
5314 
5315     /* Check if message fits in reported side */
5316     if (nw_size > (uintptr_t) (message_end - start)) {
5317         return NULL;
5318     }
5319 
5320     /* Validated extents and calculated size */
5321     data = (uint8_t *)(mem_size > UINT32_MAX ? NULL : malloc(mem_size));
5322     if (SPICE_UNLIKELY(data == NULL)) {
5323         goto error;
5324     }
5325     end = data + sizeof(SpiceMsgDisplayDrawText);
5326     in = start;
5327 
5328     out = (SpiceMsgDisplayDrawText *)data;
5329 
5330     /* base */ {
5331         out->base.surface_id = consume_uint32(&in);
5332         /* box */ {
5333             out->base.box.top = consume_int32(&in);
5334             out->base.box.left = consume_int32(&in);
5335             out->base.box.bottom = consume_int32(&in);
5336             out->base.box.right = consume_int32(&in);
5337         }
5338         /* clip */ {
5339             out->base.clip.type = consume_uint8(&in);
5340             if (out->base.clip.type == SPICE_CLIP_TYPE_RECTS) {
5341                 ptr_info[n_ptr].offset = in - start;
5342                 ptr_info[n_ptr].parse = parse_struct_SpiceClipRects;
5343                 ptr_info[n_ptr].dest = (void **)&out->base.clip.rects;
5344                 n_ptr++;
5345                 in += rects__saved_size;
5346             }
5347         }
5348     }
5349     /* data */ {
5350         ptr_info[n_ptr].offset = consume_uint32(&in);
5351         ptr_info[n_ptr].parse = parse_struct_SpiceString;
5352         ptr_info[n_ptr].dest = (void **)&out->data.str;
5353         n_ptr++;
5354         /* back_area */ {
5355             out->data.back_area.top = consume_int32(&in);
5356             out->data.back_area.left = consume_int32(&in);
5357             out->data.back_area.bottom = consume_int32(&in);
5358             out->data.back_area.right = consume_int32(&in);
5359         }
5360         /* fore_brush */ {
5361             out->data.fore_brush.type = consume_uint8(&in);
5362             if (out->data.fore_brush.type == SPICE_BRUSH_TYPE_SOLID) {
5363                 out->data.fore_brush.u.color = consume_uint32(&in);
5364             } else if (out->data.fore_brush.type == SPICE_BRUSH_TYPE_PATTERN) {
5365                 ptr_info[n_ptr].offset = consume_uint32(&in);
5366                 ptr_info[n_ptr].parse = parse_struct_SpiceImage;
5367                 ptr_info[n_ptr].dest = (void **)&out->data.fore_brush.u.pattern.pat;
5368                 n_ptr++;
5369                 /* pos */ {
5370                     out->data.fore_brush.u.pattern.pos.x = consume_int32(&in);
5371                     out->data.fore_brush.u.pattern.pos.y = consume_int32(&in);
5372                 }
5373             }
5374         }
5375         /* back_brush */ {
5376             out->data.back_brush.type = consume_uint8(&in);
5377             if (out->data.back_brush.type == SPICE_BRUSH_TYPE_SOLID) {
5378                 out->data.back_brush.u.color = consume_uint32(&in);
5379             } else if (out->data.back_brush.type == SPICE_BRUSH_TYPE_PATTERN) {
5380                 ptr_info[n_ptr].offset = consume_uint32(&in);
5381                 ptr_info[n_ptr].parse = parse_struct_SpiceImage;
5382                 ptr_info[n_ptr].dest = (void **)&out->data.back_brush.u.pattern.pat;
5383                 n_ptr++;
5384                 /* pos */ {
5385                     out->data.back_brush.u.pattern.pos.x = consume_int32(&in);
5386                     out->data.back_brush.u.pattern.pos.y = consume_int32(&in);
5387                 }
5388             }
5389         }
5390         out->data.fore_mode = consume_uint16(&in);
5391         out->data.back_mode = consume_uint16(&in);
5392     }
5393 
5394     assert(in <= message_end);
5395 
5396     for (i = 0; i < n_ptr; i++) {
5397         if (ptr_info[i].offset == 0) {
5398             *ptr_info[i].dest = NULL;
5399         } else {
5400             /* Align to 32 bit */
5401             end = (uint8_t *)SPICE_ALIGN((uintptr_t)end, 4);
5402             *ptr_info[i].dest = (void *)end;
5403             end = ptr_info[i].parse(message_start, message_end, end, &ptr_info[i]);
5404             if (SPICE_UNLIKELY(end == NULL)) {
5405                 goto error;
5406             }
5407         }
5408     }
5409 
5410     assert(end <= data + mem_size);
5411 
5412     *size = end - data;
5413     *free_message = (message_destructor_t) free;
5414     return data;
5415 
5416    error:
5417     free(data);
5418     return NULL;
5419 }
5420 
parse_msg_display_draw_transparent(uint8_t * message_start,uint8_t * message_end,size_t * size,message_destructor_t * free_message)5421 static uint8_t * parse_msg_display_draw_transparent(uint8_t *message_start, uint8_t *message_end, size_t *size, message_destructor_t *free_message)
5422 {
5423     SPICE_GNUC_UNUSED uint8_t *pos;
5424     uint8_t *start = message_start;
5425     uint8_t *data = NULL;
5426     uint64_t nw_size;
5427     uint64_t mem_size;
5428     uint8_t *in, *end;
5429     SPICE_GNUC_UNUSED intptr_t ptr_size;
5430     uint32_t n_ptr=0;
5431     PointerInfo ptr_info[2];
5432     uint64_t base__nw_size, base__extra_size;
5433     uint32_t rects__saved_size = 0;
5434     uint64_t data__extra_size;
5435     SpiceMsgDisplayDrawTransparent *out;
5436     uint32_t i;
5437 
5438     { /* base */
5439         SPICE_GNUC_UNUSED uint8_t *start2 = (start + 0);
5440         uint64_t base_clip__nw_size, base_clip__extra_size;
5441         { /* clip */
5442             SPICE_GNUC_UNUSED uint8_t *start3 = (start2 + 20);
5443             uint64_t base_clip_u__nw_size, base_clip_u__extra_size;
5444             uint8_t type__value;
5445             { /* u */
5446                 uint64_t base_clip_u__mem_size;
5447                 pos = start3 + 0;
5448                 if (SPICE_UNLIKELY(pos + 1 > message_end)) {
5449                     goto error;
5450                 }
5451                 type__value = read_uint8(pos);
5452                 if (type__value == SPICE_CLIP_TYPE_RECTS) {
5453                     SPICE_GNUC_UNUSED uint8_t *start4 = (start3 + 1);
5454                     uint64_t base_clip_u_rects__nw_size, base_clip_u_rects__mem_size;
5455                     uint64_t base_clip_u_rects__nelements;
5456                     { /* rects */
5457                         uint32_t num_rects__value;
5458                         pos = start4 + 0;
5459                         if (SPICE_UNLIKELY(pos + 4 > message_end)) {
5460                             goto error;
5461                         }
5462                         num_rects__value = read_uint32(pos);
5463                         base_clip_u_rects__nelements = num_rects__value;
5464 
5465                         base_clip_u_rects__nw_size = (16) * base_clip_u_rects__nelements;
5466                         base_clip_u_rects__mem_size = sizeof(SpiceRect) * base_clip_u_rects__nelements;
5467                     }
5468 
5469                     base_clip_u__nw_size = 4 + base_clip_u_rects__nw_size;
5470                     base_clip_u__mem_size = sizeof(SpiceClipRects) + base_clip_u_rects__mem_size;
5471                     rects__saved_size = base_clip_u__nw_size;
5472                     base_clip_u__extra_size = base_clip_u__mem_size;
5473                 } else {
5474                     base_clip_u__nw_size = 0;
5475                     base_clip_u__extra_size = 0;
5476                 }
5477 
5478             }
5479 
5480             base_clip__nw_size = 1 + base_clip_u__nw_size;
5481             base_clip__extra_size = base_clip_u__extra_size;
5482         }
5483 
5484         base__nw_size = 20 + base_clip__nw_size;
5485         base__extra_size = base_clip__extra_size;
5486     }
5487 
5488     { /* data */
5489         SPICE_GNUC_UNUSED uint8_t *start2 = (start + 0 + base__nw_size);
5490         uint64_t data_src_bitmap__extra_size;
5491         { /* src_bitmap */
5492             uint32_t src_bitmap__value;
5493             pos = (start2 + 0);
5494             if (SPICE_UNLIKELY(pos + 4 > message_end)) {
5495                 goto error;
5496             }
5497             src_bitmap__value = read_uint32(pos);
5498             ptr_size = validate_SpiceImage(message_start, message_end, src_bitmap__value);
5499             if (SPICE_UNLIKELY(ptr_size < 0)) {
5500                 goto error;
5501             }
5502             data_src_bitmap__extra_size = ptr_size + /* for alignment */ 3;
5503         }
5504 
5505         data__extra_size = data_src_bitmap__extra_size;
5506     }
5507 
5508     nw_size = 28 + base__nw_size;
5509     mem_size = sizeof(SpiceMsgDisplayDrawTransparent) + base__extra_size + data__extra_size;
5510 
5511     /* Check if message fits in reported side */
5512     if (nw_size > (uintptr_t) (message_end - start)) {
5513         return NULL;
5514     }
5515 
5516     /* Validated extents and calculated size */
5517     data = (uint8_t *)(mem_size > UINT32_MAX ? NULL : malloc(mem_size));
5518     if (SPICE_UNLIKELY(data == NULL)) {
5519         goto error;
5520     }
5521     end = data + sizeof(SpiceMsgDisplayDrawTransparent);
5522     in = start;
5523 
5524     out = (SpiceMsgDisplayDrawTransparent *)data;
5525 
5526     /* base */ {
5527         out->base.surface_id = consume_uint32(&in);
5528         /* box */ {
5529             out->base.box.top = consume_int32(&in);
5530             out->base.box.left = consume_int32(&in);
5531             out->base.box.bottom = consume_int32(&in);
5532             out->base.box.right = consume_int32(&in);
5533         }
5534         /* clip */ {
5535             out->base.clip.type = consume_uint8(&in);
5536             if (out->base.clip.type == SPICE_CLIP_TYPE_RECTS) {
5537                 ptr_info[n_ptr].offset = in - start;
5538                 ptr_info[n_ptr].parse = parse_struct_SpiceClipRects;
5539                 ptr_info[n_ptr].dest = (void **)&out->base.clip.rects;
5540                 n_ptr++;
5541                 in += rects__saved_size;
5542             }
5543         }
5544     }
5545     /* data */ {
5546         ptr_info[n_ptr].offset = consume_uint32(&in);
5547         ptr_info[n_ptr].parse = parse_struct_SpiceImage;
5548         ptr_info[n_ptr].dest = (void **)&out->data.src_bitmap;
5549         n_ptr++;
5550         /* src_area */ {
5551             out->data.src_area.top = consume_int32(&in);
5552             out->data.src_area.left = consume_int32(&in);
5553             out->data.src_area.bottom = consume_int32(&in);
5554             out->data.src_area.right = consume_int32(&in);
5555         }
5556         out->data.src_color = consume_uint32(&in);
5557         out->data.true_color = consume_uint32(&in);
5558     }
5559 
5560     assert(in <= message_end);
5561 
5562     for (i = 0; i < n_ptr; i++) {
5563         if (ptr_info[i].offset == 0) {
5564             *ptr_info[i].dest = NULL;
5565         } else {
5566             /* Align to 32 bit */
5567             end = (uint8_t *)SPICE_ALIGN((uintptr_t)end, 4);
5568             *ptr_info[i].dest = (void *)end;
5569             end = ptr_info[i].parse(message_start, message_end, end, &ptr_info[i]);
5570             if (SPICE_UNLIKELY(end == NULL)) {
5571                 goto error;
5572             }
5573         }
5574     }
5575 
5576     assert(end <= data + mem_size);
5577 
5578     *size = end - data;
5579     *free_message = (message_destructor_t) free;
5580     return data;
5581 
5582    error:
5583     free(data);
5584     return NULL;
5585 }
5586 
parse_msg_display_draw_alpha_blend(uint8_t * message_start,uint8_t * message_end,size_t * size,message_destructor_t * free_message)5587 static uint8_t * parse_msg_display_draw_alpha_blend(uint8_t *message_start, uint8_t *message_end, size_t *size, message_destructor_t *free_message)
5588 {
5589     SPICE_GNUC_UNUSED uint8_t *pos;
5590     uint8_t *start = message_start;
5591     uint8_t *data = NULL;
5592     uint64_t nw_size;
5593     uint64_t mem_size;
5594     uint8_t *in, *end;
5595     SPICE_GNUC_UNUSED intptr_t ptr_size;
5596     uint32_t n_ptr=0;
5597     PointerInfo ptr_info[2];
5598     uint64_t base__nw_size, base__extra_size;
5599     uint32_t rects__saved_size = 0;
5600     uint64_t data__extra_size;
5601     SpiceMsgDisplayDrawAlphaBlend *out;
5602     uint32_t i;
5603 
5604     { /* base */
5605         SPICE_GNUC_UNUSED uint8_t *start2 = (start + 0);
5606         uint64_t base_clip__nw_size, base_clip__extra_size;
5607         { /* clip */
5608             SPICE_GNUC_UNUSED uint8_t *start3 = (start2 + 20);
5609             uint64_t base_clip_u__nw_size, base_clip_u__extra_size;
5610             uint8_t type__value;
5611             { /* u */
5612                 uint64_t base_clip_u__mem_size;
5613                 pos = start3 + 0;
5614                 if (SPICE_UNLIKELY(pos + 1 > message_end)) {
5615                     goto error;
5616                 }
5617                 type__value = read_uint8(pos);
5618                 if (type__value == SPICE_CLIP_TYPE_RECTS) {
5619                     SPICE_GNUC_UNUSED uint8_t *start4 = (start3 + 1);
5620                     uint64_t base_clip_u_rects__nw_size, base_clip_u_rects__mem_size;
5621                     uint64_t base_clip_u_rects__nelements;
5622                     { /* rects */
5623                         uint32_t num_rects__value;
5624                         pos = start4 + 0;
5625                         if (SPICE_UNLIKELY(pos + 4 > message_end)) {
5626                             goto error;
5627                         }
5628                         num_rects__value = read_uint32(pos);
5629                         base_clip_u_rects__nelements = num_rects__value;
5630 
5631                         base_clip_u_rects__nw_size = (16) * base_clip_u_rects__nelements;
5632                         base_clip_u_rects__mem_size = sizeof(SpiceRect) * base_clip_u_rects__nelements;
5633                     }
5634 
5635                     base_clip_u__nw_size = 4 + base_clip_u_rects__nw_size;
5636                     base_clip_u__mem_size = sizeof(SpiceClipRects) + base_clip_u_rects__mem_size;
5637                     rects__saved_size = base_clip_u__nw_size;
5638                     base_clip_u__extra_size = base_clip_u__mem_size;
5639                 } else {
5640                     base_clip_u__nw_size = 0;
5641                     base_clip_u__extra_size = 0;
5642                 }
5643 
5644             }
5645 
5646             base_clip__nw_size = 1 + base_clip_u__nw_size;
5647             base_clip__extra_size = base_clip_u__extra_size;
5648         }
5649 
5650         base__nw_size = 20 + base_clip__nw_size;
5651         base__extra_size = base_clip__extra_size;
5652     }
5653 
5654     { /* data */
5655         SPICE_GNUC_UNUSED uint8_t *start2 = (start + 0 + base__nw_size);
5656         uint64_t data_src_bitmap__extra_size;
5657         { /* src_bitmap */
5658             uint32_t src_bitmap__value;
5659             pos = (start2 + 2);
5660             if (SPICE_UNLIKELY(pos + 4 > message_end)) {
5661                 goto error;
5662             }
5663             src_bitmap__value = read_uint32(pos);
5664             ptr_size = validate_SpiceImage(message_start, message_end, src_bitmap__value);
5665             if (SPICE_UNLIKELY(ptr_size < 0)) {
5666                 goto error;
5667             }
5668             data_src_bitmap__extra_size = ptr_size + /* for alignment */ 3;
5669         }
5670 
5671         data__extra_size = data_src_bitmap__extra_size;
5672     }
5673 
5674     nw_size = 22 + base__nw_size;
5675     mem_size = sizeof(SpiceMsgDisplayDrawAlphaBlend) + base__extra_size + data__extra_size;
5676 
5677     /* Check if message fits in reported side */
5678     if (nw_size > (uintptr_t) (message_end - start)) {
5679         return NULL;
5680     }
5681 
5682     /* Validated extents and calculated size */
5683     data = (uint8_t *)(mem_size > UINT32_MAX ? NULL : malloc(mem_size));
5684     if (SPICE_UNLIKELY(data == NULL)) {
5685         goto error;
5686     }
5687     end = data + sizeof(SpiceMsgDisplayDrawAlphaBlend);
5688     in = start;
5689 
5690     out = (SpiceMsgDisplayDrawAlphaBlend *)data;
5691 
5692     /* base */ {
5693         out->base.surface_id = consume_uint32(&in);
5694         /* box */ {
5695             out->base.box.top = consume_int32(&in);
5696             out->base.box.left = consume_int32(&in);
5697             out->base.box.bottom = consume_int32(&in);
5698             out->base.box.right = consume_int32(&in);
5699         }
5700         /* clip */ {
5701             out->base.clip.type = consume_uint8(&in);
5702             if (out->base.clip.type == SPICE_CLIP_TYPE_RECTS) {
5703                 ptr_info[n_ptr].offset = in - start;
5704                 ptr_info[n_ptr].parse = parse_struct_SpiceClipRects;
5705                 ptr_info[n_ptr].dest = (void **)&out->base.clip.rects;
5706                 n_ptr++;
5707                 in += rects__saved_size;
5708             }
5709         }
5710     }
5711     /* data */ {
5712         out->data.alpha_flags = consume_uint8(&in);
5713         out->data.alpha = consume_uint8(&in);
5714         ptr_info[n_ptr].offset = consume_uint32(&in);
5715         ptr_info[n_ptr].parse = parse_struct_SpiceImage;
5716         ptr_info[n_ptr].dest = (void **)&out->data.src_bitmap;
5717         n_ptr++;
5718         /* src_area */ {
5719             out->data.src_area.top = consume_int32(&in);
5720             out->data.src_area.left = consume_int32(&in);
5721             out->data.src_area.bottom = consume_int32(&in);
5722             out->data.src_area.right = consume_int32(&in);
5723         }
5724     }
5725 
5726     assert(in <= message_end);
5727 
5728     for (i = 0; i < n_ptr; i++) {
5729         if (ptr_info[i].offset == 0) {
5730             *ptr_info[i].dest = NULL;
5731         } else {
5732             /* Align to 32 bit */
5733             end = (uint8_t *)SPICE_ALIGN((uintptr_t)end, 4);
5734             *ptr_info[i].dest = (void *)end;
5735             end = ptr_info[i].parse(message_start, message_end, end, &ptr_info[i]);
5736             if (SPICE_UNLIKELY(end == NULL)) {
5737                 goto error;
5738             }
5739         }
5740     }
5741 
5742     assert(end <= data + mem_size);
5743 
5744     *size = end - data;
5745     *free_message = (message_destructor_t) free;
5746     return data;
5747 
5748    error:
5749     free(data);
5750     return NULL;
5751 }
5752 
parse_msg_display_surface_create(uint8_t * message_start,uint8_t * message_end,size_t * size,message_destructor_t * free_message)5753 static uint8_t * parse_msg_display_surface_create(uint8_t *message_start, uint8_t *message_end, size_t *size, message_destructor_t *free_message)
5754 {
5755     SPICE_GNUC_UNUSED uint8_t *pos;
5756     uint8_t *start = message_start;
5757     uint8_t *data = NULL;
5758     uint64_t nw_size;
5759     uint64_t mem_size;
5760     uint8_t *in, *end;
5761     SpiceMsgSurfaceCreate *out;
5762 
5763     nw_size = 20;
5764     mem_size = sizeof(SpiceMsgSurfaceCreate);
5765 
5766     /* Check if message fits in reported side */
5767     if (nw_size > (uintptr_t) (message_end - start)) {
5768         return NULL;
5769     }
5770 
5771     /* Validated extents and calculated size */
5772     data = (uint8_t *)(mem_size > UINT32_MAX ? NULL : malloc(mem_size));
5773     if (SPICE_UNLIKELY(data == NULL)) {
5774         goto error;
5775     }
5776     end = data + sizeof(SpiceMsgSurfaceCreate);
5777     in = start;
5778 
5779     out = (SpiceMsgSurfaceCreate *)data;
5780 
5781     out->surface_id = consume_uint32(&in);
5782     out->width = consume_uint32(&in);
5783     out->height = consume_uint32(&in);
5784     out->format = consume_uint32(&in);
5785     out->flags = consume_uint32(&in);
5786 
5787     assert(in <= message_end);
5788     assert(end <= data + mem_size);
5789 
5790     *size = end - data;
5791     *free_message = (message_destructor_t) free;
5792     return data;
5793 
5794    error:
5795     free(data);
5796     return NULL;
5797 }
5798 
parse_msg_display_surface_destroy(uint8_t * message_start,uint8_t * message_end,size_t * size,message_destructor_t * free_message)5799 static uint8_t * parse_msg_display_surface_destroy(uint8_t *message_start, uint8_t *message_end, size_t *size, message_destructor_t *free_message)
5800 {
5801     SPICE_GNUC_UNUSED uint8_t *pos;
5802     uint8_t *start = message_start;
5803     uint8_t *data = NULL;
5804     uint64_t nw_size;
5805     uint64_t mem_size;
5806     uint8_t *in, *end;
5807     SpiceMsgSurfaceDestroy *out;
5808 
5809     nw_size = 4;
5810     mem_size = sizeof(SpiceMsgSurfaceDestroy);
5811 
5812     /* Check if message fits in reported side */
5813     if (nw_size > (uintptr_t) (message_end - start)) {
5814         return NULL;
5815     }
5816 
5817     /* Validated extents and calculated size */
5818     data = (uint8_t *)(mem_size > UINT32_MAX ? NULL : malloc(mem_size));
5819     if (SPICE_UNLIKELY(data == NULL)) {
5820         goto error;
5821     }
5822     end = data + sizeof(SpiceMsgSurfaceDestroy);
5823     in = start;
5824 
5825     out = (SpiceMsgSurfaceDestroy *)data;
5826 
5827     out->surface_id = consume_uint32(&in);
5828 
5829     assert(in <= message_end);
5830     assert(end <= data + mem_size);
5831 
5832     *size = end - data;
5833     *free_message = (message_destructor_t) free;
5834     return data;
5835 
5836    error:
5837     free(data);
5838     return NULL;
5839 }
5840 
parse_msg_display_stream_data_sized(uint8_t * message_start,uint8_t * message_end,size_t * size,message_destructor_t * free_message)5841 static uint8_t * parse_msg_display_stream_data_sized(uint8_t *message_start, uint8_t *message_end, size_t *size, message_destructor_t *free_message)
5842 {
5843     SPICE_GNUC_UNUSED uint8_t *pos;
5844     uint8_t *start = message_start;
5845     uint8_t *data = NULL;
5846     uint64_t nw_size;
5847     uint64_t mem_size;
5848     uint8_t *in, *end;
5849     uint64_t data__nw_size, data__mem_size;
5850     uint64_t data__nelements;
5851     SpiceMsgDisplayStreamDataSized *out;
5852 
5853     { /* data */
5854         uint32_t data_size__value;
5855         pos = start + 32;
5856         if (SPICE_UNLIKELY(pos + 4 > message_end)) {
5857             goto error;
5858         }
5859         data_size__value = read_uint32(pos);
5860         data__nelements = data_size__value;
5861 
5862         data__nw_size = data__nelements;
5863         data__mem_size = sizeof(uint8_t) * data__nelements;
5864     }
5865 
5866     nw_size = 36 + data__nw_size;
5867     mem_size = sizeof(SpiceMsgDisplayStreamDataSized) + data__mem_size;
5868 
5869     /* Check if message fits in reported side */
5870     if (nw_size > (uintptr_t) (message_end - start)) {
5871         return NULL;
5872     }
5873 
5874     /* Validated extents and calculated size */
5875     data = (uint8_t *)(mem_size > UINT32_MAX ? NULL : malloc(mem_size));
5876     if (SPICE_UNLIKELY(data == NULL)) {
5877         goto error;
5878     }
5879     end = data + sizeof(SpiceMsgDisplayStreamDataSized);
5880     in = start;
5881 
5882     out = (SpiceMsgDisplayStreamDataSized *)data;
5883 
5884     /* base */ {
5885         out->base.id = consume_uint32(&in);
5886         out->base.multi_media_time = consume_uint32(&in);
5887     }
5888     out->width = consume_uint32(&in);
5889     out->height = consume_uint32(&in);
5890     /* dest */ {
5891         out->dest.top = consume_int32(&in);
5892         out->dest.left = consume_int32(&in);
5893         out->dest.bottom = consume_int32(&in);
5894         out->dest.right = consume_int32(&in);
5895     }
5896     out->data_size = consume_uint32(&in);
5897     memcpy(out->data, in, data__nelements);
5898     in += data__nelements;
5899     end += data__nelements;
5900 
5901     assert(in <= message_end);
5902     assert(end <= data + mem_size);
5903 
5904     *size = end - data;
5905     *free_message = (message_destructor_t) free;
5906     return data;
5907 
5908    error:
5909     free(data);
5910     return NULL;
5911 }
5912 
parse_msg_display_monitors_config(uint8_t * message_start,uint8_t * message_end,size_t * size,message_destructor_t * free_message)5913 static uint8_t * parse_msg_display_monitors_config(uint8_t *message_start, uint8_t *message_end, size_t *size, message_destructor_t *free_message)
5914 {
5915     SPICE_GNUC_UNUSED uint8_t *pos;
5916     uint8_t *start = message_start;
5917     uint8_t *data = NULL;
5918     uint64_t nw_size;
5919     uint64_t mem_size;
5920     uint8_t *in, *end;
5921     uint64_t heads__nw_size, heads__mem_size;
5922     uint64_t heads__nelements;
5923     SpiceMsgDisplayMonitorsConfig *out;
5924     uint32_t i;
5925 
5926     { /* heads */
5927         uint16_t count__value;
5928         pos = start + 0;
5929         if (SPICE_UNLIKELY(pos + 2 > message_end)) {
5930             goto error;
5931         }
5932         count__value = read_uint16(pos);
5933         heads__nelements = count__value;
5934 
5935         heads__nw_size = (28) * heads__nelements;
5936         heads__mem_size = sizeof(SpiceHead) * heads__nelements;
5937     }
5938 
5939     nw_size = 4 + heads__nw_size;
5940     mem_size = sizeof(SpiceMsgDisplayMonitorsConfig) + heads__mem_size;
5941 
5942     /* Check if message fits in reported side */
5943     if (nw_size > (uintptr_t) (message_end - start)) {
5944         return NULL;
5945     }
5946 
5947     /* Validated extents and calculated size */
5948     data = (uint8_t *)(mem_size > UINT32_MAX ? NULL : malloc(mem_size));
5949     if (SPICE_UNLIKELY(data == NULL)) {
5950         goto error;
5951     }
5952     end = data + sizeof(SpiceMsgDisplayMonitorsConfig);
5953     in = start;
5954 
5955     out = (SpiceMsgDisplayMonitorsConfig *)data;
5956 
5957     out->count = consume_uint16(&in);
5958     out->max_allowed = consume_uint16(&in);
5959     for (i = 0; i < heads__nelements; i++) {
5960         SpiceHead *out2;
5961         out2 = (SpiceHead *)end;
5962         end += sizeof(SpiceHead);
5963 
5964         out2->monitor_id = consume_uint32(&in);
5965         out2->surface_id = consume_uint32(&in);
5966         out2->width = consume_uint32(&in);
5967         out2->height = consume_uint32(&in);
5968         out2->x = consume_uint32(&in);
5969         out2->y = consume_uint32(&in);
5970         out2->flags = consume_uint32(&in);
5971     }
5972 
5973     assert(in <= message_end);
5974     assert(end <= data + mem_size);
5975 
5976     *size = end - data;
5977     *free_message = (message_destructor_t) free;
5978     return data;
5979 
5980    error:
5981     free(data);
5982     return NULL;
5983 }
5984 
parse_msg_display_draw_composite(uint8_t * message_start,uint8_t * message_end,size_t * size,message_destructor_t * free_message)5985 static uint8_t * parse_msg_display_draw_composite(uint8_t *message_start, uint8_t *message_end, size_t *size, message_destructor_t *free_message)
5986 {
5987     SPICE_GNUC_UNUSED uint8_t *pos;
5988     uint8_t *start = message_start;
5989     uint8_t *data = NULL;
5990     uint64_t nw_size;
5991     uint64_t mem_size;
5992     uint8_t *in, *end;
5993     SPICE_GNUC_UNUSED intptr_t ptr_size;
5994     uint32_t n_ptr=0;
5995     PointerInfo ptr_info[3];
5996     uint64_t base__nw_size, base__extra_size;
5997     uint32_t rects__saved_size = 0;
5998     uint64_t data__nw_size, data__extra_size;
5999     SpiceMsgDisplayDrawComposite *out;
6000     uint32_t i;
6001 
6002     { /* base */
6003         SPICE_GNUC_UNUSED uint8_t *start2 = (start + 0);
6004         uint64_t base_clip__nw_size, base_clip__extra_size;
6005         { /* clip */
6006             SPICE_GNUC_UNUSED uint8_t *start3 = (start2 + 20);
6007             uint64_t base_clip_u__nw_size, base_clip_u__extra_size;
6008             uint8_t type__value;
6009             { /* u */
6010                 uint64_t base_clip_u__mem_size;
6011                 pos = start3 + 0;
6012                 if (SPICE_UNLIKELY(pos + 1 > message_end)) {
6013                     goto error;
6014                 }
6015                 type__value = read_uint8(pos);
6016                 if (type__value == SPICE_CLIP_TYPE_RECTS) {
6017                     SPICE_GNUC_UNUSED uint8_t *start4 = (start3 + 1);
6018                     uint64_t base_clip_u_rects__nw_size, base_clip_u_rects__mem_size;
6019                     uint64_t base_clip_u_rects__nelements;
6020                     { /* rects */
6021                         uint32_t num_rects__value;
6022                         pos = start4 + 0;
6023                         if (SPICE_UNLIKELY(pos + 4 > message_end)) {
6024                             goto error;
6025                         }
6026                         num_rects__value = read_uint32(pos);
6027                         base_clip_u_rects__nelements = num_rects__value;
6028 
6029                         base_clip_u_rects__nw_size = (16) * base_clip_u_rects__nelements;
6030                         base_clip_u_rects__mem_size = sizeof(SpiceRect) * base_clip_u_rects__nelements;
6031                     }
6032 
6033                     base_clip_u__nw_size = 4 + base_clip_u_rects__nw_size;
6034                     base_clip_u__mem_size = sizeof(SpiceClipRects) + base_clip_u_rects__mem_size;
6035                     rects__saved_size = base_clip_u__nw_size;
6036                     base_clip_u__extra_size = base_clip_u__mem_size;
6037                 } else {
6038                     base_clip_u__nw_size = 0;
6039                     base_clip_u__extra_size = 0;
6040                 }
6041 
6042             }
6043 
6044             base_clip__nw_size = 1 + base_clip_u__nw_size;
6045             base_clip__extra_size = base_clip_u__extra_size;
6046         }
6047 
6048         base__nw_size = 20 + base_clip__nw_size;
6049         base__extra_size = base_clip__extra_size;
6050     }
6051 
6052     { /* data */
6053         SPICE_GNUC_UNUSED uint8_t *start2 = (start + 0 + base__nw_size);
6054         uint64_t data_src_bitmap__extra_size;
6055         uint64_t data_a__nw_size, data_a__extra_size;
6056         uint32_t flags__value;
6057         uint64_t data_b__nw_size;
6058         uint64_t data_c__nw_size;
6059         { /* src_bitmap */
6060             uint32_t src_bitmap__value;
6061             pos = (start2 + 4);
6062             if (SPICE_UNLIKELY(pos + 4 > message_end)) {
6063                 goto error;
6064             }
6065             src_bitmap__value = read_uint32(pos);
6066             ptr_size = validate_SpiceImage(message_start, message_end, src_bitmap__value);
6067             if (SPICE_UNLIKELY(ptr_size < 0)) {
6068                 goto error;
6069             }
6070             data_src_bitmap__extra_size = ptr_size + /* for alignment */ 3;
6071         }
6072 
6073         { /* a */
6074             pos = start2 + 0;
6075             if (SPICE_UNLIKELY(pos + 4 > message_end)) {
6076                 goto error;
6077             }
6078             flags__value = read_uint32(pos);
6079             if ((flags__value & SPICE_COMPOSITE_HAS_MASK)) {
6080                 uint32_t data_a_mask_bitmap__value;
6081                 data_a__nw_size = 4;
6082                 pos = (start2 + 8);
6083                 if (SPICE_UNLIKELY(pos + 4 > message_end)) {
6084                     goto error;
6085                 }
6086                 data_a_mask_bitmap__value = read_uint32(pos);
6087                 ptr_size = validate_SpiceImage(message_start, message_end, data_a_mask_bitmap__value);
6088                 if (SPICE_UNLIKELY(ptr_size < 0)) {
6089                     goto error;
6090                 }
6091                 data_a__extra_size = ptr_size + /* for alignment */ 3;
6092             } else {
6093                 data_a__nw_size = 0;
6094                 data_a__extra_size = 0;
6095             }
6096 
6097         }
6098 
6099         { /* b */
6100             pos = start2 + 0;
6101             if (SPICE_UNLIKELY(pos + 4 > message_end)) {
6102                 goto error;
6103             }
6104             flags__value = read_uint32(pos);
6105             if ((flags__value & SPICE_COMPOSITE_HAS_SRC_TRANSFORM)) {
6106                 SPICE_GNUC_UNUSED uint8_t *start3 = (start2 + 8 + data_a__nw_size);
6107                 data_b__nw_size = 24;
6108             } else {
6109                 data_b__nw_size = 0;
6110             }
6111 
6112         }
6113 
6114         { /* c */
6115             pos = start2 + 0;
6116             if (SPICE_UNLIKELY(pos + 4 > message_end)) {
6117                 goto error;
6118             }
6119             flags__value = read_uint32(pos);
6120             if ((flags__value & SPICE_COMPOSITE_HAS_MASK_TRANSFORM)) {
6121                 SPICE_GNUC_UNUSED uint8_t *start3 = (start2 + 8 + data_a__nw_size + data_b__nw_size);
6122                 data_c__nw_size = 24;
6123             } else {
6124                 data_c__nw_size = 0;
6125             }
6126 
6127         }
6128 
6129         data__nw_size = 16 + data_a__nw_size + data_b__nw_size + data_c__nw_size;
6130         data__extra_size = data_src_bitmap__extra_size + data_a__extra_size;
6131     }
6132 
6133     nw_size = 0 + base__nw_size + data__nw_size;
6134     mem_size = sizeof(SpiceMsgDisplayDrawComposite) + base__extra_size + data__extra_size;
6135 
6136     /* Check if message fits in reported side */
6137     if (nw_size > (uintptr_t) (message_end - start)) {
6138         return NULL;
6139     }
6140 
6141     /* Validated extents and calculated size */
6142     data = (uint8_t *)(mem_size > UINT32_MAX ? NULL : malloc(mem_size));
6143     if (SPICE_UNLIKELY(data == NULL)) {
6144         goto error;
6145     }
6146     end = data + sizeof(SpiceMsgDisplayDrawComposite);
6147     in = start;
6148 
6149     out = (SpiceMsgDisplayDrawComposite *)data;
6150 
6151     /* base */ {
6152         out->base.surface_id = consume_uint32(&in);
6153         /* box */ {
6154             out->base.box.top = consume_int32(&in);
6155             out->base.box.left = consume_int32(&in);
6156             out->base.box.bottom = consume_int32(&in);
6157             out->base.box.right = consume_int32(&in);
6158         }
6159         /* clip */ {
6160             out->base.clip.type = consume_uint8(&in);
6161             if (out->base.clip.type == SPICE_CLIP_TYPE_RECTS) {
6162                 ptr_info[n_ptr].offset = in - start;
6163                 ptr_info[n_ptr].parse = parse_struct_SpiceClipRects;
6164                 ptr_info[n_ptr].dest = (void **)&out->base.clip.rects;
6165                 n_ptr++;
6166                 in += rects__saved_size;
6167             }
6168         }
6169     }
6170     /* data */ {
6171         out->data.flags = consume_uint32(&in);
6172         ptr_info[n_ptr].offset = consume_uint32(&in);
6173         ptr_info[n_ptr].parse = parse_struct_SpiceImage;
6174         ptr_info[n_ptr].dest = (void **)&out->data.src_bitmap;
6175         n_ptr++;
6176         if ((out->data.flags & SPICE_COMPOSITE_HAS_MASK)) {
6177             ptr_info[n_ptr].offset = consume_uint32(&in);
6178             ptr_info[n_ptr].parse = parse_struct_SpiceImage;
6179             ptr_info[n_ptr].dest = (void **)&out->data.mask_bitmap;
6180             n_ptr++;
6181         }
6182         if ((out->data.flags & SPICE_COMPOSITE_HAS_SRC_TRANSFORM)) {
6183             out->data.src_transform.t00 = consume_uint32(&in);
6184             out->data.src_transform.t01 = consume_uint32(&in);
6185             out->data.src_transform.t02 = consume_uint32(&in);
6186             out->data.src_transform.t10 = consume_uint32(&in);
6187             out->data.src_transform.t11 = consume_uint32(&in);
6188             out->data.src_transform.t12 = consume_uint32(&in);
6189         }
6190         if ((out->data.flags & SPICE_COMPOSITE_HAS_MASK_TRANSFORM)) {
6191             out->data.mask_transform.t00 = consume_uint32(&in);
6192             out->data.mask_transform.t01 = consume_uint32(&in);
6193             out->data.mask_transform.t02 = consume_uint32(&in);
6194             out->data.mask_transform.t10 = consume_uint32(&in);
6195             out->data.mask_transform.t11 = consume_uint32(&in);
6196             out->data.mask_transform.t12 = consume_uint32(&in);
6197         }
6198         /* src_origin */ {
6199             out->data.src_origin.x = consume_int16(&in);
6200             out->data.src_origin.y = consume_int16(&in);
6201         }
6202         /* mask_origin */ {
6203             out->data.mask_origin.x = consume_int16(&in);
6204             out->data.mask_origin.y = consume_int16(&in);
6205         }
6206     }
6207 
6208     assert(in <= message_end);
6209 
6210     for (i = 0; i < n_ptr; i++) {
6211         if (ptr_info[i].offset == 0) {
6212             *ptr_info[i].dest = NULL;
6213         } else {
6214             /* Align to 32 bit */
6215             end = (uint8_t *)SPICE_ALIGN((uintptr_t)end, 4);
6216             *ptr_info[i].dest = (void *)end;
6217             end = ptr_info[i].parse(message_start, message_end, end, &ptr_info[i]);
6218             if (SPICE_UNLIKELY(end == NULL)) {
6219                 goto error;
6220             }
6221         }
6222     }
6223 
6224     assert(end <= data + mem_size);
6225 
6226     *size = end - data;
6227     *free_message = (message_destructor_t) free;
6228     return data;
6229 
6230    error:
6231     free(data);
6232     return NULL;
6233 }
6234 
parse_msg_display_stream_activate_report(uint8_t * message_start,uint8_t * message_end,size_t * size,message_destructor_t * free_message)6235 static uint8_t * parse_msg_display_stream_activate_report(uint8_t *message_start, uint8_t *message_end, size_t *size, message_destructor_t *free_message)
6236 {
6237     SPICE_GNUC_UNUSED uint8_t *pos;
6238     uint8_t *start = message_start;
6239     uint8_t *data = NULL;
6240     uint64_t nw_size;
6241     uint64_t mem_size;
6242     uint8_t *in, *end;
6243     SpiceMsgDisplayStreamActivateReport *out;
6244 
6245     nw_size = 16;
6246     mem_size = sizeof(SpiceMsgDisplayStreamActivateReport);
6247 
6248     /* Check if message fits in reported side */
6249     if (nw_size > (uintptr_t) (message_end - start)) {
6250         return NULL;
6251     }
6252 
6253     /* Validated extents and calculated size */
6254     data = (uint8_t *)(mem_size > UINT32_MAX ? NULL : malloc(mem_size));
6255     if (SPICE_UNLIKELY(data == NULL)) {
6256         goto error;
6257     }
6258     end = data + sizeof(SpiceMsgDisplayStreamActivateReport);
6259     in = start;
6260 
6261     out = (SpiceMsgDisplayStreamActivateReport *)data;
6262 
6263     out->stream_id = consume_uint32(&in);
6264     out->unique_id = consume_uint32(&in);
6265     out->max_window_size = consume_uint32(&in);
6266     out->timeout_ms = consume_uint32(&in);
6267 
6268     assert(in <= message_end);
6269     assert(end <= data + mem_size);
6270 
6271     *size = end - data;
6272     *free_message = (message_destructor_t) free;
6273     return data;
6274 
6275    error:
6276     free(data);
6277     return NULL;
6278 }
6279 
parse_msg_display_gl_scanout_unix(uint8_t * message_start,uint8_t * message_end,size_t * size,message_destructor_t * free_message)6280 static uint8_t * parse_msg_display_gl_scanout_unix(uint8_t *message_start, uint8_t *message_end, size_t *size, message_destructor_t *free_message)
6281 {
6282     SPICE_GNUC_UNUSED uint8_t *pos;
6283     uint8_t *start = message_start;
6284     uint8_t *data = NULL;
6285     uint64_t nw_size;
6286     uint64_t mem_size;
6287     uint8_t *in, *end;
6288     SpiceMsgDisplayGlScanoutUnix *out;
6289 
6290     nw_size = 20;
6291     mem_size = sizeof(SpiceMsgDisplayGlScanoutUnix);
6292 
6293     /* Check if message fits in reported side */
6294     if (nw_size > (uintptr_t) (message_end - start)) {
6295         return NULL;
6296     }
6297 
6298     /* Validated extents and calculated size */
6299     data = (uint8_t *)(mem_size > UINT32_MAX ? NULL : malloc(mem_size));
6300     if (SPICE_UNLIKELY(data == NULL)) {
6301         goto error;
6302     }
6303     end = data + sizeof(SpiceMsgDisplayGlScanoutUnix);
6304     in = start;
6305 
6306     out = (SpiceMsgDisplayGlScanoutUnix *)data;
6307 
6308     out->drm_dma_buf_fd = consume_fd(&in);
6309     out->width = consume_uint32(&in);
6310     out->height = consume_uint32(&in);
6311     out->stride = consume_uint32(&in);
6312     out->drm_fourcc_format = consume_uint32(&in);
6313     out->flags = consume_uint32(&in);
6314 
6315     assert(in <= message_end);
6316     assert(end <= data + mem_size);
6317 
6318     *size = end - data;
6319     *free_message = (message_destructor_t) free;
6320     return data;
6321 
6322    error:
6323     free(data);
6324     return NULL;
6325 }
6326 
parse_msg_display_gl_draw(uint8_t * message_start,uint8_t * message_end,size_t * size,message_destructor_t * free_message)6327 static uint8_t * parse_msg_display_gl_draw(uint8_t *message_start, uint8_t *message_end, size_t *size, message_destructor_t *free_message)
6328 {
6329     SPICE_GNUC_UNUSED uint8_t *pos;
6330     uint8_t *start = message_start;
6331     uint8_t *data = NULL;
6332     uint64_t nw_size;
6333     uint64_t mem_size;
6334     uint8_t *in, *end;
6335     SpiceMsgDisplayGlDraw *out;
6336 
6337     nw_size = 16;
6338     mem_size = sizeof(SpiceMsgDisplayGlDraw);
6339 
6340     /* Check if message fits in reported side */
6341     if (nw_size > (uintptr_t) (message_end - start)) {
6342         return NULL;
6343     }
6344 
6345     /* Validated extents and calculated size */
6346     data = (uint8_t *)(mem_size > UINT32_MAX ? NULL : malloc(mem_size));
6347     if (SPICE_UNLIKELY(data == NULL)) {
6348         goto error;
6349     }
6350     end = data + sizeof(SpiceMsgDisplayGlDraw);
6351     in = start;
6352 
6353     out = (SpiceMsgDisplayGlDraw *)data;
6354 
6355     out->x = consume_uint32(&in);
6356     out->y = consume_uint32(&in);
6357     out->w = consume_uint32(&in);
6358     out->h = consume_uint32(&in);
6359 
6360     assert(in <= message_end);
6361     assert(end <= data + mem_size);
6362 
6363     *size = end - data;
6364     *free_message = (message_destructor_t) free;
6365     return data;
6366 
6367    error:
6368     free(data);
6369     return NULL;
6370 }
6371 
parse_DisplayChannel_msg(uint8_t * message_start,uint8_t * message_end,uint16_t message_type,SPICE_GNUC_UNUSED int minor,size_t * size_out,message_destructor_t * free_message)6372 static uint8_t * parse_DisplayChannel_msg(uint8_t *message_start, uint8_t *message_end, uint16_t message_type, SPICE_GNUC_UNUSED int minor, size_t *size_out, message_destructor_t *free_message)
6373 {
6374     static parse_msg_func_t funcs1[8] =  {
6375         parse_msg_migrate,
6376         parse_SpiceMsgData,
6377         parse_msg_set_ack,
6378         parse_msg_ping,
6379         parse_msg_wait_for_channels,
6380         parse_msg_disconnecting,
6381         parse_msg_notify,
6382         parse_SpiceMsgData
6383     };
6384     static parse_msg_func_t funcs2[9] =  {
6385         parse_SpiceMsgEmpty,
6386         parse_msg_display_mode,
6387         parse_SpiceMsgEmpty,
6388         parse_SpiceMsgEmpty,
6389         parse_msg_display_copy_bits,
6390         parse_msg_display_inval_list,
6391         parse_msg_display_inval_all_pixmaps,
6392         parse_msg_display_inval_palette,
6393         parse_SpiceMsgEmpty
6394     };
6395     static parse_msg_func_t funcs3[5] =  {
6396         parse_msg_display_stream_create,
6397         parse_msg_display_stream_data,
6398         parse_msg_display_stream_clip,
6399         parse_msg_display_stream_destroy,
6400         parse_SpiceMsgEmpty
6401     };
6402     static parse_msg_func_t funcs4[20] =  {
6403         parse_msg_display_draw_fill,
6404         parse_msg_display_draw_opaque,
6405         parse_msg_display_draw_copy,
6406         parse_msg_display_draw_blend,
6407         parse_msg_display_draw_blackness,
6408         parse_msg_display_draw_whiteness,
6409         parse_msg_display_draw_invers,
6410         parse_msg_display_draw_rop3,
6411         parse_msg_display_draw_stroke,
6412         parse_msg_display_draw_text,
6413         parse_msg_display_draw_transparent,
6414         parse_msg_display_draw_alpha_blend,
6415         parse_msg_display_surface_create,
6416         parse_msg_display_surface_destroy,
6417         parse_msg_display_stream_data_sized,
6418         parse_msg_display_monitors_config,
6419         parse_msg_display_draw_composite,
6420         parse_msg_display_stream_activate_report,
6421         parse_msg_display_gl_scanout_unix,
6422         parse_msg_display_gl_draw
6423     };
6424     if (message_type >= 1 && message_type < 9) {
6425         return funcs1[message_type-1](message_start, message_end, size_out, free_message);
6426     } else if (message_type >= 100 && message_type < 109) {
6427         return funcs2[message_type-100](message_start, message_end, size_out, free_message);
6428     } else if (message_type >= 122 && message_type < 127) {
6429         return funcs3[message_type-122](message_start, message_end, size_out, free_message);
6430     } else if (message_type >= 302 && message_type < 322) {
6431         return funcs4[message_type-302](message_start, message_end, size_out, free_message);
6432     }
6433     return NULL;
6434 }
6435 
6436 
6437 
parse_msg_inputs_init(uint8_t * message_start,uint8_t * message_end,size_t * size,message_destructor_t * free_message)6438 static uint8_t * parse_msg_inputs_init(uint8_t *message_start, uint8_t *message_end, size_t *size, message_destructor_t *free_message)
6439 {
6440     SPICE_GNUC_UNUSED uint8_t *pos;
6441     uint8_t *start = message_start;
6442     uint8_t *data = NULL;
6443     uint64_t nw_size;
6444     uint64_t mem_size;
6445     uint8_t *in, *end;
6446     SpiceMsgInputsInit *out;
6447 
6448     nw_size = 2;
6449     mem_size = sizeof(SpiceMsgInputsInit);
6450 
6451     /* Check if message fits in reported side */
6452     if (nw_size > (uintptr_t) (message_end - start)) {
6453         return NULL;
6454     }
6455 
6456     /* Validated extents and calculated size */
6457     data = (uint8_t *)(mem_size > UINT32_MAX ? NULL : malloc(mem_size));
6458     if (SPICE_UNLIKELY(data == NULL)) {
6459         goto error;
6460     }
6461     end = data + sizeof(SpiceMsgInputsInit);
6462     in = start;
6463 
6464     out = (SpiceMsgInputsInit *)data;
6465 
6466     out->keyboard_modifiers = consume_uint16(&in);
6467 
6468     assert(in <= message_end);
6469     assert(end <= data + mem_size);
6470 
6471     *size = end - data;
6472     *free_message = (message_destructor_t) free;
6473     return data;
6474 
6475    error:
6476     free(data);
6477     return NULL;
6478 }
6479 
parse_msg_inputs_key_modifiers(uint8_t * message_start,uint8_t * message_end,size_t * size,message_destructor_t * free_message)6480 static uint8_t * parse_msg_inputs_key_modifiers(uint8_t *message_start, uint8_t *message_end, size_t *size, message_destructor_t *free_message)
6481 {
6482     SPICE_GNUC_UNUSED uint8_t *pos;
6483     uint8_t *start = message_start;
6484     uint8_t *data = NULL;
6485     uint64_t nw_size;
6486     uint64_t mem_size;
6487     uint8_t *in, *end;
6488     SpiceMsgInputsKeyModifiers *out;
6489 
6490     nw_size = 2;
6491     mem_size = sizeof(SpiceMsgInputsKeyModifiers);
6492 
6493     /* Check if message fits in reported side */
6494     if (nw_size > (uintptr_t) (message_end - start)) {
6495         return NULL;
6496     }
6497 
6498     /* Validated extents and calculated size */
6499     data = (uint8_t *)(mem_size > UINT32_MAX ? NULL : malloc(mem_size));
6500     if (SPICE_UNLIKELY(data == NULL)) {
6501         goto error;
6502     }
6503     end = data + sizeof(SpiceMsgInputsKeyModifiers);
6504     in = start;
6505 
6506     out = (SpiceMsgInputsKeyModifiers *)data;
6507 
6508     out->modifiers = consume_uint16(&in);
6509 
6510     assert(in <= message_end);
6511     assert(end <= data + mem_size);
6512 
6513     *size = end - data;
6514     *free_message = (message_destructor_t) free;
6515     return data;
6516 
6517    error:
6518     free(data);
6519     return NULL;
6520 }
6521 
parse_InputsChannel_msg(uint8_t * message_start,uint8_t * message_end,uint16_t message_type,SPICE_GNUC_UNUSED int minor,size_t * size_out,message_destructor_t * free_message)6522 static uint8_t * parse_InputsChannel_msg(uint8_t *message_start, uint8_t *message_end, uint16_t message_type, SPICE_GNUC_UNUSED int minor, size_t *size_out, message_destructor_t *free_message)
6523 {
6524     static parse_msg_func_t funcs1[8] =  {
6525         parse_msg_migrate,
6526         parse_SpiceMsgData,
6527         parse_msg_set_ack,
6528         parse_msg_ping,
6529         parse_msg_wait_for_channels,
6530         parse_msg_disconnecting,
6531         parse_msg_notify,
6532         parse_SpiceMsgData
6533     };
6534     static parse_msg_func_t funcs2[3] =  {
6535         parse_SpiceMsgEmpty,
6536         parse_msg_inputs_init,
6537         parse_msg_inputs_key_modifiers
6538     };
6539     static parse_msg_func_t funcs3[1] =  {
6540         parse_SpiceMsgEmpty
6541     };
6542     if (message_type >= 1 && message_type < 9) {
6543         return funcs1[message_type-1](message_start, message_end, size_out, free_message);
6544     } else if (message_type >= 100 && message_type < 103) {
6545         return funcs2[message_type-100](message_start, message_end, size_out, free_message);
6546     } else if (message_type >= 111 && message_type < 112) {
6547         return funcs3[message_type-111](message_start, message_end, size_out, free_message);
6548     }
6549     return NULL;
6550 }
6551 
6552 
6553 
parse_msg_cursor_init(uint8_t * message_start,uint8_t * message_end,size_t * size,message_destructor_t * free_message)6554 static uint8_t * parse_msg_cursor_init(uint8_t *message_start, uint8_t *message_end, size_t *size, message_destructor_t *free_message)
6555 {
6556     SPICE_GNUC_UNUSED uint8_t *pos;
6557     uint8_t *start = message_start;
6558     uint8_t *data = NULL;
6559     uint64_t nw_size;
6560     uint64_t mem_size;
6561     uint8_t *in, *end;
6562     uint64_t cursor__nw_size;
6563     SpiceMsgCursorInit *out;
6564 
6565     { /* cursor */
6566         SPICE_GNUC_UNUSED uint8_t *start2 = (start + 9);
6567         uint64_t cursor_u__nw_size;
6568         uint16_t flags__value;
6569         uint64_t cursor_data__nw_size;
6570         uint64_t cursor_data__nelements;
6571         { /* u */
6572             pos = start2 + 0;
6573             if (SPICE_UNLIKELY(pos + 2 > message_end)) {
6574                 goto error;
6575             }
6576             flags__value = read_uint16(pos);
6577             if (!(flags__value & SPICE_CURSOR_FLAGS_NONE)) {
6578                 SPICE_GNUC_UNUSED uint8_t *start3 = (start2 + 2);
6579                 cursor_u__nw_size = 17;
6580             } else {
6581                 cursor_u__nw_size = 0;
6582             }
6583 
6584         }
6585 
6586         { /* data */
6587             if (SPICE_UNLIKELY((start2 + 2 + cursor_u__nw_size) > message_end)) {
6588                 goto error;
6589             }
6590             cursor_data__nelements = message_end - (start2 + 2 + cursor_u__nw_size);
6591 
6592             cursor_data__nw_size = cursor_data__nelements;
6593         }
6594 
6595         cursor__nw_size = 2 + cursor_u__nw_size + cursor_data__nw_size;
6596     }
6597 
6598     nw_size = 9 + cursor__nw_size;
6599     mem_size = sizeof(SpiceMsgCursorInit);
6600 
6601     /* Check if message fits in reported side */
6602     if (nw_size > (uintptr_t) (message_end - start)) {
6603         return NULL;
6604     }
6605 
6606     /* Validated extents and calculated size */
6607     data = (uint8_t *)(mem_size > UINT32_MAX ? NULL : malloc(mem_size));
6608     if (SPICE_UNLIKELY(data == NULL)) {
6609         goto error;
6610     }
6611     end = data + sizeof(SpiceMsgCursorInit);
6612     in = start;
6613 
6614     out = (SpiceMsgCursorInit *)data;
6615 
6616     /* position */ {
6617         out->position.x = consume_int16(&in);
6618         out->position.y = consume_int16(&in);
6619     }
6620     out->trail_length = consume_uint16(&in);
6621     out->trail_frequency = consume_uint16(&in);
6622     out->visible = consume_uint8(&in);
6623     /* cursor */ {
6624         uint64_t data__nelements;
6625         out->cursor.flags = consume_uint16(&in);
6626         if (!(out->cursor.flags & SPICE_CURSOR_FLAGS_NONE)) {
6627             out->cursor.header.unique = consume_uint64(&in);
6628             out->cursor.header.type = consume_uint8(&in);
6629             out->cursor.header.width = consume_uint16(&in);
6630             out->cursor.header.height = consume_uint16(&in);
6631             out->cursor.header.hot_spot_x = consume_uint16(&in);
6632             out->cursor.header.hot_spot_y = consume_uint16(&in);
6633         }
6634         data__nelements = (message_end - in) / (1);
6635         /* use array as pointer */
6636         out->cursor.data = (uint8_t *)in;
6637         out->cursor.data_size = data__nelements;
6638         in += data__nelements;
6639     }
6640 
6641     assert(in <= message_end);
6642     assert(end <= data + mem_size);
6643 
6644     *size = end - data;
6645     *free_message = (message_destructor_t) free;
6646     return data;
6647 
6648    error:
6649     free(data);
6650     return NULL;
6651 }
6652 
parse_msg_cursor_set(uint8_t * message_start,uint8_t * message_end,size_t * size,message_destructor_t * free_message)6653 static uint8_t * parse_msg_cursor_set(uint8_t *message_start, uint8_t *message_end, size_t *size, message_destructor_t *free_message)
6654 {
6655     SPICE_GNUC_UNUSED uint8_t *pos;
6656     uint8_t *start = message_start;
6657     uint8_t *data = NULL;
6658     uint64_t nw_size;
6659     uint64_t mem_size;
6660     uint8_t *in, *end;
6661     uint64_t cursor__nw_size;
6662     SpiceMsgCursorSet *out;
6663 
6664     { /* cursor */
6665         SPICE_GNUC_UNUSED uint8_t *start2 = (start + 5);
6666         uint64_t cursor_u__nw_size;
6667         uint16_t flags__value;
6668         uint64_t cursor_data__nw_size;
6669         uint64_t cursor_data__nelements;
6670         { /* u */
6671             pos = start2 + 0;
6672             if (SPICE_UNLIKELY(pos + 2 > message_end)) {
6673                 goto error;
6674             }
6675             flags__value = read_uint16(pos);
6676             if (!(flags__value & SPICE_CURSOR_FLAGS_NONE)) {
6677                 SPICE_GNUC_UNUSED uint8_t *start3 = (start2 + 2);
6678                 cursor_u__nw_size = 17;
6679             } else {
6680                 cursor_u__nw_size = 0;
6681             }
6682 
6683         }
6684 
6685         { /* data */
6686             if (SPICE_UNLIKELY((start2 + 2 + cursor_u__nw_size) > message_end)) {
6687                 goto error;
6688             }
6689             cursor_data__nelements = message_end - (start2 + 2 + cursor_u__nw_size);
6690 
6691             cursor_data__nw_size = cursor_data__nelements;
6692         }
6693 
6694         cursor__nw_size = 2 + cursor_u__nw_size + cursor_data__nw_size;
6695     }
6696 
6697     nw_size = 5 + cursor__nw_size;
6698     mem_size = sizeof(SpiceMsgCursorSet);
6699 
6700     /* Check if message fits in reported side */
6701     if (nw_size > (uintptr_t) (message_end - start)) {
6702         return NULL;
6703     }
6704 
6705     /* Validated extents and calculated size */
6706     data = (uint8_t *)(mem_size > UINT32_MAX ? NULL : malloc(mem_size));
6707     if (SPICE_UNLIKELY(data == NULL)) {
6708         goto error;
6709     }
6710     end = data + sizeof(SpiceMsgCursorSet);
6711     in = start;
6712 
6713     out = (SpiceMsgCursorSet *)data;
6714 
6715     /* position */ {
6716         out->position.x = consume_int16(&in);
6717         out->position.y = consume_int16(&in);
6718     }
6719     out->visible = consume_uint8(&in);
6720     /* cursor */ {
6721         uint64_t data__nelements;
6722         out->cursor.flags = consume_uint16(&in);
6723         if (!(out->cursor.flags & SPICE_CURSOR_FLAGS_NONE)) {
6724             out->cursor.header.unique = consume_uint64(&in);
6725             out->cursor.header.type = consume_uint8(&in);
6726             out->cursor.header.width = consume_uint16(&in);
6727             out->cursor.header.height = consume_uint16(&in);
6728             out->cursor.header.hot_spot_x = consume_uint16(&in);
6729             out->cursor.header.hot_spot_y = consume_uint16(&in);
6730         }
6731         data__nelements = (message_end - in) / (1);
6732         /* use array as pointer */
6733         out->cursor.data = (uint8_t *)in;
6734         out->cursor.data_size = data__nelements;
6735         in += data__nelements;
6736     }
6737 
6738     assert(in <= message_end);
6739     assert(end <= data + mem_size);
6740 
6741     *size = end - data;
6742     *free_message = (message_destructor_t) free;
6743     return data;
6744 
6745    error:
6746     free(data);
6747     return NULL;
6748 }
6749 
parse_msg_cursor_move(uint8_t * message_start,uint8_t * message_end,size_t * size,message_destructor_t * free_message)6750 static uint8_t * parse_msg_cursor_move(uint8_t *message_start, uint8_t *message_end, size_t *size, message_destructor_t *free_message)
6751 {
6752     SPICE_GNUC_UNUSED uint8_t *pos;
6753     uint8_t *start = message_start;
6754     uint8_t *data = NULL;
6755     uint64_t nw_size;
6756     uint64_t mem_size;
6757     uint8_t *in, *end;
6758     SpiceMsgCursorMove *out;
6759 
6760     nw_size = 4;
6761     mem_size = sizeof(SpiceMsgCursorMove);
6762 
6763     /* Check if message fits in reported side */
6764     if (nw_size > (uintptr_t) (message_end - start)) {
6765         return NULL;
6766     }
6767 
6768     /* Validated extents and calculated size */
6769     data = (uint8_t *)(mem_size > UINT32_MAX ? NULL : malloc(mem_size));
6770     if (SPICE_UNLIKELY(data == NULL)) {
6771         goto error;
6772     }
6773     end = data + sizeof(SpiceMsgCursorMove);
6774     in = start;
6775 
6776     out = (SpiceMsgCursorMove *)data;
6777 
6778     /* position */ {
6779         out->position.x = consume_int16(&in);
6780         out->position.y = consume_int16(&in);
6781     }
6782 
6783     assert(in <= message_end);
6784     assert(end <= data + mem_size);
6785 
6786     *size = end - data;
6787     *free_message = (message_destructor_t) free;
6788     return data;
6789 
6790    error:
6791     free(data);
6792     return NULL;
6793 }
6794 
parse_msg_cursor_trail(uint8_t * message_start,uint8_t * message_end,size_t * size,message_destructor_t * free_message)6795 static uint8_t * parse_msg_cursor_trail(uint8_t *message_start, uint8_t *message_end, size_t *size, message_destructor_t *free_message)
6796 {
6797     SPICE_GNUC_UNUSED uint8_t *pos;
6798     uint8_t *start = message_start;
6799     uint8_t *data = NULL;
6800     uint64_t nw_size;
6801     uint64_t mem_size;
6802     uint8_t *in, *end;
6803     SpiceMsgCursorTrail *out;
6804 
6805     nw_size = 4;
6806     mem_size = sizeof(SpiceMsgCursorTrail);
6807 
6808     /* Check if message fits in reported side */
6809     if (nw_size > (uintptr_t) (message_end - start)) {
6810         return NULL;
6811     }
6812 
6813     /* Validated extents and calculated size */
6814     data = (uint8_t *)(mem_size > UINT32_MAX ? NULL : malloc(mem_size));
6815     if (SPICE_UNLIKELY(data == NULL)) {
6816         goto error;
6817     }
6818     end = data + sizeof(SpiceMsgCursorTrail);
6819     in = start;
6820 
6821     out = (SpiceMsgCursorTrail *)data;
6822 
6823     out->length = consume_uint16(&in);
6824     out->frequency = consume_uint16(&in);
6825 
6826     assert(in <= message_end);
6827     assert(end <= data + mem_size);
6828 
6829     *size = end - data;
6830     *free_message = (message_destructor_t) free;
6831     return data;
6832 
6833    error:
6834     free(data);
6835     return NULL;
6836 }
6837 
parse_msg_cursor_inval_one(uint8_t * message_start,uint8_t * message_end,size_t * size,message_destructor_t * free_message)6838 static uint8_t * parse_msg_cursor_inval_one(uint8_t *message_start, uint8_t *message_end, size_t *size, message_destructor_t *free_message)
6839 {
6840     SPICE_GNUC_UNUSED uint8_t *pos;
6841     uint8_t *start = message_start;
6842     uint8_t *data = NULL;
6843     uint64_t nw_size;
6844     uint64_t mem_size;
6845     uint8_t *in, *end;
6846     SpiceMsgDisplayInvalOne *out;
6847 
6848     nw_size = 8;
6849     mem_size = sizeof(SpiceMsgDisplayInvalOne);
6850 
6851     /* Check if message fits in reported side */
6852     if (nw_size > (uintptr_t) (message_end - start)) {
6853         return NULL;
6854     }
6855 
6856     /* Validated extents and calculated size */
6857     data = (uint8_t *)(mem_size > UINT32_MAX ? NULL : malloc(mem_size));
6858     if (SPICE_UNLIKELY(data == NULL)) {
6859         goto error;
6860     }
6861     end = data + sizeof(SpiceMsgDisplayInvalOne);
6862     in = start;
6863 
6864     out = (SpiceMsgDisplayInvalOne *)data;
6865 
6866     out->id = consume_uint64(&in);
6867 
6868     assert(in <= message_end);
6869     assert(end <= data + mem_size);
6870 
6871     *size = end - data;
6872     *free_message = (message_destructor_t) free;
6873     return data;
6874 
6875    error:
6876     free(data);
6877     return NULL;
6878 }
6879 
parse_CursorChannel_msg(uint8_t * message_start,uint8_t * message_end,uint16_t message_type,SPICE_GNUC_UNUSED int minor,size_t * size_out,message_destructor_t * free_message)6880 static uint8_t * parse_CursorChannel_msg(uint8_t *message_start, uint8_t *message_end, uint16_t message_type, SPICE_GNUC_UNUSED int minor, size_t *size_out, message_destructor_t *free_message)
6881 {
6882     static parse_msg_func_t funcs1[8] =  {
6883         parse_msg_migrate,
6884         parse_SpiceMsgData,
6885         parse_msg_set_ack,
6886         parse_msg_ping,
6887         parse_msg_wait_for_channels,
6888         parse_msg_disconnecting,
6889         parse_msg_notify,
6890         parse_SpiceMsgData
6891     };
6892     static parse_msg_func_t funcs2[9] =  {
6893         parse_SpiceMsgEmpty,
6894         parse_msg_cursor_init,
6895         parse_SpiceMsgEmpty,
6896         parse_msg_cursor_set,
6897         parse_msg_cursor_move,
6898         parse_SpiceMsgEmpty,
6899         parse_msg_cursor_trail,
6900         parse_msg_cursor_inval_one,
6901         parse_SpiceMsgEmpty
6902     };
6903     if (message_type >= 1 && message_type < 9) {
6904         return funcs1[message_type-1](message_start, message_end, size_out, free_message);
6905     } else if (message_type >= 100 && message_type < 109) {
6906         return funcs2[message_type-100](message_start, message_end, size_out, free_message);
6907     }
6908     return NULL;
6909 }
6910 
6911 
6912 
parse_msg_playback_data(uint8_t * message_start,uint8_t * message_end,size_t * size,message_destructor_t * free_message)6913 static uint8_t * parse_msg_playback_data(uint8_t *message_start, uint8_t *message_end, size_t *size, message_destructor_t *free_message)
6914 {
6915     SPICE_GNUC_UNUSED uint8_t *pos;
6916     uint8_t *start = message_start;
6917     uint8_t *data = NULL;
6918     uint64_t nw_size;
6919     uint64_t mem_size;
6920     uint8_t *in, *end;
6921     uint64_t data__nw_size;
6922     uint64_t data__nelements;
6923     SpiceMsgPlaybackPacket *out;
6924 
6925     { /* data */
6926         if (SPICE_UNLIKELY((start + 4) > message_end)) {
6927             goto error;
6928         }
6929         data__nelements = message_end - (start + 4);
6930 
6931         data__nw_size = data__nelements;
6932     }
6933 
6934     nw_size = 4 + data__nw_size;
6935     mem_size = sizeof(SpiceMsgPlaybackPacket);
6936 
6937     /* Check if message fits in reported side */
6938     if (nw_size > (uintptr_t) (message_end - start)) {
6939         return NULL;
6940     }
6941 
6942     /* Validated extents and calculated size */
6943     data = (uint8_t *)(mem_size > UINT32_MAX ? NULL : malloc(mem_size));
6944     if (SPICE_UNLIKELY(data == NULL)) {
6945         goto error;
6946     }
6947     end = data + sizeof(SpiceMsgPlaybackPacket);
6948     in = start;
6949 
6950     out = (SpiceMsgPlaybackPacket *)data;
6951 
6952     out->time = consume_uint32(&in);
6953     /* use array as pointer */
6954     out->data = (uint8_t *)in;
6955     out->data_size = data__nelements;
6956     in += data__nelements;
6957 
6958     assert(in <= message_end);
6959     assert(end <= data + mem_size);
6960 
6961     *size = end - data;
6962     *free_message = (message_destructor_t) free;
6963     return data;
6964 
6965    error:
6966     free(data);
6967     return NULL;
6968 }
6969 
parse_msg_playback_mode(uint8_t * message_start,uint8_t * message_end,size_t * size,message_destructor_t * free_message)6970 static uint8_t * parse_msg_playback_mode(uint8_t *message_start, uint8_t *message_end, size_t *size, message_destructor_t *free_message)
6971 {
6972     SPICE_GNUC_UNUSED uint8_t *pos;
6973     uint8_t *start = message_start;
6974     uint8_t *data = NULL;
6975     uint64_t nw_size;
6976     uint64_t mem_size;
6977     uint8_t *in, *end;
6978     uint64_t data__nw_size;
6979     uint64_t data__nelements;
6980     SpiceMsgPlaybackMode *out;
6981 
6982     { /* data */
6983         if (SPICE_UNLIKELY((start + 6) > message_end)) {
6984             goto error;
6985         }
6986         data__nelements = message_end - (start + 6);
6987 
6988         data__nw_size = data__nelements;
6989     }
6990 
6991     nw_size = 6 + data__nw_size;
6992     mem_size = sizeof(SpiceMsgPlaybackMode);
6993 
6994     /* Check if message fits in reported side */
6995     if (nw_size > (uintptr_t) (message_end - start)) {
6996         return NULL;
6997     }
6998 
6999     /* Validated extents and calculated size */
7000     data = (uint8_t *)(mem_size > UINT32_MAX ? NULL : malloc(mem_size));
7001     if (SPICE_UNLIKELY(data == NULL)) {
7002         goto error;
7003     }
7004     end = data + sizeof(SpiceMsgPlaybackMode);
7005     in = start;
7006 
7007     out = (SpiceMsgPlaybackMode *)data;
7008 
7009     out->time = consume_uint32(&in);
7010     out->mode = consume_uint16(&in);
7011     /* use array as pointer */
7012     out->data = (uint8_t *)in;
7013     out->data_size = data__nelements;
7014     in += data__nelements;
7015 
7016     assert(in <= message_end);
7017     assert(end <= data + mem_size);
7018 
7019     *size = end - data;
7020     *free_message = (message_destructor_t) free;
7021     return data;
7022 
7023    error:
7024     free(data);
7025     return NULL;
7026 }
7027 
parse_msg_playback_start(uint8_t * message_start,uint8_t * message_end,size_t * size,message_destructor_t * free_message)7028 static uint8_t * parse_msg_playback_start(uint8_t *message_start, uint8_t *message_end, size_t *size, message_destructor_t *free_message)
7029 {
7030     SPICE_GNUC_UNUSED uint8_t *pos;
7031     uint8_t *start = message_start;
7032     uint8_t *data = NULL;
7033     uint64_t nw_size;
7034     uint64_t mem_size;
7035     uint8_t *in, *end;
7036     SpiceMsgPlaybackStart *out;
7037 
7038     nw_size = 14;
7039     mem_size = sizeof(SpiceMsgPlaybackStart);
7040 
7041     /* Check if message fits in reported side */
7042     if (nw_size > (uintptr_t) (message_end - start)) {
7043         return NULL;
7044     }
7045 
7046     /* Validated extents and calculated size */
7047     data = (uint8_t *)(mem_size > UINT32_MAX ? NULL : malloc(mem_size));
7048     if (SPICE_UNLIKELY(data == NULL)) {
7049         goto error;
7050     }
7051     end = data + sizeof(SpiceMsgPlaybackStart);
7052     in = start;
7053 
7054     out = (SpiceMsgPlaybackStart *)data;
7055 
7056     out->channels = consume_uint32(&in);
7057     out->format = consume_uint16(&in);
7058     out->frequency = consume_uint32(&in);
7059     out->time = consume_uint32(&in);
7060 
7061     assert(in <= message_end);
7062     assert(end <= data + mem_size);
7063 
7064     *size = end - data;
7065     *free_message = (message_destructor_t) free;
7066     return data;
7067 
7068    error:
7069     free(data);
7070     return NULL;
7071 }
7072 
parse_SpiceMsgAudioVolume(uint8_t * message_start,uint8_t * message_end,size_t * size,message_destructor_t * free_message)7073 static uint8_t * parse_SpiceMsgAudioVolume(uint8_t *message_start, uint8_t *message_end, size_t *size, message_destructor_t *free_message)
7074 {
7075     SPICE_GNUC_UNUSED uint8_t *pos;
7076     uint8_t *start = message_start;
7077     uint8_t *data = NULL;
7078     uint64_t nw_size;
7079     uint64_t mem_size;
7080     uint8_t *in, *end;
7081     uint64_t volume__nw_size, volume__mem_size;
7082     uint64_t volume__nelements;
7083     SpiceMsgAudioVolume *out;
7084     uint32_t i;
7085 
7086     { /* volume */
7087         uint8_t nchannels__value;
7088         pos = start + 0;
7089         if (SPICE_UNLIKELY(pos + 1 > message_end)) {
7090             goto error;
7091         }
7092         nchannels__value = read_uint8(pos);
7093         volume__nelements = nchannels__value;
7094 
7095         volume__nw_size = (2) * volume__nelements;
7096         volume__mem_size = sizeof(uint16_t) * volume__nelements;
7097     }
7098 
7099     nw_size = 1 + volume__nw_size;
7100     mem_size = sizeof(SpiceMsgAudioVolume) + volume__mem_size;
7101 
7102     /* Check if message fits in reported side */
7103     if (nw_size > (uintptr_t) (message_end - start)) {
7104         return NULL;
7105     }
7106 
7107     /* Validated extents and calculated size */
7108     data = (uint8_t *)(mem_size > UINT32_MAX ? NULL : malloc(mem_size));
7109     if (SPICE_UNLIKELY(data == NULL)) {
7110         goto error;
7111     }
7112     end = data + sizeof(SpiceMsgAudioVolume);
7113     in = start;
7114 
7115     out = (SpiceMsgAudioVolume *)data;
7116 
7117     out->nchannels = consume_uint8(&in);
7118     for (i = 0; i < volume__nelements; i++) {
7119         out->volume[i] = consume_uint16(&in);
7120         end += sizeof(uint16_t);
7121     }
7122 
7123     assert(in <= message_end);
7124     assert(end <= data + mem_size);
7125 
7126     *size = end - data;
7127     *free_message = (message_destructor_t) free;
7128     return data;
7129 
7130    error:
7131     free(data);
7132     return NULL;
7133 }
7134 
parse_SpiceMsgAudioMute(uint8_t * message_start,uint8_t * message_end,size_t * size,message_destructor_t * free_message)7135 static uint8_t * parse_SpiceMsgAudioMute(uint8_t *message_start, uint8_t *message_end, size_t *size, message_destructor_t *free_message)
7136 {
7137     SPICE_GNUC_UNUSED uint8_t *pos;
7138     uint8_t *start = message_start;
7139     uint8_t *data = NULL;
7140     uint64_t nw_size;
7141     uint64_t mem_size;
7142     uint8_t *in, *end;
7143     SpiceMsgAudioMute *out;
7144 
7145     nw_size = 1;
7146     mem_size = sizeof(SpiceMsgAudioMute);
7147 
7148     /* Check if message fits in reported side */
7149     if (nw_size > (uintptr_t) (message_end - start)) {
7150         return NULL;
7151     }
7152 
7153     /* Validated extents and calculated size */
7154     data = (uint8_t *)(mem_size > UINT32_MAX ? NULL : malloc(mem_size));
7155     if (SPICE_UNLIKELY(data == NULL)) {
7156         goto error;
7157     }
7158     end = data + sizeof(SpiceMsgAudioMute);
7159     in = start;
7160 
7161     out = (SpiceMsgAudioMute *)data;
7162 
7163     out->mute = consume_uint8(&in);
7164 
7165     assert(in <= message_end);
7166     assert(end <= data + mem_size);
7167 
7168     *size = end - data;
7169     *free_message = (message_destructor_t) free;
7170     return data;
7171 
7172    error:
7173     free(data);
7174     return NULL;
7175 }
7176 
parse_msg_playback_latency(uint8_t * message_start,uint8_t * message_end,size_t * size,message_destructor_t * free_message)7177 static uint8_t * parse_msg_playback_latency(uint8_t *message_start, uint8_t *message_end, size_t *size, message_destructor_t *free_message)
7178 {
7179     SPICE_GNUC_UNUSED uint8_t *pos;
7180     uint8_t *start = message_start;
7181     uint8_t *data = NULL;
7182     uint64_t nw_size;
7183     uint64_t mem_size;
7184     uint8_t *in, *end;
7185     SpiceMsgPlaybackLatency *out;
7186 
7187     nw_size = 4;
7188     mem_size = sizeof(SpiceMsgPlaybackLatency);
7189 
7190     /* Check if message fits in reported side */
7191     if (nw_size > (uintptr_t) (message_end - start)) {
7192         return NULL;
7193     }
7194 
7195     /* Validated extents and calculated size */
7196     data = (uint8_t *)(mem_size > UINT32_MAX ? NULL : malloc(mem_size));
7197     if (SPICE_UNLIKELY(data == NULL)) {
7198         goto error;
7199     }
7200     end = data + sizeof(SpiceMsgPlaybackLatency);
7201     in = start;
7202 
7203     out = (SpiceMsgPlaybackLatency *)data;
7204 
7205     out->latency_ms = consume_uint32(&in);
7206 
7207     assert(in <= message_end);
7208     assert(end <= data + mem_size);
7209 
7210     *size = end - data;
7211     *free_message = (message_destructor_t) free;
7212     return data;
7213 
7214    error:
7215     free(data);
7216     return NULL;
7217 }
7218 
parse_PlaybackChannel_msg(uint8_t * message_start,uint8_t * message_end,uint16_t message_type,SPICE_GNUC_UNUSED int minor,size_t * size_out,message_destructor_t * free_message)7219 static uint8_t * parse_PlaybackChannel_msg(uint8_t *message_start, uint8_t *message_end, uint16_t message_type, SPICE_GNUC_UNUSED int minor, size_t *size_out, message_destructor_t *free_message)
7220 {
7221     static parse_msg_func_t funcs1[8] =  {
7222         parse_msg_migrate,
7223         parse_SpiceMsgData,
7224         parse_msg_set_ack,
7225         parse_msg_ping,
7226         parse_msg_wait_for_channels,
7227         parse_msg_disconnecting,
7228         parse_msg_notify,
7229         parse_SpiceMsgData
7230     };
7231     static parse_msg_func_t funcs2[8] =  {
7232         parse_SpiceMsgEmpty,
7233         parse_msg_playback_data,
7234         parse_msg_playback_mode,
7235         parse_msg_playback_start,
7236         parse_SpiceMsgEmpty,
7237         parse_SpiceMsgAudioVolume,
7238         parse_SpiceMsgAudioMute,
7239         parse_msg_playback_latency
7240     };
7241     if (message_type >= 1 && message_type < 9) {
7242         return funcs1[message_type-1](message_start, message_end, size_out, free_message);
7243     } else if (message_type >= 100 && message_type < 108) {
7244         return funcs2[message_type-100](message_start, message_end, size_out, free_message);
7245     }
7246     return NULL;
7247 }
7248 
7249 
7250 
parse_msg_record_start(uint8_t * message_start,uint8_t * message_end,size_t * size,message_destructor_t * free_message)7251 static uint8_t * parse_msg_record_start(uint8_t *message_start, uint8_t *message_end, size_t *size, message_destructor_t *free_message)
7252 {
7253     SPICE_GNUC_UNUSED uint8_t *pos;
7254     uint8_t *start = message_start;
7255     uint8_t *data = NULL;
7256     uint64_t nw_size;
7257     uint64_t mem_size;
7258     uint8_t *in, *end;
7259     SpiceMsgRecordStart *out;
7260 
7261     nw_size = 10;
7262     mem_size = sizeof(SpiceMsgRecordStart);
7263 
7264     /* Check if message fits in reported side */
7265     if (nw_size > (uintptr_t) (message_end - start)) {
7266         return NULL;
7267     }
7268 
7269     /* Validated extents and calculated size */
7270     data = (uint8_t *)(mem_size > UINT32_MAX ? NULL : malloc(mem_size));
7271     if (SPICE_UNLIKELY(data == NULL)) {
7272         goto error;
7273     }
7274     end = data + sizeof(SpiceMsgRecordStart);
7275     in = start;
7276 
7277     out = (SpiceMsgRecordStart *)data;
7278 
7279     out->channels = consume_uint32(&in);
7280     out->format = consume_uint16(&in);
7281     out->frequency = consume_uint32(&in);
7282 
7283     assert(in <= message_end);
7284     assert(end <= data + mem_size);
7285 
7286     *size = end - data;
7287     *free_message = (message_destructor_t) free;
7288     return data;
7289 
7290    error:
7291     free(data);
7292     return NULL;
7293 }
7294 
parse_RecordChannel_msg(uint8_t * message_start,uint8_t * message_end,uint16_t message_type,SPICE_GNUC_UNUSED int minor,size_t * size_out,message_destructor_t * free_message)7295 static uint8_t * parse_RecordChannel_msg(uint8_t *message_start, uint8_t *message_end, uint16_t message_type, SPICE_GNUC_UNUSED int minor, size_t *size_out, message_destructor_t *free_message)
7296 {
7297     static parse_msg_func_t funcs1[8] =  {
7298         parse_msg_migrate,
7299         parse_SpiceMsgData,
7300         parse_msg_set_ack,
7301         parse_msg_ping,
7302         parse_msg_wait_for_channels,
7303         parse_msg_disconnecting,
7304         parse_msg_notify,
7305         parse_SpiceMsgData
7306     };
7307     static parse_msg_func_t funcs2[5] =  {
7308         parse_SpiceMsgEmpty,
7309         parse_msg_record_start,
7310         parse_SpiceMsgEmpty,
7311         parse_SpiceMsgAudioVolume,
7312         parse_SpiceMsgAudioMute
7313     };
7314     if (message_type >= 1 && message_type < 9) {
7315         return funcs1[message_type-1](message_start, message_end, size_out, free_message);
7316     } else if (message_type >= 100 && message_type < 105) {
7317         return funcs2[message_type-100](message_start, message_end, size_out, free_message);
7318     }
7319     return NULL;
7320 }
7321 
7322 
7323 
parse_TunnelChannel_msg(uint8_t * message_start,uint8_t * message_end,uint16_t message_type,SPICE_GNUC_UNUSED int minor,size_t * size_out,message_destructor_t * free_message)7324 static uint8_t * parse_TunnelChannel_msg(uint8_t *message_start, uint8_t *message_end, uint16_t message_type, SPICE_GNUC_UNUSED int minor, size_t *size_out, message_destructor_t *free_message)
7325 {
7326 
7327     return NULL;
7328 }
7329 
7330 
7331 #ifdef USE_SMARTCARD
7332 
parse_msg_smartcard_data(uint8_t * message_start,uint8_t * message_end,size_t * size,message_destructor_t * free_message)7333 static uint8_t * parse_msg_smartcard_data(uint8_t *message_start, uint8_t *message_end, size_t *size, message_destructor_t *free_message)
7334 {
7335     SPICE_GNUC_UNUSED uint8_t *pos;
7336     uint8_t *start = message_start;
7337     uint8_t *data = NULL;
7338     uint64_t nw_size;
7339     uint64_t mem_size;
7340     uint8_t *in, *end;
7341     uint64_t data__nw_size, data__mem_size;
7342     uint64_t data__nelements;
7343     SpiceMsgSmartcard *out;
7344 
7345     { /* data */
7346         uint32_t length__value;
7347         pos = start + 8;
7348         if (SPICE_UNLIKELY(pos + 4 > message_end)) {
7349             goto error;
7350         }
7351         length__value = read_uint32(pos);
7352         data__nelements = length__value;
7353 
7354         data__nw_size = data__nelements;
7355         data__mem_size = sizeof(uint8_t) * data__nelements;
7356     }
7357 
7358     nw_size = 12 + data__nw_size;
7359     mem_size = sizeof(SpiceMsgSmartcard) + data__mem_size;
7360 
7361     /* Check if message fits in reported side */
7362     if (nw_size > (uintptr_t) (message_end - start)) {
7363         return NULL;
7364     }
7365 
7366     /* Validated extents and calculated size */
7367     data = (uint8_t *)(mem_size > UINT32_MAX ? NULL : malloc(mem_size));
7368     if (SPICE_UNLIKELY(data == NULL)) {
7369         goto error;
7370     }
7371     end = data + sizeof(SpiceMsgSmartcard);
7372     in = start;
7373 
7374     out = (SpiceMsgSmartcard *)data;
7375 
7376     out->type = consume_uint32(&in);
7377     out->reader_id = consume_uint32(&in);
7378     out->length = consume_uint32(&in);
7379     memcpy(out->data, in, data__nelements);
7380     in += data__nelements;
7381     end += data__nelements;
7382 
7383     assert(in <= message_end);
7384     assert(end <= data + mem_size);
7385 
7386     *size = end - data;
7387     *free_message = (message_destructor_t) free;
7388     return data;
7389 
7390    error:
7391     free(data);
7392     return NULL;
7393 }
7394 
parse_SmartcardChannel_msg(uint8_t * message_start,uint8_t * message_end,uint16_t message_type,SPICE_GNUC_UNUSED int minor,size_t * size_out,message_destructor_t * free_message)7395 static uint8_t * parse_SmartcardChannel_msg(uint8_t *message_start, uint8_t *message_end, uint16_t message_type, SPICE_GNUC_UNUSED int minor, size_t *size_out, message_destructor_t *free_message)
7396 {
7397     static parse_msg_func_t funcs1[8] =  {
7398         parse_msg_migrate,
7399         parse_SpiceMsgData,
7400         parse_msg_set_ack,
7401         parse_msg_ping,
7402         parse_msg_wait_for_channels,
7403         parse_msg_disconnecting,
7404         parse_msg_notify,
7405         parse_SpiceMsgData
7406     };
7407     static parse_msg_func_t funcs2[2] =  {
7408         parse_SpiceMsgEmpty,
7409         parse_msg_smartcard_data
7410     };
7411     if (message_type >= 1 && message_type < 9) {
7412         return funcs1[message_type-1](message_start, message_end, size_out, free_message);
7413     } else if (message_type >= 100 && message_type < 102) {
7414         return funcs2[message_type-100](message_start, message_end, size_out, free_message);
7415     }
7416     return NULL;
7417 }
7418 #endif /* USE_SMARTCARD */
7419 
7420 
7421 
parse_SpiceMsgCompressedData(uint8_t * message_start,uint8_t * message_end,size_t * size,message_destructor_t * free_message)7422 static uint8_t * parse_SpiceMsgCompressedData(uint8_t *message_start, uint8_t *message_end, size_t *size, message_destructor_t *free_message)
7423 {
7424     SPICE_GNUC_UNUSED uint8_t *pos;
7425     uint8_t *start = message_start;
7426     uint8_t *data = NULL;
7427     uint64_t nw_size;
7428     uint64_t mem_size;
7429     uint8_t *in, *end;
7430     uint64_t u__nw_size;
7431     uint8_t type__value;
7432     uint64_t compressed_data__nw_size;
7433     uint64_t compressed_data__nelements;
7434     SpiceMsgCompressedData *out;
7435 
7436     { /* u */
7437         pos = start + 0;
7438         if (SPICE_UNLIKELY(pos + 1 > message_end)) {
7439             goto error;
7440         }
7441         type__value = read_uint8(pos);
7442         if (type__value == SPICE_DATA_COMPRESSION_TYPE_NONE) {
7443             SPICE_GNUC_UNUSED uint8_t *start2 = (start + 1);
7444             u__nw_size = 0;
7445         } else if (1) {
7446             u__nw_size = 4;
7447         } else {
7448             u__nw_size = 0;
7449         }
7450 
7451     }
7452 
7453     { /* compressed_data */
7454         if (SPICE_UNLIKELY((start + 1 + u__nw_size) > message_end)) {
7455             goto error;
7456         }
7457         compressed_data__nelements = message_end - (start + 1 + u__nw_size);
7458 
7459         compressed_data__nw_size = compressed_data__nelements;
7460     }
7461 
7462     nw_size = 1 + u__nw_size + compressed_data__nw_size;
7463     mem_size = sizeof(SpiceMsgCompressedData);
7464 
7465     /* Check if message fits in reported side */
7466     if (nw_size > (uintptr_t) (message_end - start)) {
7467         return NULL;
7468     }
7469 
7470     /* Validated extents and calculated size */
7471     data = (uint8_t *)(mem_size > UINT32_MAX ? NULL : malloc(mem_size));
7472     if (SPICE_UNLIKELY(data == NULL)) {
7473         goto error;
7474     }
7475     end = data + sizeof(SpiceMsgCompressedData);
7476     in = start;
7477 
7478     out = (SpiceMsgCompressedData *)data;
7479 
7480     out->type = consume_uint8(&in);
7481     if (out->type == SPICE_DATA_COMPRESSION_TYPE_NONE) {
7482     } else if (1) {
7483         out->uncompressed_size = consume_uint32(&in);
7484     }
7485     /* use array as pointer */
7486     out->compressed_data = (uint8_t *)in;
7487     out->compressed_size = compressed_data__nelements;
7488     in += compressed_data__nelements;
7489 
7490     assert(in <= message_end);
7491     assert(end <= data + mem_size);
7492 
7493     *size = end - data;
7494     *free_message = (message_destructor_t) free;
7495     return data;
7496 
7497    error:
7498     free(data);
7499     return NULL;
7500 }
7501 
parse_UsbredirChannel_msg(uint8_t * message_start,uint8_t * message_end,uint16_t message_type,SPICE_GNUC_UNUSED int minor,size_t * size_out,message_destructor_t * free_message)7502 static uint8_t * parse_UsbredirChannel_msg(uint8_t *message_start, uint8_t *message_end, uint16_t message_type, SPICE_GNUC_UNUSED int minor, size_t *size_out, message_destructor_t *free_message)
7503 {
7504     static parse_msg_func_t funcs1[8] =  {
7505         parse_msg_migrate,
7506         parse_SpiceMsgData,
7507         parse_msg_set_ack,
7508         parse_msg_ping,
7509         parse_msg_wait_for_channels,
7510         parse_msg_disconnecting,
7511         parse_msg_notify,
7512         parse_SpiceMsgData
7513     };
7514     static parse_msg_func_t funcs2[3] =  {
7515         parse_SpiceMsgEmpty,
7516         parse_SpiceMsgData,
7517         parse_SpiceMsgCompressedData
7518     };
7519     if (message_type >= 1 && message_type < 9) {
7520         return funcs1[message_type-1](message_start, message_end, size_out, free_message);
7521     } else if (message_type >= 100 && message_type < 103) {
7522         return funcs2[message_type-100](message_start, message_end, size_out, free_message);
7523     }
7524     return NULL;
7525 }
7526 
7527 
7528 
parse_msg_port_init(uint8_t * message_start,uint8_t * message_end,size_t * size,message_destructor_t * free_message)7529 static uint8_t * parse_msg_port_init(uint8_t *message_start, uint8_t *message_end, size_t *size, message_destructor_t *free_message)
7530 {
7531     SPICE_GNUC_UNUSED uint8_t *pos;
7532     uint8_t *start = message_start;
7533     uint8_t *data = NULL;
7534     uint64_t nw_size;
7535     uint64_t mem_size;
7536     uint8_t *in, *end;
7537     SPICE_GNUC_UNUSED intptr_t ptr_size;
7538     uint32_t n_ptr=0;
7539     PointerInfo ptr_info[1];
7540     uint64_t name__extra_size;
7541     uint64_t name__array__nelements;
7542     SpiceMsgPortInit *out;
7543     uint32_t i;
7544 
7545     { /* name */
7546         uint32_t name__value;
7547         uint64_t name__array__nw_size;
7548         uint64_t name__array__mem_size;
7549         uint32_t name_size__value;
7550         pos = (start + 4);
7551         if (SPICE_UNLIKELY(pos + 4 > message_end)) {
7552             goto error;
7553         }
7554         name__value = read_uint32(pos);
7555         if (SPICE_UNLIKELY(name__value == 0)) {
7556             goto error;
7557         }
7558         if (SPICE_UNLIKELY(name__value >= (uintptr_t) (message_end - message_start))) {
7559             goto error;
7560         }
7561         pos = start + 0;
7562         if (SPICE_UNLIKELY(pos + 4 > message_end)) {
7563             goto error;
7564         }
7565         name_size__value = read_uint32(pos);
7566         name__array__nelements = name_size__value;
7567 
7568         name__array__nw_size = name__array__nelements;
7569         name__array__mem_size = sizeof(uint8_t) * name__array__nelements;
7570         if (SPICE_UNLIKELY(name__value + name__array__nw_size > (uintptr_t) (message_end - message_start))) {
7571             goto error;
7572         }
7573         name__extra_size = name__array__mem_size + /* for alignment */ 3;
7574     }
7575 
7576     nw_size = 9;
7577     mem_size = sizeof(SpiceMsgPortInit) + name__extra_size;
7578 
7579     /* Check if message fits in reported side */
7580     if (nw_size > (uintptr_t) (message_end - start)) {
7581         return NULL;
7582     }
7583 
7584     /* Validated extents and calculated size */
7585     data = (uint8_t *)(mem_size > UINT32_MAX ? NULL : malloc(mem_size));
7586     if (SPICE_UNLIKELY(data == NULL)) {
7587         goto error;
7588     }
7589     end = data + sizeof(SpiceMsgPortInit);
7590     in = start;
7591 
7592     out = (SpiceMsgPortInit *)data;
7593 
7594     out->name_size = consume_uint32(&in);
7595     ptr_info[n_ptr].offset = consume_uint32(&in);
7596     ptr_info[n_ptr].parse = parse_array_uint8;
7597     ptr_info[n_ptr].dest = (void **)&out->name;
7598     ptr_info[n_ptr].nelements = name__array__nelements;
7599     n_ptr++;
7600     out->opened = consume_uint8(&in);
7601 
7602     assert(in <= message_end);
7603 
7604     for (i = 0; i < n_ptr; i++) {
7605         if (ptr_info[i].offset == 0) {
7606             *ptr_info[i].dest = NULL;
7607         } else {
7608             /* Align to 32 bit */
7609             end = (uint8_t *)SPICE_ALIGN((uintptr_t)end, 4);
7610             *ptr_info[i].dest = (void *)end;
7611             end = ptr_info[i].parse(message_start, message_end, end, &ptr_info[i]);
7612             if (SPICE_UNLIKELY(end == NULL)) {
7613                 goto error;
7614             }
7615         }
7616     }
7617 
7618     assert(end <= data + mem_size);
7619 
7620     *size = end - data;
7621     *free_message = (message_destructor_t) free;
7622     return data;
7623 
7624    error:
7625     free(data);
7626     return NULL;
7627 }
7628 
parse_msg_port_event(uint8_t * message_start,uint8_t * message_end,size_t * size,message_destructor_t * free_message)7629 static uint8_t * parse_msg_port_event(uint8_t *message_start, uint8_t *message_end, size_t *size, message_destructor_t *free_message)
7630 {
7631     SPICE_GNUC_UNUSED uint8_t *pos;
7632     uint8_t *start = message_start;
7633     uint8_t *data = NULL;
7634     uint64_t nw_size;
7635     uint64_t mem_size;
7636     uint8_t *in, *end;
7637     SpiceMsgPortEvent *out;
7638 
7639     nw_size = 1;
7640     mem_size = sizeof(SpiceMsgPortEvent);
7641 
7642     /* Check if message fits in reported side */
7643     if (nw_size > (uintptr_t) (message_end - start)) {
7644         return NULL;
7645     }
7646 
7647     /* Validated extents and calculated size */
7648     data = (uint8_t *)(mem_size > UINT32_MAX ? NULL : malloc(mem_size));
7649     if (SPICE_UNLIKELY(data == NULL)) {
7650         goto error;
7651     }
7652     end = data + sizeof(SpiceMsgPortEvent);
7653     in = start;
7654 
7655     out = (SpiceMsgPortEvent *)data;
7656 
7657     out->event = consume_uint8(&in);
7658 
7659     assert(in <= message_end);
7660     assert(end <= data + mem_size);
7661 
7662     *size = end - data;
7663     *free_message = (message_destructor_t) free;
7664     return data;
7665 
7666    error:
7667     free(data);
7668     return NULL;
7669 }
7670 
parse_PortChannel_msg(uint8_t * message_start,uint8_t * message_end,uint16_t message_type,SPICE_GNUC_UNUSED int minor,size_t * size_out,message_destructor_t * free_message)7671 static uint8_t * parse_PortChannel_msg(uint8_t *message_start, uint8_t *message_end, uint16_t message_type, SPICE_GNUC_UNUSED int minor, size_t *size_out, message_destructor_t *free_message)
7672 {
7673     static parse_msg_func_t funcs1[8] =  {
7674         parse_msg_migrate,
7675         parse_SpiceMsgData,
7676         parse_msg_set_ack,
7677         parse_msg_ping,
7678         parse_msg_wait_for_channels,
7679         parse_msg_disconnecting,
7680         parse_msg_notify,
7681         parse_SpiceMsgData
7682     };
7683     static parse_msg_func_t funcs2[3] =  {
7684         parse_SpiceMsgEmpty,
7685         parse_SpiceMsgData,
7686         parse_SpiceMsgCompressedData
7687     };
7688     static parse_msg_func_t funcs3[2] =  {
7689         parse_msg_port_init,
7690         parse_msg_port_event
7691     };
7692     if (message_type >= 1 && message_type < 9) {
7693         return funcs1[message_type-1](message_start, message_end, size_out, free_message);
7694     } else if (message_type >= 100 && message_type < 103) {
7695         return funcs2[message_type-100](message_start, message_end, size_out, free_message);
7696     } else if (message_type >= 201 && message_type < 203) {
7697         return funcs3[message_type-201](message_start, message_end, size_out, free_message);
7698     }
7699     return NULL;
7700 }
7701 
7702 
7703 
parse_WebDAVChannel_msg(uint8_t * message_start,uint8_t * message_end,uint16_t message_type,SPICE_GNUC_UNUSED int minor,size_t * size_out,message_destructor_t * free_message)7704 static uint8_t * parse_WebDAVChannel_msg(uint8_t *message_start, uint8_t *message_end, uint16_t message_type, SPICE_GNUC_UNUSED int minor, size_t *size_out, message_destructor_t *free_message)
7705 {
7706     static parse_msg_func_t funcs1[8] =  {
7707         parse_msg_migrate,
7708         parse_SpiceMsgData,
7709         parse_msg_set_ack,
7710         parse_msg_ping,
7711         parse_msg_wait_for_channels,
7712         parse_msg_disconnecting,
7713         parse_msg_notify,
7714         parse_SpiceMsgData
7715     };
7716     static parse_msg_func_t funcs2[3] =  {
7717         parse_SpiceMsgEmpty,
7718         parse_SpiceMsgData,
7719         parse_SpiceMsgCompressedData
7720     };
7721     static parse_msg_func_t funcs3[2] =  {
7722         parse_msg_port_init,
7723         parse_msg_port_event
7724     };
7725     if (message_type >= 1 && message_type < 9) {
7726         return funcs1[message_type-1](message_start, message_end, size_out, free_message);
7727     } else if (message_type >= 100 && message_type < 103) {
7728         return funcs2[message_type-100](message_start, message_end, size_out, free_message);
7729     } else if (message_type >= 201 && message_type < 203) {
7730         return funcs3[message_type-201](message_start, message_end, size_out, free_message);
7731     }
7732     return NULL;
7733 }
7734 
spice_get_server_channel_parser(uint32_t channel,unsigned int * max_message_type)7735 spice_parse_channel_func_t spice_get_server_channel_parser(uint32_t channel, unsigned int *max_message_type)
7736 {
7737     static struct {spice_parse_channel_func_t func; unsigned int max_messages; } channels[12] =  {
7738         { NULL, 0 },
7739         { parse_MainChannel_msg, 118},
7740         { parse_DisplayChannel_msg, 321},
7741         { parse_InputsChannel_msg, 111},
7742         { parse_CursorChannel_msg, 108},
7743         { parse_PlaybackChannel_msg, 107},
7744         { parse_RecordChannel_msg, 104},
7745         { parse_TunnelChannel_msg, 0},
7746 #ifdef USE_SMARTCARD
7747         { parse_SmartcardChannel_msg, 101},
7748 #else /* USE_SMARTCARD */
7749         { NULL, 0 },
7750 #endif /* USE_SMARTCARD */
7751         { parse_UsbredirChannel_msg, 102},
7752         { parse_PortChannel_msg, 202},
7753         { parse_WebDAVChannel_msg, 202}
7754     };
7755     if (channel < 12) {
7756         if (max_message_type != NULL) {
7757             *max_message_type = channels[channel].max_messages;
7758         }
7759         return channels[channel].func;
7760     }
7761     return NULL;
7762 }
7763 
spice_parse_msg(uint8_t * message_start,uint8_t * message_end,uint32_t channel,uint16_t message_type,SPICE_GNUC_UNUSED int minor,size_t * size_out,message_destructor_t * free_message)7764 uint8_t * spice_parse_msg(uint8_t *message_start, uint8_t *message_end, uint32_t channel, uint16_t message_type, SPICE_GNUC_UNUSED int minor, size_t *size_out, message_destructor_t *free_message)
7765 {
7766     spice_parse_channel_func_t func;
7767     func = spice_get_server_channel_parser(channel, NULL);
7768     if (func != NULL) {
7769         return func(message_start, message_end, message_type, minor, size_out, free_message);
7770     }
7771     return NULL;
7772 }
7773