]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
lib: Allow only known %chars in printf_format_fix_noalloc()
authorTimo Sirainen <timo.sirainen@dovecot.fi>
Tue, 29 Nov 2016 21:37:43 +0000 (23:37 +0200)
committerGitLab <gitlab@git.dovecot.net>
Sun, 18 Dec 2016 10:35:20 +0000 (12:35 +0200)
Otherwise if some libc adds a new unsupported character, our %n check might
break.

src/lib/printf-format-fix.c

index 64513d198eb4eea1939ef5da8b07041ffa5c914f..7ee0335b3942bad3573b5d160e137d14e433fdda 100644 (file)
@@ -36,6 +36,9 @@ static const char *
 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 @@ printf_format_fix_noalloc(const char *format, size_t *len_r)
                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++;
        }