mirror of
https://github.com/norandom/OpenUltraSAST.git
synced 2026-10-18 20:49:28 +00:00
Harvest 176 isolated vuln-vs-fix functions (109 CVEs, 352 training rows) into benchmarks/pairs/vfc with provenance and a JSONL training manifest. Score the slice as an honesty dashboard (ousast pairs --slice vfc); keep the pair gate on the local fixtures only.
179 lines
5.5 KiB
C
179 lines
5.5 KiB
C
/* Provenance: openssl/openssl ssl3_read_n (fixed).
|
|
* repo: openssl/openssl
|
|
* commit: 2d05959073c4bf8803401668b9df85931a08e020
|
|
* parent: b3f0eb0a295f58f16ba43ba99dad70d4ee5c437d
|
|
* commit_url: https://github.com/openssl/openssl/commit/2d05959073c4bf8803401668b9df85931a08e020
|
|
* cve: CVE-2024-4741
|
|
* license: Apache-2.0
|
|
* function: ssl3_read_n
|
|
* relpath: ssl/record/rec_layer_s3.c
|
|
*/
|
|
|
|
int ssl3_read_n(SSL *s, size_t n, size_t max, int extend, int clearold,
|
|
size_t *readbytes)
|
|
{
|
|
/*
|
|
* If extend == 0, obtain new n-byte packet; if extend == 1, increase
|
|
* packet by another n bytes. The packet will be in the sub-array of
|
|
* s->rlayer.rbuf.buf specified by s->rlayer.packet and
|
|
* s->rlayer.packet_length. (If s->rlayer.read_ahead is set, 'max' bytes may
|
|
* be stored in rbuf [plus s->rlayer.packet_length bytes if extend == 1].)
|
|
* if clearold == 1, move the packet to the start of the buffer; if
|
|
* clearold == 0 then leave any old packets where they were
|
|
*/
|
|
size_t len, left, align = 0;
|
|
unsigned char *pkt;
|
|
SSL3_BUFFER *rb;
|
|
|
|
if (n == 0)
|
|
return 0;
|
|
|
|
rb = &s->rlayer.rbuf;
|
|
if (rb->buf == NULL)
|
|
if (!ssl3_setup_read_buffer(s)) {
|
|
/* SSLfatal() already called */
|
|
return -1;
|
|
}
|
|
|
|
left = rb->left;
|
|
#if defined(SSL3_ALIGN_PAYLOAD) && SSL3_ALIGN_PAYLOAD!=0
|
|
align = (size_t)rb->buf + SSL3_RT_HEADER_LENGTH;
|
|
align = SSL3_ALIGN_PAYLOAD - 1 - ((align - 1) % SSL3_ALIGN_PAYLOAD);
|
|
#endif
|
|
|
|
if (!extend) {
|
|
/* start with empty packet ... */
|
|
if (left == 0)
|
|
rb->offset = align;
|
|
|
|
s->rlayer.packet = rb->buf + rb->offset;
|
|
s->rlayer.packet_length = 0;
|
|
/* ... now we can act as if 'extend' was set */
|
|
}
|
|
|
|
if (!ossl_assert(s->rlayer.packet != NULL)) {
|
|
/* does not happen */
|
|
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
|
|
return -1;
|
|
}
|
|
|
|
len = s->rlayer.packet_length;
|
|
pkt = rb->buf + align;
|
|
/*
|
|
* Move any available bytes to front of buffer: 'len' bytes already
|
|
* pointed to by 'packet', 'left' extra ones at the end
|
|
*/
|
|
if (s->rlayer.packet != pkt && clearold == 1) {
|
|
memmove(pkt, s->rlayer.packet, len + left);
|
|
s->rlayer.packet = pkt;
|
|
rb->offset = len + align;
|
|
}
|
|
|
|
/*
|
|
* For DTLS/UDP reads should not span multiple packets because the read
|
|
* operation returns the whole packet at once (as long as it fits into
|
|
* the buffer).
|
|
*/
|
|
if (SSL_IS_DTLS(s)) {
|
|
if (left == 0 && extend)
|
|
return 0;
|
|
if (left > 0 && n > left)
|
|
n = left;
|
|
}
|
|
|
|
/* if there is enough in the buffer from a previous read, take some */
|
|
if (left >= n) {
|
|
s->rlayer.packet_length += n;
|
|
rb->left = left - n;
|
|
rb->offset += n;
|
|
*readbytes = n;
|
|
return 1;
|
|
}
|
|
|
|
/* else we need to read more data */
|
|
|
|
if (n > rb->len - rb->offset) {
|
|
/* does not happen */
|
|
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
|
|
return -1;
|
|
}
|
|
|
|
/*
|
|
* Ktls always reads full records.
|
|
* Also, we always act like read_ahead is set for DTLS.
|
|
*/
|
|
if (!BIO_get_ktls_recv(s->rbio) && !s->rlayer.read_ahead
|
|
&& !SSL_IS_DTLS(s)) {
|
|
/* ignore max parameter */
|
|
max = n;
|
|
} else {
|
|
if (max < n)
|
|
max = n;
|
|
if (max > rb->len - rb->offset)
|
|
max = rb->len - rb->offset;
|
|
}
|
|
|
|
while (left < n) {
|
|
size_t bioread = 0;
|
|
int ret;
|
|
|
|
/*
|
|
* Now we have len+left bytes at the front of s->s3.rbuf.buf and
|
|
* need to read in more until we have len+n (up to len+max if
|
|
* possible)
|
|
*/
|
|
|
|
clear_sys_error();
|
|
if (s->rbio != NULL) {
|
|
s->rwstate = SSL_READING;
|
|
ret = BIO_read(s->rbio, pkt + len + left, max - left);
|
|
if (ret >= 0)
|
|
bioread = ret;
|
|
if (ret <= 0
|
|
&& !BIO_should_retry(s->rbio)
|
|
&& BIO_eof(s->rbio)) {
|
|
if (s->options & SSL_OP_IGNORE_UNEXPECTED_EOF) {
|
|
SSL_set_shutdown(s, SSL_RECEIVED_SHUTDOWN);
|
|
s->s3.warn_alert = SSL_AD_CLOSE_NOTIFY;
|
|
} else {
|
|
/*
|
|
* This reason code is part of the API and may be used by
|
|
* applications for control flow decisions.
|
|
*/
|
|
SSLfatal(s, SSL_AD_DECODE_ERROR,
|
|
SSL_R_UNEXPECTED_EOF_WHILE_READING);
|
|
}
|
|
}
|
|
} else {
|
|
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_R_READ_BIO_NOT_SET);
|
|
ret = -1;
|
|
}
|
|
|
|
if (ret <= 0) {
|
|
rb->left = left;
|
|
if (s->mode & SSL_MODE_RELEASE_BUFFERS && !SSL_IS_DTLS(s))
|
|
if (len + left == 0)
|
|
ssl3_release_read_buffer(s);
|
|
return ret;
|
|
}
|
|
left += bioread;
|
|
/*
|
|
* reads should *never* span multiple packets for DTLS because the
|
|
* underlying transport protocol is message oriented as opposed to
|
|
* byte oriented as in the TLS case.
|
|
*/
|
|
if (SSL_IS_DTLS(s)) {
|
|
if (n > left)
|
|
n = left; /* makes the while condition false */
|
|
}
|
|
}
|
|
|
|
/* done reading, now the book-keeping */
|
|
rb->offset += n;
|
|
rb->left = left - n;
|
|
s->rlayer.packet_length += n;
|
|
s->rwstate = SSL_NOTHING;
|
|
*readbytes = n;
|
|
return 1;
|
|
}
|