Mercurial > dovecot > core-2.2
annotate src/lib/printf-format-fix.c @ 23007:36e01285b5b8
lib: buffer - Improve header comment for buffer_insert() and buffer_delete().
author | Stephan Bosch <stephan.bosch@dovecot.fi> |
---|---|
date | Mon, 18 Mar 2019 00:52:37 +0100 |
parents | dcec0ced2c50 |
children |
rev | line source |
---|---|
22713
cb108f786fb4
Updated copyright notices to include the year 2018.
Stephan Bosch <stephan.bosch@dovecot.fi>
parents:
21390
diff
changeset
|
1 /* Copyright (c) 2002-2018 Dovecot authors, see the included COPYING file */ |
5679
74e06273985b
Renamed printf_string_fix_format() to printf_format_fix() and moved it to
Timo Sirainen <tss@iki.fi>
parents:
diff
changeset
|
2 |
74e06273985b
Renamed printf_string_fix_format() to printf_format_fix() and moved it to
Timo Sirainen <tss@iki.fi>
parents:
diff
changeset
|
3 #include "lib.h" |
74e06273985b
Renamed printf_string_fix_format() to printf_format_fix() and moved it to
Timo Sirainen <tss@iki.fi>
parents:
diff
changeset
|
4 #include "printf-format-fix.h" |
74e06273985b
Renamed printf_string_fix_format() to printf_format_fix() and moved it to
Timo Sirainen <tss@iki.fi>
parents:
diff
changeset
|
5 |
5681
09415e6a0892
Require C99 compatible vsnprintf(). Removed printf_string_upper_bound() and
Timo Sirainen <tss@iki.fi>
parents:
5679
diff
changeset
|
6 static const char * |
21322
5ab8dc1a4a6f
global: Change string position/length from unsigned int to size_t
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
19552
diff
changeset
|
7 fix_format_real(const char *fmt, const char *p, size_t *len_r) |
5679
74e06273985b
Renamed printf_string_fix_format() to printf_format_fix() and moved it to
Timo Sirainen <tss@iki.fi>
parents:
diff
changeset
|
8 { |
74e06273985b
Renamed printf_string_fix_format() to printf_format_fix() and moved it to
Timo Sirainen <tss@iki.fi>
parents:
diff
changeset
|
9 const char *errstr; |
74e06273985b
Renamed printf_string_fix_format() to printf_format_fix() and moved it to
Timo Sirainen <tss@iki.fi>
parents:
diff
changeset
|
10 char *buf; |
21322
5ab8dc1a4a6f
global: Change string position/length from unsigned int to size_t
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
19552
diff
changeset
|
11 size_t len1, len2, len3; |
5681
09415e6a0892
Require C99 compatible vsnprintf(). Removed printf_string_upper_bound() and
Timo Sirainen <tss@iki.fi>
parents:
5679
diff
changeset
|
12 |
09415e6a0892
Require C99 compatible vsnprintf(). Removed printf_string_upper_bound() and
Timo Sirainen <tss@iki.fi>
parents:
5679
diff
changeset
|
13 i_assert((size_t)(p - fmt) < INT_MAX); |
17528
06f90ecbfb70
lib: make printf_format_fix safer against shadowed %m behaviour
Phil Carmody <phil@dovecot.fi>
parents:
17130
diff
changeset
|
14 i_assert(p[0] == '%' && p[1] == 'm'); |
5679
74e06273985b
Renamed printf_string_fix_format() to printf_format_fix() and moved it to
Timo Sirainen <tss@iki.fi>
parents:
diff
changeset
|
15 |
74e06273985b
Renamed printf_string_fix_format() to printf_format_fix() and moved it to
Timo Sirainen <tss@iki.fi>
parents:
diff
changeset
|
16 errstr = strerror(errno); |
74e06273985b
Renamed printf_string_fix_format() to printf_format_fix() and moved it to
Timo Sirainen <tss@iki.fi>
parents:
diff
changeset
|
17 |
5681
09415e6a0892
Require C99 compatible vsnprintf(). Removed printf_string_upper_bound() and
Timo Sirainen <tss@iki.fi>
parents:
5679
diff
changeset
|
18 /* we'll assume that there's only one %m in the format string. |
09415e6a0892
Require C99 compatible vsnprintf(). Removed printf_string_upper_bound() and
Timo Sirainen <tss@iki.fi>
parents:
5679
diff
changeset
|
19 this simplifies the code and there's really no good reason to have |
17528
06f90ecbfb70
lib: make printf_format_fix safer against shadowed %m behaviour
Phil Carmody <phil@dovecot.fi>
parents:
17130
diff
changeset
|
20 it multiple times. Callers can trap this case themselves. */ |
5681
09415e6a0892
Require C99 compatible vsnprintf(). Removed printf_string_upper_bound() and
Timo Sirainen <tss@iki.fi>
parents:
5679
diff
changeset
|
21 len1 = p - fmt; |
09415e6a0892
Require C99 compatible vsnprintf(). Removed printf_string_upper_bound() and
Timo Sirainen <tss@iki.fi>
parents:
5679
diff
changeset
|
22 len2 = strlen(errstr); |
5698 | 23 len3 = strlen(p + 2); |
5679
74e06273985b
Renamed printf_string_fix_format() to printf_format_fix() and moved it to
Timo Sirainen <tss@iki.fi>
parents:
diff
changeset
|
24 |
5681
09415e6a0892
Require C99 compatible vsnprintf(). Removed printf_string_upper_bound() and
Timo Sirainen <tss@iki.fi>
parents:
5679
diff
changeset
|
25 /* @UNSAFE */ |
09415e6a0892
Require C99 compatible vsnprintf(). Removed printf_string_upper_bound() and
Timo Sirainen <tss@iki.fi>
parents:
5679
diff
changeset
|
26 buf = t_buffer_get(len1 + len2 + len3 + 1); |
09415e6a0892
Require C99 compatible vsnprintf(). Removed printf_string_upper_bound() and
Timo Sirainen <tss@iki.fi>
parents:
5679
diff
changeset
|
27 memcpy(buf, fmt, len1); |
09415e6a0892
Require C99 compatible vsnprintf(). Removed printf_string_upper_bound() and
Timo Sirainen <tss@iki.fi>
parents:
5679
diff
changeset
|
28 memcpy(buf + len1, errstr, len2); |
5698 | 29 memcpy(buf + len1 + len2, p + 2, len3 + 1); |
5679
74e06273985b
Renamed printf_string_fix_format() to printf_format_fix() and moved it to
Timo Sirainen <tss@iki.fi>
parents:
diff
changeset
|
30 |
5681
09415e6a0892
Require C99 compatible vsnprintf(). Removed printf_string_upper_bound() and
Timo Sirainen <tss@iki.fi>
parents:
5679
diff
changeset
|
31 *len_r = len1 + len2 + len3; |
5679
74e06273985b
Renamed printf_string_fix_format() to printf_format_fix() and moved it to
Timo Sirainen <tss@iki.fi>
parents:
diff
changeset
|
32 return buf; |
74e06273985b
Renamed printf_string_fix_format() to printf_format_fix() and moved it to
Timo Sirainen <tss@iki.fi>
parents:
diff
changeset
|
33 } |
74e06273985b
Renamed printf_string_fix_format() to printf_format_fix() and moved it to
Timo Sirainen <tss@iki.fi>
parents:
diff
changeset
|
34 |
22725
878a4f623242
lib: printf_format_fix*() - Move minimum field width check to its own function
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
22724
diff
changeset
|
35 static bool verify_length(const char **p) |
878a4f623242
lib: printf_format_fix*() - Move minimum field width check to its own function
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
22724
diff
changeset
|
36 { |
878a4f623242
lib: printf_format_fix*() - Move minimum field width check to its own function
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
22724
diff
changeset
|
37 if (**p == '*') { |
878a4f623242
lib: printf_format_fix*() - Move minimum field width check to its own function
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
22724
diff
changeset
|
38 /* We don't bother supporting "*m$" - it's not used |
878a4f623242
lib: printf_format_fix*() - Move minimum field width check to its own function
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
22724
diff
changeset
|
39 anywhere and seems a bit dangerous. */ |
878a4f623242
lib: printf_format_fix*() - Move minimum field width check to its own function
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
22724
diff
changeset
|
40 *p += 1; |
878a4f623242
lib: printf_format_fix*() - Move minimum field width check to its own function
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
22724
diff
changeset
|
41 } else if (**p >= '1' && **p <= '9') { |
878a4f623242
lib: printf_format_fix*() - Move minimum field width check to its own function
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
22724
diff
changeset
|
42 /* Limit to 4 digits - we'll never want more than that. |
878a4f623242
lib: printf_format_fix*() - Move minimum field width check to its own function
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
22724
diff
changeset
|
43 Some implementations might not handle long digits |
878a4f623242
lib: printf_format_fix*() - Move minimum field width check to its own function
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
22724
diff
changeset
|
44 correctly, or maybe even could be used for DoS due |
878a4f623242
lib: printf_format_fix*() - Move minimum field width check to its own function
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
22724
diff
changeset
|
45 to using too much CPU. */ |
878a4f623242
lib: printf_format_fix*() - Move minimum field width check to its own function
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
22724
diff
changeset
|
46 unsigned int i = 0; |
878a4f623242
lib: printf_format_fix*() - Move minimum field width check to its own function
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
22724
diff
changeset
|
47 do { |
878a4f623242
lib: printf_format_fix*() - Move minimum field width check to its own function
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
22724
diff
changeset
|
48 *p += 1; |
878a4f623242
lib: printf_format_fix*() - Move minimum field width check to its own function
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
22724
diff
changeset
|
49 if (++i > 4) |
878a4f623242
lib: printf_format_fix*() - Move minimum field width check to its own function
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
22724
diff
changeset
|
50 return FALSE; |
878a4f623242
lib: printf_format_fix*() - Move minimum field width check to its own function
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
22724
diff
changeset
|
51 } while (**p >= '0' && **p <= '9'); |
878a4f623242
lib: printf_format_fix*() - Move minimum field width check to its own function
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
22724
diff
changeset
|
52 } |
878a4f623242
lib: printf_format_fix*() - Move minimum field width check to its own function
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
22724
diff
changeset
|
53 return TRUE; |
878a4f623242
lib: printf_format_fix*() - Move minimum field width check to its own function
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
22724
diff
changeset
|
54 } |
878a4f623242
lib: printf_format_fix*() - Move minimum field width check to its own function
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
22724
diff
changeset
|
55 |
5681
09415e6a0892
Require C99 compatible vsnprintf(). Removed printf_string_upper_bound() and
Timo Sirainen <tss@iki.fi>
parents:
5679
diff
changeset
|
56 static const char * |
21322
5ab8dc1a4a6f
global: Change string position/length from unsigned int to size_t
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
19552
diff
changeset
|
57 printf_format_fix_noalloc(const char *format, size_t *len_r) |
5679
74e06273985b
Renamed printf_string_fix_format() to printf_format_fix() and moved it to
Timo Sirainen <tss@iki.fi>
parents:
diff
changeset
|
58 { |
22723
781ee592b295
lib: printf_format_fix*() - Be over-strict in what format strings are allowed
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
22713
diff
changeset
|
59 /* NOTE: This function is overly strict in what it accepts. Some |
781ee592b295
lib: printf_format_fix*() - Be over-strict in what format strings are allowed
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
22713
diff
changeset
|
60 format strings that are valid (and safe) in C99 will cause a panic |
781ee592b295
lib: printf_format_fix*() - Be over-strict in what format strings are allowed
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
22713
diff
changeset
|
61 here. This is because we don't really need to support the weirdest |
781ee592b295
lib: printf_format_fix*() - Be over-strict in what format strings are allowed
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
22713
diff
changeset
|
62 special cases, and we're also being extra careful not to pass |
781ee592b295
lib: printf_format_fix*() - Be over-strict in what format strings are allowed
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
22713
diff
changeset
|
63 anything to the underlying libc printf, which might treat the string |
781ee592b295
lib: printf_format_fix*() - Be over-strict in what format strings are allowed
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
22713
diff
changeset
|
64 differently than us and unexpectedly handling it as %n. For example |
781ee592b295
lib: printf_format_fix*() - Be over-strict in what format strings are allowed
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
22713
diff
changeset
|
65 "%**%n" with glibc. */ |
781ee592b295
lib: printf_format_fix*() - Be over-strict in what format strings are allowed
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
22713
diff
changeset
|
66 |
781ee592b295
lib: printf_format_fix*() - Be over-strict in what format strings are allowed
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
22713
diff
changeset
|
67 /* Allow only the standard C99 flags. There are also <'> and <I> flags, |
781ee592b295
lib: printf_format_fix*() - Be over-strict in what format strings are allowed
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
22713
diff
changeset
|
68 but we don't really need them. And at worst if they're not supported |
781ee592b295
lib: printf_format_fix*() - Be over-strict in what format strings are allowed
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
22713
diff
changeset
|
69 by the underlying printf, they could potentially be used to work |
781ee592b295
lib: printf_format_fix*() - Be over-strict in what format strings are allowed
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
22713
diff
changeset
|
70 around our restrictions. */ |
781ee592b295
lib: printf_format_fix*() - Be over-strict in what format strings are allowed
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
22713
diff
changeset
|
71 const char printf_flags[] = "#0- +"; |
781ee592b295
lib: printf_format_fix*() - Be over-strict in what format strings are allowed
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
22713
diff
changeset
|
72 /* As a tiny optimization keep the most commonly used conversion |
781ee592b295
lib: printf_format_fix*() - Be over-strict in what format strings are allowed
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
22713
diff
changeset
|
73 specifiers first, so strchr() stops early. */ |
781ee592b295
lib: printf_format_fix*() - Be over-strict in what format strings are allowed
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
22713
diff
changeset
|
74 static const char *printf_specifiers = "sudcixXpoeEfFgGaA"; |
21338
bc57c62167fc
lib: Optimize printf_format_fix_noalloc()
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
21322
diff
changeset
|
75 const char *ret, *p, *p2; |
22723
781ee592b295
lib: printf_format_fix*() - Be over-strict in what format strings are allowed
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
22713
diff
changeset
|
76 char *flag; |
5679
74e06273985b
Renamed printf_string_fix_format() to printf_format_fix() and moved it to
Timo Sirainen <tss@iki.fi>
parents:
diff
changeset
|
77 |
21338
bc57c62167fc
lib: Optimize printf_format_fix_noalloc()
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
21322
diff
changeset
|
78 p = ret = format; |
bc57c62167fc
lib: Optimize printf_format_fix_noalloc()
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
21322
diff
changeset
|
79 while ((p2 = strchr(p, '%')) != NULL) { |
22723
781ee592b295
lib: printf_format_fix*() - Be over-strict in what format strings are allowed
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
22713
diff
changeset
|
80 const unsigned int start_pos = p2 - format; |
781ee592b295
lib: printf_format_fix*() - Be over-strict in what format strings are allowed
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
22713
diff
changeset
|
81 |
21338
bc57c62167fc
lib: Optimize printf_format_fix_noalloc()
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
21322
diff
changeset
|
82 p = p2+1; |
22723
781ee592b295
lib: printf_format_fix*() - Be over-strict in what format strings are allowed
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
22713
diff
changeset
|
83 if (*p == '%') { |
781ee592b295
lib: printf_format_fix*() - Be over-strict in what format strings are allowed
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
22713
diff
changeset
|
84 /* we'll be strict and allow %% only when there are no |
781ee592b295
lib: printf_format_fix*() - Be over-strict in what format strings are allowed
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
22713
diff
changeset
|
85 optinal flags or modifiers. */ |
21339
8d49b6ed7bab
lib: Fix %n detection in printf_format_fix_noalloc()
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
21338
diff
changeset
|
86 p++; |
22723
781ee592b295
lib: printf_format_fix*() - Be over-strict in what format strings are allowed
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
22713
diff
changeset
|
87 continue; |
781ee592b295
lib: printf_format_fix*() - Be over-strict in what format strings are allowed
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
22713
diff
changeset
|
88 } |
781ee592b295
lib: printf_format_fix*() - Be over-strict in what format strings are allowed
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
22713
diff
changeset
|
89 /* 1) zero or more flags. We'll add a further restriction that |
781ee592b295
lib: printf_format_fix*() - Be over-strict in what format strings are allowed
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
22713
diff
changeset
|
90 each flag can be used only once, since there's no need to |
781ee592b295
lib: printf_format_fix*() - Be over-strict in what format strings are allowed
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
22713
diff
changeset
|
91 use them more than once, and some implementations might |
781ee592b295
lib: printf_format_fix*() - Be over-strict in what format strings are allowed
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
22713
diff
changeset
|
92 add their own limits. */ |
781ee592b295
lib: printf_format_fix*() - Be over-strict in what format strings are allowed
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
22713
diff
changeset
|
93 bool printf_flags_seen[N_ELEMENTS(printf_flags)] = { FALSE, }; |
781ee592b295
lib: printf_format_fix*() - Be over-strict in what format strings are allowed
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
22713
diff
changeset
|
94 while (*p != '\0' && |
781ee592b295
lib: printf_format_fix*() - Be over-strict in what format strings are allowed
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
22713
diff
changeset
|
95 (flag = strchr(printf_flags, *p)) != NULL) { |
781ee592b295
lib: printf_format_fix*() - Be over-strict in what format strings are allowed
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
22713
diff
changeset
|
96 unsigned int flag_idx = flag - printf_flags; |
781ee592b295
lib: printf_format_fix*() - Be over-strict in what format strings are allowed
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
22713
diff
changeset
|
97 |
781ee592b295
lib: printf_format_fix*() - Be over-strict in what format strings are allowed
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
22713
diff
changeset
|
98 if (printf_flags_seen[flag_idx]) { |
781ee592b295
lib: printf_format_fix*() - Be over-strict in what format strings are allowed
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
22713
diff
changeset
|
99 i_panic("Duplicate %% flag '%c' starting at #%u in '%s'", |
781ee592b295
lib: printf_format_fix*() - Be over-strict in what format strings are allowed
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
22713
diff
changeset
|
100 *p, start_pos, format); |
781ee592b295
lib: printf_format_fix*() - Be over-strict in what format strings are allowed
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
22713
diff
changeset
|
101 } |
781ee592b295
lib: printf_format_fix*() - Be over-strict in what format strings are allowed
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
22713
diff
changeset
|
102 printf_flags_seen[flag_idx] = TRUE; |
781ee592b295
lib: printf_format_fix*() - Be over-strict in what format strings are allowed
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
22713
diff
changeset
|
103 p++; |
781ee592b295
lib: printf_format_fix*() - Be over-strict in what format strings are allowed
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
22713
diff
changeset
|
104 } |
21340
4efaa627264d
lib: Allow only known %chars in printf_format_fix_noalloc()
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
21339
diff
changeset
|
105 |
22723
781ee592b295
lib: printf_format_fix*() - Be over-strict in what format strings are allowed
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
22713
diff
changeset
|
106 /* 2) Optional minimum field width */ |
22725
878a4f623242
lib: printf_format_fix*() - Move minimum field width check to its own function
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
22724
diff
changeset
|
107 if (!verify_length(&p)) { |
878a4f623242
lib: printf_format_fix*() - Move minimum field width check to its own function
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
22724
diff
changeset
|
108 i_panic("Too large minimum field width starting at #%u in '%s'", |
878a4f623242
lib: printf_format_fix*() - Move minimum field width check to its own function
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
22724
diff
changeset
|
109 start_pos, format); |
22723
781ee592b295
lib: printf_format_fix*() - Be over-strict in what format strings are allowed
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
22713
diff
changeset
|
110 } |
781ee592b295
lib: printf_format_fix*() - Be over-strict in what format strings are allowed
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
22713
diff
changeset
|
111 |
781ee592b295
lib: printf_format_fix*() - Be over-strict in what format strings are allowed
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
22713
diff
changeset
|
112 /* 3) Optional precision */ |
781ee592b295
lib: printf_format_fix*() - Be over-strict in what format strings are allowed
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
22713
diff
changeset
|
113 if (*p == '.') { |
781ee592b295
lib: printf_format_fix*() - Be over-strict in what format strings are allowed
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
22713
diff
changeset
|
114 p++; |
22726
dcec0ced2c50
lib: printf_format_fix*() - Support '*' in precision
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
22725
diff
changeset
|
115 if (!verify_length(&p)) { |
dcec0ced2c50
lib: printf_format_fix*() - Support '*' in precision
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
22725
diff
changeset
|
116 i_panic("Too large precision starting at #%u in '%s'", |
dcec0ced2c50
lib: printf_format_fix*() - Support '*' in precision
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
22725
diff
changeset
|
117 start_pos, format); |
22723
781ee592b295
lib: printf_format_fix*() - Be over-strict in what format strings are allowed
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
22713
diff
changeset
|
118 } |
781ee592b295
lib: printf_format_fix*() - Be over-strict in what format strings are allowed
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
22713
diff
changeset
|
119 } |
781ee592b295
lib: printf_format_fix*() - Be over-strict in what format strings are allowed
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
22713
diff
changeset
|
120 |
781ee592b295
lib: printf_format_fix*() - Be over-strict in what format strings are allowed
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
22713
diff
changeset
|
121 /* 4) Optional length modifier */ |
781ee592b295
lib: printf_format_fix*() - Be over-strict in what format strings are allowed
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
22713
diff
changeset
|
122 switch (*p) { |
781ee592b295
lib: printf_format_fix*() - Be over-strict in what format strings are allowed
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
22713
diff
changeset
|
123 case 'h': |
781ee592b295
lib: printf_format_fix*() - Be over-strict in what format strings are allowed
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
22713
diff
changeset
|
124 if (*++p == 'h') |
781ee592b295
lib: printf_format_fix*() - Be over-strict in what format strings are allowed
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
22713
diff
changeset
|
125 p++; |
781ee592b295
lib: printf_format_fix*() - Be over-strict in what format strings are allowed
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
22713
diff
changeset
|
126 break; |
781ee592b295
lib: printf_format_fix*() - Be over-strict in what format strings are allowed
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
22713
diff
changeset
|
127 case 'l': |
781ee592b295
lib: printf_format_fix*() - Be over-strict in what format strings are allowed
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
22713
diff
changeset
|
128 if (*++p == 'l') |
781ee592b295
lib: printf_format_fix*() - Be over-strict in what format strings are allowed
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
22713
diff
changeset
|
129 p++; |
781ee592b295
lib: printf_format_fix*() - Be over-strict in what format strings are allowed
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
22713
diff
changeset
|
130 break; |
781ee592b295
lib: printf_format_fix*() - Be over-strict in what format strings are allowed
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
22713
diff
changeset
|
131 case 'L': |
781ee592b295
lib: printf_format_fix*() - Be over-strict in what format strings are allowed
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
22713
diff
changeset
|
132 case 'j': |
781ee592b295
lib: printf_format_fix*() - Be over-strict in what format strings are allowed
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
22713
diff
changeset
|
133 case 'z': |
781ee592b295
lib: printf_format_fix*() - Be over-strict in what format strings are allowed
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
22713
diff
changeset
|
134 case 't': |
781ee592b295
lib: printf_format_fix*() - Be over-strict in what format strings are allowed
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
22713
diff
changeset
|
135 p++; |
781ee592b295
lib: printf_format_fix*() - Be over-strict in what format strings are allowed
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
22713
diff
changeset
|
136 break; |
781ee592b295
lib: printf_format_fix*() - Be over-strict in what format strings are allowed
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
22713
diff
changeset
|
137 } |
781ee592b295
lib: printf_format_fix*() - Be over-strict in what format strings are allowed
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
22713
diff
changeset
|
138 |
781ee592b295
lib: printf_format_fix*() - Be over-strict in what format strings are allowed
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
22713
diff
changeset
|
139 /* 5) conversion specifier */ |
781ee592b295
lib: printf_format_fix*() - Be over-strict in what format strings are allowed
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
22713
diff
changeset
|
140 if (*p == '\0' || strchr(printf_specifiers, *p) == NULL) { |
21340
4efaa627264d
lib: Allow only known %chars in printf_format_fix_noalloc()
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
21339
diff
changeset
|
141 switch (*p) { |
4efaa627264d
lib: Allow only known %chars in printf_format_fix_noalloc()
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
21339
diff
changeset
|
142 case 'n': |
4efaa627264d
lib: Allow only known %chars in printf_format_fix_noalloc()
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
21339
diff
changeset
|
143 i_panic("%%n modifier used"); |
4efaa627264d
lib: Allow only known %chars in printf_format_fix_noalloc()
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
21339
diff
changeset
|
144 case 'm': |
4efaa627264d
lib: Allow only known %chars in printf_format_fix_noalloc()
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
21339
diff
changeset
|
145 if (ret != format) |
4efaa627264d
lib: Allow only known %chars in printf_format_fix_noalloc()
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
21339
diff
changeset
|
146 i_panic("%%m used twice"); |
4efaa627264d
lib: Allow only known %chars in printf_format_fix_noalloc()
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
21339
diff
changeset
|
147 ret = fix_format_real(format, p-1, len_r); |
4efaa627264d
lib: Allow only known %chars in printf_format_fix_noalloc()
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
21339
diff
changeset
|
148 break; |
22723
781ee592b295
lib: printf_format_fix*() - Be over-strict in what format strings are allowed
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
22713
diff
changeset
|
149 case '\0': |
781ee592b295
lib: printf_format_fix*() - Be over-strict in what format strings are allowed
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
22713
diff
changeset
|
150 i_panic("Missing %% specifier starting at #%u in '%s'", |
781ee592b295
lib: printf_format_fix*() - Be over-strict in what format strings are allowed
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
22713
diff
changeset
|
151 start_pos, format); |
21340
4efaa627264d
lib: Allow only known %chars in printf_format_fix_noalloc()
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
21339
diff
changeset
|
152 default: |
22723
781ee592b295
lib: printf_format_fix*() - Be over-strict in what format strings are allowed
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
22713
diff
changeset
|
153 i_panic("Unsupported 0x%02x specifier starting at #%u in '%s'", |
781ee592b295
lib: printf_format_fix*() - Be over-strict in what format strings are allowed
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
22713
diff
changeset
|
154 *p, start_pos, format); |
21340
4efaa627264d
lib: Allow only known %chars in printf_format_fix_noalloc()
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
21339
diff
changeset
|
155 } |
5679
74e06273985b
Renamed printf_string_fix_format() to printf_format_fix() and moved it to
Timo Sirainen <tss@iki.fi>
parents:
diff
changeset
|
156 } |
21338
bc57c62167fc
lib: Optimize printf_format_fix_noalloc()
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
21322
diff
changeset
|
157 p++; |
5679
74e06273985b
Renamed printf_string_fix_format() to printf_format_fix() and moved it to
Timo Sirainen <tss@iki.fi>
parents:
diff
changeset
|
158 } |
74e06273985b
Renamed printf_string_fix_format() to printf_format_fix() and moved it to
Timo Sirainen <tss@iki.fi>
parents:
diff
changeset
|
159 |
17528
06f90ecbfb70
lib: make printf_format_fix safer against shadowed %m behaviour
Phil Carmody <phil@dovecot.fi>
parents:
17130
diff
changeset
|
160 if (ret == format) |
21338
bc57c62167fc
lib: Optimize printf_format_fix_noalloc()
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
21322
diff
changeset
|
161 *len_r = p - format + strlen(p); |
17528
06f90ecbfb70
lib: make printf_format_fix safer against shadowed %m behaviour
Phil Carmody <phil@dovecot.fi>
parents:
17130
diff
changeset
|
162 return ret; |
5681
09415e6a0892
Require C99 compatible vsnprintf(). Removed printf_string_upper_bound() and
Timo Sirainen <tss@iki.fi>
parents:
5679
diff
changeset
|
163 } |
09415e6a0892
Require C99 compatible vsnprintf(). Removed printf_string_upper_bound() and
Timo Sirainen <tss@iki.fi>
parents:
5679
diff
changeset
|
164 |
21322
5ab8dc1a4a6f
global: Change string position/length from unsigned int to size_t
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
19552
diff
changeset
|
165 const char *printf_format_fix_get_len(const char *format, size_t *len_r) |
5681
09415e6a0892
Require C99 compatible vsnprintf(). Removed printf_string_upper_bound() and
Timo Sirainen <tss@iki.fi>
parents:
5679
diff
changeset
|
166 { |
09415e6a0892
Require C99 compatible vsnprintf(). Removed printf_string_upper_bound() and
Timo Sirainen <tss@iki.fi>
parents:
5679
diff
changeset
|
167 const char *ret; |
09415e6a0892
Require C99 compatible vsnprintf(). Removed printf_string_upper_bound() and
Timo Sirainen <tss@iki.fi>
parents:
5679
diff
changeset
|
168 |
09415e6a0892
Require C99 compatible vsnprintf(). Removed printf_string_upper_bound() and
Timo Sirainen <tss@iki.fi>
parents:
5679
diff
changeset
|
169 ret = printf_format_fix_noalloc(format, len_r); |
09415e6a0892
Require C99 compatible vsnprintf(). Removed printf_string_upper_bound() and
Timo Sirainen <tss@iki.fi>
parents:
5679
diff
changeset
|
170 if (ret != format) |
09415e6a0892
Require C99 compatible vsnprintf(). Removed printf_string_upper_bound() and
Timo Sirainen <tss@iki.fi>
parents:
5679
diff
changeset
|
171 t_buffer_alloc(*len_r + 1); |
09415e6a0892
Require C99 compatible vsnprintf(). Removed printf_string_upper_bound() and
Timo Sirainen <tss@iki.fi>
parents:
5679
diff
changeset
|
172 return ret; |
5679
74e06273985b
Renamed printf_string_fix_format() to printf_format_fix() and moved it to
Timo Sirainen <tss@iki.fi>
parents:
diff
changeset
|
173 } |
74e06273985b
Renamed printf_string_fix_format() to printf_format_fix() and moved it to
Timo Sirainen <tss@iki.fi>
parents:
diff
changeset
|
174 |
5681
09415e6a0892
Require C99 compatible vsnprintf(). Removed printf_string_upper_bound() and
Timo Sirainen <tss@iki.fi>
parents:
5679
diff
changeset
|
175 const char *printf_format_fix(const char *format) |
09415e6a0892
Require C99 compatible vsnprintf(). Removed printf_string_upper_bound() and
Timo Sirainen <tss@iki.fi>
parents:
5679
diff
changeset
|
176 { |
09415e6a0892
Require C99 compatible vsnprintf(). Removed printf_string_upper_bound() and
Timo Sirainen <tss@iki.fi>
parents:
5679
diff
changeset
|
177 const char *ret; |
21322
5ab8dc1a4a6f
global: Change string position/length from unsigned int to size_t
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
19552
diff
changeset
|
178 size_t len; |
5681
09415e6a0892
Require C99 compatible vsnprintf(). Removed printf_string_upper_bound() and
Timo Sirainen <tss@iki.fi>
parents:
5679
diff
changeset
|
179 |
09415e6a0892
Require C99 compatible vsnprintf(). Removed printf_string_upper_bound() and
Timo Sirainen <tss@iki.fi>
parents:
5679
diff
changeset
|
180 ret = printf_format_fix_noalloc(format, &len); |
09415e6a0892
Require C99 compatible vsnprintf(). Removed printf_string_upper_bound() and
Timo Sirainen <tss@iki.fi>
parents:
5679
diff
changeset
|
181 if (ret != format) |
09415e6a0892
Require C99 compatible vsnprintf(). Removed printf_string_upper_bound() and
Timo Sirainen <tss@iki.fi>
parents:
5679
diff
changeset
|
182 t_buffer_alloc(len + 1); |
09415e6a0892
Require C99 compatible vsnprintf(). Removed printf_string_upper_bound() and
Timo Sirainen <tss@iki.fi>
parents:
5679
diff
changeset
|
183 return ret; |
09415e6a0892
Require C99 compatible vsnprintf(). Removed printf_string_upper_bound() and
Timo Sirainen <tss@iki.fi>
parents:
5679
diff
changeset
|
184 } |
09415e6a0892
Require C99 compatible vsnprintf(). Removed printf_string_upper_bound() and
Timo Sirainen <tss@iki.fi>
parents:
5679
diff
changeset
|
185 |
09415e6a0892
Require C99 compatible vsnprintf(). Removed printf_string_upper_bound() and
Timo Sirainen <tss@iki.fi>
parents:
5679
diff
changeset
|
186 const char *printf_format_fix_unsafe(const char *format) |
09415e6a0892
Require C99 compatible vsnprintf(). Removed printf_string_upper_bound() and
Timo Sirainen <tss@iki.fi>
parents:
5679
diff
changeset
|
187 { |
21322
5ab8dc1a4a6f
global: Change string position/length from unsigned int to size_t
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
19552
diff
changeset
|
188 size_t len; |
5681
09415e6a0892
Require C99 compatible vsnprintf(). Removed printf_string_upper_bound() and
Timo Sirainen <tss@iki.fi>
parents:
5679
diff
changeset
|
189 |
09415e6a0892
Require C99 compatible vsnprintf(). Removed printf_string_upper_bound() and
Timo Sirainen <tss@iki.fi>
parents:
5679
diff
changeset
|
190 return printf_format_fix_noalloc(format, &len); |
09415e6a0892
Require C99 compatible vsnprintf(). Removed printf_string_upper_bound() and
Timo Sirainen <tss@iki.fi>
parents:
5679
diff
changeset
|
191 } |