Skip to content

Commit 9ed6059

Browse files
committed
Fixed bugs in UUValidator and added more tests
1 parent 396549e commit 9ed6059

File tree

2 files changed

+148
-135
lines changed

2 files changed

+148
-135
lines changed

MimeKit/Encodings/UUValidator.cs

Lines changed: 65 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,8 @@ enum UUValidatorState : byte
6666
int lineNumber;
6767
UUValidatorState state;
6868
bool invalidPretext;
69+
bool invalidFileMode;
70+
bool eoln;
6971
byte nsaved;
7072
byte uulen;
7173

@@ -268,24 +270,39 @@ unsafe bool ScanBeginMarker (ref byte* inptr, byte* inend)
268270
inptr++;
269271
}
270272

271-
if (nsaved > 4) {
273+
if (!invalidFileMode && nsaved > 4) {
272274
// file mode is too long
273275
reader.OnMimeComplianceViolation (MimeComplianceViolation.InvalidUUEncodeFileMode, streamOffset - nsaved + 4, lineNumber);
276+
invalidFileMode = true;
274277
}
275278

276279
if (inptr == inend)
277280
break;
278281

279-
if (nsaved < 3) {
282+
if (!invalidFileMode && nsaved < 3) {
280283
// file mode is too short
281284
reader.OnMimeComplianceViolation (MimeComplianceViolation.InvalidUUEncodeFileMode, streamOffset, lineNumber);
285+
invalidFileMode = true;
282286
}
283287

284-
if (nsaved == 3 && *inptr != (byte) ' ') {
285-
// no space after file mode
286-
reader.OnMimeComplianceViolation (MimeComplianceViolation.InvalidUUEncodeFileMode, streamOffset, lineNumber);
288+
// scan ahead for the space after the file mode
289+
while (inptr < inend && *inptr != (byte) ' ') {
290+
if (!invalidFileMode) {
291+
// invalid character in file mode
292+
reader.OnMimeComplianceViolation (MimeComplianceViolation.InvalidUUEncodeFileMode, streamOffset, lineNumber);
293+
invalidFileMode = true;
294+
}
295+
296+
if (*inptr == (byte) '\n')
297+
break;
298+
299+
streamOffset++;
300+
inptr++;
287301
}
288302

303+
if (inptr == inend)
304+
break;
305+
289306
if (*inptr != (byte) '\n') {
290307
streamOffset++;
291308
inptr++;
@@ -314,6 +331,7 @@ unsafe bool ScanBeginMarker (ref byte* inptr, byte* inend)
314331
SkipByte (ref inptr);
315332

316333
state = UUValidatorState.Payload;
334+
eoln = true;
317335
nsaved = 0;
318336

319337
return true;
@@ -329,7 +347,6 @@ unsafe bool ScanBeginMarker (ref byte* inptr, byte* inend)
329347
[MethodImpl (MethodImplOptions.AggressiveInlining)]
330348
unsafe void Validate (byte* input, int length)
331349
{
332-
bool last_was_eoln = uulen == 0;
333350
byte* inend = input + length;
334351
byte* inptr = input;
335352

@@ -339,58 +356,61 @@ unsafe void Validate (byte* input, int length)
339356
return;
340357
}
341358

342-
while (inptr < inend) {
343-
if (*inptr == (byte) '\r') {
344-
SkipByte (ref inptr);
345-
continue;
346-
}
359+
if (state == UUValidatorState.Payload) {
360+
while (inptr < inend) {
361+
if (*inptr == (byte) '\r') {
362+
SkipByte (ref inptr);
363+
continue;
364+
}
347365

348-
if (*inptr == (byte) '\n') {
349-
if (uulen > 0) {
350-
// incomplete line
351-
reader.OnMimeComplianceViolation (MimeComplianceViolation.InvalidUUEncodedLineLength, streamOffset, lineNumber);
366+
if (*inptr == (byte) '\n') {
367+
if (uulen > 0) {
368+
// incomplete line
369+
reader.OnMimeComplianceViolation (MimeComplianceViolation.InvalidUUEncodedLineLength, streamOffset, lineNumber);
370+
}
371+
372+
SkipByte (ref inptr);
373+
eoln = true;
374+
continue;
352375
}
353376

354-
last_was_eoln = true;
355-
SkipByte (ref inptr);
356-
continue;
357-
}
377+
if (eoln) {
378+
// first octet on a line is the uulen octet
379+
uulen = UUDecoder.uudecode_rank[*inptr];
380+
eoln = false;
381+
382+
if (uulen == 0) {
383+
state = UUValidatorState.Ended;
384+
SkipByte (ref inptr);
385+
break;
386+
}
358387

359-
if (last_was_eoln) {
360-
// first octet on a line is the uulen octet
361-
uulen = UUDecoder.uudecode_rank[*inptr];
362-
last_was_eoln = false;
363-
if (uulen == 0) {
364-
state = UUValidatorState.Ended;
365388
SkipByte (ref inptr);
366-
break;
389+
continue;
367390
}
368391

369-
SkipByte (ref inptr);
370-
continue;
371-
}
392+
byte c = ReadByte (ref inptr);
372393

373-
byte c = ReadByte (ref inptr);
394+
if (uulen > 0) {
395+
nsaved++;
374396

375-
if (uulen > 0) {
376-
nsaved++;
397+
if (nsaved == 4) {
398+
if (uulen >= 3) {
399+
uulen -= 3;
400+
} else {
401+
if (uulen >= 1)
402+
uulen--;
377403

378-
if (nsaved == 4) {
379-
if (uulen >= 3) {
380-
uulen -= 3;
381-
} else {
382-
if (uulen >= 1)
383-
uulen--;
404+
if (uulen >= 1)
405+
uulen--;
406+
}
384407

385-
if (uulen >= 1)
386-
uulen--;
408+
nsaved = 0;
387409
}
388-
389-
nsaved = 0;
410+
} else {
411+
// extra data beyond the end of the uuencoded line
412+
reader.OnMimeComplianceViolation (MimeComplianceViolation.InvalidUUEncodedLineLength, streamOffset - 1, lineNumber);
390413
}
391-
} else {
392-
// extra data beyond the end of the uuencoded line
393-
reader.OnMimeComplianceViolation (MimeComplianceViolation.InvalidUUEncodedLineLength, streamOffset - 1, lineNumber);
394414
}
395415
}
396416
}

0 commit comments

Comments
 (0)