aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAleksander Morgado <aleksander@lanedo.com>2013-05-28 15:33:57 +0200
committerAleksander Morgado <aleksander@lanedo.com>2013-05-31 08:12:23 +0200
commit9cc1c7e7793bacc17e4e167b55053cb86cfb3ae8 (patch)
tree21db446c8cbb041d97843d3c7cfe40e28aa99d47
parent14c50e01264e6326d4ad66f46c3e9c71d8621f7b (diff)
downloadexternal_libqmi-9cc1c7e7793bacc17e4e167b55053cb86cfb3ae8.zip
external_libqmi-9cc1c7e7793bacc17e4e167b55053cb86cfb3ae8.tar.gz
external_libqmi-9cc1c7e7793bacc17e4e167b55053cb86cfb3ae8.tar.bz2
libqmi-glib,utils: fix reading sized uint from Big Endian buffers
When reading a sized Little Endian uint from a buffer, we just need to read N bytes from the buffer and place them at the beginning of a new 8-byte buffer, (as if it were a guint64) and finally convert from LE to HE. But when reading a sized Big Endian uint from a buffer, the N bytes that we read from the beginning of the buffer need to be placed at the *end* of the new 8-byte buffer before converting from BE to HE. Sized integers are used to read e.g. 6-byte integers, like part of the 'Device Time' TLV in the 'DMS Get Time' call. https://bugs.freedesktop.org/show_bug.cgi?id=65078
-rw-r--r--libqmi-glib/qmi-utils.c33
-rw-r--r--libqmi-glib/test/test-utils.c164
2 files changed, 159 insertions, 38 deletions
diff --git a/libqmi-glib/qmi-utils.c b/libqmi-glib/qmi-utils.c
index 2134a48..8482277 100644
--- a/libqmi-glib/qmi-utils.c
+++ b/libqmi-glib/qmi-utils.c
@@ -432,13 +432,24 @@ qmi_utils_read_sized_guint_from_buffer (const guint8 **buffer,
g_assert (buffer != NULL);
g_assert (buffer_size != NULL);
g_assert (*buffer_size >= n_bytes);
+ g_assert (n_bytes <= 8);
*out = 0;
- memcpy (out, *buffer, n_bytes);
- if (endian == QMI_ENDIAN_BIG)
- *out = GUINT64_FROM_BE (*out);
- else
+
+ /* In Little Endian, we copy the bytes to the beginning of the output
+ * buffer. */
+ if (endian == QMI_ENDIAN_LITTLE) {
+ memcpy (out, *buffer, n_bytes);
*out = GUINT64_FROM_LE (*out);
+ }
+ /* In Big Endian, we copy the bytes to the end of the output buffer */
+ else {
+ guint8 tmp[8] = { 0 };
+
+ memcpy (&tmp[8 - n_bytes], *buffer, n_bytes);
+ memcpy (out, &tmp[0], 8);
+ *out = GUINT64_FROM_BE (*out);
+ }
*buffer = &((*buffer)[n_bytes]);
*buffer_size = (*buffer_size) - n_bytes;
@@ -766,12 +777,24 @@ qmi_utils_write_sized_guint_to_buffer (guint8 **buffer,
g_assert (buffer != NULL);
g_assert (buffer_size != NULL);
g_assert (*buffer_size >= n_bytes);
+ g_assert (n_bytes <= 8);
if (endian == QMI_ENDIAN_BIG)
tmp = GUINT64_TO_BE (*in);
else
tmp = GUINT64_TO_LE (*in);
- memcpy (*buffer, &tmp, n_bytes);
+
+ /* In Little Endian, we read the bytes from the beginning of the buffer */
+ if (endian == QMI_ENDIAN_LITTLE) {
+ memcpy (*buffer, &tmp, n_bytes);
+ }
+ /* In Big Endian, we read the bytes from the end of the buffer */
+ else {
+ guint8 tmp_buffer[8];
+
+ memcpy (&tmp_buffer[0], &tmp, 8);
+ memcpy (*buffer, &tmp_buffer[8 - n_bytes], n_bytes);
+ }
*buffer = &((*buffer)[n_bytes]);
*buffer_size = (*buffer_size) - n_bytes;
diff --git a/libqmi-glib/test/test-utils.c b/libqmi-glib/test/test-utils.c
index b468317..04f552f 100644
--- a/libqmi-glib/test/test-utils.c
+++ b/libqmi-glib/test/test-utils.c
@@ -958,13 +958,27 @@ common_test_utils_uint_sized_le (guint n_bytes)
}
static void
-test_utils_uint_sized_le (void)
+test_utils_uint_sized_1_le (void)
{
- guint i;
+ common_test_utils_uint_sized_le (1);
+}
- for (i = 1; i <= 8; i++) {
- common_test_utils_uint_sized_le (i);
- }
+static void
+test_utils_uint_sized_2_le (void)
+{
+ common_test_utils_uint_sized_le (2);
+}
+
+static void
+test_utils_uint_sized_4_le (void)
+{
+ common_test_utils_uint_sized_le (4);
+}
+
+static void
+test_utils_uint_sized_8_le (void)
+{
+ common_test_utils_uint_sized_le (8);
}
static void
@@ -976,6 +990,7 @@ common_test_utils_uint_sized_be (guint n_bytes)
guint64 value = 0x000000B6E2EB500FULL;
guint8 expected_out_buffer[8] = { 0 };
guint8 out_buffer[8] = { 0 };
+ guint8 in_buffer_aux[8] = { 0 };
guint64 tmp;
guint i;
@@ -992,31 +1007,59 @@ common_test_utils_uint_sized_be (guint n_bytes)
}
value &= tmp;
+ /* In BIG ENDIAN buffers, let's read only the bytes we want, starting from
+ * the byte we want, not from the beginning of the input buffer. But we do
+ * want to be aligned while reading, so we copy the bytes to read to the
+ * beginning of an aux buffer */
+ g_assert (n_bytes <= sizeof (in_buffer));
+ memcpy (&in_buffer_aux[0], &in_buffer[sizeof (in_buffer) - n_bytes], n_bytes);
+
/* Build expected output buffer */
- memcpy (expected_out_buffer, in_buffer, n_bytes);
+ memcpy (&expected_out_buffer[0], &in_buffer_aux[0], n_bytes);
in_buffer_size = sizeof (in_buffer);
- in_buffer_walker = &in_buffer[0];
+ in_buffer_walker = &in_buffer_aux[0];
out_buffer_size = sizeof (out_buffer);
out_buffer_walker = &out_buffer[0];
- i = 0;
qmi_utils_read_sized_guint_from_buffer (&in_buffer_walker, &in_buffer_size, n_bytes, QMI_ENDIAN_BIG, &tmp);
g_assert_cmpuint (tmp, ==, value);
qmi_utils_write_sized_guint_to_buffer (&out_buffer_walker, &out_buffer_size, n_bytes, QMI_ENDIAN_BIG, &tmp);
g_assert_cmpuint (out_buffer_size, ==, 8 - n_bytes);
+ if (memcmp (expected_out_buffer, out_buffer, sizeof (expected_out_buffer)) != 0) {
+ g_print ("OUTPUT: %x, %x, %x, %x, %x, %x, %x, %x\n",
+ out_buffer[0], out_buffer[1], out_buffer[2], out_buffer[3],
+ out_buffer[4], out_buffer[5], out_buffer[6], out_buffer[7]);
+ g_print ("EXPECTED: %x, %x, %x, %x, %x, %x, %x, %x\n",
+ expected_out_buffer[0], expected_out_buffer[1], expected_out_buffer[2], expected_out_buffer[3],
+ expected_out_buffer[4], expected_out_buffer[5], expected_out_buffer[6], expected_out_buffer[7]);
+ }
g_assert (memcmp (expected_out_buffer, out_buffer, sizeof (expected_out_buffer)) == 0);
}
static void
-test_utils_uint_sized_be (void)
+test_utils_uint_sized_1_be (void)
{
- guint i;
+ common_test_utils_uint_sized_be (1);
+}
- for (i = 1; i <= 8; i++) {
- common_test_utils_uint_sized_be (i);
- }
+static void
+test_utils_uint_sized_2_be (void)
+{
+ common_test_utils_uint_sized_be (2);
+}
+
+static void
+test_utils_uint_sized_4_be (void)
+{
+ common_test_utils_uint_sized_be (4);
+}
+
+static void
+test_utils_uint_sized_8_be (void)
+{
+ common_test_utils_uint_sized_be (8);
}
static void
@@ -1051,7 +1094,6 @@ common_test_utils_uint_sized_unaligned_le (guint n_bytes)
in_buffer_walker = &in_buffer[1];
out_buffer_size = sizeof (out_buffer);
out_buffer_walker = &out_buffer[0];
- i = 0;
qmi_utils_read_sized_guint_from_buffer (&in_buffer_walker, &in_buffer_size, n_bytes, QMI_ENDIAN_LITTLE, &tmp);
g_assert_cmpuint (tmp, ==, value);
@@ -1062,24 +1104,39 @@ common_test_utils_uint_sized_unaligned_le (guint n_bytes)
}
static void
-test_utils_uint_sized_unaligned_le (void)
+test_utils_uint_sized_1_unaligned_le (void)
{
- guint i;
+ common_test_utils_uint_sized_unaligned_le (1);
+}
- for (i = 1; i <= 8; i++) {
- common_test_utils_uint_sized_unaligned_le (i);
- }
+static void
+test_utils_uint_sized_2_unaligned_le (void)
+{
+ common_test_utils_uint_sized_unaligned_le (2);
+}
+
+static void
+test_utils_uint_sized_4_unaligned_le (void)
+{
+ common_test_utils_uint_sized_unaligned_le (4);
+}
+
+static void
+test_utils_uint_sized_8_unaligned_le (void)
+{
+ common_test_utils_uint_sized_unaligned_le (8);
}
static void
common_test_utils_uint_sized_unaligned_be (guint n_bytes)
{
- static const guint8 in_buffer[9] = {
- 0x00, 0x00, 0x00, 0xB6, 0xE2, 0xEB, 0x50, 0x0F, 0x00
+ static const guint8 in_buffer[8] = {
+ 0x00, 0x00, 0x00, 0xB6, 0xE2, 0xEB, 0x50, 0x0F
};
guint64 value = 0x000000B6E2EB500FULL;
guint8 expected_out_buffer[8] = { 0 };
guint8 out_buffer[8] = { 0 };
+ guint8 in_buffer_aux[9] = { 0 };
guint64 tmp;
guint i;
@@ -1096,11 +1153,18 @@ common_test_utils_uint_sized_unaligned_be (guint n_bytes)
}
value &= tmp;
+ /* In BIG ENDIAN buffers, let's read only the bytes we want, starting from
+ * the byte we want, not from the beginning of the input buffer. But we do
+ * not want to be aligned while reading, so we copy the bytes to read to
+ * almost the beginning of an aux buffer */
+ g_assert (n_bytes <= (sizeof (in_buffer)));
+ memcpy (&in_buffer_aux[1], &in_buffer[sizeof (in_buffer) - n_bytes], n_bytes);
+
/* Build expected output buffer */
- memcpy (expected_out_buffer, &in_buffer[1], n_bytes);
+ memcpy (expected_out_buffer, &in_buffer_aux[1], n_bytes);
- in_buffer_size = sizeof (in_buffer) - 1;
- in_buffer_walker = &in_buffer[1];
+ in_buffer_size = sizeof (in_buffer_aux) - 1;
+ in_buffer_walker = &in_buffer_aux[1];
out_buffer_size = sizeof (out_buffer);
out_buffer_walker = &out_buffer[0];
i = 0;
@@ -1110,17 +1174,39 @@ common_test_utils_uint_sized_unaligned_be (guint n_bytes)
qmi_utils_write_sized_guint_to_buffer (&out_buffer_walker, &out_buffer_size, n_bytes, QMI_ENDIAN_BIG, &tmp);
g_assert_cmpuint (out_buffer_size, ==, 8 - n_bytes);
+ if (memcmp (expected_out_buffer, out_buffer, sizeof (expected_out_buffer)) != 0) {
+ g_print ("OUTPUT: %x, %x, %x, %x, %x, %x, %x, %x\n",
+ out_buffer[0], out_buffer[1], out_buffer[2], out_buffer[3],
+ out_buffer[4], out_buffer[5], out_buffer[6], out_buffer[7]);
+ g_print ("EXPECTED: %x, %x, %x, %x, %x, %x, %x, %x\n",
+ expected_out_buffer[0], expected_out_buffer[1], expected_out_buffer[2], expected_out_buffer[3],
+ expected_out_buffer[4], expected_out_buffer[5], expected_out_buffer[6], expected_out_buffer[7]);
+ }
g_assert (memcmp (expected_out_buffer, out_buffer, sizeof (expected_out_buffer)) == 0);
}
static void
-test_utils_uint_sized_unaligned_be (void)
+test_utils_uint_sized_1_unaligned_be (void)
{
- guint i;
+ common_test_utils_uint_sized_unaligned_be (1);
+}
- for (i = 1; i <= 8; i++) {
- common_test_utils_uint_sized_unaligned_be (i);
- }
+static void
+test_utils_uint_sized_2_unaligned_be (void)
+{
+ common_test_utils_uint_sized_unaligned_be (2);
+}
+
+static void
+test_utils_uint_sized_4_unaligned_be (void)
+{
+ common_test_utils_uint_sized_unaligned_be (4);
+}
+
+static void
+test_utils_uint_sized_8_unaligned_be (void)
+{
+ common_test_utils_uint_sized_unaligned_be (8);
}
int main (int argc, char **argv)
@@ -1158,10 +1244,22 @@ int main (int argc, char **argv)
g_test_add_func ("/libqmi-glib/utils/int64/unaligned-LE", test_utils_int64_unaligned_le);
g_test_add_func ("/libqmi-glib/utils/int64/unaligned-BE", test_utils_int64_unaligned_be);
- g_test_add_func ("/libqmi-glib/utils/uint-sized-LE", test_utils_uint_sized_le);
- g_test_add_func ("/libqmi-glib/utils/uint-sized-BE", test_utils_uint_sized_be);
- g_test_add_func ("/libqmi-glib/utils/uint-sized/unaligned-LE", test_utils_uint_sized_unaligned_le);
- g_test_add_func ("/libqmi-glib/utils/uint-sized/unaligned-BE", test_utils_uint_sized_unaligned_be);
+ g_test_add_func ("/libqmi-glib/utils/uint-sized-1-LE", test_utils_uint_sized_1_le);
+ g_test_add_func ("/libqmi-glib/utils/uint-sized-2-LE", test_utils_uint_sized_2_le);
+ g_test_add_func ("/libqmi-glib/utils/uint-sized-4-LE", test_utils_uint_sized_4_le);
+ g_test_add_func ("/libqmi-glib/utils/uint-sized-8-LE", test_utils_uint_sized_8_le);
+ g_test_add_func ("/libqmi-glib/utils/uint-sized-1-BE", test_utils_uint_sized_1_be);
+ g_test_add_func ("/libqmi-glib/utils/uint-sized-2-BE", test_utils_uint_sized_2_be);
+ g_test_add_func ("/libqmi-glib/utils/uint-sized-4-BE", test_utils_uint_sized_4_be);
+ g_test_add_func ("/libqmi-glib/utils/uint-sized-8-BE", test_utils_uint_sized_8_be);
+ g_test_add_func ("/libqmi-glib/utils/uint-sized-1-unaligned-LE", test_utils_uint_sized_1_unaligned_le);
+ g_test_add_func ("/libqmi-glib/utils/uint-sized-2-unaligned-LE", test_utils_uint_sized_2_unaligned_le);
+ g_test_add_func ("/libqmi-glib/utils/uint-sized-4-unaligned-LE", test_utils_uint_sized_4_unaligned_le);
+ g_test_add_func ("/libqmi-glib/utils/uint-sized-8-unaligned-LE", test_utils_uint_sized_8_unaligned_le);
+ g_test_add_func ("/libqmi-glib/utils/uint-sized-1-unaligned-BE", test_utils_uint_sized_1_unaligned_be);
+ g_test_add_func ("/libqmi-glib/utils/uint-sized-2-unaligned-BE", test_utils_uint_sized_2_unaligned_be);
+ g_test_add_func ("/libqmi-glib/utils/uint-sized-4-unaligned-BE", test_utils_uint_sized_4_unaligned_be);
+ g_test_add_func ("/libqmi-glib/utils/uint-sized-8-unaligned-BE", test_utils_uint_sized_8_unaligned_be);
return g_test_run ();
}