diff --git a/buffer/apr_buffer.c b/buffer/apr_buffer.c index 4efd1ef75d..a76c39d16f 100644 --- a/buffer/apr_buffer.c +++ b/buffer/apr_buffer.c @@ -297,6 +297,9 @@ APR_DECLARE(apr_buffer_t *) apr_buffer_cpy(apr_buffer_t *dst, apr_size_t size = src->size + src->zero_terminated; void *mem = alloc(ctx, size); + if (!mem) { + return NULL; + } memcpy(mem, src->d.mem, size); dst->zero_terminated = src->zero_terminated; diff --git a/include/apr_buffer.h b/include/apr_buffer.h index 711c772776..4f54b248f9 100644 --- a/include/apr_buffer.h +++ b/include/apr_buffer.h @@ -354,7 +354,7 @@ APR_DECLARE(apr_status_t) apr_buffer_dup(apr_buffer_t **out, * @param src The second buffer * @param alloc The function callback to allocate memory for the buffer * @param ctx The context for the callback - * @return Returns dst. + * @return Returns dst, or NULL if alloc is provided and returns NULL. */ APR_DECLARE(apr_buffer_t *) apr_buffer_cpy(apr_buffer_t *dst, const apr_buffer_t *src, diff --git a/test/testbuffer.c b/test/testbuffer.c index fd4d7edc32..e129d61c2f 100644 --- a/test/testbuffer.c +++ b/test/testbuffer.c @@ -265,6 +265,22 @@ static void test_compare_buffers(abts_case *tc, void *data) apr_pool_destroy(pool); } +static void *test_failing_alloc(void *ctx, apr_size_t size) +{ + return NULL; +} + +static void test_buffer_cpy_alloc_failure(abts_case *tc, void *data) +{ + apr_buffer_t src, dst; + + apr_buffer_str_set(&src, "test", APR_BUFFER_STRING); + memset(&dst, 0, sizeof(dst)); + + ABTS_ASSERT(tc, "apr_buffer_cpy returns NULL on alloc failure", + apr_buffer_cpy(&dst, &src, test_failing_alloc, NULL) == NULL); +} + abts_suite *testbuffer(abts_suite *suite) { suite = ADD_SUITE(suite); @@ -274,6 +290,7 @@ abts_suite *testbuffer(abts_suite *suite) abts_run_test(suite, test_null_buffer, NULL); abts_run_test(suite, test_buffers, NULL); abts_run_test(suite, test_compare_buffers, NULL); + abts_run_test(suite, test_buffer_cpy_alloc_failure, NULL); return suite; }