@@ -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