diff options
Diffstat (limited to 'security/nss/lib/ssl/sslencode.c')
-rw-r--r-- | security/nss/lib/ssl/sslencode.c | 64 |
1 files changed, 48 insertions, 16 deletions
diff --git a/security/nss/lib/ssl/sslencode.c b/security/nss/lib/ssl/sslencode.c index 2f127fe8f..e50880451 100644 --- a/security/nss/lib/ssl/sslencode.c +++ b/security/nss/lib/ssl/sslencode.c @@ -29,6 +29,7 @@ ssl_EncodeUintX(PRUint8 *to, PRUint64 value, unsigned int bytes) SECStatus sslBuffer_Grow(sslBuffer *b, unsigned int newLen) { + PORT_Assert(b); if (b->fixed) { PORT_Assert(newLen <= b->space); if (newLen > b->space) { @@ -84,6 +85,7 @@ sslBuffer_AppendVariable(sslBuffer *b, const PRUint8 *data, unsigned int len, unsigned int size) { PORT_Assert(size <= 4 && size > 0); + PORT_Assert(b); if (len >= (1ULL << (8 * size))) { PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); return SECFailure; @@ -95,7 +97,11 @@ sslBuffer_AppendVariable(sslBuffer *b, const PRUint8 *data, unsigned int len, ssl_EncodeUintX(SSL_BUFFER_NEXT(b), len, size); b->len += size; - PORT_Memcpy(SSL_BUFFER_NEXT(b), data, len); + if (len != 0) { + PORT_Assert(data); + /* We sometimes pass NULL, 0 and memcpy() doesn't want NULL. */ + PORT_Memcpy(SSL_BUFFER_NEXT(b), data, len); + } b->len += len; return SECSuccess; } @@ -169,37 +175,63 @@ sslBuffer_Clear(sslBuffer *b) } SECStatus -ssl3_ConsumeFromItem(SECItem *item, unsigned char **buf, unsigned int size) +sslRead_Read(sslReader *reader, unsigned int count, sslReadBuffer *out) { - if (size > item->len) { + if (!reader || !out) { + PORT_SetError(SEC_ERROR_INVALID_ARGS); + return SECFailure; + } + if (reader->buf.len < reader->offset || + count > SSL_READER_REMAINING(reader)) { PORT_SetError(SEC_ERROR_BAD_DATA); return SECFailure; } - *buf = item->data; - item->data += size; - item->len -= size; + out->buf = SSL_READER_CURRENT(reader); + out->len = count; + reader->offset += count; + return SECSuccess; } SECStatus -ssl3_ConsumeNumberFromItem(SECItem *item, PRUint32 *num, unsigned int size) +sslRead_ReadVariable(sslReader *reader, unsigned int sizeLen, sslReadBuffer *out) { - int i; - - if (size > item->len || size > sizeof(*num)) { + PRUint64 variableLen = 0; + SECStatus rv = sslRead_ReadNumber(reader, sizeLen, &variableLen); + if (rv != SECSuccess) { PORT_SetError(SEC_ERROR_BAD_DATA); return SECFailure; } - - *num = 0; - for (i = 0; i < size; i++) { - *num = (*num << 8) + item->data[i]; + if (!variableLen) { + // It is ok to have an empty variable. + out->len = variableLen; + return SECSuccess; } + return sslRead_Read(reader, variableLen, out); +} - item->data += size; - item->len -= size; +SECStatus +sslRead_ReadNumber(sslReader *reader, unsigned int bytes, PRUint64 *num) +{ + if (!reader || !num) { + PORT_SetError(SEC_ERROR_INVALID_ARGS); + return SECFailure; + } + if (reader->buf.len < reader->offset || + bytes > SSL_READER_REMAINING(reader) || + bytes > 8) { + PORT_SetError(SEC_ERROR_BAD_DATA); + return SECFailure; + } + unsigned int i; + PRUint64 number = 0; + for (i = 0; i < bytes; i++) { + number = (number << 8) + reader->buf.buf[i + reader->offset]; + } + reader->offset = reader->offset + bytes; + *num = number; return SECSuccess; } |