Coverage Report

Created: 2026-09-14 06:49

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/dovecot/src/lib/base64.h
Line
Count
Source
1
#ifndef BASE64_H
2
#define BASE64_H
3
4
/*
5
 * Common Base64
6
 */
7
8
/* max. buffer size required for base64_encode() */
9
#define MAX_BASE64_ENCODED_SIZE(size) \
10
0
  ((((size) + 2) / 3) * 4)
11
/* max. buffer size required for base64_decode() */
12
#define MAX_BASE64_DECODED_SIZE(size) \
13
  (((size) + 3) / 4 * 3)
14
15
struct base64_scheme {
16
  const char encmap[64];
17
  const unsigned char decmap[256];
18
};
19
20
/*
21
 * Low-level Base64 encoder
22
 */
23
24
enum base64_encode_flags {
25
  /* Use CRLF instead of the default LF as line ending. */
26
  BASE64_ENCODE_FLAG_CRLF                 = BIT(0),
27
  /* Encode no padding at the end of the data. */
28
  BASE64_ENCODE_FLAG_NO_PADDING           = BIT(1),
29
};
30
31
struct base64_encoder {
32
  const struct base64_scheme *b64;
33
  enum base64_encode_flags flags;
34
  size_t max_line_len;
35
36
  /* state */
37
  unsigned int sub_pos;
38
  unsigned char buf;
39
  size_t cur_line_len;
40
41
  unsigned char w_buf[10];
42
  unsigned int w_buf_len;
43
44
  bool pending_lf:1;
45
  bool finishing:1;
46
  bool finished:1;
47
};
48
49
/* Returns TRUE when base64_encode_finish() was called on this encoder. */
50
static inline bool
51
base64_encode_is_finished(struct base64_encoder *enc)
52
0
{
53
0
  return enc->finished;
54
0
}
Unexecuted instantiation: smtp-server-connection.c:base64_encode_is_finished
Unexecuted instantiation: expansion-filter.c:base64_encode_is_finished
Unexecuted instantiation: base64.c:base64_encode_is_finished
55
56
/* Initialize the Base64 encoder. The b64 parameter is the definition of the
57
   particular Base64 encoding scheme that is used.
58
 */
59
static inline void
60
base64_encode_init(struct base64_encoder *enc,
61
       const struct base64_scheme *b64,
62
       enum base64_encode_flags flags,
63
       size_t max_line_len)
64
5.97k
{
65
5.97k
  i_zero(enc);
66
5.97k
  enc->b64 = b64;
67
5.97k
  enc->flags = flags;
68
5.97k
  enc->max_line_len = (max_line_len == 0 ? SIZE_MAX : max_line_len);
69
5.97k
}
smtp-server-connection.c:base64_encode_init
Line
Count
Source
64
5.97k
{
65
5.97k
  i_zero(enc);
66
5.97k
  enc->b64 = b64;
67
5.97k
  enc->flags = flags;
68
5.97k
  enc->max_line_len = (max_line_len == 0 ? SIZE_MAX : max_line_len);
69
5.97k
}
Unexecuted instantiation: expansion-filter.c:base64_encode_init
Unexecuted instantiation: base64.c:base64_encode_init
70
71
/* Reset the Base64 encoder to its initial state. */
72
static inline void
73
base64_encode_reset(struct base64_encoder *enc)
74
0
{
75
0
  const struct base64_scheme *b64 = enc->b64;
76
0
  enum base64_encode_flags flags = enc->flags;
77
0
  size_t max_line_len = enc->max_line_len;
78
0
79
0
  base64_encode_init(enc, b64, flags, max_line_len);
80
0
}
Unexecuted instantiation: smtp-server-connection.c:base64_encode_reset
Unexecuted instantiation: expansion-filter.c:base64_encode_reset
Unexecuted instantiation: base64.c:base64_encode_reset
81
82
/* Translate the size of the full encoder input to the size of the encoder
83
   output.
84
 */
85
uoff_t base64_get_full_encoded_size(struct base64_encoder *enc,
86
            uoff_t src_size);
87
/* Translate the size of the next input to the size of the output once encoded.
88
   This yields the amount of data appended to the dest buffer by
89
   base64_encode_more() with the indicated src_size. */
90
size_t base64_encode_get_size(struct base64_encoder *enc, size_t src_size);
91
92
/* Translate the space in the destination buffer to the number of bytes that can
93
   be encoded at most to complete the full base64 encoding, including padding
94
   and newlines if configured. */
95
size_t base64_encode_get_full_space(struct base64_encoder *enc,
96
            size_t dst_space);
97
98
/* Translates binary data into some form of Base64. The src must not point to
99
   dest buffer. Returns TRUE when all the provided data is encoded. Returns
100
   FALSE when the space in the provided buffer is insufficient. The return value
101
   may be ignored. If src_pos_r is non-NULL, it's updated to first
102
   non-translated character in src.
103
 */
104
bool ATTR_NOWARN_UNUSED_RESULT
105
base64_encode_more(struct base64_encoder *enc, const void *src, size_t src_size,
106
       size_t *src_pos_r, buffer_t *dest) ATTR_NULL(4);
107
108
/* Finishes Base64 encoding. Returns TRUE when all the provided data is encoded.
109
   Returns FALSE when the space in the provided buffer is insufficient. The
110
   return value may be ignored.
111
 */
112
bool ATTR_NOWARN_UNUSED_RESULT
113
base64_encode_finish(struct base64_encoder *enc, buffer_t *dest) ATTR_NULL(2);
114
115
/*
116
 * Low-level Base64 decoder
117
 */
118
119
enum base64_decode_flags {
120
  /* Decode input until a boundary is reached. This boundary is a
121
     non-Base64 input sequence that would normally trigger a decode error;
122
     e.g., Base64 data followed by a ':'. With this flag, it is possible
123
     to decode such a Base64 prefix. The base64_decode_finish() function
124
     will still check that the Base64 data ends properly (padding). */
125
  BASE64_DECODE_FLAG_EXPECT_BOUNDARY = BIT(0),
126
  /* Prohibit whitespace in the input. */
127
  BASE64_DECODE_FLAG_NO_WHITESPACE   = BIT(1),
128
  /* Require absence of padding at the end of the input. */
129
  BASE64_DECODE_FLAG_NO_PADDING      = BIT(2),
130
  /* Ignore padding at the end of the input. This flag is ignored when
131
     BASE64_DECODE_FLAG_NO_PADDING is also set. If both of these flags are
132
     absent, padding is required (the default). */
133
  BASE64_DECODE_FLAG_IGNORE_PADDING  = BIT(3),
134
};
135
136
struct base64_decoder {
137
  const struct base64_scheme *b64;
138
  enum base64_decode_flags flags;
139
140
  /* state */
141
  unsigned int sub_pos;
142
  unsigned char buf;
143
144
  bool seen_padding:1;
145
  bool seen_end:1;
146
  bool seen_boundary:1;
147
  bool finished:1;
148
  bool failed:1;
149
};
150
151
/* Returns TRUE when base64_decode_finish() was called on this decoder. */
152
static inline bool
153
base64_decode_is_finished(struct base64_decoder *dec)
154
0
{
155
0
  return dec->finished;
156
0
}
Unexecuted instantiation: smtp-server-connection.c:base64_decode_is_finished
Unexecuted instantiation: expansion-filter.c:base64_decode_is_finished
Unexecuted instantiation: base64.c:base64_decode_is_finished
157
158
/* Initialize the Base64 decoder. The b64 parameter is the definition of the
159
   particular Base64 encoding scheme that is expected.
160
 */
161
static inline void
162
base64_decode_init(struct base64_decoder *dec,
163
       const struct base64_scheme *b64,
164
       enum base64_decode_flags flags)
165
0
{
166
0
  i_zero(dec);
167
0
  dec->b64 = b64;
168
0
  dec->flags = flags;
169
0
}
Unexecuted instantiation: smtp-server-connection.c:base64_decode_init
Unexecuted instantiation: expansion-filter.c:base64_decode_init
Unexecuted instantiation: base64.c:base64_decode_init
170
171
/* Reset the Base64 decoder to its initial state. */
172
static inline void
173
base64_decode_reset(struct base64_decoder *dec)
174
0
{
175
0
  const struct base64_scheme *b64 = dec->b64;
176
0
  enum base64_decode_flags flags = dec->flags;
177
0
178
0
  base64_decode_init(dec, b64, flags);
179
0
}
Unexecuted instantiation: smtp-server-connection.c:base64_decode_reset
Unexecuted instantiation: expansion-filter.c:base64_decode_reset
Unexecuted instantiation: base64.c:base64_decode_reset
180
181
/* Translates some form of Base64 data into binary and appends it to dest
182
   buffer. dest may point to same buffer as src. Returns 1 if all ok, 0 if end
183
   of base64 data found, -1 if data is invalid.
184
185
   By default, any CR, LF characters are ignored, as well as any whitespace.
186
   This can be overridden using the BASE64_DECODE_FLAG_NO_WHITESPACE flag.
187
188
   If src_pos is non-NULL, it's updated to first non-translated character in
189
   src.
190
 */
191
int base64_decode_more(struct base64_decoder *dec,
192
           const void *src, size_t src_size, size_t *src_pos_r,
193
           buffer_t *dest) ATTR_NULL(4);
194
/* Finishes Base64 decoding. This function checks whether the encoded data ends
195
   in the proper padding. Returns 0 if all ok, and -1 if data is invalid.
196
 */
197
int base64_decode_finish(struct base64_decoder *dec);
198
199
/*
200
 * Generic Base64 API
201
 */
202
203
/* Translates binary data into some variant of Base64. The src must not point to
204
   dest buffer.
205
206
   The b64 parameter is the definition of the particular Base 64 encoding scheme
207
   that is used. See below for specific functions.
208
 */
209
static inline void
210
base64_scheme_encode(const struct base64_scheme *b64,
211
         enum base64_encode_flags flags, size_t max_line_len,
212
         const void *src, size_t src_size, buffer_t *dest)
213
5.97k
{
214
5.97k
  struct base64_encoder enc;
215
216
5.97k
  base64_encode_init(&enc, b64, flags, max_line_len);
217
5.97k
  base64_encode_more(&enc, src, src_size, NULL, dest);
218
5.97k
  base64_encode_finish(&enc, dest);
219
5.97k
}
smtp-server-connection.c:base64_scheme_encode
Line
Count
Source
213
5.97k
{
214
5.97k
  struct base64_encoder enc;
215
216
5.97k
  base64_encode_init(&enc, b64, flags, max_line_len);
217
5.97k
  base64_encode_more(&enc, src, src_size, NULL, dest);
218
5.97k
  base64_encode_finish(&enc, dest);
219
5.97k
}
Unexecuted instantiation: expansion-filter.c:base64_scheme_encode
Unexecuted instantiation: base64.c:base64_scheme_encode
220
221
buffer_t *t_base64_scheme_encode(const struct base64_scheme *b64,
222
         enum base64_encode_flags flags,
223
         size_t max_line_len,
224
         const void *src, size_t src_size);
225
226
static inline buffer_t *
227
t_base64_scheme_encode_str(const struct base64_scheme *b64,
228
         enum base64_encode_flags flags, size_t max_line_len,
229
         const char *src)
230
0
{
231
0
        return t_base64_scheme_encode(b64, flags, max_line_len,
232
0
              src, strlen(src));
233
0
}
Unexecuted instantiation: smtp-server-connection.c:t_base64_scheme_encode_str
Unexecuted instantiation: expansion-filter.c:t_base64_scheme_encode_str
Unexecuted instantiation: base64.c:t_base64_scheme_encode_str
234
235
/* Translates some variant of Base64 data into binary and appends it to dest
236
   buffer. dest may point to same buffer as src. Returns 1 if all ok, 0 if end
237
   of Base64 data found, -1 if data is invalid.
238
239
   The b64 parameter is the definition of the particular Base 64 encoding scheme
240
   that is expected. See below for specific functions.
241
242
   Any CR, LF characters are ignored, as well as whitespace at beginning or
243
   end of line.
244
 */
245
int base64_scheme_decode(const struct base64_scheme *b64,
246
       enum base64_decode_flags flags,
247
       const void *src, size_t src_size, buffer_t *dest);
248
249
/* Decode given data to a buffer allocated from data stack.
250
251
   The b64 parameter is the definition of the particular Base 64 encoding scheme
252
   that is expected. See below for specific functions.
253
 */
254
buffer_t *t_base64_scheme_decode(const struct base64_scheme *b64,
255
         enum base64_decode_flags flags,
256
         const void *src, size_t src_size);
257
/* Decode given string to a buffer allocated from data stack.
258
259
   The b64 parameter is the definition of the particular Base 64 encoding scheme
260
   that is expected. See below for specific functions.
261
 */
262
static inline buffer_t *
263
t_base64_scheme_decode_str(const struct base64_scheme *b64,
264
         enum base64_decode_flags flags, const char *str)
265
0
{
266
0
  return t_base64_scheme_decode(b64, flags, str, strlen(str));
267
0
}
Unexecuted instantiation: smtp-server-connection.c:t_base64_scheme_decode_str
Unexecuted instantiation: expansion-filter.c:t_base64_scheme_decode_str
Unexecuted instantiation: base64.c:t_base64_scheme_decode_str
268
269
/* Returns TRUE if c is a valid encoding character (excluding '=') for the
270
   provided base64 mapping table */
271
static inline bool
272
base64_scheme_is_valid_char(const struct base64_scheme *b64, char c)
273
0
{
274
0
  return b64->decmap[(uint8_t)c] != 0xff;
275
0
}
Unexecuted instantiation: smtp-server-connection.c:base64_scheme_is_valid_char
Unexecuted instantiation: expansion-filter.c:base64_scheme_is_valid_char
Unexecuted instantiation: base64.c:base64_scheme_is_valid_char
276
277
/*
278
 * "base64" encoding scheme (RFC 4648, Section 4)
279
 */
280
281
extern struct base64_scheme base64_scheme;
282
283
/* Translates binary data into base64. See base64_scheme_encode(). */
284
static inline void
285
base64_encode(const void *src, size_t src_size, buffer_t *dest)
286
5.97k
{
287
5.97k
  base64_scheme_encode(&base64_scheme, 0, 0, src, src_size, dest);
288
5.97k
}
smtp-server-connection.c:base64_encode
Line
Count
Source
286
5.97k
{
287
5.97k
  base64_scheme_encode(&base64_scheme, 0, 0, src, src_size, dest);
288
5.97k
}
Unexecuted instantiation: expansion-filter.c:base64_encode
Unexecuted instantiation: base64.c:base64_encode
289
290
static inline buffer_t *
291
t_base64_encode(enum base64_encode_flags flags, size_t max_line_len,
292
    const void *src, size_t src_size)
293
0
{
294
0
  return t_base64_scheme_encode(&base64_scheme, flags, max_line_len,
295
0
              src, src_size);
296
0
}
Unexecuted instantiation: smtp-server-connection.c:t_base64_encode
Unexecuted instantiation: expansion-filter.c:t_base64_encode
Unexecuted instantiation: base64.c:t_base64_encode
297
298
static inline buffer_t *
299
t_base64_encode_str(enum base64_encode_flags flags, size_t max_line_len,
300
        const char *src)
301
0
{
302
0
        return t_base64_scheme_encode(&base64_scheme, flags, max_line_len,
303
0
              src, strlen(src));
304
0
}
Unexecuted instantiation: smtp-server-connection.c:t_base64_encode_str
Unexecuted instantiation: expansion-filter.c:t_base64_encode_str
Unexecuted instantiation: base64.c:t_base64_encode_str
305
306
/* Translates base64 data into binary and appends it to dest buffer. See
307
   base64_scheme_decode().
308
 */
309
static inline int
310
base64_decode(const void *src, size_t src_size, buffer_t *dest)
311
0
{
312
0
  return base64_scheme_decode(&base64_scheme, 0, src, src_size, dest);
313
0
}
Unexecuted instantiation: smtp-server-connection.c:base64_decode
Unexecuted instantiation: expansion-filter.c:base64_decode
Unexecuted instantiation: base64.c:base64_decode
314
315
/* Decode given data to a buffer allocated from data stack. */
316
static inline buffer_t *
317
t_base64_decode(enum base64_decode_flags flags,
318
    const void *src, size_t src_size)
319
0
{
320
0
  return t_base64_scheme_decode(&base64_scheme, flags, src, src_size);
321
0
}
Unexecuted instantiation: smtp-server-connection.c:t_base64_decode
Unexecuted instantiation: expansion-filter.c:t_base64_decode
Unexecuted instantiation: base64.c:t_base64_decode
322
323
/* Decode given string to a buffer allocated from data stack. */
324
static inline buffer_t *t_base64_decode_str(const char *str)
325
0
{
326
0
  return t_base64_scheme_decode_str(&base64_scheme, 0, str);
327
0
}
Unexecuted instantiation: smtp-server-connection.c:t_base64_decode_str
Unexecuted instantiation: expansion-filter.c:t_base64_decode_str
Unexecuted instantiation: base64.c:t_base64_decode_str
328
329
/* Returns TRUE if c is a valid base64 encoding character (excluding '=') */
330
static inline bool base64_is_valid_char(char c)
331
0
{
332
0
  return base64_scheme_is_valid_char(&base64_scheme, c);
333
0
}
Unexecuted instantiation: smtp-server-connection.c:base64_is_valid_char
Unexecuted instantiation: expansion-filter.c:base64_is_valid_char
Unexecuted instantiation: base64.c:base64_is_valid_char
334
335
/*
336
 * "base64url" encoding scheme (RFC 4648, Section 5)
337
 */
338
339
extern struct base64_scheme base64url_scheme;
340
341
/* Translates binary data into base64url. See base64_scheme_encode(). */
342
static inline void
343
base64url_encode(enum base64_encode_flags flags, size_t max_line_len,
344
     const void *src, size_t src_size, buffer_t *dest)
345
0
{
346
0
  base64_scheme_encode(&base64url_scheme, flags, max_line_len,
347
0
           src, src_size, dest);
348
0
}
Unexecuted instantiation: smtp-server-connection.c:base64url_encode
Unexecuted instantiation: expansion-filter.c:base64url_encode
Unexecuted instantiation: base64.c:base64url_encode
349
350
static inline buffer_t *
351
t_base64url_encode(enum base64_encode_flags flags, size_t max_line_len,
352
    const void *src, size_t src_size)
353
0
{
354
0
  return t_base64_scheme_encode(&base64url_scheme, flags, max_line_len,
355
0
              src, src_size);
356
0
}
Unexecuted instantiation: smtp-server-connection.c:t_base64url_encode
Unexecuted instantiation: expansion-filter.c:t_base64url_encode
Unexecuted instantiation: base64.c:t_base64url_encode
357
358
static inline buffer_t *
359
t_base64url_encode_str(enum base64_encode_flags flags, size_t max_line_len,
360
           const char *src)
361
0
{
362
0
        return t_base64_scheme_encode(&base64url_scheme, flags, max_line_len,
363
0
              src, strlen(src));
364
0
}
Unexecuted instantiation: smtp-server-connection.c:t_base64url_encode_str
Unexecuted instantiation: expansion-filter.c:t_base64url_encode_str
Unexecuted instantiation: base64.c:t_base64url_encode_str
365
366
/* Translates base64url data into binary and appends it to dest buffer. See
367
   base64_scheme_decode(). */
368
static inline int
369
base64url_decode(enum base64_decode_flags flags,
370
     const void *src, size_t src_size, buffer_t *dest)
371
0
{
372
0
  return base64_scheme_decode(&base64url_scheme, flags,
373
0
            src, src_size, dest);
374
0
}
Unexecuted instantiation: smtp-server-connection.c:base64url_decode
Unexecuted instantiation: expansion-filter.c:base64url_decode
Unexecuted instantiation: base64.c:base64url_decode
375
376
/* Decode given data to a buffer allocated from data stack. */
377
static inline buffer_t *
378
t_base64url_decode(enum base64_decode_flags flags,
379
       const void *src, size_t src_size)
380
0
{
381
0
  return t_base64_scheme_decode(&base64url_scheme, flags, src, src_size);
382
0
}
Unexecuted instantiation: smtp-server-connection.c:t_base64url_decode
Unexecuted instantiation: expansion-filter.c:t_base64url_decode
Unexecuted instantiation: base64.c:t_base64url_decode
383
384
/* Decode given string to a buffer allocated from data stack. */
385
static inline buffer_t *
386
t_base64url_decode_str(enum base64_decode_flags flags, const char *str)
387
0
{
388
0
  return t_base64_scheme_decode_str(&base64url_scheme, flags, str);
389
0
}
Unexecuted instantiation: smtp-server-connection.c:t_base64url_decode_str
Unexecuted instantiation: expansion-filter.c:t_base64url_decode_str
Unexecuted instantiation: base64.c:t_base64url_decode_str
390
391
/* Returns TRUE if c is a valid base64url encoding character (excluding '=') */
392
static inline bool base64url_is_valid_char(char c)
393
0
{
394
0
  return base64_scheme_is_valid_char(&base64url_scheme, c);
395
0
}
Unexecuted instantiation: smtp-server-connection.c:base64url_is_valid_char
Unexecuted instantiation: expansion-filter.c:base64url_is_valid_char
Unexecuted instantiation: base64.c:base64url_is_valid_char
396
397
#endif