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