[egg] Make the hex decoder more robust
authorStef Walter <stef@memberwebs.com>
Mon, 9 Aug 2010 18:15:43 +0000 (20:15 +0200)
committerStef Walter <stef@memberwebs.com>
Mon, 9 Aug 2010 18:15:43 +0000 (20:15 +0200)
egg/egg-hex.c
egg/egg-hex.h
egg/tests/unit-test-hex.c

index 64d3185..0e74f57 100644 (file)
 static const char HEXC_UPPER[] = "0123456789ABCDEF";
 static const char HEXC_LOWER[] = "0123456789abcdef";
 
-guchar*
+gpointer
 egg_hex_decode (const gchar *data, gssize n_data, gsize *n_decoded)
 {
+       return egg_hex_decode_full (data, n_data, 0, 1, n_decoded);
+}
+
+gpointer
+egg_hex_decode_full (const gchar *data, gssize n_data,
+                     gchar delim, guint group, gsize *n_decoded)
+{
        guchar *result;
        guchar *decoded;
        gushort j;
        gint state = 0;
+       gint part = 0;
        const gchar* pos;
 
        g_return_val_if_fail (data || !n_data, NULL);
        g_return_val_if_fail (n_decoded, NULL);
+       g_return_val_if_fail (group >= 1, NULL);
 
        if (n_data == -1)
                n_data = strlen (data);
@@ -46,13 +55,27 @@ egg_hex_decode (const gchar *data, gssize n_data, gsize *n_decoded)
        decoded = result = g_malloc0 ((n_data / 2) + 1);
        *n_decoded = 0;
 
-       while (n_data > 0) {
-               if (!g_ascii_isspace (*data)) {
+       while (n_data > 0 && state == 0) {
 
-                       /* Find the position */
+               if (decoded != result && delim) {
+                       if (*data != delim) {
+                               state = -1;
+                               break;
+                       }
+
+                       ++data;
+                       --n_data;
+               }
+
+               while (part < group && n_data > 0) {
+
+                       /* Find the position */
                        pos = strchr (HEXC_UPPER, g_ascii_toupper (*data));
-                       if (pos == 0)
+                       if (pos == 0) {
+                               if (n_data > 0)
+                                       state = -1;
                                break;
+                       }
 
                        j = pos - HEXC_UPPER;
                        if(!state) {
@@ -63,11 +86,14 @@ egg_hex_decode (const gchar *data, gssize n_data, gsize *n_decoded)
                                (*n_decoded)++;
                                decoded++;
                                state = 0;
+                               part++;
                        }
-               }
 
-               ++data;
-               --n_data;
+                       ++data;
+                       --n_data;
+               }
+
+               part = 0;
        }
 
        /* Parsing error */
@@ -80,22 +106,24 @@ egg_hex_decode (const gchar *data, gssize n_data, gsize *n_decoded)
 }
 
 gchar*
-egg_hex_encode (const guchar *data, gsize n_data)
+egg_hex_encode (gconstpointer data, gsize n_data)
 {
        return egg_hex_encode_full (data, n_data, TRUE, '\0', 0);
 }
 
 gchar*
-egg_hex_encode_full (const guchar *data, gsize n_data,
+egg_hex_encode_full (gconstpointer data, gsize n_data,
                      gboolean upper_case, gchar delim, guint group)
 {
        GString *result;
+       const gchar *input;
        const char *hexc;
        gsize bytes;
        guchar j;
 
        g_return_val_if_fail (data || !n_data, NULL);
 
+       input = data;
        hexc = upper_case ? HEXC_UPPER : HEXC_LOWER;
 
        result = g_string_sized_new (n_data * 2 + 1);
@@ -106,10 +134,10 @@ egg_hex_encode_full (const guchar *data, gsize n_data,
                if (group && bytes && (bytes % group) == 0)
                        g_string_append_c (result, delim);
 
-               j = *(data) >> 4 & 0xf;
+               j = *(input) >> 4 & 0xf;
                g_string_append_c (result, hexc[j]);
 
-               j = *(data++) & 0xf;
+               j = *(input++) & 0xf;
                g_string_append_c (result, hexc[j]);
 
                ++bytes;
index ddd9b99..d30b641 100644 (file)
 
 #include <glib.h>
 
-guchar*               egg_hex_decode                         (const gchar *data,
+gpointer              egg_hex_decode                         (const gchar *data,
                                                               gssize n_data,
                                                               gsize *n_decoded);
 
-gchar*                egg_hex_encode                         (const guchar *data,
+gpointer              egg_hex_decode_full                    (const gchar *data,
+                                                              gssize n_data,
+                                                              gchar delim,
+                                                              guint group,
+                                                              gsize *n_decoded);
+
+gchar*                egg_hex_encode                         (gconstpointer data,
                                                               gsize n_data);
 
-gchar*                egg_hex_encode_full                    (const guchar *data,
+gchar*                egg_hex_encode_full                    (gconstpointer data,
                                                               gsize n_data,
                                                               gboolean upper_case,
                                                               gchar delim,
index 2bd222b..a5be72c 100644 (file)
@@ -32,7 +32,6 @@
 static const guchar TEST_DATA[] = { 0x05, 0xD6, 0x95, 0x96, 0x10, 0x12, 0xAE, 0x35 };
 static const gchar *TEST_HEX = "05D695961012AE35";
 static const gchar *TEST_HEX_DELIM = "05 D6 95 96 10 12 AE 35";
-static const gchar *TEST_HEX_SPACE = "\n05 D695 \r961012AE35\n\n";
 
 DEFINE_TEST(hex_encode)
 {
@@ -67,19 +66,36 @@ DEFINE_TEST(hex_decode)
        g_assert (data);
        g_assert (n_data == sizeof (TEST_DATA));
        g_assert (memcmp (data, TEST_DATA, n_data) == 0);
+       g_free (data);
 
-       /* Spaces should be ignored */
-       data = egg_hex_decode (TEST_HEX_SPACE, -1, &n_data);
+       /* Nothing in, empty out */
+       data = egg_hex_decode ("AB", 0, &n_data);
+       g_assert (data);
+       g_assert (n_data == 0);
+       g_free (data);
+
+       /* Delimited*/
+       data = egg_hex_decode_full (TEST_HEX_DELIM, -1, ' ', 1, &n_data);
        g_assert (data);
        g_assert (n_data == sizeof (TEST_DATA));
        g_assert (memcmp (data, TEST_DATA, n_data) == 0);
+       g_free (data);
+}
+
+DEFINE_TEST(hex_decode_fail)
+{
+       guchar *data;
+       gsize n_data;
 
        /* Invalid input, null out */
        data = egg_hex_decode ("AB", 1, &n_data);
        g_assert (!data);
 
-       /* Nothing in, empty out */
-       data = egg_hex_decode ("AB", 0, &n_data);
-       g_assert (data);
-       g_assert (n_data == 0);
+       /* Bad characters, null out */
+       data = egg_hex_decode ("ABXX", -1, &n_data);
+       g_assert (!data);
+
+       /* Not Delimited, null out*/
+       data = egg_hex_decode_full ("ABABAB", -1, ':', 1, &n_data);
+       g_assert (!data);
 }