From 0d8fab51768540fbef93420826b9f59989d4b3e0 Mon Sep 17 00:00:00 2001 From: ouki Date: Fri, 30 Oct 2026 18:36:33 +0900 Subject: [PATCH 1/2] Leave req and cid unchanged on failure in OCSP_request_add0_id --- src/ocsp.c | 23 ++++++++++----- tests/api.c | 80 ++++++++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 95 insertions(+), 8 deletions(-) diff --git a/src/ocsp.c b/src/ocsp.c index 2d49b0dcbd2..9ff0e622f50 100644 --- a/src/ocsp.c +++ b/src/ocsp.c @@ -1393,9 +1393,25 @@ int wolfSSL_i2d_OCSP_REQUEST(OcspRequest* request, unsigned char** data) WOLFSSL_OCSP_ONEREQ* wolfSSL_OCSP_request_add0_id(OcspRequest *req, WOLFSSL_OCSP_CERTID *cid) { + byte* serial = NULL; + if (req == NULL || cid == NULL || cid->status == NULL) return NULL; + /* Allocate before changing req so that it is unchanged on failure and the + * caller still owns cid. */ + if (cid->status->serialSz > req->serialSz) { + serial = (byte*)XMALLOC((size_t)cid->status->serialSz, + req->heap, DYNAMIC_TYPE_OCSP_REQUEST); + if (serial == NULL) + return NULL; + } + + if (serial != NULL) { + XFREE(req->serial, req->heap, DYNAMIC_TYPE_OCSP_REQUEST); + req->serial = serial; + } + if (req->cid != NULL) wolfSSL_OCSP_CERTID_free((WOLFSSL_OCSP_CERTID*)req->cid); /* Keep to free */ @@ -1404,13 +1420,6 @@ WOLFSSL_OCSP_ONEREQ* wolfSSL_OCSP_request_add0_id(OcspRequest *req, XMEMCPY(req->issuerHash, cid->issuerHash, WC_MAX_DIGEST_SIZE); XMEMCPY(req->issuerKeyHash, cid->issuerKeyHash, WC_MAX_DIGEST_SIZE); req->hashAlg = (int)cid->hashAlgoOID; - if (cid->status->serialSz > req->serialSz) { - XFREE(req->serial, req->heap, DYNAMIC_TYPE_OCSP); - req->serial = (byte*)XMALLOC((size_t)cid->status->serialSz, - req->heap, DYNAMIC_TYPE_OCSP_REQUEST); - if (req->serial == NULL) - return NULL; - } XMEMCPY(req->serial, cid->status->serial, (size_t)cid->status->serialSz); req->serialSz = cid->status->serialSz; diff --git a/tests/api.c b/tests/api.c index 3874969255e..c3bd3ee1cb9 100644 --- a/tests/api.c +++ b/tests/api.c @@ -27643,6 +27643,56 @@ static time_t test_wolfSSL_OCSP_REQ_CTX_time_cb(time_t* t) } #endif +#if (defined(OPENSSL_ALL) || defined(WOLFSSL_HAPROXY)) && defined(HAVE_OCSP) && \ + defined(USE_WOLFSSL_MEMORY) && !defined(WOLFSSL_NO_MALLOC) && \ + !defined(WOLFSSL_STATIC_MEMORY) +static int ocsp_fail_next_alloc = 0; +static int ocsp_alloc_failed = 0; + +#ifdef WOLFSSL_DEBUG_MEMORY +static void* ocsp_oom_malloc_cb(size_t size, const char* func, + unsigned int line) +{ + (void)func; + (void)line; +#else +static void* ocsp_oom_malloc_cb(size_t size) +{ +#endif + if (ocsp_fail_next_alloc) { + ocsp_fail_next_alloc = 0; + ocsp_alloc_failed = 1; + return NULL; + } + return malloc(size); +} + +#ifdef WOLFSSL_DEBUG_MEMORY +static void ocsp_oom_free_cb(void* ptr, const char* func, unsigned int line) +{ + (void)func; + (void)line; +#else +static void ocsp_oom_free_cb(void* ptr) +{ +#endif + free(ptr); +} + +#ifdef WOLFSSL_DEBUG_MEMORY +static void* ocsp_oom_realloc_cb(void* ptr, size_t size, const char* func, + unsigned int line) +{ + (void)func; + (void)line; +#else +static void* ocsp_oom_realloc_cb(void* ptr, size_t size) +{ +#endif + return realloc(ptr, size); +} +#endif + static int test_wolfSSL_OCSP_REQ_CTX(void) { EXPECT_DECLS; @@ -27816,7 +27866,9 @@ static int test_wolfSSL_OCSP_REQ_CTX(void) }; OCSP_REQ_CTX *ctx = NULL; OCSP_REQUEST *req = NULL; + OCSP_REQUEST *req2 = NULL; OCSP_CERTID *cid = NULL; + OCSP_CERTID *cid2 = NULL; OCSP_RESPONSE *rsp = NULL; BIO* bio1 = NULL; BIO* bio2 = NULL; @@ -27828,6 +27880,10 @@ static int test_wolfSSL_OCSP_REQ_CTX(void) STACK_OF(X509_OBJECT) *str_objs = NULL; X509_OBJECT *x509_obj = NULL; STACK_OF(WOLFSSL_STRING) *skStr = NULL; + wolfSSL_Malloc_cb prev_mc = NULL; + wolfSSL_Free_cb prev_fc = NULL; + wolfSSL_Realloc_cb prev_rc = NULL; + int allocators_set = 0; ExpectNotNull(bio1 = BIO_new(BIO_s_bio())); ExpectNotNull(bio2 = BIO_new(BIO_s_bio())); @@ -27869,6 +27925,27 @@ static int test_wolfSSL_OCSP_REQ_CTX(void) ExpectNotNull(cid = OCSP_cert_to_id(EVP_sha1(), cert, issuer)); ExpectNotNull(OCSP_request_add0_id(req, cid)); ExpectIntEQ(OCSP_request_add1_nonce(req, NULL, -1), 1); + /* A failed allocation must leave req unchanged and cid owned by the + * caller. */ + ExpectNotNull(req2 = OCSP_REQUEST_new()); + ExpectNotNull(cid2 = OCSP_cert_to_id(EVP_sha1(), cert, issuer)); + ExpectIntEQ(wolfSSL_GetAllocators(&prev_mc, &prev_fc, &prev_rc), 0); + ExpectIntEQ(wolfSSL_SetAllocators(ocsp_oom_malloc_cb, ocsp_oom_free_cb, + ocsp_oom_realloc_cb), 0); + if (EXPECT_SUCCESS()) + allocators_set = 1; + ocsp_alloc_failed = 0; + ocsp_fail_next_alloc = 1; + ExpectNull(OCSP_request_add0_id(req2, cid2)); + ocsp_fail_next_alloc = 0; + if (allocators_set) + (void)wolfSSL_SetAllocators(prev_mc, prev_fc, prev_rc); + ExpectIntEQ(ocsp_alloc_failed, 1); + if (req2 != NULL) { + ExpectNull(req2->cid); + ExpectNull(req2->serial); + ExpectIntEQ(req2->serialSz, 0); + } ExpectNull(OCSP_sendreq_new(bio1, "/\r\nX-Injected: yes", NULL, -1)); ExpectNull(OCSP_sendreq_new(bio1, "/\nX-Injected: yes", NULL, -1)); @@ -27904,9 +27981,10 @@ static int test_wolfSSL_OCSP_REQ_CTX(void) ExpectIntEQ(wc_SetTimeCb(NULL), 0); ExpectNotNull(rsp); #endif - + OCSP_CERTID_free(cid2); OCSP_REQ_CTX_free(ctx); OCSP_REQUEST_free(req); + OCSP_REQUEST_free(req2); OCSP_RESPONSE_free(rsp); BIO_free(bio1); BIO_free(bio2); From 956324913699136da58639507d580e35f7def661 Mon Sep 17 00:00:00 2001 From: ouki Date: Sat, 31 Oct 2026 15:57:59 +0900 Subject: [PATCH 2/2] Guard OCSP allocation-failure test with allocator conditions --- tests/api.c | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/tests/api.c b/tests/api.c index c3bd3ee1cb9..ade492b9054 100644 --- a/tests/api.c +++ b/tests/api.c @@ -27643,9 +27643,13 @@ static time_t test_wolfSSL_OCSP_REQ_CTX_time_cb(time_t* t) } #endif -#if (defined(OPENSSL_ALL) || defined(WOLFSSL_HAPROXY)) && defined(HAVE_OCSP) && \ +#if defined(OPENSSL_ALL) && defined(HAVE_OCSP) && \ + defined(WOLFSSL_SIGNER_DER_CERT) && !defined(NO_FILESYSTEM) && \ + !defined(WOLFSSL_SM2) && !defined(WOLFSSL_SM3) && \ defined(USE_WOLFSSL_MEMORY) && !defined(WOLFSSL_NO_MALLOC) && \ !defined(WOLFSSL_STATIC_MEMORY) + +#define TEST_OCSP_OOM static int ocsp_fail_next_alloc = 0; static int ocsp_alloc_failed = 0; @@ -27866,9 +27870,7 @@ static int test_wolfSSL_OCSP_REQ_CTX(void) }; OCSP_REQ_CTX *ctx = NULL; OCSP_REQUEST *req = NULL; - OCSP_REQUEST *req2 = NULL; OCSP_CERTID *cid = NULL; - OCSP_CERTID *cid2 = NULL; OCSP_RESPONSE *rsp = NULL; BIO* bio1 = NULL; BIO* bio2 = NULL; @@ -27880,10 +27882,14 @@ static int test_wolfSSL_OCSP_REQ_CTX(void) STACK_OF(X509_OBJECT) *str_objs = NULL; X509_OBJECT *x509_obj = NULL; STACK_OF(WOLFSSL_STRING) *skStr = NULL; +#ifdef TEST_OCSP_OOM + OCSP_CERTID *cid2 = NULL; + OCSP_REQUEST *req2 = NULL; wolfSSL_Malloc_cb prev_mc = NULL; wolfSSL_Free_cb prev_fc = NULL; wolfSSL_Realloc_cb prev_rc = NULL; int allocators_set = 0; +#endif ExpectNotNull(bio1 = BIO_new(BIO_s_bio())); ExpectNotNull(bio2 = BIO_new(BIO_s_bio())); @@ -27925,6 +27931,7 @@ static int test_wolfSSL_OCSP_REQ_CTX(void) ExpectNotNull(cid = OCSP_cert_to_id(EVP_sha1(), cert, issuer)); ExpectNotNull(OCSP_request_add0_id(req, cid)); ExpectIntEQ(OCSP_request_add1_nonce(req, NULL, -1), 1); +#ifdef TEST_OCSP_OOM /* A failed allocation must leave req unchanged and cid owned by the * caller. */ ExpectNotNull(req2 = OCSP_REQUEST_new()); @@ -27946,6 +27953,7 @@ static int test_wolfSSL_OCSP_REQ_CTX(void) ExpectNull(req2->serial); ExpectIntEQ(req2->serialSz, 0); } +#endif ExpectNull(OCSP_sendreq_new(bio1, "/\r\nX-Injected: yes", NULL, -1)); ExpectNull(OCSP_sendreq_new(bio1, "/\nX-Injected: yes", NULL, -1)); @@ -27981,10 +27989,12 @@ static int test_wolfSSL_OCSP_REQ_CTX(void) ExpectIntEQ(wc_SetTimeCb(NULL), 0); ExpectNotNull(rsp); #endif +#ifdef TEST_OCSP_OOM OCSP_CERTID_free(cid2); + OCSP_REQUEST_free(req2); +#endif OCSP_REQ_CTX_free(ctx); OCSP_REQUEST_free(req); - OCSP_REQUEST_free(req2); OCSP_RESPONSE_free(rsp); BIO_free(bio1); BIO_free(bio2);