test-printf-format-fix.c revision ba1a5db879b08d2fefcb42160af67853cdfe7687
bcb4e51a409d94ae670de96afb8483a4f7855294Stephan Bosch/* Copyright (c) 2001-2017 Dovecot authors, see the included COPYING file */
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen/* Unit tests for printf-format-fix helper */
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen#include "test-lib.h"
9ddd3d7d8651985e373a6c48e0ddc76b8a4ef1c7Timo Sirainen#include "printf-format-fix.h"
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen#include <string.h>
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen
bdd36cfdba3ff66d25570a9ff568d69e1eb543cfTimo Sirainenstruct format_fix_rewrites {
7a60e1dc9e93ef3f7c7fe1af6385a0bfa1e31bc3Timo Sirainen const char *input;
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen const char *output;
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen size_t length;
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen};
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainenstatic void test_unchanged()
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen{
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen static const char *tests[] = {
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen "Hello world",
0cb5a9bfbf40b3b323956792aa13d342a459585eTimo Sirainen "Embedded %%, %u, %f, %s, etc. are OK",
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen "Allow %#0- +s flags",
0cb5a9bfbf40b3b323956792aa13d342a459585eTimo Sirainen "duplicate flags in different args %0-123s %0-123s",
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen "Minimum length %9999s",
9ddd3d7d8651985e373a6c48e0ddc76b8a4ef1c7Timo Sirainen "Minimum length parameter %*s",
9ddd3d7d8651985e373a6c48e0ddc76b8a4ef1c7Timo Sirainen "Precision %.9999s",
a272994d43de80a306a8ed1f2983960d1f3102d0Timo Sirainen "Precision %1.9999s",
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen "Precision parameter %1.*s %.*s",
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen "Length modifiers %hd %hhd %ld %lld %Lg %jd %zd %td",
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen "Specifiers %s %u %d %c %i %x %X %p %o %e %E %f %F %g %G %a %A",
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen "%%doesn't cause confusion in %%m and %%n",
d1414c09cf0d58ac983054e2f4e1a1f329272dcfTimo Sirainen };
d1414c09cf0d58ac983054e2f4e1a1f329272dcfTimo Sirainen unsigned int i;
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen test_begin("printf_format_fix(safe)");
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen for (i = 0; i < N_ELEMENTS(tests); ++i) {
d1414c09cf0d58ac983054e2f4e1a1f329272dcfTimo Sirainen size_t len;
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen T_BEGIN {
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen test_assert_idx(printf_format_fix(tests[i])
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen == tests[i], i);
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen test_assert_idx(printf_format_fix_get_len(tests[i], &len)
d1414c09cf0d58ac983054e2f4e1a1f329272dcfTimo Sirainen == tests[i], i);
efe78d3ba24fc866af1c79b9223dc0809ba26cadStephan Bosch test_assert_idx(len == strlen(tests[i]), i);
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen } T_END;
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen }
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen test_end();
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen}
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainenstatic void test_ok_changes()
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen{
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen static const char *tests[] = {
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen "OK to have a trailing %m",
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen "%m can appear at the start too",
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen "Even %m in the middle with a confusing %%m elsewhere is OK",
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen };
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen unsigned int i;
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen const char *needle;
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen unsigned int needlen;
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen int old_errno = errno;
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen test_begin("printf_format_fix(rewrites)");
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen errno = EINVAL;
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen needle = strerror(errno);
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen i_assert(needle != NULL);
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen needlen = strlen(needle);
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen
d1414c09cf0d58ac983054e2f4e1a1f329272dcfTimo Sirainen for (i = 0; i < N_ELEMENTS(tests); ++i) {
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen size_t len;
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen char const *chgd;
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen char const *insert;
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen unsigned int offs;
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen T_BEGIN {
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen chgd = printf_format_fix(tests[i]);
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen test_assert_idx(chgd != tests[i], i);
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen insert = strstr(chgd, needle);
9261dbf0675204898c6557591c7aa376e23a52b2Timo Sirainen test_assert_idx(insert != NULL, i);
9261dbf0675204898c6557591c7aa376e23a52b2Timo Sirainen offs = insert - chgd;
9261dbf0675204898c6557591c7aa376e23a52b2Timo Sirainen test_assert_idx(memcmp(chgd, tests[i], offs) == 0, i);
9261dbf0675204898c6557591c7aa376e23a52b2Timo Sirainen test_assert_idx(memcmp(chgd+offs, needle, needlen) == 0, i);
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen test_assert_idx(strcmp(chgd+offs+needlen, tests[i]+offs+2) == 0, i);
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen
d1414c09cf0d58ac983054e2f4e1a1f329272dcfTimo Sirainen chgd = printf_format_fix_get_len(tests[i], &len);
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen test_assert_idx(chgd != tests[i], i);
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen test_assert_idx(len == strlen(chgd), i);
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen insert = strstr(chgd, needle);
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen test_assert_idx(insert != NULL, i);
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen offs = insert - chgd;
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen test_assert_idx(memcmp(chgd, tests[i], offs) == 0, i);
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen test_assert_idx(memcmp(chgd+offs, needle, needlen) == 0, i);
d1414c09cf0d58ac983054e2f4e1a1f329272dcfTimo Sirainen test_assert_idx(memcmp(chgd+offs+needlen, tests[i]+offs+2, len-needlen-offs) == 0, i);
9261dbf0675204898c6557591c7aa376e23a52b2Timo Sirainen } T_END;
9261dbf0675204898c6557591c7aa376e23a52b2Timo Sirainen }
419baa2c17c63ae516b2df6cc5695f15aaccbff8Timo Sirainen
419baa2c17c63ae516b2df6cc5695f15aaccbff8Timo Sirainen errno = old_errno;
419baa2c17c63ae516b2df6cc5695f15aaccbff8Timo Sirainen
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen test_end();
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen}
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen
419baa2c17c63ae516b2df6cc5695f15aaccbff8Timo Sirainenvoid test_printf_format_fix()
419baa2c17c63ae516b2df6cc5695f15aaccbff8Timo Sirainen{
419baa2c17c63ae516b2df6cc5695f15aaccbff8Timo Sirainen test_unchanged();
419baa2c17c63ae516b2df6cc5695f15aaccbff8Timo Sirainen test_ok_changes();
419baa2c17c63ae516b2df6cc5695f15aaccbff8Timo Sirainen}
419baa2c17c63ae516b2df6cc5695f15aaccbff8Timo Sirainen
419baa2c17c63ae516b2df6cc5695f15aaccbff8Timo Sirainen/* Want to test the panics too? go for it! */
419baa2c17c63ae516b2df6cc5695f15aaccbff8Timo Sirainenenum fatal_test_state fatal_printf_format_fix(unsigned int stage)
419baa2c17c63ae516b2df6cc5695f15aaccbff8Timo Sirainen{
419baa2c17c63ae516b2df6cc5695f15aaccbff8Timo Sirainen static const struct {
419baa2c17c63ae516b2df6cc5695f15aaccbff8Timo Sirainen const char *format;
419baa2c17c63ae516b2df6cc5695f15aaccbff8Timo Sirainen const char *expected_fatal;
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen } fatals[] = {
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen { "no no no %n's", "%n modifier used" },
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen { "no no no %-1234567890123n's with extra stuff", "Too large minimum field width" },
e2ae85924b0ef1a7c97e021a3b901b498f599c18Timo Sirainen { "%m allowed once, but not twice: %m", "%m used twice" },
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen { "%m must not obscure a later %n", "%n modifier used" },
e2ae85924b0ef1a7c97e021a3b901b498f599c18Timo Sirainen { "definitely can't have a tailing %", "Missing % specifier" },
419baa2c17c63ae516b2df6cc5695f15aaccbff8Timo Sirainen { "Evil %**%n", "Unsupported 0x2a specifier" },
419baa2c17c63ae516b2df6cc5695f15aaccbff8Timo Sirainen { "Evil %*#%99999$s", "Unsupported 0x23 specifier" },
419baa2c17c63ae516b2df6cc5695f15aaccbff8Timo Sirainen { "No weird %% with %0%", "Unsupported 0x25 specifier" },
419baa2c17c63ae516b2df6cc5695f15aaccbff8Timo Sirainen { "No duplicate modifiers %00s", "Duplicate % flag '0'" },
e2ae85924b0ef1a7c97e021a3b901b498f599c18Timo Sirainen { "Minimum length can't be too long %10000s", "Too large minimum field width" },
0d1b8b6bec79746c5d89d57dd8c1688946bd9237Josef 'Jeff' Sipek { "Minimum length doesn't support %*1$s", "Unsupported 0x31 specifier" },
0cb5a9bfbf40b3b323956792aa13d342a459585eTimo Sirainen { "Precision can't be too long %.10000s", "Too large precision" },
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen { "Precision can't be too long %1.10000s", "Too large precision" },
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen { "Precision doesn't support %1.-1s", "Unsupported 0x2d specifier" },
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen };
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen if(stage >= N_ELEMENTS(fatals)) {
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen test_end();
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen return FATAL_TEST_FINISHED;
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen }
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen if(stage == 0)
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen test_begin("fatal_printf_format_fix");
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen /* let's crash! */
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen test_expect_fatal_string(fatals[stage].expected_fatal);
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen (void)printf_format_fix(fatals[stage].format);
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen return FATAL_TEST_FAILURE;
9261dbf0675204898c6557591c7aa376e23a52b2Timo Sirainen}
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen