spice-common/tests/test-marshallers.c
Frediano Ziglio 2060672e81 Create common header for demarshallers declarations
Code generated for demarshallers define and declare some types and
functions.
However these types and functions are also declared separately in other
headers (currently spice-common/client_demarshallers.h and
spice/server/demarshallers.h) resulting in potential ABI mismatch if the
different declarations do not match.
Using a common header shared between generated code and code using
these functions prevent potentially multiple different declarations.

Signed-off-by: Frediano Ziglio <fziglio@redhat.com>
Acked-by: Christophe Fergeau <cfergeau@redhat.com>
2018-10-15 13:31:16 +01:00

165 lines
5.2 KiB
C

/*
Copyright (C) 2015-2018 Red Hat, Inc.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, see <http://www.gnu.org/licenses/>.
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <glib.h>
#include <string.h>
#include <common/marshaller.h>
#include <common/demarshallers.h>
#include "generated_test_enums.h"
#include "generated_test_marshallers.h"
#ifndef g_assert_true
#define g_assert_true g_assert
#endif
#define NUM_CHANNELS 3u
void test_overflow(SpiceMarshaller *m)
{
SpiceMsgChannels *msg;
uint8_t *data, *out;
size_t len;
int to_free = 0;
spice_parse_channel_func_t func;
unsigned int max_message_type, n;
message_destructor_t free_output;
msg = (SpiceMsgChannels *) malloc(sizeof(SpiceMsgChannels) +
NUM_CHANNELS * sizeof(uint16_t));
g_assert_nonnull(msg);
// build a message and marshal it
msg->num_of_channels = NUM_CHANNELS;
for (n = 0; n < NUM_CHANNELS; ++n) {
msg->channels[n] = n + 1;
}
spice_marshall_msg_main_channels_list(m, msg);
// get linear data
data = spice_marshaller_linearize(m, 0, &len, &to_free);
g_assert_nonnull(data);
printf("output len %lu\n", (unsigned long) len);
// hack: setting the number of channels in the marshalled message to a
// value that will cause overflow while parsing the message to make sure
// that the parser can handle this situation
*((uint32_t *) data) = 0x80000002u;
// extract the message
func = spice_get_server_channel_parser(SPICE_CHANNEL_MAIN, &max_message_type);
g_assert_nonnull(func);
out = func(data, data+len, SPICE_MSG_MAIN_CHANNELS_LIST, 0, &len, &free_output);
g_assert_null(out);
// cleanup
if (to_free) {
free(data);
}
if (out) {
free_output(out);
}
free(msg);
}
static uint8_t expected_data[] = { 123, /* dummy byte */
0x02, 0x00, 0x00, 0x00, /* data_size */
0x09, 0x00, 0x00, 0x00, /* data offset */
0xef, 0xcd, 0xab, 0x90, 0x78, 0x56, 0x34, 0x12, /* data */
0x21, 0x43, 0x65, 0x87, 0x09, 0xba, 0xdc, 0xfe, /* data */
};
typedef void (*message_destructor_t)(uint8_t *message);
uint8_t * spice_parse_msg(uint8_t *message_start, uint8_t *message_end,
uint32_t channel, uint16_t message_type, int minor,
size_t *size_out, message_destructor_t *free_message);
int main(int argc G_GNUC_UNUSED, char **argv G_GNUC_UNUSED)
{
SpiceMarshaller *marshaller;
SpiceMsgMainShortDataSubMarshall *msg;
size_t len, msg_len;
int free_res;
uint8_t *data;
message_destructor_t free_message;
msg = g_new0(SpiceMsgMainShortDataSubMarshall, 1);
msg->data = g_new(uint64_t, 2);
msg->dummy_byte = 123;
msg->data_size = 2;
msg->data[0] = 0x1234567890abcdef;
msg->data[1] = 0xfedcba0987654321;
marshaller = spice_marshaller_new();
spice_marshall_msg_main_ShortDataSubMarshall(marshaller, msg);
spice_marshaller_flush(marshaller);
data = spice_marshaller_linearize(marshaller, 0, &len, &free_res);
g_assert_cmpint(len, ==, G_N_ELEMENTS(expected_data));
g_assert_true(memcmp(data, expected_data, len) == 0);
g_free(msg->data);
g_free(msg);
// test demarshaller
msg = (SpiceMsgMainShortDataSubMarshall *)
spice_parse_msg(data, data + len, SPICE_CHANNEL_MAIN, SPICE_MSG_MAIN_SHORTDATASUBMARSHALL,
0, &msg_len, &free_message);
g_assert_nonnull(msg);
g_assert_cmpint(msg->dummy_byte, ==, 123);
g_assert_cmpint(msg->data_size, ==, 2);
g_assert_nonnull(msg->data);
g_assert_cmpint(msg->data[0], ==, 0x1234567890abcdef);
g_assert_cmpint(msg->data[1], ==, 0xfedcba0987654321);
free_message((uint8_t *) msg);
if (free_res) {
free(data);
}
spice_marshaller_reset(marshaller);
SpiceMsgMainZeroes msg_zeroes = { 0x0102 };
spice_marshall_msg_main_Zeroes(marshaller, &msg_zeroes);
spice_marshaller_flush(marshaller);
data = spice_marshaller_linearize(marshaller, 0, &len, &free_res);
g_assert_cmpint(len, ==, 7);
g_assert_true(memcmp(data, "\x00\x02\x01\x00\x00\x00\x00", 7) == 0);
if (free_res) {
free(data);
}
test_overflow(marshaller);
len = 4;
data = g_new0(uint8_t, len);
memset(data, 0, len);
msg = (SpiceMsgMainShortDataSubMarshall *) spice_parse_msg(data, data + len, 1, 3, 0,
&msg_len, &free_message);
g_assert_null(msg);
g_free(data);
spice_marshaller_destroy(marshaller);
return 0;
}