openssl/openssl

BIO buffer APIs allow negative length → heap corruption, missing input validation (OpenSSL 3.0.2, 3.6.1)

Open

#30725 opened on Apr 8, 2026

View on GitHub
 (2 comments) (1 reaction) (0 assignees)C (30,157 stars) (11,262 forks)batch import
branch: 3.0branch: 3.3branch: 3.4branch: 3.5branch: 3.6branch: 4.0branch: mastergood first issuetriaged: bug

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

Contributor guide