From d681443f69080ec68f2323e7f53fae2f863d69ee Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= <mpg@elzevir.fr>
Date: Wed, 12 Nov 2014 01:25:31 +0100
Subject: [PATCH] Fix potential stack overflow

---
 ChangeLog      |  7 +++++--
 library/x509.c | 46 +++++++++++++++++++++++++---------------------
 2 files changed, 30 insertions(+), 23 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index f06f582d13..a8cb94a208 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -4,10 +4,13 @@ PolarSSL ChangeLog (Sorted per branch, date)
 
 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 941472c9de..89ba7633dd 100644
--- a/library/x509.c
+++ b/library/x509.c
@@ -421,35 +421,39 @@ int x509_get_name( unsigned char **p, const unsigned char *end,
     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;
+    }
 }
 
 /*