Fix an assert that happens on malformed XML (#21)
Add two tests that are hitting the assert. Names starting with a colon are valid according to the spec, but the spec also recommends that they only be used for namespaces. To allow proper error recovery we simplify and do not accept colons in names.
This commit is contained in:
Родитель
5d483b5143
Коммит
f112aae3b9
|
@ -59,6 +59,15 @@ namespace MonoDevelop.Xml.Parser
|
|||
|
||||
public static bool IsFirstNameChar (int ch)
|
||||
{
|
||||
// Names starting with a colon are valid according to the spec,
|
||||
// but the spec also recommends that they only be used for namespaces.
|
||||
// To allow proper error recovery we simplify and do not accept
|
||||
// colons in names.
|
||||
// https://www.w3.org/TR/xml/#NT-NameStartChar
|
||||
if (ch == ':') {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z')) {
|
||||
return true;
|
||||
} else if ((uint) ch <= 0xFFFF) {
|
||||
|
@ -134,6 +143,15 @@ namespace MonoDevelop.Xml.Parser
|
|||
|
||||
public static bool IsNameChar (int ch)
|
||||
{
|
||||
// Names starting with a colon are valid according to the spec,
|
||||
// but the spec also recommends that they only be used for namespaces.
|
||||
// To allow proper error recovery we simplify and do not accept
|
||||
// colons in names.
|
||||
// https://www.w3.org/TR/xml/#NT-NameStartChar
|
||||
if (ch == ':') {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z')) {
|
||||
return true;
|
||||
} else if ((uint) ch <= 0xFFFF) {
|
||||
|
|
|
@ -34,22 +34,17 @@ namespace MonoDevelop.Xml.Parser
|
|||
{
|
||||
public class XmlNameState : XmlParserState
|
||||
{
|
||||
internal static bool IsValidNameStart (char c)
|
||||
{
|
||||
return char.IsLetter (c) || c == '_';
|
||||
}
|
||||
|
||||
public override XmlParserState PushChar (char c, XmlParserContext context, ref string rollback)
|
||||
{
|
||||
var namedObject = context.Nodes.Peek () as INamedXObject;
|
||||
if (namedObject == null || namedObject.Name.Prefix != null)
|
||||
throw new InvalidOperationException ("Invalid state");
|
||||
|
||||
Debug.Assert (context.CurrentStateLength > 0 || IsValidNameStart (c),
|
||||
Debug.Assert (context.CurrentStateLength > 0 || XmlChar.IsFirstNameChar (c),
|
||||
"First character pushed to a XmlTagNameState must be a letter.");
|
||||
Debug.Assert (context.CurrentStateLength > 0 || context.KeywordBuilder.Length == 0,
|
||||
"Keyword builder must be empty when state begins.");
|
||||
|
||||
|
||||
if (XmlChar.IsWhitespace (c) || c == '<' || c == '>' || c == '/' || c == '=') {
|
||||
rollback = string.Empty;
|
||||
if (context.KeywordBuilder.Length == 0) {
|
||||
|
|
|
@ -435,5 +435,23 @@ namespace MonoDevelop.Xml.Tests.Parser
|
|||
Assert.AreEqual (0, processingInstruction.Span.Start);
|
||||
Assert.AreEqual (5, processingInstruction.Span.Length);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void NameStartsWithWhitespaceAndColon ()
|
||||
{
|
||||
var docTxt = "< :";
|
||||
var parser = new XmlTreeParser (CreateRootState ());
|
||||
parser.Parse (docTxt);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void MismatchedElementNameWithWhitespaceInName2 ()
|
||||
{
|
||||
var docTxt = "<X><n\n:a></a><b></X>";
|
||||
var parser = new XmlTreeParser (CreateRootState ());
|
||||
parser.Parse (docTxt);
|
||||
parser.AssertEmpty ();
|
||||
parser.AssertErrorCount (4);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче