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

Spring fails to determine that XML is DTD-based if DTD declaration is followed by a comment #23605

Closed
kangjianwei opened this issue Sep 7, 2019 · 7 comments
Assignees
Labels
in: core Issues in core modules (aop, beans, core, context, expression) type: bug A general bug
Milestone

Comments

@kangjianwei
Copy link

kangjianwei commented Sep 7, 2019

Version

Tested on spring 5.1.9.RELEASE.

Repro

  1. First create a simple configuration file: spring-config.xml (note that there is a comment at the end of the DOCTYPE line)
<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN 2.0//EN" "https://www.springframework.org/dtd/spring-beans-2.0.dtd"><!--BUG-->

<beans>
</beans>
  1. Load this configuration file
    ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");

  2. An exception has occurred

Exception in thread "main" org.springframework.beans.factory.xml.XmlBeanDefinitionStoreException: Line 5 in XML document from class path resource [spring-config.xml] is invalid; nested exception is org.xml.sax.SAXParseException; lineNumber: 5; columnNumber: 8; cvc-elt.1.a: 找不到元素 'beans' 的声明。
	at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.doLoadBeanDefinitions(XmlBeanDefinitionReader.java:404)
	at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.loadBeanDefinitions(XmlBeanDefinitionReader.java:336)
	at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.loadBeanDefinitions(XmlBeanDefinitionReader.java:304)
	at org.springframework.beans.factory.support.AbstractBeanDefinitionReader.loadBeanDefinitions(AbstractBeanDefinitionReader.java:188)
	at org.springframework.beans.factory.support.AbstractBeanDefinitionReader.loadBeanDefinitions(AbstractBeanDefinitionReader.java:224)
	at org.springframework.beans.factory.support.AbstractBeanDefinitionReader.loadBeanDefinitions(AbstractBeanDefinitionReader.java:195)
	at org.springframework.beans.factory.support.AbstractBeanDefinitionReader.loadBeanDefinitions(AbstractBeanDefinitionReader.java:257)
	at org.springframework.context.support.AbstractXmlApplicationContext.loadBeanDefinitions(AbstractXmlApplicationContext.java:128)
	at org.springframework.context.support.AbstractXmlApplicationContext.loadBeanDefinitions(AbstractXmlApplicationContext.java:94)
	at org.springframework.context.support.AbstractRefreshableApplicationContext.refreshBeanFactory(AbstractRefreshableApplicationContext.java:133)
	at org.springframework.context.support.AbstractApplicationContext.obtainFreshBeanFactory(AbstractApplicationContext.java:636)
	at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:521)
	at org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:144)
	at org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:85)
	at com.kang.Test.main(Test.java:8)
Caused by: org.xml.sax.SAXParseException; lineNumber: 5; columnNumber: 8; cvc-elt.1.a: 找不到元素 'beans' 的声明。
	at java.xml/com.sun.org.apache.xerces.internal.util.ErrorHandlerWrapper.createSAXParseException(ErrorHandlerWrapper.java:204)
	at java.xml/com.sun.org.apache.xerces.internal.util.ErrorHandlerWrapper.error(ErrorHandlerWrapper.java:135)
	at java.xml/com.sun.org.apache.xerces.internal.impl.XMLErrorReporter.reportError(XMLErrorReporter.java:395)
	at java.xml/com.sun.org.apache.xerces.internal.impl.XMLErrorReporter.reportError(XMLErrorReporter.java:326)
	at java.xml/com.sun.org.apache.xerces.internal.impl.XMLErrorReporter.reportError(XMLErrorReporter.java:283)
	at java.xml/com.sun.org.apache.xerces.internal.impl.xs.XMLSchemaValidator.handleStartElement(XMLSchemaValidator.java:2131)
	at java.xml/com.sun.org.apache.xerces.internal.impl.xs.XMLSchemaValidator.startElement(XMLSchemaValidator.java:828)
	at java.xml/com.sun.org.apache.xerces.internal.impl.dtd.XMLDTDValidator.startElement(XMLDTDValidator.java:746)
	at java.xml/com.sun.org.apache.xerces.internal.impl.XMLNSDocumentScannerImpl.scanStartElement(XMLNSDocumentScannerImpl.java:374)
	at java.xml/com.sun.org.apache.xerces.internal.impl.XMLNSDocumentScannerImpl$NSContentDriver.scanRootElementHook(XMLNSDocumentScannerImpl.java:613)
	at java.xml/com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl$FragmentContentDriver.next(XMLDocumentFragmentScannerImpl.java:3058)
	at java.xml/com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl$PrologDriver.next(XMLDocumentScannerImpl.java:820)
	at java.xml/com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl.next(XMLDocumentScannerImpl.java:601)
	at java.xml/com.sun.org.apache.xerces.internal.impl.XMLNSDocumentScannerImpl.next(XMLNSDocumentScannerImpl.java:112)
	at java.xml/com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanDocument(XMLDocumentFragmentScannerImpl.java:531)
	at java.xml/com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:887)
	at java.xml/com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:823)
	at java.xml/com.sun.org.apache.xerces.internal.parsers.XMLParser.parse(XMLParser.java:141)
	at java.xml/com.sun.org.apache.xerces.internal.parsers.DOMParser.parse(DOMParser.java:243)
	at java.xml/com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderImpl.parse(DocumentBuilderImpl.java:339)
	at org.springframework.beans.factory.xml.DefaultDocumentLoader.loadDocument(DefaultDocumentLoader.java:77)
	at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.doLoadDocument(XmlBeanDefinitionReader.java:434)
	at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.doLoadBeanDefinitions(XmlBeanDefinitionReader.java:392)
	... 14 more
  1. If you remove the comment at the last position in the DOCTYPE line, then everything works fine...

Analysis

The cause of the exception is to incorrectly parse the validation mode of the XML document.

The code that causes the bug is in the consumeCommentTokens(String) method of the org.springframework.util.xml.XmlValidationModeDetector.

This method not only consumes the comment itself, but also consumes the content before the comment.

Suppose a line in the xml file has the following code:
aaa<!--BUG-->bbb
After this content is processed by this method, only the "bbb" string will be returned.
In other words, the effective information "aaa" is lost.

This is why the xml validation type cannot be parsed correctly after adding a comment after the DOCTYPE line.

@spring-projects-issues spring-projects-issues added the status: waiting-for-triage An issue we've not yet triaged or decided on label Sep 7, 2019
@qw81641493
Copy link

兄弟,你用的spring5.1.9,配置文件用的2.x版本的 那有啥用啊

@kangjianwei
Copy link
Author

兄弟,你用的spring5.1.9,配置文件用的2.x版本的 那有啥用啊

这个bug跟使用哪个版本的xml配置文件无关。不过,这确实是一个很小的bug,几乎不会影响到正常使用...

@qw81641493
Copy link

兄弟,你用的spring5.1.9,配置文件用的2.x版本的那有啥用啊

这个错误跟使用哪个版本的XML配置文件无关。不过,这确实是一个很小的错误,几乎不会影响到正常使用...

我刚刚又测试了一下,发现如果
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN 2.0//EN" "https://www.springframework.org/dtd/spring-beans-2.0.dtd"><!--BUG-->
写在一行的话,就会出现这个BUG,但是如果加入一个换行的话,就不会出现BUG,如:
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN 2.0//EN"
"https://www.springframework.org/dtd/spring-beans-2.0.dtd"><!--BUG-->
您可以测试一下

@kangjianwei
Copy link
Author

这个我知道,因为它在猜测验证模式时,是先去掉注释以及注释之前的部分,然后在剩下的部分里查看是否有DOCTYPE标记。加入换行后,在第一行就可以检测出DOCTYPE标记了,所以没问题。

@sbrannen
Copy link
Member

sbrannen commented Sep 8, 2019

@kangjianwei, thanks for raising the issue.

@kangjianwei and @qw81641493, it would be very helpful to the Spring maintainers reading this issue if you would translate your discussion into English.

@sbrannen sbrannen added in: core Issues in core modules (aop, beans, core, context, expression) type: bug A general bug and removed status: waiting-for-triage An issue we've not yet triaged or decided on labels Sep 8, 2019
@sbrannen
Copy link
Member

sbrannen commented Sep 8, 2019

I have confirmed that this is a bug.

Appending <!-- BUG --> to the DTD declaration in spring-beans/src/test/resources/org/springframework/beans/factory/xml/test.xml causes various tests in XmlBeanDefinitionReaderTests to fail.

@sbrannen sbrannen changed the title Spring's xml configuration file has an exception during the loading process. Spring fails to determine that XML is DTD-based if DTD declaration is followed by a comment Sep 8, 2019
@sbrannen sbrannen self-assigned this Sep 9, 2019
@sbrannen sbrannen added this to the 5.1.10 milestone Sep 9, 2019
@sbrannen
Copy link
Member

sbrannen commented Sep 9, 2019

The fix for this will be available in 5.1.10 and 5.2.0.

Feel free to try it out in upcoming snapshot builds for 5.1.10 and 5.2.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
in: core Issues in core modules (aop, beans, core, context, expression) type: bug A general bug
Projects
None yet
Development

No branches or pull requests

4 participants