Line data Source code
1 : /*
2 : Copyright (C) 2015-2021 Red Hat, Inc.
3 :
4 : This library is free software; you can redistribute it and/or
5 : modify it under the terms of the GNU Lesser General Public
6 : License as published by the Free Software Foundation; either
7 : version 2.1 of the License, or (at your option) any later version.
8 :
9 : This library is distributed in the hope that it will be useful,
10 : but WITHOUT ANY WARRANTY; without even the implied warranty of
11 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 : Lesser General Public License for more details.
13 :
14 : You should have received a copy of the GNU Lesser General Public
15 : License along with this library; if not, see <http://www.gnu.org/licenses/>.
16 : */
17 : #include <config.h>
18 :
19 : #include <glib.h>
20 : #include <string.h>
21 :
22 : #include <common/marshaller.h>
23 : #include <common/demarshallers.h>
24 : #include "generated_test_enums.h"
25 : #include "generated_test_marshallers.h"
26 :
27 : #ifndef g_assert_true
28 : #define g_assert_true g_assert
29 : #endif
30 :
31 : #define NUM_CHANNELS 3u
32 :
33 : spice_parse_channel_func_t
34 : spice_get_server_channel_parser_test(uint32_t channel, unsigned int *max_message_type);
35 :
36 1 : static void test_overflow(SpiceMarshaller *m)
37 : {
38 : SpiceMsgChannels *msg;
39 : uint8_t *data, *out;
40 : size_t len;
41 1 : int to_free = 0;
42 : spice_parse_channel_func_t func;
43 : unsigned int max_message_type, n;
44 : message_destructor_t free_output;
45 :
46 1 : msg = (SpiceMsgChannels *) malloc(sizeof(SpiceMsgChannels) +
47 : NUM_CHANNELS * sizeof(uint16_t));
48 1 : g_assert_nonnull(msg);
49 :
50 : // build a message and marshal it
51 1 : msg->num_of_channels = NUM_CHANNELS;
52 4 : for (n = 0; n < NUM_CHANNELS; ++n) {
53 3 : msg->channels[n] = n + 1;
54 : }
55 1 : spice_marshall_msg_main_channels_list(m, msg);
56 :
57 : // get linear data
58 1 : data = spice_marshaller_linearize(m, 0, &len, &to_free);
59 1 : g_assert_nonnull(data);
60 :
61 1 : printf("output len %lu\n", (unsigned long) len);
62 :
63 : // hack: setting the number of channels in the marshalled message to a
64 : // value that will cause overflow while parsing the message to make sure
65 : // that the parser can handle this situation
66 1 : *((uint32_t *) data) = 0x80000002u;
67 :
68 : // extract the message
69 1 : func = spice_get_server_channel_parser_test(SPICE_CHANNEL_MAIN, &max_message_type);
70 1 : g_assert_nonnull(func);
71 1 : out = func(data, data+len, SPICE_MSG_MAIN_CHANNELS_LIST, 0, &len, &free_output);
72 1 : g_assert_null(out);
73 :
74 : // cleanup
75 1 : if (to_free) {
76 0 : free(data);
77 : }
78 1 : if (out) {
79 0 : free_output(out);
80 : }
81 1 : free(msg);
82 1 : }
83 :
84 : static uint8_t expected_data[] = { 123, /* dummy byte */
85 : 0x02, 0x00, 0x00, 0x00, /* data_size */
86 : 0x09, 0x00, 0x00, 0x00, /* data offset */
87 : 0xef, 0xcd, 0xab, 0x90, 0x78, 0x56, 0x34, 0x12, /* data */
88 : 0x21, 0x43, 0x65, 0x87, 0x09, 0xba, 0xdc, 0xfe, /* data */
89 : };
90 :
91 : typedef void (*message_destructor_t)(uint8_t *message);
92 : uint8_t * spice_parse_msg_test(uint8_t *message_start, uint8_t *message_end,
93 : uint32_t channel, uint16_t message_type, int minor,
94 : size_t *size_out, message_destructor_t *free_message);
95 :
96 1 : static void test_zerolen1(void)
97 : {
98 : static uint8_t data[] = {
99 : 'd', 'a', 't', 'a', // txt1
100 : 123, // sep1
101 : 4, 0, 0, 0, // len
102 : 26, 0, 0, 0, // ptr to txt2
103 : 'n','e','k','o', // txt3
104 : 12, 13, 14, 15, // n
105 : 3, 0, // txt4_len
106 : 'b','a','r', // txt4
107 : 'f', 'o', 'o', '!', // string
108 : 'x', 'x', // garbage at the end
109 : };
110 :
111 : size_t msg_len;
112 : message_destructor_t free_message;
113 :
114 : // demarshal array with @zero_terminated data
115 : SpiceMsgMainZeroLen1 *msg = (SpiceMsgMainZeroLen1 *)
116 1 : spice_parse_msg_test(data, data + sizeof(data), SPICE_CHANNEL_MAIN, SPICE_MSG_MAIN_ZEROLEN1,
117 : 0, &msg_len, &free_message);
118 :
119 1 : g_assert_nonnull(msg);
120 1 : g_assert_cmpmem(msg->txt1, 5, "data", 5);
121 1 : g_assert_cmpint(msg->sep1, ==, 123);
122 1 : g_assert_cmpint(msg->txt2_len, ==, 4);
123 1 : g_assert_cmpint(msg->n , ==, 0x0f0e0d0c);
124 1 : g_assert_nonnull(msg->txt2);
125 1 : g_assert_cmpmem(msg->txt2, 5, "foo!", 5);
126 1 : g_assert_nonnull(msg->txt3);
127 1 : g_assert_cmpmem(msg->txt3, 5, "neko", 5);
128 1 : g_assert_cmpint(msg->txt4_len, ==, 3);
129 1 : g_assert_cmpmem(msg->txt4, 4, "bar", 4);
130 :
131 1 : free_message((uint8_t *) msg);
132 1 : }
133 :
134 1 : int main(void)
135 : {
136 : SpiceMarshaller *marshaller;
137 : SpiceMsgMainShortDataSubMarshall *msg;
138 : size_t len, msg_len;
139 : int free_res;
140 : uint8_t *data;
141 : message_destructor_t free_message;
142 :
143 1 : msg = g_new0(SpiceMsgMainShortDataSubMarshall, 1);
144 1 : msg->data = g_new(uint64_t, 2);
145 1 : msg->dummy_byte = 123;
146 1 : msg->data_size = 2;
147 1 : msg->data[0] = 0x1234567890abcdef;
148 1 : msg->data[1] = 0xfedcba0987654321;
149 :
150 1 : marshaller = spice_marshaller_new();
151 1 : spice_marshall_msg_main_ShortDataSubMarshall(marshaller, msg);
152 1 : spice_marshaller_flush(marshaller);
153 1 : data = spice_marshaller_linearize(marshaller, 0, &len, &free_res);
154 1 : g_assert_cmpint(len, ==, G_N_ELEMENTS(expected_data));
155 1 : g_assert_true(memcmp(data, expected_data, len) == 0);
156 :
157 1 : g_free(msg->data);
158 1 : g_free(msg);
159 :
160 : // test demarshaller
161 : msg = (SpiceMsgMainShortDataSubMarshall *)
162 1 : spice_parse_msg_test(data, data + len, SPICE_CHANNEL_MAIN,
163 : SPICE_MSG_MAIN_SHORTDATASUBMARSHALL,
164 : 0, &msg_len, &free_message);
165 :
166 1 : g_assert_nonnull(msg);
167 1 : g_assert_cmpint(msg->dummy_byte, ==, 123);
168 1 : g_assert_cmpint(msg->data_size, ==, 2);
169 1 : g_assert_nonnull(msg->data);
170 1 : g_assert_cmpint(msg->data[0], ==, 0x1234567890abcdef);
171 1 : g_assert_cmpint(msg->data[1], ==, 0xfedcba0987654321);
172 :
173 1 : free_message((uint8_t *) msg);
174 :
175 1 : if (free_res) {
176 1 : free(data);
177 : }
178 1 : spice_marshaller_reset(marshaller);
179 :
180 1 : test_zerolen1();
181 :
182 1 : SpiceMsgMainZeroes msg_zeroes = { 0x0102 };
183 :
184 1 : spice_marshall_msg_main_Zeroes(marshaller, &msg_zeroes);
185 1 : spice_marshaller_flush(marshaller);
186 1 : data = spice_marshaller_linearize(marshaller, 0, &len, &free_res);
187 1 : g_assert_cmpint(len, ==, 7);
188 1 : g_assert_true(memcmp(data, "\x00\x02\x01\x00\x00\x00\x00", 7) == 0);
189 1 : if (free_res) {
190 0 : free(data);
191 : }
192 :
193 1 : test_overflow(marshaller);
194 :
195 1 : len = 4;
196 1 : data = g_new0(uint8_t, len);
197 1 : memset(data, 0, len);
198 1 : msg = (SpiceMsgMainShortDataSubMarshall *) spice_parse_msg_test(data, data + len, 1, 3, 0,
199 : &msg_len, &free_message);
200 1 : g_assert_null(msg);
201 1 : g_free(data);
202 :
203 1 : spice_marshaller_destroy(marshaller);
204 :
205 1 : return 0;
206 : }
|