bcb4e51a409d94ae670de96afb8483a4f7855294Stephan Bosch/* Copyright (c) 2016-2018 Dovecot authors, see the included COPYING file */
b716136fc47efd434d60be5db262b4013e375fa9Timo Sirainen
b716136fc47efd434d60be5db262b4013e375fa9Timo Sirainen#include "test-lib.h"
b716136fc47efd434d60be5db262b4013e375fa9Timo Sirainen
b716136fc47efd434d60be5db262b4013e375fa9Timo Sirainenstatic void test_malloc_overflow_multiply(void)
b716136fc47efd434d60be5db262b4013e375fa9Timo Sirainen{
b7324e421e2132cbbf753e6fdbe675bbaecdf929Timo Sirainen static const struct {
b716136fc47efd434d60be5db262b4013e375fa9Timo Sirainen size_t a, b;
b716136fc47efd434d60be5db262b4013e375fa9Timo Sirainen } tests[] = {
b716136fc47efd434d60be5db262b4013e375fa9Timo Sirainen { 0, SIZE_MAX },
b716136fc47efd434d60be5db262b4013e375fa9Timo Sirainen { 1, SIZE_MAX },
b716136fc47efd434d60be5db262b4013e375fa9Timo Sirainen { SIZE_MAX/2, 2 },
b716136fc47efd434d60be5db262b4013e375fa9Timo Sirainen };
b716136fc47efd434d60be5db262b4013e375fa9Timo Sirainen test_begin("MALLOC_MULTIPLY()");
b716136fc47efd434d60be5db262b4013e375fa9Timo Sirainen for (unsigned int i = 0; i < N_ELEMENTS(tests); i++) {
b716136fc47efd434d60be5db262b4013e375fa9Timo Sirainen test_assert_idx(MALLOC_MULTIPLY(tests[i].a, tests[i].b) == tests[i].a * tests[i].b, i);
b716136fc47efd434d60be5db262b4013e375fa9Timo Sirainen test_assert_idx(MALLOC_MULTIPLY(tests[i].b, tests[i].a) == tests[i].b * tests[i].a, i);
b716136fc47efd434d60be5db262b4013e375fa9Timo Sirainen }
b716136fc47efd434d60be5db262b4013e375fa9Timo Sirainen test_end();
b716136fc47efd434d60be5db262b4013e375fa9Timo Sirainen}
b716136fc47efd434d60be5db262b4013e375fa9Timo Sirainen
b716136fc47efd434d60be5db262b4013e375fa9Timo Sirainenstatic void test_malloc_overflow_add(void)
b716136fc47efd434d60be5db262b4013e375fa9Timo Sirainen{
b7324e421e2132cbbf753e6fdbe675bbaecdf929Timo Sirainen static const struct {
b716136fc47efd434d60be5db262b4013e375fa9Timo Sirainen size_t a, b;
b716136fc47efd434d60be5db262b4013e375fa9Timo Sirainen } tests[] = {
b716136fc47efd434d60be5db262b4013e375fa9Timo Sirainen { 0, SIZE_MAX },
b716136fc47efd434d60be5db262b4013e375fa9Timo Sirainen { 1, SIZE_MAX-1 },
b716136fc47efd434d60be5db262b4013e375fa9Timo Sirainen { SIZE_MAX/2+1, SIZE_MAX/2 },
b716136fc47efd434d60be5db262b4013e375fa9Timo Sirainen };
b716136fc47efd434d60be5db262b4013e375fa9Timo Sirainen unsigned short n = 2;
b716136fc47efd434d60be5db262b4013e375fa9Timo Sirainen
b716136fc47efd434d60be5db262b4013e375fa9Timo Sirainen test_begin("MALLOC_ADD()");
b716136fc47efd434d60be5db262b4013e375fa9Timo Sirainen /* check that no compiler warning is given */
ad5ece2a07cca5fa033287f70bafdd312e2338a5Timo Sirainen test_assert(MALLOC_ADD(2, n) == 2U+n);
b716136fc47efd434d60be5db262b4013e375fa9Timo Sirainen for (unsigned int i = 0; i < N_ELEMENTS(tests); i++) {
b716136fc47efd434d60be5db262b4013e375fa9Timo Sirainen test_assert_idx(MALLOC_ADD(tests[i].a, tests[i].b) == tests[i].a + tests[i].b, i);
b716136fc47efd434d60be5db262b4013e375fa9Timo Sirainen test_assert_idx(MALLOC_ADD(tests[i].b, tests[i].a) == tests[i].b + tests[i].a, i);
b716136fc47efd434d60be5db262b4013e375fa9Timo Sirainen }
b716136fc47efd434d60be5db262b4013e375fa9Timo Sirainen test_end();
b716136fc47efd434d60be5db262b4013e375fa9Timo Sirainen}
b716136fc47efd434d60be5db262b4013e375fa9Timo Sirainen
b716136fc47efd434d60be5db262b4013e375fa9Timo Sirainenvoid test_malloc_overflow(void)
b716136fc47efd434d60be5db262b4013e375fa9Timo Sirainen{
b716136fc47efd434d60be5db262b4013e375fa9Timo Sirainen test_malloc_overflow_multiply();
b716136fc47efd434d60be5db262b4013e375fa9Timo Sirainen test_malloc_overflow_add();
b716136fc47efd434d60be5db262b4013e375fa9Timo Sirainen}
b716136fc47efd434d60be5db262b4013e375fa9Timo Sirainen
b716136fc47efd434d60be5db262b4013e375fa9Timo Sirainenstatic enum fatal_test_state fatal_malloc_overflow_multiply(unsigned int *stage)
b716136fc47efd434d60be5db262b4013e375fa9Timo Sirainen{
b716136fc47efd434d60be5db262b4013e375fa9Timo Sirainen const struct {
b716136fc47efd434d60be5db262b4013e375fa9Timo Sirainen size_t a, b;
b716136fc47efd434d60be5db262b4013e375fa9Timo Sirainen } mul_tests[] = {
b716136fc47efd434d60be5db262b4013e375fa9Timo Sirainen { SIZE_MAX/2+1, 2 },
b716136fc47efd434d60be5db262b4013e375fa9Timo Sirainen };
b716136fc47efd434d60be5db262b4013e375fa9Timo Sirainen unsigned int i;
b716136fc47efd434d60be5db262b4013e375fa9Timo Sirainen
ba1a5db879b08d2fefcb42160af67853cdfe7687Timo Sirainen test_expect_fatal_string("memory allocation overflow");
b716136fc47efd434d60be5db262b4013e375fa9Timo Sirainen switch (*stage) {
b716136fc47efd434d60be5db262b4013e375fa9Timo Sirainen case 0:
b716136fc47efd434d60be5db262b4013e375fa9Timo Sirainen test_begin("MALLOC_MULTIPLY() overflows");
b716136fc47efd434d60be5db262b4013e375fa9Timo Sirainen i_error("%"PRIuSIZE_T, MALLOC_MULTIPLY((size_t)SIZE_MAX/2, (uint8_t)3));
b716136fc47efd434d60be5db262b4013e375fa9Timo Sirainen break;
b716136fc47efd434d60be5db262b4013e375fa9Timo Sirainen case 1:
b716136fc47efd434d60be5db262b4013e375fa9Timo Sirainen i_error("%"PRIuSIZE_T, MALLOC_MULTIPLY((uint8_t)3, (size_t)SIZE_MAX/2));
b716136fc47efd434d60be5db262b4013e375fa9Timo Sirainen break;
b716136fc47efd434d60be5db262b4013e375fa9Timo Sirainen }
b716136fc47efd434d60be5db262b4013e375fa9Timo Sirainen *stage -= 2;
b716136fc47efd434d60be5db262b4013e375fa9Timo Sirainen
b716136fc47efd434d60be5db262b4013e375fa9Timo Sirainen if (*stage >= N_ELEMENTS(mul_tests)*2) {
b716136fc47efd434d60be5db262b4013e375fa9Timo Sirainen *stage -= N_ELEMENTS(mul_tests)*2;
b716136fc47efd434d60be5db262b4013e375fa9Timo Sirainen if (*stage == 0)
b716136fc47efd434d60be5db262b4013e375fa9Timo Sirainen test_end();
ba1a5db879b08d2fefcb42160af67853cdfe7687Timo Sirainen test_expect_fatal_string(NULL);
b716136fc47efd434d60be5db262b4013e375fa9Timo Sirainen return FATAL_TEST_FINISHED;
b716136fc47efd434d60be5db262b4013e375fa9Timo Sirainen }
b716136fc47efd434d60be5db262b4013e375fa9Timo Sirainen i = *stage / 2;
b716136fc47efd434d60be5db262b4013e375fa9Timo Sirainen
b716136fc47efd434d60be5db262b4013e375fa9Timo Sirainen if (*stage % 2 == 0)
b716136fc47efd434d60be5db262b4013e375fa9Timo Sirainen i_error("%"PRIuSIZE_T, MALLOC_MULTIPLY(mul_tests[i].a, mul_tests[i].b));
b716136fc47efd434d60be5db262b4013e375fa9Timo Sirainen else
b716136fc47efd434d60be5db262b4013e375fa9Timo Sirainen i_error("%"PRIuSIZE_T, MALLOC_MULTIPLY(mul_tests[i].b, mul_tests[i].a));
b716136fc47efd434d60be5db262b4013e375fa9Timo Sirainen return FATAL_TEST_FAILURE;
b716136fc47efd434d60be5db262b4013e375fa9Timo Sirainen}
b716136fc47efd434d60be5db262b4013e375fa9Timo Sirainen
b716136fc47efd434d60be5db262b4013e375fa9Timo Sirainenstatic enum fatal_test_state fatal_malloc_overflow_add(unsigned int *stage)
b716136fc47efd434d60be5db262b4013e375fa9Timo Sirainen{
b716136fc47efd434d60be5db262b4013e375fa9Timo Sirainen const struct {
b716136fc47efd434d60be5db262b4013e375fa9Timo Sirainen size_t a, b;
b716136fc47efd434d60be5db262b4013e375fa9Timo Sirainen } add_tests[] = {
b716136fc47efd434d60be5db262b4013e375fa9Timo Sirainen { SIZE_MAX, 1 },
b716136fc47efd434d60be5db262b4013e375fa9Timo Sirainen { SIZE_MAX/2+1, SIZE_MAX/2+1 },
b716136fc47efd434d60be5db262b4013e375fa9Timo Sirainen };
b716136fc47efd434d60be5db262b4013e375fa9Timo Sirainen unsigned int i;
b716136fc47efd434d60be5db262b4013e375fa9Timo Sirainen
ba1a5db879b08d2fefcb42160af67853cdfe7687Timo Sirainen test_expect_fatal_string("memory allocation overflow");
b716136fc47efd434d60be5db262b4013e375fa9Timo Sirainen switch (*stage) {
b716136fc47efd434d60be5db262b4013e375fa9Timo Sirainen case 0:
b716136fc47efd434d60be5db262b4013e375fa9Timo Sirainen test_begin("MALLOC_ADD() overflows");
b716136fc47efd434d60be5db262b4013e375fa9Timo Sirainen i_error("%"PRIuSIZE_T, MALLOC_ADD((size_t)SIZE_MAX, (uint8_t)1));
b716136fc47efd434d60be5db262b4013e375fa9Timo Sirainen break;
b716136fc47efd434d60be5db262b4013e375fa9Timo Sirainen case 1:
b716136fc47efd434d60be5db262b4013e375fa9Timo Sirainen i_error("%"PRIuSIZE_T, MALLOC_ADD((uint8_t)1, (size_t)SIZE_MAX));
b716136fc47efd434d60be5db262b4013e375fa9Timo Sirainen break;
b716136fc47efd434d60be5db262b4013e375fa9Timo Sirainen }
b716136fc47efd434d60be5db262b4013e375fa9Timo Sirainen *stage -= 2;
b716136fc47efd434d60be5db262b4013e375fa9Timo Sirainen
b716136fc47efd434d60be5db262b4013e375fa9Timo Sirainen if (*stage >= N_ELEMENTS(add_tests)*2) {
b716136fc47efd434d60be5db262b4013e375fa9Timo Sirainen *stage -= N_ELEMENTS(add_tests)*2;
b716136fc47efd434d60be5db262b4013e375fa9Timo Sirainen if (*stage == 0)
b716136fc47efd434d60be5db262b4013e375fa9Timo Sirainen test_end();
ba1a5db879b08d2fefcb42160af67853cdfe7687Timo Sirainen test_expect_fatal_string(NULL);
b716136fc47efd434d60be5db262b4013e375fa9Timo Sirainen return FATAL_TEST_FINISHED;
b716136fc47efd434d60be5db262b4013e375fa9Timo Sirainen }
b716136fc47efd434d60be5db262b4013e375fa9Timo Sirainen i = *stage / 2;
b716136fc47efd434d60be5db262b4013e375fa9Timo Sirainen
b716136fc47efd434d60be5db262b4013e375fa9Timo Sirainen if (*stage % 2 == 0)
b716136fc47efd434d60be5db262b4013e375fa9Timo Sirainen i_error("%"PRIuSIZE_T, MALLOC_ADD(add_tests[i].a, add_tests[i].b));
b716136fc47efd434d60be5db262b4013e375fa9Timo Sirainen else
b716136fc47efd434d60be5db262b4013e375fa9Timo Sirainen i_error("%"PRIuSIZE_T, MALLOC_ADD(add_tests[i].b, add_tests[i].a));
b716136fc47efd434d60be5db262b4013e375fa9Timo Sirainen return FATAL_TEST_FAILURE;
b716136fc47efd434d60be5db262b4013e375fa9Timo Sirainen}
b716136fc47efd434d60be5db262b4013e375fa9Timo Sirainen
b716136fc47efd434d60be5db262b4013e375fa9Timo Sirainenenum fatal_test_state fatal_malloc_overflow(unsigned int stage)
b716136fc47efd434d60be5db262b4013e375fa9Timo Sirainen{
b716136fc47efd434d60be5db262b4013e375fa9Timo Sirainen enum fatal_test_state state;
b716136fc47efd434d60be5db262b4013e375fa9Timo Sirainen
b716136fc47efd434d60be5db262b4013e375fa9Timo Sirainen state = fatal_malloc_overflow_multiply(&stage);
b716136fc47efd434d60be5db262b4013e375fa9Timo Sirainen if (state != FATAL_TEST_FINISHED)
b716136fc47efd434d60be5db262b4013e375fa9Timo Sirainen return state;
b716136fc47efd434d60be5db262b4013e375fa9Timo Sirainen return fatal_malloc_overflow_add(&stage);
b716136fc47efd434d60be5db262b4013e375fa9Timo Sirainen}