egg-asn1x: Fix crash when parsing invalid DER files
authorStef Walter <stefw@gnome.org>
Mon, 5 Nov 2012 20:24:31 +0000 (21:24 +0100)
committerStef Walter <stefw@gnome.org>
Wed, 7 Nov 2012 22:14:17 +0000 (23:14 +0100)
 * When parsing invalid DER files and more than one sub-TLV is
   encountered we would do a NULL dereference.
 * Catch this condition and test for it.

egg/egg-asn1x.c
egg/tests/test-asn1.c

index 5168e3f..7e6e854 100644 (file)
@@ -1181,11 +1181,17 @@ static gboolean
 anode_decode_anything (GNode *node,
                        Atlv *tlv)
 {
+       GNode *prev = NULL;
        GNode *next;
        gulong tag;
        gint flags;
 
+       g_assert (node != NULL);
+
        while (tlv != NULL) {
+               if (node == NULL)
+                       return anode_failure (prev, "encountered extra tag");
+
                flags = anode_def_flags (node);
                tag = anode_calc_tag_for_flags (node, flags);
 
@@ -1205,6 +1211,7 @@ anode_decode_anything (GNode *node,
                        if (next == NULL)
                                return anode_failure (node, "decoded tag did not match expected");
 
+                       prev = node;
                        node = next;
                        continue;
                }
@@ -1213,6 +1220,7 @@ anode_decode_anything (GNode *node,
                        return FALSE;
 
                /* Next node and tag */
+               prev = node;
                node = g_node_next_sibling (node);
                tlv = tlv->next;
        }
index 1313099..09645d6 100644 (file)
@@ -1331,6 +1331,51 @@ test_count (Test* test, gconstpointer unused)
        g_assert_cmpuint (egg_asn1x_count (node), ==, 7);
 }
 
+static void
+test_nested_fails_with_extra (void)
+{
+       gboolean ret;
+       GBytes *bytes;
+       GNode *asn;
+
+       const gchar SEQ_NESTED[] =  "\x30\x0C"
+                                        "\x04\x03""one"
+                                        "\x04\x05""extra";
+
+       asn = egg_asn1x_create (test_asn1_tab, "TestData");
+       g_assert ("asn test structure is null" && asn != NULL);
+
+       bytes = g_bytes_new_static (SEQ_NESTED, XL (SEQ_NESTED));
+       ret = egg_asn1x_decode (asn, bytes);
+       egg_asn1x_assert (ret == FALSE, asn);
+       egg_asn1x_assert (strstr (egg_asn1x_message (asn), "encountered extra tag"), asn);
+       g_bytes_unref (bytes);
+
+       egg_asn1x_destroy (asn);
+}
+
+static void
+test_nested_unexpected (void)
+{
+       gboolean ret;
+       GBytes *bytes;
+       GNode *asn;
+
+       const gchar SEQ_NESTED[] =  "\x30\x03"
+                                        "\x02\x01\x2A";
+
+       asn = egg_asn1x_create (test_asn1_tab, "TestData");
+       g_assert ("asn test structure is null" && asn != NULL);
+
+       bytes = g_bytes_new_static (SEQ_NESTED, XL (SEQ_NESTED));
+       ret = egg_asn1x_decode (asn, bytes);
+       egg_asn1x_assert (ret == FALSE, asn);
+       egg_asn1x_assert (strstr (egg_asn1x_message (asn), "decoded tag did not match expected"), asn);
+       g_bytes_unref (bytes);
+
+       egg_asn1x_destroy (asn);
+}
+
 int
 main (int argc, char **argv)
 {
@@ -1365,6 +1410,8 @@ main (int argc, char **argv)
        g_test_add_func ("/asn1/setof", test_setof);
        g_test_add_func ("/asn1/setof_empty", test_setof_empty);
        g_test_add_func ("/asn1/enumerated", test_enumerated);
+       g_test_add_func ("/asn1/nested-fails-with-extra", test_nested_fails_with_extra);
+       g_test_add_func ("/asn1/nested-unexpected", test_nested_unexpected);
        g_test_add ("/asn1/node_name", Test, NULL, setup, test_node_name, teardown);
        g_test_add ("/asn1/asn1_integers", Test, NULL, setup, test_asn1_integers, teardown);
        g_test_add ("/asn1/boolean_seq", Test, NULL, setup, test_boolean_seq, teardown);