/*
* Copyright 2022 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include <stdio.h>
#include <errno.h>
#include "bio_local.h"
#include "internal/cryptlib.h"
#include "internal/safe_math.h"
#if !defined(OPENSSL_NO_DGRAM) && !defined(OPENSSL_NO_SOCK)
OSSL_SAFE_MATH_UNSIGNED(size_t, size_t)
/* ===========================================================================
* Byte-wise ring buffer which supports pushing and popping blocks of multiple
* bytes at a time.
*/
struct ring_buf {
unsigned char *start; /* start of buffer */
size_t len; /* size of buffer allocation in bytes */
size_t count; /* number of bytes currently pushed */
/*
* These index into start. Where idx[0] == idx[1], the buffer is full
* (if count is nonzero) and empty otherwise.
*/
size_t idx[2]; /* 0: head, 1: tail */
};
static int ring_buf_init(struct ring_buf *r, size_t nbytes)
{
r->start = OPENSSL_malloc(nbytes);
if (r->start == NULL)
return 0;
r->len = nbytes;
r->idx[0] = r->idx[1] = r->count = 0;
return 1;
}
static void ring_buf_destroy(struct ring_buf *r)
{
OPENSSL_free(r->start);
r->start = NULL;
r->len = 0;
r->count = 0;
}
/*
* Get a pointer to the next place to write data to be pushed to the ring buffer
* (idx=0), or the next data to be popped from the ring buffer (idx=1). The
* pointer is written to *buf and the maximum number of bytes which can be
* read/written are written to *len. After writing data to the buffer, call
* ring_buf_push/pop() with the number of bytes actually read/written, which
* must not exceed the returned length.
*/
static void ring_buf_head_tail(struct ring_buf *r, int idx, uint8_t **buf, size_t *len)
{
size_t max_len = r->len - r->idx[idx];
if (idx == 0 && max_len > r->len - r->count)
max_len =