Skip to content

Commit 78dc160

Browse files
committed
Catch and handle errors in mUTF-7 (IMAP) conversion
1 parent cef4b94 commit 78dc160

File tree

1 file changed

+21
-3
lines changed

1 file changed

+21
-3
lines changed

ext/mbstring/libmbfl/filters/mbfilter_utf7imap.c

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@
7979
#include "mbfilter_utf7imap.h"
8080

8181
static int mbfl_filt_conv_wchar_utf7imap_flush(mbfl_convert_filter *filter);
82+
static int mbfl_filt_conv_utf7imap_wchar_flush(mbfl_convert_filter *filter);
8283

8384
static const char *mbfl_encoding_utf7imap_aliases[] = {"mUTF-7", NULL};
8485

@@ -99,7 +100,7 @@ const struct mbfl_convert_vtbl vtbl_utf7imap_wchar = {
99100
mbfl_filt_conv_common_ctor,
100101
NULL,
101102
mbfl_filt_conv_utf7imap_wchar,
102-
mbfl_filt_conv_common_flush,
103+
mbfl_filt_conv_utf7imap_wchar_flush,
103104
NULL,
104105
};
105106

@@ -136,9 +137,11 @@ int mbfl_filt_conv_utf7imap_wchar(int c, mbfl_convert_filter *filter)
136137
if (c == '-') {
137138
if (filter->status == 1) { /* "&-" -> "&" */
138139
CK((*filter->output_function)('&', filter->data));
140+
} else if (filter->cache) {
141+
/* Base64-encoded section ended abruptly, with partially encoded characters,
142+
* or it could be that it ended on the first half of a surrogate pair */
143+
CK((*filter->output_function)(filter->cache | MBFL_WCSGROUP_THROUGH, filter->data));
139144
}
140-
} else if (c >= 0 && c < 0x80) { /* ASCII exclude '-' */
141-
CK((*filter->output_function)(c, filter->data));
142145
} else { /* illegal character */
143146
CK((*filter->output_function)(c | MBFL_WCSGROUP_THROUGH, filter->data));
144147
}
@@ -272,6 +275,21 @@ int mbfl_filt_conv_utf7imap_wchar(int c, mbfl_convert_filter *filter)
272275
return c;
273276
}
274277

278+
static int mbfl_filt_conv_utf7imap_wchar_flush(mbfl_convert_filter *filter)
279+
{
280+
if (filter->status) {
281+
/* It is illegal for a UTF-7 IMAP string to end in a Base-64 encoded
282+
* section. It should always change back to ASCII before the end. */
283+
(*filter->output_function)(filter->cache | MBFL_WCSGROUP_THROUGH, filter->data);
284+
}
285+
286+
if (filter->flush_function) {
287+
(*filter->flush_function)(filter->data);
288+
}
289+
290+
return 0;
291+
}
292+
275293
static const unsigned char mbfl_utf7imap_base64_table[] =
276294
{
277295
/* 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', */

0 commit comments

Comments
 (0)