Bug 32696 - Android XML Resource reader tries to read extra attributes
Summary: Android XML Resource reader tries to read extra attributes
Status: RESOLVED FIXED
Alias: None
Product: Android
Classification: Xamarin
Component: Bindings ()
Version: 5.1
Hardware: PC Windows
: --- normal
Target Milestone: 6.0 (C6)
Assignee: Atsushi Eno
URL:
Depends on:
Blocks:
 
Reported: 2015-08-02 17:08 UTC by Matthew Leibowitz
Modified: 2015-11-13 16:23 UTC (History)
2 users (show)

Tags:
Is this bug a regression?: ---
Last known good build:


Attachments
The sample app that shows what is happening (30.17 KB, application/x-zip-compressed)
2015-08-02 17:08 UTC, Matthew Leibowitz
Details


Notice (2018-05-24): bugzilla.xamarin.com is now in read-only mode.

Please join us on Visual Studio Developer Community and in the Xamarin and Mono organizations on GitHub to continue tracking issues. Bugzilla will remain available for reference in read-only mode. We will continue to work on open Bugzilla bugs, copy them to the new locations as needed for follow-up, and add the new items under Related Links.

Our sincere thanks to everyone who has contributed on this bug tracker over the years. Thanks also for your understanding as we make these adjustments and improvements for the future.


Please create a new report on Developer Community or GitHub with your current version information, steps to reproduce, and relevant error messages or log files if you are hitting an issue that looks similar to this resolved bug and you do not yet see a matching new report.

Related Links:
Status:
RESOLVED FIXED

Description Matthew Leibowitz 2015-08-02 17:08:35 UTC
Created attachment 12333 [details]
The sample app that shows what is happening

When reading a resource from the xml resources, the reader does not correctly read the attributes.

Given the XML saved to /Resources/xml/Simple.xml:

  <?xml version="1.0" encoding="UTF-8" ?>
  <RootElement attribute="attribute value"></RootElement>

We get an 'XmlPullParserException' exception when we parse it:

  var reader = Resources.GetXml (Resource.Xml.Simple);
  var xdoc = new XmlDocument ();
  xdoc.Load (reader);

Although not directly related to the issue, as it is trying to perform an operation that is not supported, the real issue is the fact that we are reading more attributes than there actually are.

What I did to detect this (I can do this as there is only 1 attribute), is to wrap the reader (see the sample) and count the attributes read:

  public override bool MoveToFirstAttribute()
  {
    var result = source.MoveToFirstAttribute();
    if (result)
    {
      attribute = 0; // reset
      Console.WriteLine("There are {0} attributes.", AttributeCount);
      Console.WriteLine("We moved to attribute {0} (first) now.", attribute);
    }
    return result;
  }
  
  private int attribute = -1;
  public override bool MoveToNextAttribute()
  {
    var result = source.MoveToNextAttribute();
    if (result)
    {
      attribute++; // move on
      Console.WriteLine("We moved to attribute {0} now.", attribute);

      if (attribute + 1 > AttributeCount) {
        // we have read an extra attribute than there is, and we are still returning true
        Console.WriteLine("We are now reading the future, so undo...");
        return false;
      }
    }
    return result;
  }

To have a look around, I checked out the source for MoveToNextAttribute():

  public override bool MoveToNextAttribute()
  {
    if (this.attr_pos + 1 >= this.source.AttributeCount && 
        this.attr_pos - this.source.AttributeCount >= this.ns_count)
    {
      return false;
    }
    this.attr_pos++;
    this.attr_value = false;
    return true;
  }

When debugging, and just before the method executes (this is correct):
  attr_pos = 0 
  AttributeCount = 1
  ns_count = 0

The error seems to be in the logic. The first bit of the if statement:
  (this.attr_pos + 1 >= this.source.AttributeCount)
evaluates correctly, but the second bit:
  (this.attr_pos - this.source.AttributeCount >= this.ns_count)
does not. Substitution of the values on the second bit:
  (0 - 1 >= 0) == (-1 >= 0) == (false)
This will always evaluate to false, thus only after trying to read the one extra attribute than there really are, will the reader move to the next element.

The output from the sample app:

  There are 1 attributes.
  We moved to attribute 0 (first) now.
  We moved to attribute 1 now.
  We are now reading the future, so undo...
Comment 1 Atsushi Eno 2015-08-07 04:06:38 UTC
Thanks for the in-depth analysis of the issue. It is now fixed in our code base and will be included in the next major release.

[monodroid master c236d22]