source: npl/overig/libvmime/vmime-wrongly-padded-B64-words.diff @ c5c522c

gcc484ntopperl-5.22
Last change on this file since c5c522c was c5c522c, checked in by Edwin Eefting <edwin@datux.nl>, 8 years ago

initial commit, transferred from cleaned syn3 svn tree

  • Property mode set to 100644
File size: 6.1 KB
RevLine 
[c5c522c]1diff -urb libvmime-0.9.2-patched/src/word.cpp libvmime-0.9.2/src/word.cpp
2--- libvmime-0.9.2-patched/src/word.cpp 2015-01-16 15:04:04.124264216 +0100
3+++ libvmime-0.9.2/src/word.cpp 2015-01-16 15:05:13.672262038 +0100
4@@ -64,8 +64,7 @@
5 
6 
7 ref <word> word::parseNext(const string& buffer, const string::size_type position,
8-       const string::size_type end, string::size_type* newPosition,
9-       bool prevIsEncoded, bool* isEncoded, bool isFirst)
10+       const string::size_type end, string::size_type* newPosition, parserState* state)
11 {
12        string::size_type pos = position;
13 
14@@ -120,7 +119,7 @@
15 
16                        if (!unencoded.empty())
17                        {
18-                               if (prevIsEncoded)
19+                               if (state->prevIsEncoded && !state->isFirst)
20                                        unencoded = whiteSpaces + unencoded;
21 
22                                ref <word> w = vmime::create <word>(unencoded, charset(charsets::US_ASCII));
23@@ -129,8 +128,8 @@
24                                if (newPosition)
25                                        *newPosition = pos;
26 
27-                               if (isEncoded)
28-                                       *isEncoded = false;
29+                               state->prevIsEncoded = false;
30+                               state->isFirst = false;
31 
32                                return (w);
33                        }
34@@ -181,13 +180,13 @@
35                        pos += 2; // ?=
36 
37                        ref <word> w = vmime::create <word>();
38-                       w->parse(buffer, wordStart, pos, NULL);
39+                       w->parseWithState(buffer, wordStart, pos, NULL, state);
40 
41                        if (newPosition)
42                                *newPosition = pos;
43 
44-                       if (isEncoded)
45-                               *isEncoded = true;
46+                       state->prevIsEncoded = true;
47+                       state->isFirst = false;
48 
49                        return (w);
50                }
51@@ -195,7 +194,7 @@
52                ++pos;
53        }
54 
55-       if (startPos != end && !isFirst && prevIsEncoded)
56+       if (startPos != end && !state->isFirst && state->prevIsEncoded)
57                unencoded += whiteSpaces;
58 
59        if (startPos != end)
60@@ -210,8 +209,8 @@
61                if (newPosition)
62                        *newPosition = end;
63 
64-               if (isEncoded)
65-                       *isEncoded = false;
66+               state->prevIsEncoded = false;
67+               state->isFirst = false;
68 
69                return (w);
70        }
71@@ -228,9 +227,9 @@
72 
73        string::size_type pos = position;
74 
75-       bool prevIsEncoded = false;
76+       parserState state;
77 
78-       while ((w = word::parseNext(buffer, pos, end, &pos, prevIsEncoded, &prevIsEncoded, (w == NULL))) != NULL)
79+       while ((w = word::parseNext(buffer, pos, end, &pos, &state)) != NULL)
80                res.push_back(w);
81 
82        if (newPosition)
83@@ -243,6 +242,14 @@
84 void word::parse(const string& buffer, const string::size_type position,
85        const string::size_type end, string::size_type* newPosition)
86 {
87+       parseWithState(buffer, position, end, newPosition, NULL);
88+}
89+
90+
91+void word::parseWithState
92+       (const string& buffer, const size_t position,
93+        const size_t end, size_t* newPosition, parserState* state)
94+{
95        if (position + 6 < end && // 6 = "=?(.+)?(.*)?="
96            buffer[position] == '=' && buffer[position + 1] == '?')
97        {
98@@ -289,12 +296,20 @@
99                                        if (theEncoder)
100                                        {
101                                                // Decode text
102+                                               string encodedBuffer(dataPos, dataEnd);
103                                                string decodedBuffer;
104 
105-                                               utility::inputStreamStringAdapter ein(string(dataPos, dataEnd));
106+
107+                                                if (state && !state->undecodedBytes.empty())
108+                                                {
109+                                                        encodedBuffer = state->undecodedBytes + encodedBuffer;
110+                                                        state->undecodedBytes.clear();
111+                                                }
112+
113+                                                utility::inputStreamStringAdapter ein(encodedBuffer);
114                                                utility::outputStreamStringAdapter eout(decodedBuffer);
115 
116-                                               theEncoder->decode(ein, eout);
117+                                               const size_t decodedLen = theEncoder->decode(ein, eout);
118                                                delete (theEncoder);
119 
120                                                m_buffer = decodedBuffer;
121@@ -305,6 +320,21 @@
122                                                if (newPosition)
123                                                        *newPosition = (p - buffer.begin());
124 
125+                                               // For Base64 encoding, ensure all bytes have been decoded.
126+                                               // If there are remaining bytes, keep them for the next run.
127+                                               //
128+                                               // This allows decoding some insanities like:
129+                                               //     =?utf-8?B?5Lit5?= =?utf-8?B?paH?=
130+                                               if (*encPos == 'B' || *encPos == 'b')
131+                                               {
132+                                                       const size_t actualEncodedLen = encodedBuffer.length();
133+                                                       const size_t theoricalEncodedLen =
134+                                                               ((decodedLen + ((decodedLen % 3) ? (3 - (decodedLen % 3)) : 0) ) / 3) * 4;
135+
136+                                                       if (state && actualEncodedLen != theoricalEncodedLen)
137+                                                               state->undecodedBytes.assign(dataPos + theoricalEncodedLen, dataEnd);
138+                                               }
139+
140                                                return;
141                                        }
142                                }
143diff -urb libvmime-0.9.2-patched/vmime/word.hpp libvmime-0.9.2/vmime/word.hpp
144--- libvmime-0.9.2-patched/vmime/word.hpp       2015-01-16 15:04:04.128264216 +0100
145+++ libvmime-0.9.2/vmime/word.hpp       2015-01-16 15:05:13.672262038 +0100
146@@ -125,6 +125,20 @@
147                bool prevWordIsEncoded;
148                bool lastCharIsSpace;
149        };
150+
151+       class parserState
152+       {
153+       public:
154+
155+               parserState()
156+                       : prevIsEncoded(false), isFirst(true)
157+               {
158+               }
159+
160+               bool prevIsEncoded;
161+               bool isFirst;
162+               std::string undecodedBytes;
163+       };
164 #endif
165 
166 
167@@ -134,13 +148,20 @@
168        void parse(const string& buffer, const string::size_type position, const string::size_type end, string::size_type* newPosition = NULL);
169        void generate(utility::outputStream& os, const string::size_type maxLineLength = lineLengthLimits::infinite, const string::size_type curLinePos = 0, string::size_type* newLinePos = NULL) const;
170 
171+       void parseWithState
172+               (const string& buffer,
173+                const size_t position,
174+                const size_t end,
175+                size_t* newPosition,
176+                parserState* state);
177+
178        void generate(utility::outputStream& os, const string::size_type maxLineLength, const string::size_type curLinePos, string::size_type* newLinePos, const int flags, generatorState* state) const;
179 
180        const std::vector <ref <const component> > getChildComponents() const;
181 
182 private:
183 
184-       static ref <word> parseNext(const string& buffer, const string::size_type position, const string::size_type end, string::size_type* newPosition, bool prevIsEncoded, bool* isEncoded, bool isFirst);
185+       static ref <word> parseNext(const string& buffer, const string::size_type position, const string::size_type end, string::size_type* newPosition, parserState* state);
186 
187        static const std::vector <ref <word> > parseMultiple(const string& buffer, const string::size_type position, const string::size_type end, string::size_type* newPosition);
188 
Note: See TracBrowser for help on using the repository browser.