Fix heap-buffer overread in ALPN ext parsing
diff --git a/ChangeLog b/ChangeLog
index 3f5e56f..ef5abb8 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -38,6 +38,9 @@
      corrupt 6 bytes on the peer's heap, potentially leading to crash or
      remote code execution. This can be triggered remotely from either
      side in both TLS and DTLS.
+   * Fix a potential heap buffer overread in ALPN extension parsing
+     (server-side). Could result in application crash, but only if an ALPN
+     name larger than 16 bytes had been configured on the server.
 
 Features
    * Allow comments in test data files.
diff --git a/library/ssl_srv.c b/library/ssl_srv.c
index de3ea80..85c3c30 100644
--- a/library/ssl_srv.c
+++ b/library/ssl_srv.c
@@ -603,33 +603,41 @@
     }
 
     /*
-     * Use our order of preference
+     * Validate peer's list (lengths)
      */
     start = buf + 2;
     end = buf + len;
+    for( theirs = start; theirs != end; theirs += cur_len )
+    {
+        cur_len = *theirs++;
+
+        /* Current identifier must fit in list */
+        if( cur_len > (size_t)( end - theirs ) )
+        {
+            mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
+                                            MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR );
+            return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO );
+        }
+
+        /* Empty strings MUST NOT be included */
+        if( cur_len == 0 )
+        {
+            mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
+                                            MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER );
+            return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO );
+        }
+    }
+
+    /*
+     * Use our order of preference
+     */
     for( ours = ssl->conf->alpn_list; *ours != NULL; ours++ )
     {
         ours_len = strlen( *ours );
         for( theirs = start; theirs != end; theirs += cur_len )
         {
-            /* If the list is well formed, we should get equality first */
-            if( theirs > end )
-            {
-                mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
-                                                MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER );
-                return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO );
-            }
-
             cur_len = *theirs++;
 
-            /* Empty strings MUST NOT be included */
-            if( cur_len == 0 )
-            {
-                mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
-                                                MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER );
-                return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO );
-            }
-
             if( cur_len == ours_len &&
                 memcmp( theirs, *ours, cur_len ) == 0 )
             {