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