Hello,

the attached patch fixes an out-of-bounds write in SSL_get_shared_ciphers.

According to Bodo Moeller, the bug should not be critical because the
function never gets called with an empty list, but it may still be nice to
have that check in place.

Without the patch, when SSL_get_shared_ciphers gets called with an empty
list of ciphers, it will skip the for-loop completely, write buf[-1]='\0',
and return a pointer to uninitialized memory.

I found this with the Clang static analyzer.  (Great tool. :))

Thanks,
Günther

PS: To illustrate,
1449 char *SSL_get_shared_ciphers(const SSL *s,char *buf,int len)
1450         {
1451         char *p;
1452         STACK_OF(SSL_CIPHER) *sk;
1453         SSL_CIPHER *c;
1454         int i;
1455
1456         if ((s->session == NULL) || (s->session->ciphers == NULL) ||
1457                 (len < 2))
1458                 return(NULL);
1459
1460         p=buf;
1461         sk=s->session->ciphers;
1462         for (i=0; i<sk_SSL_CIPHER_num(sk); i++)   // assume
sk_SSL_CIPHER_num(sk) == 0
1463                 {
1464                 int n;
1465
1466                 c=sk_SSL_CIPHER_value(sk,i);
1467                 n=strlen(c->name);
1468                 if (n+1 > len)
1469                         {
1470                         if (p != buf)
1471                                 --p;
1472                         *p='\0';
1473                         return buf;
1474                         }
1475                 strcpy(p,c->name);
1476                 p+=n;
1477                 *(p++)=':';
1478                 len-=n+1;
1479                 }
1480         p[-1]='\0';  // out of bounds write, returns pointer to
uninitialized memory
1481         return(buf);
1482         }

diff --git a/ssl/ssl_lib.c b/ssl/ssl_lib.c
index c6ca137..4720680 100644
--- a/ssl/ssl_lib.c
+++ b/ssl/ssl_lib.c
@@ -1442,40 +1442,44 @@ int SSL_set_cipher_list(SSL *s,const char *str)
                SSLerr(SSL_F_SSL_SET_CIPHER_LIST, SSL_R_NO_CIPHER_MATCH);
                return 0;
                }
        return 1;
        }
 
 /* works well for SSLv2, not so good for SSLv3 */
 char *SSL_get_shared_ciphers(const SSL *s,char *buf,int len)
        {
        char *p;
        STACK_OF(SSL_CIPHER) *sk;
        SSL_CIPHER *c;
        int i;
 
        if ((s->session == NULL) || (s->session->ciphers == NULL) ||
                (len < 2))
                return(NULL);
 
        p=buf;
        sk=s->session->ciphers;
+
+       if (sk_SSL_CIPHER_num(sk) == 0)
+               return NULL;
+
        for (i=0; i<sk_SSL_CIPHER_num(sk); i++)
                {
                int n;
 
                c=sk_SSL_CIPHER_value(sk,i);
                n=strlen(c->name);
                if (n+1 > len)
                        {
                        if (p != buf)
                                --p;
                        *p='\0';
                        return buf;
                        }
                strcpy(p,c->name);
                p+=n;
                *(p++)=':';
                len-=n+1;
                }
        p[-1]='\0';
        return(buf);

Reply via email to