Mercurial > dovecot > core-2.2
changeset 21340:4efaa627264d
lib: Allow only known %chars in printf_format_fix_noalloc()
Otherwise if some libc adds a new unsupported character, our %n check might
break.
author | Timo Sirainen <timo.sirainen@dovecot.fi> |
---|---|
date | Tue, 29 Nov 2016 23:37:43 +0200 |
parents | 8d49b6ed7bab |
children | 499e52172881 |
files | src/lib/printf-format-fix.c |
diffstat | 1 files changed, 19 insertions(+), 9 deletions(-) [+] |
line wrap: on
line diff
--- a/src/lib/printf-format-fix.c Tue Nov 29 23:29:04 2016 +0200 +++ b/src/lib/printf-format-fix.c Tue Nov 29 23:37:43 2016 +0200 @@ -36,6 +36,9 @@ printf_format_fix_noalloc(const char *format, size_t *len_r) { static const char *printf_skip_chars = "# -+'I.*0123456789hlLjzt"; + /* as a tiny optimization keep the most commonly used conversion + modifiers first, so strchr() stops early. */ + static const char *printf_allowed_conversions = "sudcioxXp%eEfFgGaA"; const char *ret, *p, *p2; p = ret = format; @@ -43,16 +46,23 @@ p = p2+1; while (*p != '\0' && strchr(printf_skip_chars, *p) != NULL) p++; - switch (*p) { - case 'n': - i_panic("%%n modifier used"); - case 'm': - if (ret != format) - i_panic("%%m used twice"); - ret = fix_format_real(format, p-1, len_r); - break; - case '\0': + + if (*p == '\0') { i_panic("%% modifier missing in '%s'", format); + } else if (strchr(printf_allowed_conversions, *p) != NULL) { + /* allow & ignore */ + } else { + switch (*p) { + case 'n': + i_panic("%%n modifier used"); + case 'm': + if (ret != format) + i_panic("%%m used twice"); + ret = fix_format_real(format, p-1, len_r); + break; + default: + i_panic("Unsupported %%%c modifier", *p); + } } p++; }