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);