Fix potential stack overflow
diff --git a/ChangeLog b/ChangeLog
index 87dc23a..8b5848a 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -9,6 +9,9 @@
    * Fix remotely-triggerable memory leak caused by crafted X.509 certificates
      (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).
 
 Changes
    * Blind RSA private operations even when POLARSSL_RSA_NO_CRT is defined.
diff --git a/library/x509parse.c b/library/x509parse.c
index c00c5db..4a9b7c1 100644
--- a/library/x509parse.c
+++ b/library/x509parse.c
@@ -296,36 +296,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_CERT_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_CERT_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 *) malloc(
-         sizeof( x509_name ) );
+        cur->next = (x509_name *) 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;
+    }
 }
 
 /*