Fix potential stack overflow
diff --git a/ChangeLog b/ChangeLog
index f06f582..a8cb94a 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -4,10 +4,13 @@
 
 Security
    * Fix remotely-triggerable uninitialised pointer dereference caused by
-     crafted X.509 certificate (server is not affected if it doesn't ask for a
+     crafted X.509 certificate (TLS server is not affected if it doesn't ask for a
      client certificate) (found using Codenomicon Defensics).
    * Fix remotely-triggerable memory leak caused by crafted X.509 certificates
-     (server is not affected if it doesn't ask for a client certificate)
+     (TLS server is not affected if it doesn't ask for a client certificate)
+     (found using Codenomicon Defensics).
+   * Fix potential stack overflow while parsing crafted X.509 certificates
+     (TLS server is not affected if it doesn't ask for a client certificate)
      (found using Codenomicon Defensics).
 
 Features
diff --git a/library/x509.c b/library/x509.c
index 941472c..89ba763 100644
--- a/library/x509.c
+++ b/library/x509.c
@@ -421,35 +421,39 @@
     size_t set_len;
     const unsigned char *end_set;
 
-    /*
-     * parse first SET, restricted to 1 element
-     */
-    if( ( ret = asn1_get_tag( p, end, &set_len,
-            ASN1_CONSTRUCTED | ASN1_SET ) ) != 0 )
-        return( POLARSSL_ERR_X509_INVALID_NAME + ret );
+    /* don't use recursion, we'd risk stack overflow if not optimized */
+    while( 1 )
+    {
+        /*
+         * parse first SET, restricted to 1 element
+         */
+        if( ( ret = asn1_get_tag( p, end, &set_len,
+                ASN1_CONSTRUCTED | ASN1_SET ) ) != 0 )
+            return( POLARSSL_ERR_X509_INVALID_NAME + ret );
 
-    end_set  = *p + set_len;
+        end_set  = *p + set_len;
 
-    if( ( ret = x509_get_attr_type_value( p, end_set, cur ) ) != 0 )
-        return( ret );
+        if( ( ret = x509_get_attr_type_value( p, end_set, cur ) ) != 0 )
+            return( ret );
 
-    if( *p != end_set )
-        return( POLARSSL_ERR_X509_FEATURE_UNAVAILABLE );
+        if( *p != end_set )
+            return( POLARSSL_ERR_X509_FEATURE_UNAVAILABLE );
 
-    /*
-     * recurse until end of SEQUENCE is reached
-     */
-    if( *p == end )
-        return( 0 );
+        /*
+         * continue until end of SEQUENCE is reached
+         */
+        if( *p == end )
+            return( 0 );
 
-    cur->next = (x509_name *) polarssl_malloc( sizeof( x509_name ) );
+        cur->next = (x509_name *) polarssl_malloc( sizeof( x509_name ) );
 
-    if( cur->next == NULL )
-        return( POLARSSL_ERR_X509_MALLOC_FAILED );
+        if( cur->next == NULL )
+            return( POLARSSL_ERR_X509_MALLOC_FAILED );
 
-    memset( cur->next, 0, sizeof( x509_name ) );
+        memset( cur->next, 0, sizeof( x509_name ) );
 
-    return( x509_get_name( p, end, cur->next ) );
+        cur = cur->next;
+    }
 }
 
 /*