1--TEST--
2Test mb_decode_mimeheader() function: weird variations found by fuzzer
3--EXTENSIONS--
4mbstring
5--FILE--
6<?php
7
8// We convert runs of whitespace, including CR, LF, tab, and space, to a single space...
9// but ONLY when that run of whitespace does not occur right in the middle between two
10// valid MIME encoded words
11mb_internal_encoding('UCS-2');
12var_dump(bin2hex(mb_decode_mimeheader("2,\rGCG\xb3GS")));
13
14// We DO convert a run of whitespace to a single space at the very beginning of the input string,
15// as long as it is followed by a non-whitespace character
16mb_internal_encoding('ASCII');
17var_dump(bin2hex(mb_decode_mimeheader("\n8i")));
18
19// But not if it is just a CR or LF at the end of the string
20mb_internal_encoding('ASCII');
21var_dump(bin2hex(mb_decode_mimeheader("\r")));
22
23// Not if it is a run of whitespace going right up to the end of the string
24mb_internal_encoding('ASCII');
25var_dump(bin2hex(mb_decode_mimeheader("\n ")));
26
27// Handle = which doesn't initiate a valid encoded word
28mb_internal_encoding('ASCII');
29var_dump(bin2hex(mb_decode_mimeheader(",\x13@=,")));
30
31// Encoded word which should not be accepted
32mb_internal_encoding('ASCII');
33var_dump(bin2hex(mb_decode_mimeheader("=?I?B??=")));
34
35// Encoded word with invalid charset name, and input string ends with whitespace
36// The old implementation of mb_decode_mimeheader would get 'stuck' on the invalid encoding name
37// and could never get out of that state; it would not even try to interpret any other encoded words
38// up to the end of the input string
39mb_internal_encoding('ISO-8859-7');
40var_dump(bin2hex(mb_decode_mimeheader("=?=\x20?=?R\xb7=?=\x20?\x8b\x00====?===??=\xc5UC-R\xb7=?=\x20?=?=====?=\x20?======?======?=\x20?======?===??=\xc5UC-KR\xb7=?=\x20?=?===?==?\x0a")));
41
42// While the old implementation would generally trim off whitespace at the end of the input string,
43// but there was a bug whereby it would not do this when the whitespace character was the 100th
44// byte of an invalid charset name
45mb_internal_encoding('UCS-2');
46var_dump(bin2hex(mb_decode_mimeheader("=?\xc2\x86tf7,U\x01\x00`@\x00\x04|\xf1D\x18\x00\x00\x00v\xcb\xcb\xcb\xcb\xcb\xcb\xcb\xcb\xcb\xcb\xcb\xff\x13f7,U&\x00S\x01\x00\x17,D\xcb\xcb\xcb\xcb\xcb\xcb\xcb\x01\x00\x00\x14\xcb\xcb\xcb\xcb\xcb\xcb\xcb\xcb\xcb\xcb\xcb\xcb\xcb\xcb\xcb\xcb\xcb\xcb\xcb\xcb\xcb\xcb\xcb\xcb\xcb\xcb\xcb\xcb\xcb\xcb\xcb\xcb\xcb\x00\x11\x00\x00\x00\x00\x00\x00\x0a")));
47
48// Empty encoded word
49mb_internal_encoding('ASCII');
50var_dump(bin2hex(mb_decode_mimeheader("=?us?B?")));
51
52// Encoded word with just one invalid Base64 byte
53mb_internal_encoding('ASCII');
54var_dump(bin2hex(mb_decode_mimeheader("=?us?B?-")));
55
56// Encoded word with an invalid Base64 byte followed by a valid Base64 byte
57mb_internal_encoding('ASCII');
58var_dump(bin2hex(mb_decode_mimeheader("=?us?B?-s")));
59
60// Empty encoded word with a ? which looks like it should be terminator, but = is missing
61mb_internal_encoding('ASCII');
62var_dump(bin2hex(mb_decode_mimeheader("=?us?B??")));
63
64// Encoded word with just one invalid Base64 byte, but this time properly terminated
65mb_internal_encoding('ASCII');
66var_dump(bin2hex(mb_decode_mimeheader("=?us?B?\x00?=")));
67
68// Invalid encoded word, followed immediately by valid encoded word
69mb_internal_encoding('ASCII');
70var_dump(bin2hex(mb_decode_mimeheader("=?=?hz?b?")));
71
72// Another example of invalid encoded word followed immediately by valid encoded word
73mb_internal_encoding('ASCII');
74var_dump(bin2hex(mb_decode_mimeheader("=?==?hz?b?")));
75
76// Yet another example
77mb_internal_encoding('ASCII');
78var_dump(bin2hex(mb_decode_mimeheader("=?,=?hz?b?")));
79
80// In PHP 8.0-8.1 this would cause a crash
81mb_internal_encoding('UUENCODE');
82var_dump(bin2hex(mb_decode_mimeheader("")));
83
84// The conversion filter for SJIS-Mobile#SOFTBANK did not work correctly when it was
85// passed the last buffer of wchars without passing 'end' flag, then called one more
86// time with an empty buffer and 'end' flag to finish up
87mb_internal_encoding('SJIS-Mobile#SOFTBANK');
88var_dump(bin2hex(mb_decode_mimeheader("6")));
89
90// Same for SJIS-Mobile#KDDI and SJIS-Mobile#DOCOMO
91mb_internal_encoding('SJIS-Mobile#KDDI');
92var_dump(bin2hex(mb_decode_mimeheader("6")));
93mb_internal_encoding('SJIS-Mobile#DOCOMO');
94var_dump(bin2hex(mb_decode_mimeheader("6")));
95
96?>
97--EXPECT--
98string(36) "0032002c0020004700430047003f00470053"
99string(6) "203869"
100string(0) ""
101string(0) ""
102string(10) "2c13403d2c"
103string(16) "3d3f493f423f3f3d"
104string(200) "3d3f3d203f3d3f523f3d3f3d203f3f003d3d3d3d3f3d3d3d3f3f3d3f55432d523f3d3f3d203f3d3f3d3d3d3d3d3f3d203f3d3d3d3d3d3d3f3d3d3d3d3d3d3f3d203f3d3d3d3d3d3d3f3d3d3d3f3f3d3f55432d4b523f3d3f3d203f3d3f3d3d3d3f3d3d3f"
105string(400) "003d003f003f003f007400660037002c0055000100000060004000000004007c003f004400180000000000000076003f003f003f003f003f003f003f003f003f003f003f003f001300660037002c0055002600000053000100000017002c0044003f003f003f003f003f003f003f0001000000000014003f003f003f003f003f003f003f003f003f003f003f003f003f003f003f003f003f003f003f003f003f003f003f003f003f003f003f003f003f003f003f003f003f00000011000000000000000000000000"
106string(0) ""
107string(2) "3f"
108string(2) "3f"
109string(0) ""
110string(2) "3f"
111string(4) "3d3f"
112string(6) "3d3f3d"
113string(6) "3d3f2c"
114string(42) "626567696e20303634342066696c656e616d650a20"
115string(2) "36"
116string(2) "36"
117string(2) "36"
118