BIO buffer APIs allow negative length → heap corruption, missing input validation (OpenSSL 3.0.2, 3.6.1)
#30725 opened on Apr 8, 2026
Description
BIO buffer APIs allow negative length → heap corruption, missing input validation (OpenSSL 3.0.2, 3.6.1)
While testing BIO buffer APIs in OpenSSL 3.6.1, I encountered a crash caused by passing a negative length parameter to public API macros.
The issue appears to originate from missing validation of the long num parameter inside buffer_ctrl() in crypto/bio/bf_buff.c.
This report is submitted as a bug / robustness issue, not a confirmed vulnerability.
Environment
- Ubuntu 22.04.5 LTS (x86_64)
- Kernel: 6.8.0-1050-aws
- GCC: 11.4.0
- OpenSSL (system): 3.0.2
- OpenSSL (tested): 3.6.1 (manual build)
Summary of Issue
Two BIO control paths accept a signed long num parameter but do not properly validate negative values:
Negative values bypass guard conditions and later reach memcpy() with an implicitly converted large size_t, resulting in crash (heap corruption / invalid memory access).
Affected Code
Heap OOB WRITE (approx. lines 288–301)
case BIO_C_SET_BUFF_READ_DATA:
if (num > ctx->ibuf_size) {
if (num <= 0)
return 0;
p1 = OPENSSL_malloc((size_t)num);
}
ctx->ibuf_off = 0;
ctx->ibuf_len = (int)num;
memcpy(ctx->ibuf, ptr, (int)num);
Heap OOB READ (approx. lines 391–401)
case BIO_CTRL_PEEK:
{
char fake_buf[1];
(void)buffer_read(b, fake_buf, 0);
}
if (num > ctx->ibuf_len)
num = ctx->ibuf_len;
memcpy(ptr, &(ctx->ibuf[ctx->ibuf_off]), num);
Public API Usage
#define BIO_set_buffer_read_data(b,buf,num) BIO_ctrl(b,BIO_C_SET_BUFF_READ_DATA,num,buf)
#define BIO_buffer_peek(b,s,l) BIO_ctrl(b,BIO_CTRL_PEEK,(l),(s))
The large parameter is signed, and negative values are not explicitly rejected in these paths.
**Reproduction **
poc_bio_heap_read.c poc_bio_heap_write.c
Build
gcc -Wall -g -o poc_bio_heap_write poc_bio_heap_write.c -lssl -lcrypto
gcc -Wall -g -o poc_bio_heap_read poc_bio_heap_read.c -lssl -lcrypto
Run
./poc_bio_heap_write
# Result: SIGABRT (heap corruption)
./poc_bio_heap_read
# Result: SIGSEGV
Expected Behavior
The API should reject invalid negative lengths early, for example:
Return error (0 or negative) Or explicitly validate num >= 0 before use
Actual Behavior Negative values: Bypass checks (num > ctx->ibuf_size) Are cast to int and then implicitly to size_t Reach memcpy() → crash