test-printf-format-fix.c revision 85174bd658f999cb3aa145885fd85674f8595fbb
5e0ce63bb65db34d7f48b34bbb5545fa791781c4Timo Sirainen/* Copyright (c) 2001-2017 Dovecot authors, see the included COPYING file */
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen/* Unit tests for printf-format-fix helper */
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen#include "test-lib.h"
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen#include "printf-format-fix.h"
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen#include <string.h>
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainenstruct format_fix_rewrites {
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainen const char *input;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen const char *output;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen size_t length;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen};
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainenstatic void test_unchanged()
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen{
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen static const char *tests[] = {
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen "Hello world",
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainen "Embedded %%, %u, %f, %s, etc. are OK",
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen "Allow %#0- +s flags",
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen "duplicate flags in different args %0-123s %0-123s",
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen "Minimum length %9999s",
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen "Minimum length parameter %*s",
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainen "Precision %.9999s",
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen "Precision %1.9999s",
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainen "Precision parameter %1.*s %.*s",
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen "Length modifiers %hd %hhd %ld %lld %Lg %jd %zd %td",
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen "Specifiers %s %u %d %c %i %x %X %p %o %e %E %f %F %g %G %a %A",
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen "%%doesn't cause confusion in %%m and %%n",
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainen };
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen unsigned int i;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen test_begin("printf_format_fix(safe)");
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen for (i = 0; i < N_ELEMENTS(tests); ++i) {
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainen size_t len;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen T_BEGIN {
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainen test_assert_idx(printf_format_fix(tests[i])
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen == tests[i], i);
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen test_assert_idx(printf_format_fix_get_len(tests[i], &len)
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen == tests[i], i);
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainen test_assert_idx(len == strlen(tests[i]), i);
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen } T_END;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen }
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen test_end();
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen}
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainenstatic void test_ok_changes()
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen{
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainen static const char *tests[] = {
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen "OK to have a trailing %m",
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainen "%m can appear at the start too",
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen "Even %m in the middle with a confusing %%m elsewhere is OK",
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen };
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen unsigned int i;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen const char *needle;
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainen unsigned int needlen;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen int old_errno = errno;
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainen
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen test_begin("printf_format_fix(rewrites)");
03f5c621d06d6b6d77a145196c9633a7aa64dc78Timo Sirainen
03f5c621d06d6b6d77a145196c9633a7aa64dc78Timo Sirainen errno = EINVAL;
03f5c621d06d6b6d77a145196c9633a7aa64dc78Timo Sirainen needle = strerror(errno);
03f5c621d06d6b6d77a145196c9633a7aa64dc78Timo Sirainen i_assert(needle != NULL);
03f5c621d06d6b6d77a145196c9633a7aa64dc78Timo Sirainen needlen = strlen(needle);
03f5c621d06d6b6d77a145196c9633a7aa64dc78Timo Sirainen
03f5c621d06d6b6d77a145196c9633a7aa64dc78Timo Sirainen for (i = 0; i < N_ELEMENTS(tests); ++i) {
03f5c621d06d6b6d77a145196c9633a7aa64dc78Timo Sirainen size_t len;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen char const *chgd;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen char const *insert;
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainen unsigned int offs;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
f923659c0e5298263d80622c99f4dc4132b4675bTimo Sirainen T_BEGIN {
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen chgd = printf_format_fix(tests[i]);
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen test_assert_idx(chgd != tests[i], i);
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen insert = strstr(chgd, needle);
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen test_assert_idx(insert != NULL, i);
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen offs = insert - chgd;
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainen test_assert_idx(memcmp(chgd, tests[i], offs) == 0, i);
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen test_assert_idx(memcmp(chgd+offs, needle, needlen) == 0, i);
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainen test_assert_idx(strcmp(chgd+offs+needlen, tests[i]+offs+2) == 0, i);
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen
af81f402ddc897c74c1e85abd02879612ce44882Timo Sirainen chgd = printf_format_fix_get_len(tests[i], &len);
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen test_assert_idx(chgd != tests[i], i);
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen test_assert_idx(len == strlen(chgd), i);
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen insert = strstr(chgd, needle);
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen test_assert_idx(insert != NULL, i);
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen offs = insert - chgd;
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen test_assert_idx(memcmp(chgd, tests[i], offs) == 0, i);
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen test_assert_idx(memcmp(chgd+offs, needle, needlen) == 0, i);
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen test_assert_idx(memcmp(chgd+offs+needlen, tests[i]+offs+2, len-needlen-offs) == 0, i);
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen } T_END;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen errno = old_errno;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen test_end();
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen}
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainenvoid test_printf_format_fix()
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen{
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen test_unchanged();
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen test_ok_changes();
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen}
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen/* Want to test the panics too? go for it! */
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainenenum fatal_test_state fatal_printf_format_fix(unsigned int stage)
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen{
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen static const char *fatals[] = {
b3142c8e513bc78da821fa70f479016148fa95e5Timo Sirainen "no no no %n's",
af81f402ddc897c74c1e85abd02879612ce44882Timo Sirainen "no no no %-1234567890123n's with extra stuff",
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen "%m allowed once, but not twice: %m",
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen "%m must not obscure a later %n",
b3142c8e513bc78da821fa70f479016148fa95e5Timo Sirainen "definitely can't have a tailing %",
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen "Evil %**%n",
67c24901ac5e1521e38a91efc452faeb3e2135a1Timo Sirainen "Evil %*#%99999$s",
67c24901ac5e1521e38a91efc452faeb3e2135a1Timo Sirainen "No weird %% with %0%",
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen "No duplicate modifiers %00s",
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen "Minimum length can't be too long %10000s",
67c24901ac5e1521e38a91efc452faeb3e2135a1Timo Sirainen "Minimum length doesn't support %*1$s",
67c24901ac5e1521e38a91efc452faeb3e2135a1Timo Sirainen "Precision can't be too long %.10000s",
67c24901ac5e1521e38a91efc452faeb3e2135a1Timo Sirainen "Precision can't be too long %1.10000s",
67c24901ac5e1521e38a91efc452faeb3e2135a1Timo Sirainen "Precision doesn't support %1.-1s",
67c24901ac5e1521e38a91efc452faeb3e2135a1Timo Sirainen };
67c24901ac5e1521e38a91efc452faeb3e2135a1Timo Sirainen
67c24901ac5e1521e38a91efc452faeb3e2135a1Timo Sirainen if(stage >= N_ELEMENTS(fatals)) {
67c24901ac5e1521e38a91efc452faeb3e2135a1Timo Sirainen test_end();
67c24901ac5e1521e38a91efc452faeb3e2135a1Timo Sirainen return FATAL_TEST_FINISHED;
67c24901ac5e1521e38a91efc452faeb3e2135a1Timo Sirainen }
67c24901ac5e1521e38a91efc452faeb3e2135a1Timo Sirainen
67c24901ac5e1521e38a91efc452faeb3e2135a1Timo Sirainen if(stage == 0)
67c24901ac5e1521e38a91efc452faeb3e2135a1Timo Sirainen test_begin("fatal_printf_format_fix");
67c24901ac5e1521e38a91efc452faeb3e2135a1Timo Sirainen
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen /* let's crash! */
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen (void)printf_format_fix(fatals[stage]);
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen return FATAL_TEST_FAILURE;
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen}
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainen