printf-format-fix.c revision c4529ff75e8068cb63e47e455d99aea9bdf412bf
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen/* Copyright (c) 2002-2010 Dovecot authors, see the included COPYING file */
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen#include "lib.h"
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen#include "printf-format-fix.h"
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainenstatic const char *
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainenfix_format_real(const char *fmt, const char *p, unsigned int *len_r)
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen{
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen const char *errstr;
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen char *buf;
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen unsigned int len1, len2, len3;
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen i_assert((size_t)(p - fmt) < INT_MAX);
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen errstr = strerror(errno);
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen /* we'll assume that there's only one %m in the format string.
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen this simplifies the code and there's really no good reason to have
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen it multiple times. */
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen len1 = p - fmt;
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen len2 = strlen(errstr);
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen len3 = strlen(p + 2);
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen /* @UNSAFE */
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen buf = t_buffer_get(len1 + len2 + len3 + 1);
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen memcpy(buf, fmt, len1);
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen memcpy(buf + len1, errstr, len2);
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen memcpy(buf + len1 + len2, p + 2, len3 + 1);
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen
a12399903f415a7e14c2816cffa2f7a09dcbb097Timo Sirainen *len_r = len1 + len2 + len3;
a12399903f415a7e14c2816cffa2f7a09dcbb097Timo Sirainen return buf;
a12399903f415a7e14c2816cffa2f7a09dcbb097Timo Sirainen}
a12399903f415a7e14c2816cffa2f7a09dcbb097Timo Sirainen
a12399903f415a7e14c2816cffa2f7a09dcbb097Timo Sirainenstatic const char *
a12399903f415a7e14c2816cffa2f7a09dcbb097Timo Sirainenprintf_format_fix_noalloc(const char *format, unsigned int *len_r)
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen{
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen const char *p;
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen for (p = format; *p != '\0'; ) {
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen if (*p++ == '%') {
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen switch (*p) {
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen case 'n':
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen i_panic("%%n modifier used");
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen case 'm':
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen return fix_format_real(format, p-1, len_r);
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen case '\0':
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen i_panic("%% modifier missing");
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen }
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen p++;
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen }
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen }
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen *len_r = p - format;
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen return format;
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen}
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainenconst char *printf_format_fix_get_len(const char *format, unsigned int *len_r)
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen{
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen const char *ret;
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen ret = printf_format_fix_noalloc(format, len_r);
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen if (ret != format)
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen t_buffer_alloc(*len_r + 1);
90adcaa0a00eba29b7fbd50ca66be11c8d086d6aTimo Sirainen return ret;
90adcaa0a00eba29b7fbd50ca66be11c8d086d6aTimo Sirainen}
90adcaa0a00eba29b7fbd50ca66be11c8d086d6aTimo Sirainen
90adcaa0a00eba29b7fbd50ca66be11c8d086d6aTimo Sirainenconst char *printf_format_fix(const char *format)
90adcaa0a00eba29b7fbd50ca66be11c8d086d6aTimo Sirainen{
90adcaa0a00eba29b7fbd50ca66be11c8d086d6aTimo Sirainen const char *ret;
90adcaa0a00eba29b7fbd50ca66be11c8d086d6aTimo Sirainen unsigned int len;
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen ret = printf_format_fix_noalloc(format, &len);
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen if (ret != format)
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen t_buffer_alloc(len + 1);
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen return ret;
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen}
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainenconst char *printf_format_fix_unsafe(const char *format)
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen{
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen unsigned int len;
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen return printf_format_fix_noalloc(format, &len);
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen}
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen