6

以下代码

XmlDocument xdoc = new XmlDocument();
            String xml = @"<!DOCTYPE lolz [" +
                    "<!ENTITY lol \"lol\">" +
                    "<!ENTITY lol2 \"&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;\">" +
                    "<!ENTITY lol3 \"&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;\">" +
                    "<!ENTITY lol4 \"&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;\">" +
                    "<!ENTITY lol5 \"&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;\">" +
                    "<!ENTITY lol6 \"&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;\">" +
                    "<!ENTITY lol7 \"&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;\">" +
                    "<!ENTITY lol8 \"&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;\">" +
                    "<!ENTITY lol9 \"&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;\">" +
                    "]>" +
                    "<lolz>&lol9;</lolz>";
            xdoc.LoadXml(xml);

.Net 4.0 此代码将抛出异常 输入文档已超出MaxCharactersFromEntities设置的限制

.Net 2.0/3.5 此代码不会抛出任何异常,并且会在 XML 中继续增长,直到达到内存限制

有人可以解释这种差异的原因吗?

到目前为止所做的研究 我反汇编了 System.Xml v2.0 和 v4.0,我看到的唯一变化是方法RegisterConsumedCharacters v2.0 定义

private void RegisterConsumedCharacters(long characters, bool inEntityReference)
{
    if (this.maxCharactersInDocument > 0L)
    {
        long num = this.charactersInDocument + characters;
        if (num < this.charactersInDocument)
        {
            this.ThrowWithoutLineInfo("XmlSerializeErrorDetails", new string[] { "MaxCharactersInDocument", "" });
        }
        else
        {
            this.charactersInDocument = num;
        }
        if (this.charactersInDocument > this.maxCharactersInDocument)
        {
            this.ThrowWithoutLineInfo("XmlSerializeErrorDetails", new string[] { "MaxCharactersInDocument", "" });
        }
    }
    if ((this.maxCharactersFromEntities > 0L) && inEntityReference)
    {
        long num2 = this.charactersFromEntities + characters;
        if (num2 < this.charactersFromEntities)
        {
            this.ThrowWithoutLineInfo("XmlSerializeErrorDetails", new string[] { "MaxCharactersFromEntities", "" });
        }
        else
        {
            this.charactersFromEntities = num2;
        }
        if ((this.charactersFromEntities > this.maxCharactersFromEntities) && XmlTextReaderSection.LimitCharactersFromEntities)
        {
            this.ThrowWithoutLineInfo("XmlSerializeErrorDetails", new string[] { "MaxCharactersFromEntities", "" });
        }
    }
}

v4.0定义

private void RegisterConsumedCharacters(long characters, bool inEntityReference)
{
    if (this.maxCharactersInDocument > 0L)
    {
        long num = this.charactersInDocument + characters;
        if (num < this.charactersInDocument)
        {
            this.ThrowWithoutLineInfo("Xml_LimitExceeded", "MaxCharactersInDocument");
        }
        else
        {
            this.charactersInDocument = num;
        }
        if (this.charactersInDocument > this.maxCharactersInDocument)
        {
            this.ThrowWithoutLineInfo("Xml_LimitExceeded", "MaxCharactersInDocument");
        }
    }
    if ((this.maxCharactersFromEntities > 0L) && inEntityReference)
    {
        long num2 = this.charactersFromEntities + characters;
        if (num2 < this.charactersFromEntities)
        {
            this.ThrowWithoutLineInfo("Xml_LimitExceeded", "MaxCharactersFromEntities");
        }
        else
        {
            this.charactersFromEntities = num2;
        }
        if (this.charactersFromEntities > this.maxCharactersFromEntities)
        {
            this.ThrowWithoutLineInfo("Xml_LimitExceeded", "MaxCharactersFromEntities");
        }
    }
}

我在这里看到的唯一区别是 ThrowWithoutLineInfo 参数的更改和 v4.0 中 XmlTextReaderSection.LimitCharactersFromEntities 的删除,但我无法从中获得太多收益并且在这里遇到了障碍。

4

2 回答 2

3

如 MSDN 文档所述,默认值为XmlReaderSettings.MaxCharactersFromEntities0,表示“无限制”。

但是文档中没有指出一个讨厌的技巧,在 .net 4 中,如果您没有将 a 传递XmlReaderSettings给您XmlTextReader,那么限制不是设置为 0,而是设置为 10,000,000。

相关的源代码在这里,即使有评论指出这是一个重大变化https ://referencesource.microsoft.com/#System.Xml/System/Xml/Core/XmlTextReaderImpl.cs,385

于 2014-04-24T23:10:03.670 回答
1

所以,你找到了罪魁祸首。在 v2.0 中,XmlTextReaderSection.LimitCharactersFromEntities返回false所以不抛出异常。在 v4.0XmlTextReaderSection.LimitCharactersFromEntities中,条件检查中省略了,因此它会引发异常。

问题是做XmlTextReaderSection.LimitCharactersFromEntities什么以及为什么会返回false?当我们反汇编它时,我们看到它做了以下事情:

    internal string LimitCharactersFromEntitiesString
    {
        get
        {
            return (string)base["limitCharactersFromEntities"];
        }
        set
        {
            base["limitCharactersFromEntities"] = value;
        }
    }

    private bool _LimitCharactersFromEntities
    {
        get
        {
            string limitCharactersFromEntitiesString = this.LimitCharactersFromEntitiesString;
            bool result = true;
            XmlConvert.TryToBoolean(limitCharactersFromEntitiesString, out result);
            return result;
        }
    }
    internal static bool LimitCharactersFromEntities
    {
        get
        {
            XmlTextReaderSection xmlTextReaderSection = ConfigurationManager.GetSection(XmlConfigurationString.XmlTextReaderSectionPath) as XmlTextReaderSection;
            return xmlTextReaderSection == null || xmlTextReaderSection._LimitCharactersFromEntities;
        }
    }

所以internal static bool 函数调用private bool一个。private bool来电internal string。它的作用是internal string尝试"limitCharactersFromEntities"ConfigurationSection父类获取字典条目。它可能返回 null,因此不能强制转换为bool(检查XmlConvert.TryToBoolean源)并最终XmlTextReaderSection.LimitCharactersFromEntities返回 false。

我进一步检查了源代码,但我找不到LimitCharactersFromEntities在 v2.0 中初始化配置属性的方式或位置(我无法检查整个 .NET,所以我所做的是CTRL + F搜索该字符串)。但是我已经看到LimitCharactersFromEntities在 v4.0 中完全省略了它,并且它不作为配置属性名称之一存在于XmlConfiguration.cs.

所以我想我们可以得出结论,在 v2.0 中,这是一个错误。

注意:我完全不知道 XmlDocument 和 System.Xml 命名空间。我刚刚尝试在阅读源代码时做出一些有根据的猜测。

于 2014-04-19T17:58:10.973 回答