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