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