Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

XmlNodeReader MoveToAttribute bug, leaves XmlReader in inconsistent state #34443

Open
Tracked by #64602
weltkante opened this issue Apr 2, 2020 · 1 comment
Open
Tracked by #64602

Comments

@weltkante
Copy link
Contributor

weltkante commented Apr 2, 2020

When using XmlNodeReader.MoveToAttribute returns false it leaves the XmlReader in an inconsistent state which can lead to follow-up exceptions.

Use-case: we are calling some deserialization API not owned by us which only accepts XmlReader. We already have an in-memory XmlDocument and need to call the deserialization method on a lot of nodes, so we want to use XmlNodeReader instead of doing an unnecessary format/parse roundtrip through an intermediate string for every node we have to deserialize.

In some cases the code calls MoveToAttribute to detect whether an optional attribute is present. This part works, but when it then subsequently calls ReadStartElement this leads to an exception. See attached example which reduces the call sequence to present the problem.

The error happens on both Desktop Framework and .NET Core.

using System;
using System.IO;
using System.Xml;

class Program
{
    static void Main(string[] args)
    {
        var doc = new XmlDocument();
        doc.LoadXml("<root><child attr1='value1'><other /></child></root>");

        Console.WriteLine("Testing XmlReader.Create");
        using (var rd = XmlReader.Create(new StringReader(doc.DocumentElement.FirstChild.OuterXml)))
            RunTest(rd);
        Console.WriteLine();

        Console.WriteLine("Testing XmlTextReader");
        using (var rd = new XmlTextReader(new StringReader(doc.DocumentElement.FirstChild.OuterXml)))
            RunTest(rd);
        Console.WriteLine();

        Console.WriteLine("Testing XmlNodeReader");
        using (var rd = new XmlNodeReader(doc.DocumentElement.FirstChild))
            RunTest(rd);
        Console.WriteLine();
    }

    static void RunTest(XmlReader rd)
    {
        Console.WriteLine($"  reader state: {rd.NodeType} {rd.Name}");
        Console.WriteLine($"IsStartElement(child) = {rd.IsStartElement("child")}");
        Console.WriteLine($"  reader state: {rd.NodeType} {rd.Name}");
        Console.WriteLine($"MoveToAttribute(attr1) = {rd.MoveToAttribute("attr1")}");
        Console.WriteLine($"  reader state: {rd.NodeType} {rd.Name}");
        Console.WriteLine($"MoveToAttribute(attr2) = {rd.MoveToAttribute("attr2")}");
        Console.WriteLine($"  reader state: {rd.NodeType} {rd.Name}");
        try
        {
            rd.ReadStartElement("child");
            Console.WriteLine($"ReadStartElement succeeded");
        }
        catch (Exception ex)
        {
            Console.WriteLine($"ReadStartElement failed: {ex.Message}");
        }
    }
}
Testing XmlReader.Create
  reader state: None
IsStartElement(child) = True
  reader state: Element child
MoveToAttribute(attr1) = True
  reader state: Attribute attr1
MoveToAttribute(attr2) = False
  reader state: Attribute attr1
ReadStartElement succeeded

Testing XmlTextReader
  reader state: None
IsStartElement(child) = True
  reader state: Element child
MoveToAttribute(attr1) = True
  reader state: Attribute attr1
MoveToAttribute(attr2) = False
  reader state: Attribute attr1
ReadStartElement succeeded

Testing XmlNodeReader
  reader state: None
IsStartElement(child) = True
  reader state: Element child
MoveToAttribute(attr1) = True
  reader state: Attribute attr1
MoveToAttribute(attr2) = False
  reader state: Element attr1
ReadStartElement failed: Element 'child' was not found.
@Dotnet-GitSync-Bot
Copy link
Collaborator

I couldn't figure out the best area label to add to this issue. Please help me learn by adding exactly one area label.

@Dotnet-GitSync-Bot Dotnet-GitSync-Bot added the untriaged New issue has not been triaged by the area owner label Apr 2, 2020
@buyaa-n buyaa-n added this to the 6.0.0 milestone Jul 7, 2020
@buyaa-n buyaa-n added bug and removed untriaged New issue has not been triaged by the area owner labels Jul 7, 2020
@krwq krwq modified the milestones: 6.0.0, 7.0.0 Jul 19, 2021
Maximys added a commit to Maximys/runtime that referenced this issue Oct 18, 2021
@jeffhandley jeffhandley modified the milestones: 7.0.0, Future Jul 9, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
No open projects
Development

Successfully merging a pull request may close this issue.

6 participants