test-malloc-overflow.c revision ba1a5db879b08d2fefcb42160af67853cdfe7687
02c335c23bf5fa225a467c19f2c063fb0dc7b8c3Timo Sirainen/* Copyright (c) 2016-2017 Dovecot authors, see the included COPYING file */
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Bosch
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Bosch#include "test-lib.h"
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Bosch
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Boschstatic void test_malloc_overflow_multiply(void)
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Bosch{
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Bosch static const struct {
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Bosch size_t a, b;
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Bosch } tests[] = {
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Bosch { 0, SIZE_MAX },
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Bosch { 1, SIZE_MAX },
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Bosch { SIZE_MAX/2, 2 },
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Bosch };
5afe997e79978b7e989aa3b0bfdf4a813ecdc6f6Timo Sirainen test_begin("MALLOC_MULTIPLY()");
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Bosch for (unsigned int i = 0; i < N_ELEMENTS(tests); i++) {
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Bosch test_assert_idx(MALLOC_MULTIPLY(tests[i].a, tests[i].b) == tests[i].a * tests[i].b, i);
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Bosch test_assert_idx(MALLOC_MULTIPLY(tests[i].b, tests[i].a) == tests[i].b * tests[i].a, i);
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Bosch }
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Bosch test_end();
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Bosch}
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Bosch
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Boschstatic void test_malloc_overflow_add(void)
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Bosch{
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Bosch static const struct {
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Bosch size_t a, b;
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Bosch } tests[] = {
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Bosch { 0, SIZE_MAX },
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Bosch { 1, SIZE_MAX-1 },
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Bosch { SIZE_MAX/2+1, SIZE_MAX/2 },
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Bosch };
a10ed8c47534b4c6b6bf2711ccfe577e720a47b4Timo Sirainen unsigned short n = 2;
a10ed8c47534b4c6b6bf2711ccfe577e720a47b4Timo Sirainen
a10ed8c47534b4c6b6bf2711ccfe577e720a47b4Timo Sirainen test_begin("MALLOC_ADD()");
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Bosch /* check that no compiler warning is given */
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Bosch test_assert(MALLOC_ADD(2, n) == 2U+n);
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Bosch for (unsigned int i = 0; i < N_ELEMENTS(tests); i++) {
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Bosch test_assert_idx(MALLOC_ADD(tests[i].a, tests[i].b) == tests[i].a + tests[i].b, i);
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Bosch test_assert_idx(MALLOC_ADD(tests[i].b, tests[i].a) == tests[i].b + tests[i].a, i);
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Bosch }
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Bosch test_end();
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Bosch}
5afe997e79978b7e989aa3b0bfdf4a813ecdc6f6Timo Sirainen
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Boschvoid test_malloc_overflow(void)
5afe997e79978b7e989aa3b0bfdf4a813ecdc6f6Timo Sirainen{
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Bosch test_malloc_overflow_multiply();
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Bosch test_malloc_overflow_add();
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Bosch}
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Bosch
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Boschstatic enum fatal_test_state fatal_malloc_overflow_multiply(unsigned int *stage)
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Bosch{
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Bosch const struct {
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Bosch size_t a, b;
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Bosch } mul_tests[] = {
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Bosch { SIZE_MAX/2+1, 2 },
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Bosch };
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Bosch unsigned int i;
d295cff1b640240cd198b9c8e963c9116ab95510Timo Sirainen
d295cff1b640240cd198b9c8e963c9116ab95510Timo Sirainen test_expect_fatal_string("memory allocation overflow");
935a2434cd674e9cd17eabb296f84d1d891a23aeTimo Sirainen switch (*stage) {
935a2434cd674e9cd17eabb296f84d1d891a23aeTimo Sirainen case 0:
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Bosch test_begin("MALLOC_MULTIPLY() overflows");
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Bosch i_error("%"PRIuSIZE_T, MALLOC_MULTIPLY((size_t)SIZE_MAX/2, (uint8_t)3));
a10ed8c47534b4c6b6bf2711ccfe577e720a47b4Timo Sirainen break;
a10ed8c47534b4c6b6bf2711ccfe577e720a47b4Timo Sirainen case 1:
9a5980c7bb836f69a63082f4699c30596ea4ee74Timo Sirainen i_error("%"PRIuSIZE_T, MALLOC_MULTIPLY((uint8_t)3, (size_t)SIZE_MAX/2));
a10ed8c47534b4c6b6bf2711ccfe577e720a47b4Timo Sirainen break;
a10ed8c47534b4c6b6bf2711ccfe577e720a47b4Timo Sirainen }
a10ed8c47534b4c6b6bf2711ccfe577e720a47b4Timo Sirainen *stage -= 2;
a10ed8c47534b4c6b6bf2711ccfe577e720a47b4Timo Sirainen
9a5980c7bb836f69a63082f4699c30596ea4ee74Timo Sirainen if (*stage >= N_ELEMENTS(mul_tests)*2) {
a10ed8c47534b4c6b6bf2711ccfe577e720a47b4Timo Sirainen *stage -= N_ELEMENTS(mul_tests)*2;
a10ed8c47534b4c6b6bf2711ccfe577e720a47b4Timo Sirainen if (*stage == 0)
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Bosch test_end();
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Bosch test_expect_fatal_string(NULL);
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Bosch return FATAL_TEST_FINISHED;
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Bosch }
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Bosch i = *stage / 2;
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Bosch
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Bosch if (*stage % 2 == 0)
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Bosch i_error("%"PRIuSIZE_T, MALLOC_MULTIPLY(mul_tests[i].a, mul_tests[i].b));
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Bosch else
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Bosch i_error("%"PRIuSIZE_T, MALLOC_MULTIPLY(mul_tests[i].b, mul_tests[i].a));
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Bosch return FATAL_TEST_FAILURE;
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Bosch}
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Bosch
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Boschstatic enum fatal_test_state fatal_malloc_overflow_add(unsigned int *stage)
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Bosch{
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Bosch const struct {
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Bosch size_t a, b;
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Bosch } add_tests[] = {
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Bosch { SIZE_MAX, 1 },
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Bosch { SIZE_MAX/2+1, SIZE_MAX/2+1 },
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Bosch };
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Bosch unsigned int i;
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Bosch
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Bosch test_expect_fatal_string("memory allocation overflow");
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Bosch switch (*stage) {
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Bosch case 0:
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Bosch test_begin("MALLOC_ADD() overflows");
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Bosch i_error("%"PRIuSIZE_T, MALLOC_ADD((size_t)SIZE_MAX, (uint8_t)1));
5d3e31cae626840561c5313e97eef0272be26ae1Timo Sirainen break;
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Bosch case 1:
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Bosch i_error("%"PRIuSIZE_T, MALLOC_ADD((uint8_t)1, (size_t)SIZE_MAX));
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Bosch break;
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Bosch }
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Bosch *stage -= 2;
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Bosch
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Bosch if (*stage >= N_ELEMENTS(add_tests)*2) {
76f0cc074ea79151e968078906224d8b6a5806fdTimo Sirainen *stage -= N_ELEMENTS(add_tests)*2;
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Bosch if (*stage == 0)
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Bosch test_end();
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Bosch test_expect_fatal_string(NULL);
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Bosch return FATAL_TEST_FINISHED;
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Bosch }
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Bosch i = *stage / 2;
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Bosch
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Bosch if (*stage % 2 == 0)
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Bosch i_error("%"PRIuSIZE_T, MALLOC_ADD(add_tests[i].a, add_tests[i].b));
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Bosch else
5afe997e79978b7e989aa3b0bfdf4a813ecdc6f6Timo Sirainen i_error("%"PRIuSIZE_T, MALLOC_ADD(add_tests[i].b, add_tests[i].a));
5afe997e79978b7e989aa3b0bfdf4a813ecdc6f6Timo Sirainen return FATAL_TEST_FAILURE;
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Bosch}
5afe997e79978b7e989aa3b0bfdf4a813ecdc6f6Timo Sirainen
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Boschenum fatal_test_state fatal_malloc_overflow(unsigned int stage)
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Bosch{
1a3254b83ba00315cfc47d3c6e99e837914594cfTimo Sirainen enum fatal_test_state state;
76f0cc074ea79151e968078906224d8b6a5806fdTimo Sirainen
76f0cc074ea79151e968078906224d8b6a5806fdTimo Sirainen state = fatal_malloc_overflow_multiply(&stage);
76f0cc074ea79151e968078906224d8b6a5806fdTimo Sirainen if (state != FATAL_TEST_FINISHED)
76f0cc074ea79151e968078906224d8b6a5806fdTimo Sirainen return state;
76f0cc074ea79151e968078906224d8b6a5806fdTimo Sirainen return fatal_malloc_overflow_add(&stage);
76f0cc074ea79151e968078906224d8b6a5806fdTimo Sirainen}
76f0cc074ea79151e968078906224d8b6a5806fdTimo Sirainen