Skip to content

Commit c15e4ea

Browse files
committed
fix: dc:source element caused a NullPointerException
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
1 parent bd279f0 commit c15e4ea

File tree

7 files changed

+178
-93
lines changed

7 files changed

+178
-93
lines changed

src/main/java/com/adobe/epubcheck/ops/OPSHandler30.java

Lines changed: 113 additions & 93 deletions
Original file line numberDiff line numberDiff line change
@@ -334,109 +334,127 @@ public void startElement()
334334
processSectioning();
335335

336336
String name = e.getName();
337-
if (name.equals("html"))
338-
{
339-
vocabs = VocabUtil.parsePrefixDeclaration(
340-
e.getAttributeNS(EpubConstants.EpubTypeNamespaceUri, "prefix"), RESERVED_VOCABS,
341-
KNOWN_VOCAB_URIS, DEFAULT_VOCAB_URIS, report, location());
342-
}
343-
else if (EpubConstants.HtmlNamespaceUri.equals(e.getNamespace()) && name.equals("meta"))
344-
{
345-
processMeta();
346-
}
347-
else if (name.equals("form"))
348-
{
349-
requiredProperties.add(ITEM_PROPERTIES.SCRIPTED);
350-
}
351-
else if (name.equals("link"))
352-
{
353-
processLink();
354-
}
355-
else if (name.equals("math"))
337+
if (EpubConstants.HtmlNamespaceUri.equals(e.getNamespace()))
356338
{
357-
requiredProperties.add(ITEM_PROPERTIES.MATHML);
358-
inMathML = true;
359-
hasAltorAnnotation = (null != e.getAttribute("alttext"));
360-
String altimg = e.getAttribute("altimg");
361-
if (altimg != null)
339+
if (name.equals("html"))
340+
{
341+
vocabs = VocabUtil.parsePrefixDeclaration(
342+
e.getAttributeNS(EpubConstants.EpubTypeNamespaceUri, "prefix"), RESERVED_VOCABS,
343+
KNOWN_VOCAB_URIS, DEFAULT_VOCAB_URIS, report, location());
344+
}
345+
else if (name.equals("meta"))
346+
{
347+
processMeta();
348+
}
349+
else if (name.equals("form"))
362350
{
363-
super.checkImage(null, "altimg");
351+
requiredProperties.add(ITEM_PROPERTIES.SCRIPTED);
352+
}
353+
else if (name.equals("link"))
354+
{
355+
processLink();
364356
}
365357

366-
}
367-
else if (name.equals("svg"))
368-
{
369-
processSVG();
370-
}
371-
else if (EpubConstants.EpubTypeNamespaceUri.equals(e.getNamespace()) && name.equals("switch"))
372-
{
373-
requiredProperties.add(ITEM_PROPERTIES.SWITCH);
374-
}
375-
else if (name.equals("audio"))
376-
{
377-
startMediaElement();
378-
}
379-
else if (name.equals("video"))
380-
{
381-
processVideo();
382-
startMediaElement();
383-
}
384-
else if (name.equals("figure"))
385-
{
386-
processFigure();
387-
}
388-
else if (name.equals("table"))
389-
{
390-
processTable();
391-
}
392-
else if (name.equals("track"))
393-
{
394-
startTrack();
395-
}
396-
else if (name.equals("a"))
397-
{
398-
anchorNeedsText = true;
399-
processAnchor(e);
400-
}
401-
else if (name.equals("annotation-xml"))
402-
{
403-
hasAltorAnnotation = true;
404-
}
405-
else if (name.equals("input"))
406-
{
407-
startInput();
408-
}
409-
else if (name.equals("picture"))
410-
{
411-
inPicture = true;
412-
}
413-
else if (name.equals("source"))
414-
{
415-
if ("picture".equals(e.getParent().getName()))
358+
else if (name.equals("audio"))
416359
{
417-
checkImage(null, null);
360+
startMediaElement();
418361
}
419-
else // audio or video source
362+
else if (name.equals("video"))
420363
{
421-
startMediaSource();
364+
processVideo();
365+
startMediaElement();
366+
}
367+
else if (name.equals("figure"))
368+
{
369+
processFigure();
370+
}
371+
else if (name.equals("table"))
372+
{
373+
processTable();
374+
}
375+
else if (name.equals("track"))
376+
{
377+
startTrack();
378+
}
379+
else if (name.equals("a"))
380+
{
381+
anchorNeedsText = true;
382+
processAnchor(e);
383+
}
384+
else if (name.equals("input"))
385+
{
386+
startInput();
387+
}
388+
else if (name.equals("picture"))
389+
{
390+
inPicture = true;
391+
}
392+
else if (name.equals("source"))
393+
{
394+
if ("picture".equals(e.getParent().getName()))
395+
{
396+
checkImage(null, null);
397+
}
398+
else // audio or video source
399+
{
400+
startMediaSource();
401+
}
402+
}
403+
else if (name.equals("embed"))
404+
{
405+
startEmbed();
406+
}
407+
else if (name.equals("blockquote") || name.equals("q") || name.equals("ins")
408+
|| name.equals("del"))
409+
{
410+
checkCiteAttribute();
422411
}
423412
}
424-
else if ("http://www.w3.org/2000/svg".equals(e.getNamespace()) && name.equals("title"))
425-
{
426-
hasLabel = true;
427-
}
428-
else if ("http://www.w3.org/2000/svg".equals(e.getNamespace()) && name.equals("text"))
413+
else if ("http://www.w3.org/1998/Math/MathML".equals(e.getNamespace()))
429414
{
430-
hasLabel = true;
415+
if (name.equals("math"))
416+
{
417+
requiredProperties.add(ITEM_PROPERTIES.MATHML);
418+
inMathML = true;
419+
hasAltorAnnotation = (null != e.getAttribute("alttext"));
420+
String altimg = e.getAttribute("altimg");
421+
if (altimg != null)
422+
{
423+
super.checkImage(null, "altimg");
424+
}
425+
426+
}
427+
else if (name.equals("annotation-xml"))
428+
{
429+
hasAltorAnnotation = true;
430+
}
431431
}
432-
else if (name.equals("embed"))
432+
else if ("http://www.w3.org/2000/svg".equals(e.getNamespace()))
433433
{
434-
startEmbed();
434+
if (name.equals("svg"))
435+
{
436+
processSVG();
437+
}
438+
else if (name.equals("a"))
439+
{
440+
anchorNeedsText = true;
441+
processAnchor(e);
442+
}
443+
else if (name.equals("title"))
444+
{
445+
hasLabel = true;
446+
}
447+
else if (name.equals("text"))
448+
{
449+
hasLabel = true;
450+
}
435451
}
436-
else if (name.equals("blockquote") || name.equals("q") || name.equals("ins")
437-
|| name.equals("del"))
452+
else if (EpubConstants.EpubTypeNamespaceUri.equals(e.getNamespace()))
438453
{
439-
checkCiteAttribute();
454+
if (name.equals("switch"))
455+
{
456+
requiredProperties.add(ITEM_PROPERTIES.SWITCH);
457+
}
440458
}
441459

442460
processInlineScripts();
@@ -595,10 +613,12 @@ protected void endMediaElement()
595613
protected void startMediaSource()
596614
{
597615
XMLElement elem = currentElement();
598-
assert "source".equals(elem.getName())
599-
&& ("audio".equals(elem.getParent().getName())
600-
|| "video".equals(elem.getParent().getName()))
601-
&& elem.getParent().getAttribute("src") == null;
616+
assert "source".equals(elem.getName());
617+
if (!("audio".equals(elem.getParent().getName())
618+
|| "video".equals(elem.getParent().getName())))
619+
{
620+
return; // schema error was reported
621+
}
602622

603623
// check the `src` attribute
604624
URL url = checkResourceURL(elem.getAttribute("src"));

src/test/resources/epub3/06-content-document/content-document-xhtml.feature

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -551,6 +551,12 @@ Feature: EPUB 3 — Content Documents — XHTML
551551

552552
#//TODO verify script core media types
553553

554+
#### source
555+
556+
Scenario: Verify non-HTML `source` elements are skipped
557+
See https://github.com/w3c/epubcheck/issues/1514
558+
When checking EPUB 'dc-source-valid'
559+
Then no errors or warnings are reported
554560

555561
#### Style
556562

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

0 commit comments

Comments
 (0)