Skip to content

Commit 7e54bff

Browse files
belinguereshboutemy
authored andcommitted
#35 Solved infinite loop when parsing malformed Processing Instruction
1 parent 1dafbae commit 7e54bff

File tree

2 files changed

+152
-1
lines changed

2 files changed

+152
-1
lines changed

src/main/java/org/codehaus/plexus/util/xml/pull/MXParser.java

+20-1
Original file line numberDiff line numberDiff line change
@@ -3017,6 +3017,7 @@ protected boolean parsePI()
30173017

30183018
try
30193019
{
3020+
boolean seenPITarget = false;
30203021
boolean seenQ = false;
30213022
char ch = more();
30223023
if ( isS( ch ) )
@@ -3031,6 +3032,11 @@ protected boolean parsePI()
30313032

30323033
if ( ch == '?' )
30333034
{
3035+
if ( !seenPITarget )
3036+
{
3037+
throw new XmlPullParserException( "processing instruction PITarget name not found", this,
3038+
null );
3039+
}
30343040
seenQ = true;
30353041
}
30363042
else if ( ch == '>' )
@@ -3039,7 +3045,18 @@ else if ( ch == '>' )
30393045
{
30403046
break; // found end sequence!!!!
30413047
}
3042-
seenQ = false;
3048+
3049+
if ( !seenPITarget )
3050+
{
3051+
throw new XmlPullParserException( "processing instruction PITarget name not found", this,
3052+
null );
3053+
}
3054+
else
3055+
{
3056+
// seenPITarget && !seenQ
3057+
throw new XmlPullParserException( "processing instruction started on line " + curLine
3058+
+ " and column " + curColumn + " was not closed", this, null );
3059+
}
30433060
}
30443061
else
30453062
{
@@ -3078,6 +3095,7 @@ else if ( ch == '>' )
30783095
}
30793096
}
30803097
}
3098+
30813099
seenQ = false;
30823100
}
30833101
if ( normalizeIgnorableWS )
@@ -3127,6 +3145,7 @@ else if ( ch == '\n' )
31273145
normalizedCR = false;
31283146
}
31293147
}
3148+
seenPITarget = true;
31303149
ch = more();
31313150
}
31323151
}

src/test/java/org/codehaus/plexus/util/xml/pull/MXParserTest.java

+132
Original file line numberDiff line numberDiff line change
@@ -364,4 +364,136 @@ public void testSubsequentProcessingInstructionMoreThan8k()
364364
assertEquals( XmlPullParser.PROCESSING_INSTRUCTION, parser.nextToken() );
365365
assertEquals( XmlPullParser.END_TAG, parser.nextToken() );
366366
}
367+
368+
public void testMalformedProcessingInstructionAfterTag()
369+
throws Exception
370+
{
371+
MXParser parser = new MXParser();
372+
373+
String input = "<project /><?>";
374+
375+
parser.setInput( new StringReader( input ) );
376+
377+
try
378+
{
379+
assertEquals( XmlPullParser.START_TAG, parser.next() );
380+
381+
assertEquals( XmlPullParser.END_TAG, parser.next() );
382+
383+
assertEquals( XmlPullParser.PROCESSING_INSTRUCTION, parser.next() );
384+
385+
fail( "Should fail since it has an invalid Processing Instruction" );
386+
}
387+
catch ( XmlPullParserException ex )
388+
{
389+
assertTrue( ex.getMessage().contains( "processing instruction PITarget name not found" ) );
390+
}
391+
}
392+
393+
public void testMalformedProcessingInstructionBeforeTag()
394+
throws Exception
395+
{
396+
MXParser parser = new MXParser();
397+
398+
String input = "<?><project />";
399+
400+
parser.setInput( new StringReader( input ) );
401+
402+
try
403+
{
404+
assertEquals( XmlPullParser.PROCESSING_INSTRUCTION, parser.next() );
405+
406+
assertEquals( XmlPullParser.START_TAG, parser.next() );
407+
408+
assertEquals( XmlPullParser.END_TAG, parser.next() );
409+
410+
fail( "Should fail since it has invalid PI" );
411+
}
412+
catch ( XmlPullParserException ex )
413+
{
414+
assertTrue( ex.getMessage().contains( "processing instruction PITarget name not found" ) );
415+
}
416+
}
417+
418+
public void testMalformedProcessingInstructionSpaceBeforeName()
419+
throws Exception
420+
{
421+
MXParser parser = new MXParser();
422+
423+
StringBuilder sb = new StringBuilder();
424+
sb.append( "<? shouldhavenospace>" );
425+
sb.append( "<project />" );
426+
427+
parser.setInput( new StringReader( sb.toString() ) );
428+
429+
try
430+
{
431+
assertEquals( XmlPullParser.PROCESSING_INSTRUCTION, parser.next() );
432+
433+
assertEquals( XmlPullParser.START_TAG, parser.next() );
434+
435+
assertEquals( XmlPullParser.END_TAG, parser.next() );
436+
437+
fail( "Should fail since it has invalid PI" );
438+
}
439+
catch ( XmlPullParserException ex )
440+
{
441+
assertTrue( ex.getMessage().contains( "processing instruction PITarget must be exactly after <? and not white space character" ) );
442+
}
443+
}
444+
445+
public void testMalformedProcessingInstructionNoClosingQuestionMark()
446+
throws Exception
447+
{
448+
MXParser parser = new MXParser();
449+
450+
StringBuilder sb = new StringBuilder();
451+
sb.append( "<?shouldhavenospace>" );
452+
sb.append( "<project />" );
453+
454+
parser.setInput( new StringReader( sb.toString() ) );
455+
456+
try
457+
{
458+
assertEquals( XmlPullParser.PROCESSING_INSTRUCTION, parser.next() );
459+
460+
assertEquals( XmlPullParser.START_TAG, parser.next() );
461+
462+
assertEquals( XmlPullParser.END_TAG, parser.next() );
463+
464+
fail( "Should fail since it has invalid PI" );
465+
}
466+
catch ( XmlPullParserException ex )
467+
{
468+
assertTrue( ex.getMessage().contains( "processing instruction started on line 1 and column 2 was not closed" ) );
469+
}
470+
}
471+
472+
public void testSubsequentMalformedProcessingInstructionNoClosingQuestionMark()
473+
throws Exception
474+
{
475+
MXParser parser = new MXParser();
476+
477+
StringBuilder sb = new StringBuilder();
478+
sb.append( "<project />" );
479+
sb.append( "<?shouldhavenospace>" );
480+
481+
parser.setInput( new StringReader( sb.toString() ) );
482+
483+
try
484+
{
485+
assertEquals( XmlPullParser.START_TAG, parser.next() );
486+
487+
assertEquals( XmlPullParser.END_TAG, parser.next() );
488+
489+
assertEquals( XmlPullParser.PROCESSING_INSTRUCTION, parser.next() );
490+
491+
fail( "Should fail since it has invalid PI" );
492+
}
493+
catch ( XmlPullParserException ex )
494+
{
495+
assertTrue( ex.getMessage().contains( "processing instruction started on line 1 and column 13 was not closed" ) );
496+
}
497+
}
498+
367499
}

0 commit comments

Comments
 (0)