printf-format-fix.c revision c398eca6b0fc6583687bd6fe2ee2dbcca2ae9387
6781N/A/* Copyright (c) 2002-2017 Dovecot authors, see the included COPYING file */ 6781N/A /* we'll assume that there's only one %m in the format string. 6781N/A this simplifies the code and there's really no good reason to have 6781N/A it multiple times. Callers can trap this case themselves. */ 6781N/A /* NOTE: This function is overly strict in what it accepts. Some 6781N/A format strings that are valid (and safe) in C99 will cause a panic 6781N/A here. This is because we don't really need to support the weirdest 6781N/A special cases, and we're also being extra careful not to pass 6781N/A anything to the underlying libc printf, which might treat the string 6781N/A differently than us and unexpectedly handling it as %n. For example 6781N/A /* Allow only the standard C99 flags. There are also <'> and <I> flags, 6781N/A but we don't really need them. And at worst if they're not supported 6781N/A by the underlying printf, they could potentially be used to work 6781N/A around our restrictions. */ 6781N/A /* As a tiny optimization keep the most commonly used conversion 6781N/A specifiers first, so strchr() stops early. */ 6781N/A /* we'll be strict and allow %% only when there are no 6781N/A optinal flags or modifiers. */ 6781N/A /* 1) zero or more flags. We'll add a further restriction that 6781N/A each flag can be used only once, since there's no need to 6781N/A use them more than once, and some implementations might 6781N/A /* 2) Optional minimum field width */ 6781N/A /* We don't bother supporting "*m$" - it's not used 6781N/A anywhere and seems a bit dangerous. */ 6781N/A }
else if (*p >=
'1' && *p <=
'9') {
6781N/A /* Limit to 4 digits - we'll never want more than that. 6781N/A Some implementations might not handle long digits 6781N/A correctly, or maybe even could be used for DoS due 6781N/A i_panic(
"Too large minimum field width starting at #%u in '%s'",
6781N/A }
while (*p >=
'0' && *p <=
'9');
6781N/A /* 3) Optional precision */ 6781N/A /* We don't bother supporting anything but numbers 6781N/A here. 999 should be long enough precision. */ 6781N/A while (*p >=
'0' && *p <=
'9') {
6781N/A /* 4) Optional length modifier */ 6781N/A /* 5) conversion specifier */ 6781N/A i_panic(
"Unsupported 0x%02x specifier starting at #%u in '%s'",