test-malloc-overflow.c revision ad5ece2a07cca5fa033287f70bafdd312e2338a5
e59faf65ce864fe95dc00f5d52b8323cdbd0608aTimo Sirainen/* Copyright (c) 2016 Dovecot authors, see the included COPYING file */
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen#include "test-lib.h"
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
7e209b78ca757294dbbc15604c88673b3a6b0c39Timo Sirainenstatic void test_malloc_overflow_multiply(void)
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen{
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen const struct {
636f017be100bce67d66fd3ae1544a47681efd33Timo Sirainen size_t a, b;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen } tests[] = {
111a7dda02defa4d612468cfc3c40da5240645afTimo Sirainen { 0, SIZE_MAX },
7a7d2aa11e46195e2d92d6c337d7e78052a5ce67Timo Sirainen { 1, SIZE_MAX },
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen { SIZE_MAX/2, 2 },
5c2d695acf9f95ae0dcdda89c4d2391ceda4d672Timo Sirainen };
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen test_begin("MALLOC_MULTIPLY()");
111a7dda02defa4d612468cfc3c40da5240645afTimo Sirainen for (unsigned int i = 0; i < N_ELEMENTS(tests); i++) {
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen test_assert_idx(MALLOC_MULTIPLY(tests[i].a, tests[i].b) == tests[i].a * tests[i].b, i);
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen test_assert_idx(MALLOC_MULTIPLY(tests[i].b, tests[i].a) == tests[i].b * tests[i].a, i);
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen }
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen test_end();
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen}
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainenstatic void test_malloc_overflow_add(void)
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen{
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen const struct {
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen size_t a, b;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen } tests[] = {
111a7dda02defa4d612468cfc3c40da5240645afTimo Sirainen { 0, SIZE_MAX },
111a7dda02defa4d612468cfc3c40da5240645afTimo Sirainen { 1, SIZE_MAX-1 },
111a7dda02defa4d612468cfc3c40da5240645afTimo Sirainen { SIZE_MAX/2+1, SIZE_MAX/2 },
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen };
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen unsigned short n = 2;
db0735f9b388c5bcfb781b1b25015e898d63d953Timo Sirainen
db0735f9b388c5bcfb781b1b25015e898d63d953Timo Sirainen test_begin("MALLOC_ADD()");
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen /* check that no compiler warning is given */
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen test_assert(MALLOC_ADD(2, n) == 2U+n);
5c2d695acf9f95ae0dcdda89c4d2391ceda4d672Timo Sirainen for (unsigned int i = 0; i < N_ELEMENTS(tests); i++) {
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen test_assert_idx(MALLOC_ADD(tests[i].a, tests[i].b) == tests[i].a + tests[i].b, i);
5c2d695acf9f95ae0dcdda89c4d2391ceda4d672Timo Sirainen test_assert_idx(MALLOC_ADD(tests[i].b, tests[i].a) == tests[i].b + tests[i].a, i);
db0735f9b388c5bcfb781b1b25015e898d63d953Timo Sirainen }
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen test_end();
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen}
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
6b265a8a9d1ce3b3a8033445e99c9035d62ffbc7Timo Sirainenvoid test_malloc_overflow(void)
6b265a8a9d1ce3b3a8033445e99c9035d62ffbc7Timo Sirainen{
6b265a8a9d1ce3b3a8033445e99c9035d62ffbc7Timo Sirainen test_malloc_overflow_multiply();
6b265a8a9d1ce3b3a8033445e99c9035d62ffbc7Timo Sirainen test_malloc_overflow_add();
6b265a8a9d1ce3b3a8033445e99c9035d62ffbc7Timo Sirainen}
6b265a8a9d1ce3b3a8033445e99c9035d62ffbc7Timo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainenstatic enum fatal_test_state fatal_malloc_overflow_multiply(unsigned int *stage)
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen{
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen const struct {
5c2d695acf9f95ae0dcdda89c4d2391ceda4d672Timo Sirainen size_t a, b;
5c2d695acf9f95ae0dcdda89c4d2391ceda4d672Timo Sirainen } mul_tests[] = {
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen { SIZE_MAX/2+1, 2 },
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen };
5c2d695acf9f95ae0dcdda89c4d2391ceda4d672Timo Sirainen unsigned int i;
5c2d695acf9f95ae0dcdda89c4d2391ceda4d672Timo Sirainen
5c2d695acf9f95ae0dcdda89c4d2391ceda4d672Timo Sirainen switch (*stage) {
84078771687fabf75819918f0f3aecdc3ed08b36Timo Sirainen case 0:
84078771687fabf75819918f0f3aecdc3ed08b36Timo Sirainen test_begin("MALLOC_MULTIPLY() overflows");
5c2d695acf9f95ae0dcdda89c4d2391ceda4d672Timo Sirainen i_error("%"PRIuSIZE_T, MALLOC_MULTIPLY((size_t)SIZE_MAX/2, (uint8_t)3));
5c2d695acf9f95ae0dcdda89c4d2391ceda4d672Timo Sirainen break;
5c2d695acf9f95ae0dcdda89c4d2391ceda4d672Timo Sirainen case 1:
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen i_error("%"PRIuSIZE_T, MALLOC_MULTIPLY((uint8_t)3, (size_t)SIZE_MAX/2));
5c2d695acf9f95ae0dcdda89c4d2391ceda4d672Timo Sirainen break;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen }
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen *stage -= 2;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen if (*stage >= N_ELEMENTS(mul_tests)*2) {
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen *stage -= N_ELEMENTS(mul_tests)*2;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen if (*stage == 0)
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen test_end();
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen return FATAL_TEST_FINISHED;
db0735f9b388c5bcfb781b1b25015e898d63d953Timo Sirainen }
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen i = *stage / 2;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
66c0f96d704f09c88dd03b0ee13a3e9711ffe593Timo Sirainen if (*stage % 2 == 0)
66c0f96d704f09c88dd03b0ee13a3e9711ffe593Timo Sirainen i_error("%"PRIuSIZE_T, MALLOC_MULTIPLY(mul_tests[i].a, mul_tests[i].b));
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen else
66c0f96d704f09c88dd03b0ee13a3e9711ffe593Timo Sirainen i_error("%"PRIuSIZE_T, MALLOC_MULTIPLY(mul_tests[i].b, mul_tests[i].a));
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen return FATAL_TEST_FAILURE;
7e209b78ca757294dbbc15604c88673b3a6b0c39Timo Sirainen}
7e209b78ca757294dbbc15604c88673b3a6b0c39Timo Sirainen
db0735f9b388c5bcfb781b1b25015e898d63d953Timo Sirainenstatic enum fatal_test_state fatal_malloc_overflow_add(unsigned int *stage)
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen{
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen const struct {
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen size_t a, b;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen } add_tests[] = {
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen { SIZE_MAX, 1 },
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen { SIZE_MAX/2+1, SIZE_MAX/2+1 },
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen };
111a7dda02defa4d612468cfc3c40da5240645afTimo Sirainen unsigned int i;
111a7dda02defa4d612468cfc3c40da5240645afTimo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen switch (*stage) {
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen case 0:
db0735f9b388c5bcfb781b1b25015e898d63d953Timo Sirainen test_begin("MALLOC_ADD() overflows");
db0735f9b388c5bcfb781b1b25015e898d63d953Timo Sirainen i_error("%"PRIuSIZE_T, MALLOC_ADD((size_t)SIZE_MAX, (uint8_t)1));
db0735f9b388c5bcfb781b1b25015e898d63d953Timo Sirainen break;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen case 1:
db0735f9b388c5bcfb781b1b25015e898d63d953Timo Sirainen i_error("%"PRIuSIZE_T, MALLOC_ADD((uint8_t)1, (size_t)SIZE_MAX));
db0735f9b388c5bcfb781b1b25015e898d63d953Timo Sirainen break;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen }
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen *stage -= 2;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen if (*stage >= N_ELEMENTS(add_tests)*2) {
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen *stage -= N_ELEMENTS(add_tests)*2;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen if (*stage == 0)
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen test_end();
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen return FATAL_TEST_FINISHED;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen }
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen i = *stage / 2;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
834f2b9f60d93e4c7dfc6992e692f5b7213a1b11Timo Sirainen if (*stage % 2 == 0)
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen i_error("%"PRIuSIZE_T, MALLOC_ADD(add_tests[i].a, add_tests[i].b));
67770c0874918e3b73bbd1ff75b5ec91790d51dcTimo Sirainen else
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen i_error("%"PRIuSIZE_T, MALLOC_ADD(add_tests[i].b, add_tests[i].a));
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen return FATAL_TEST_FAILURE;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen}
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainenenum fatal_test_state fatal_malloc_overflow(unsigned int stage)
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen{
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen enum fatal_test_state state;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
bcdb6c0bd2e7dbb34b306d3d8c2383a7d7654612Timo Sirainen state = fatal_malloc_overflow_multiply(&stage);
bcdb6c0bd2e7dbb34b306d3d8c2383a7d7654612Timo Sirainen if (state != FATAL_TEST_FINISHED)
bcdb6c0bd2e7dbb34b306d3d8c2383a7d7654612Timo Sirainen return state;
bcdb6c0bd2e7dbb34b306d3d8c2383a7d7654612Timo Sirainen return fatal_malloc_overflow_add(&stage);
bcdb6c0bd2e7dbb34b306d3d8c2383a7d7654612Timo Sirainen
bcdb6c0bd2e7dbb34b306d3d8c2383a7d7654612Timo Sirainen /* individual checks */
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen switch (stage) {
111a7dda02defa4d612468cfc3c40da5240645afTimo Sirainen case 0:
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen if (stage == 0)
3852872e6954b7132e637294132005e86b8ebd4aTimo Sirainen test_begin("MALLOC_MULTIPLY() overflows");
3852872e6954b7132e637294132005e86b8ebd4aTimo Sirainen break;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen }
c3001a6476bae22fc0f55abc73014211b0775d98Timo Sirainen return FATAL_TEST_FINISHED;
c3001a6476bae22fc0f55abc73014211b0775d98Timo Sirainen}
c3001a6476bae22fc0f55abc73014211b0775d98Timo Sirainen