From b3ac161fc6d13fef00216a7ff4c9440f0992587f Mon Sep 17 00:00:00 2001 From: Alex Kotov Date: Tue, 15 Dec 2020 12:09:04 +0500 Subject: [PATCH] Add test "prod_jumps_to_buffer_start_and_pushes_too_long_message" --- .gitignore | 1 + Makefile.am | 5 ++ include/shmemq.h | 1 + src/main.c | 14 ++++- ...buffer_start_and_pushes_too_long_message.c | 60 +++++++++++++++++++ 5 files changed, 80 insertions(+), 1 deletion(-) create mode 100644 tests/test_prod_jumps_to_buffer_start_and_pushes_too_long_message.c diff --git a/.gitignore b/.gitignore index 0a887d9..f1c9f67 100644 --- a/.gitignore +++ b/.gitignore @@ -39,5 +39,6 @@ /tests/test_main /tests/test_cons_pops_buffer_start /tests/test_cons_reaches_queue_end +/tests/test_prod_jumps_to_buffer_start_and_pushes_too_long_message /tests/test_prod_jumps_to_buffer_start_and_reaches_cons /tests/test_prod_reaches_buffer_end diff --git a/Makefile.am b/Makefile.am index 2956d94..a35b781 100644 --- a/Makefile.am +++ b/Makefile.am @@ -12,6 +12,7 @@ TESTS = \ tests/test_main \ tests/test_cons_pops_buffer_start \ tests/test_cons_reaches_queue_end \ + tests/test_prod_jumps_to_buffer_start_and_pushes_too_long_message \ tests/test_prod_jumps_to_buffer_start_and_reaches_cons \ tests/test_prod_reaches_buffer_end @@ -42,6 +43,10 @@ tests_test_cons_reaches_queue_end_SOURCES = \ $(libshmemq_a_SOURCES) \ tests/test_cons_reaches_queue_end.c +tests_test_prod_jumps_to_buffer_start_and_pushes_too_long_message_SOURCES = \ + $(libshmemq_a_SOURCES) \ + tests/test_prod_jumps_to_buffer_start_and_pushes_too_long_message.c + tests_test_prod_jumps_to_buffer_start_and_reaches_cons_SOURCES = \ $(libshmemq_a_SOURCES) \ tests/test_prod_jumps_to_buffer_start_and_reaches_cons.c diff --git a/include/shmemq.h b/include/shmemq.h index c9e5b25..2c5211e 100644 --- a/include/shmemq.h +++ b/include/shmemq.h @@ -29,6 +29,7 @@ typedef enum ShmemqError { // Bugs in user code. SHMEMQ_ERROR_BUG_POP_END_ON_EMPTY_QUEUE = 50, SHMEMQ_ERROR_BUG_PUSH_END_ON_FULL_QUEUE = 51, + SHMEMQ_ERROR_BUG_PUSH_END_OVERFLOW = 52, // Failed system calls. SHMEMQ_ERROR_FAILED_MALLOC = 100, diff --git a/src/main.c b/src/main.c index 67f0450..995ce71 100644 --- a/src/main.c +++ b/src/main.c @@ -217,9 +217,21 @@ void shmemq_push_end( header_and_data_size / SHMEMQ_FRAME_SIZE + 1; } - shmemq->buffer->header.write_frame_index = + const size_t new_write_frame_index = shmemq->buffer->header.write_frame_index + frame->header.message_frames_count; + + if ( + shmemq->buffer->header.write_frame_index < + shmemq->buffer->header.read_frame_index && + new_write_frame_index >= + shmemq->buffer->header.read_frame_index + ) { + if (error_ptr) *error_ptr = SHMEMQ_ERROR_BUG_PUSH_END_OVERFLOW; + return; + } + + shmemq->buffer->header.write_frame_index = new_write_frame_index; } ShmemqFrame shmemq_pop_start(const Shmemq shmemq) diff --git a/tests/test_prod_jumps_to_buffer_start_and_pushes_too_long_message.c b/tests/test_prod_jumps_to_buffer_start_and_pushes_too_long_message.c new file mode 100644 index 0000000..445cbcd --- /dev/null +++ b/tests/test_prod_jumps_to_buffer_start_and_pushes_too_long_message.c @@ -0,0 +1,60 @@ +#include + +#include + +static const char name[] = "/foobar"; + +int main() +{ + ShmemqError error; + + const Shmemq consumer = shmemq_new(name, true, &error); + assert(error == SHMEMQ_ERROR_NONE); + + const Shmemq producer = shmemq_new(name, false, &error); + assert(error == SHMEMQ_ERROR_NONE); + + for (unsigned i = 0; i < 100; ++i) { + const ShmemqFrame frame = shmemq_push_start(producer); + assert(frame != NULL); + + *(unsigned*)frame->data = i; + + shmemq_push_end(producer, sizeof(unsigned), &error); + assert(error == SHMEMQ_ERROR_NONE); + } + + for (unsigned i = 0; i < 10; ++i) { + const ShmemqFrame frame = shmemq_pop_start(consumer); + assert(frame != NULL); + + assert(*(unsigned*)frame->data == i); + + shmemq_pop_end(consumer, &error); + assert(error == SHMEMQ_ERROR_NONE); + } + + for (unsigned i = 0; i < 8; ++i) { + const ShmemqFrame frame = shmemq_push_start(producer); + assert(frame != NULL); + + *(unsigned*)frame->data = i; + + shmemq_push_end(producer, sizeof(unsigned), &error); + assert(error == SHMEMQ_ERROR_NONE); + } + + const ShmemqFrame frame = shmemq_push_start(producer); + assert(frame != NULL); + + shmemq_push_end(producer, 9, &error); + assert(error == SHMEMQ_ERROR_BUG_PUSH_END_OVERFLOW); + + shmemq_delete(consumer, &error); + assert(error == SHMEMQ_ERROR_NONE); + + shmemq_delete(producer, &error); + assert(error == SHMEMQ_ERROR_NONE); + + return 0; +}