Skip to content

Commit

Permalink
fix: dc:source element caused a NullPointerException
Browse files Browse the repository at this point in the history
The checks related to the HTML `source` element were run regardless of
the element namespace, and with lack of protective coding. This caused
an NPE when the markup contained `dc:source` elements.

This commit fixes the situation by:
- only applying `OPSHandler30` checks for the elements in the target
  namespace
- returning early when the `source` element preconditions aren't met,
  as these preconditions are checked by schema

Fix #1514
  • Loading branch information
rdeltour committed Jul 5, 2023
1 parent bd279f0 commit c15e4ea
Show file tree
Hide file tree
Showing 7 changed files with 178 additions and 93 deletions.
206 changes: 113 additions & 93 deletions src/main/java/com/adobe/epubcheck/ops/OPSHandler30.java
Expand Up @@ -334,109 +334,127 @@ public void startElement()
processSectioning();

String name = e.getName();
if (name.equals("html"))
{
vocabs = VocabUtil.parsePrefixDeclaration(
e.getAttributeNS(EpubConstants.EpubTypeNamespaceUri, "prefix"), RESERVED_VOCABS,
KNOWN_VOCAB_URIS, DEFAULT_VOCAB_URIS, report, location());
}
else if (EpubConstants.HtmlNamespaceUri.equals(e.getNamespace()) && name.equals("meta"))
{
processMeta();
}
else if (name.equals("form"))
{
requiredProperties.add(ITEM_PROPERTIES.SCRIPTED);
}
else if (name.equals("link"))
{
processLink();
}
else if (name.equals("math"))
if (EpubConstants.HtmlNamespaceUri.equals(e.getNamespace()))
{
requiredProperties.add(ITEM_PROPERTIES.MATHML);
inMathML = true;
hasAltorAnnotation = (null != e.getAttribute("alttext"));
String altimg = e.getAttribute("altimg");
if (altimg != null)
if (name.equals("html"))
{
vocabs = VocabUtil.parsePrefixDeclaration(
e.getAttributeNS(EpubConstants.EpubTypeNamespaceUri, "prefix"), RESERVED_VOCABS,
KNOWN_VOCAB_URIS, DEFAULT_VOCAB_URIS, report, location());
}
else if (name.equals("meta"))
{
processMeta();
}
else if (name.equals("form"))
{
super.checkImage(null, "altimg");
requiredProperties.add(ITEM_PROPERTIES.SCRIPTED);
}
else if (name.equals("link"))
{
processLink();
}

}
else if (name.equals("svg"))
{
processSVG();
}
else if (EpubConstants.EpubTypeNamespaceUri.equals(e.getNamespace()) && name.equals("switch"))
{
requiredProperties.add(ITEM_PROPERTIES.SWITCH);
}
else if (name.equals("audio"))
{
startMediaElement();
}
else if (name.equals("video"))
{
processVideo();
startMediaElement();
}
else if (name.equals("figure"))
{
processFigure();
}
else if (name.equals("table"))
{
processTable();
}
else if (name.equals("track"))
{
startTrack();
}
else if (name.equals("a"))
{
anchorNeedsText = true;
processAnchor(e);
}
else if (name.equals("annotation-xml"))
{
hasAltorAnnotation = true;
}
else if (name.equals("input"))
{
startInput();
}
else if (name.equals("picture"))
{
inPicture = true;
}
else if (name.equals("source"))
{
if ("picture".equals(e.getParent().getName()))
else if (name.equals("audio"))
{
checkImage(null, null);
startMediaElement();
}
else // audio or video source
else if (name.equals("video"))
{
startMediaSource();
processVideo();
startMediaElement();
}
else if (name.equals("figure"))
{
processFigure();
}
else if (name.equals("table"))
{
processTable();
}
else if (name.equals("track"))
{
startTrack();
}
else if (name.equals("a"))
{
anchorNeedsText = true;
processAnchor(e);
}
else if (name.equals("input"))
{
startInput();
}
else if (name.equals("picture"))
{
inPicture = true;
}
else if (name.equals("source"))
{
if ("picture".equals(e.getParent().getName()))
{
checkImage(null, null);
}
else // audio or video source
{
startMediaSource();
}
}
else if (name.equals("embed"))
{
startEmbed();
}
else if (name.equals("blockquote") || name.equals("q") || name.equals("ins")
|| name.equals("del"))
{
checkCiteAttribute();
}
}
else if ("http://www.w3.org/2000/svg".equals(e.getNamespace()) && name.equals("title"))
{
hasLabel = true;
}
else if ("http://www.w3.org/2000/svg".equals(e.getNamespace()) && name.equals("text"))
else if ("http://www.w3.org/1998/Math/MathML".equals(e.getNamespace()))
{
hasLabel = true;
if (name.equals("math"))
{
requiredProperties.add(ITEM_PROPERTIES.MATHML);
inMathML = true;
hasAltorAnnotation = (null != e.getAttribute("alttext"));
String altimg = e.getAttribute("altimg");
if (altimg != null)
{
super.checkImage(null, "altimg");
}

}
else if (name.equals("annotation-xml"))
{
hasAltorAnnotation = true;
}
}
else if (name.equals("embed"))
else if ("http://www.w3.org/2000/svg".equals(e.getNamespace()))
{
startEmbed();
if (name.equals("svg"))
{
processSVG();
}
else if (name.equals("a"))
{
anchorNeedsText = true;
processAnchor(e);
}
else if (name.equals("title"))
{
hasLabel = true;
}
else if (name.equals("text"))
{
hasLabel = true;
}
}
else if (name.equals("blockquote") || name.equals("q") || name.equals("ins")
|| name.equals("del"))
else if (EpubConstants.EpubTypeNamespaceUri.equals(e.getNamespace()))
{
checkCiteAttribute();
if (name.equals("switch"))
{
requiredProperties.add(ITEM_PROPERTIES.SWITCH);
}
}

processInlineScripts();
Expand Down Expand Up @@ -595,10 +613,12 @@ protected void endMediaElement()
protected void startMediaSource()
{
XMLElement elem = currentElement();
assert "source".equals(elem.getName())
&& ("audio".equals(elem.getParent().getName())
|| "video".equals(elem.getParent().getName()))
&& elem.getParent().getAttribute("src") == null;
assert "source".equals(elem.getName());
if (!("audio".equals(elem.getParent().getName())
|| "video".equals(elem.getParent().getName())))
{
return; // schema error was reported
}

// check the `src` attribute
URL url = checkResourceURL(elem.getAttribute("src"));
Expand Down
Expand Up @@ -551,6 +551,12 @@ Feature: EPUB 3 — Content Documents — XHTML

#//TODO verify script core media types

#### source

Scenario: Verify non-HTML `source` elements are skipped
See https://github.com/w3c/epubcheck/issues/1514
When checking EPUB 'dc-source-valid'
Then no errors or warnings are reported

#### Style

Expand Down
@@ -0,0 +1,22 @@
<!DOCTYPE html>
<html xmlns:epub="http://www.idpf.org/2007/ops" xmlns="http://www.w3.org/1999/xhtml" xml:lang="en"
lang="en">
<head>
<meta charset="utf-8" />
<title>Minimal EPUB</title>
</head>
<body>
<h1>Loomings</h1>
<p>Call me Ishmael.</p>
<svg id="1" width="12cm" height="4cm" viewBox="0 0 1200 400" version="1.1"
xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:cc="http://web.resource.org/cc/" xmlns:dc="http://purl.org/dc/elements/1.1/">
<desc>Example</desc>
<metadata>
<cc:Work>
<dc:source>https://example.com</dc:source>
</cc:Work>
</metadata>
</svg>
</body>
</html>
@@ -0,0 +1,14 @@
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:epub="http://www.idpf.org/2007/ops" xml:lang="en" lang="en">
<head>
<meta charset="utf-8"/>
<title>Minimal Nav</title>
</head>
<body>
<nav epub:type="toc">
<ol>
<li><a href="content_001.xhtml">content 001</a></li>
</ol>
</nav>
</body>
</html>
@@ -0,0 +1,16 @@
<?xml version="1.0" encoding="UTF-8"?>
<package xmlns="http://www.idpf.org/2007/opf" version="3.0" xml:lang="en" unique-identifier="q">
<metadata xmlns:dc="http://purl.org/dc/elements/1.1/">
<dc:title id="title">Minimal EPUB 3.0</dc:title>
<dc:language>en</dc:language>
<dc:identifier id="q">NOID</dc:identifier>
<meta property="dcterms:modified">2017-06-14T00:00:01Z</meta>
</metadata>
<manifest>
<item id="content_001" href="content_001.xhtml" media-type="application/xhtml+xml" properties="svg"/>
<item id="nav" href="nav.xhtml" media-type="application/xhtml+xml" properties="nav"/>
</manifest>
<spine>
<itemref idref="content_001" />
</spine>
</package>
@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8" ?>
<container version="1.0" xmlns="urn:oasis:names:tc:opendocument:xmlns:container">
<rootfiles>
<rootfile full-path="EPUB/package.opf" media-type="application/oebps-package+xml"/>
</rootfiles>
</container>
@@ -0,0 +1 @@
application/epub+zip

0 comments on commit c15e4ea

Please sign in to comment.