Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-8167281

IIOMetadataNode bugs in getElementsByTagName and NodeList.item methods

XMLWordPrintable

    • b143
    • x86
    • windows_7

        FULL PRODUCT VERSION :


        A DESCRIPTION OF THE PROBLEM :
        (1) The specification of org.w3c.dom.Element.getElementsByTagName(String name) states:

        >The special value "*" matches all tags.

        In the class javax.imageio.metadata.IIOMetadataNode, which implements the above interface, "*" is not handled, so using it returns no elements. This is the offending code and fix:

            private void getElementsByTagName(String name, List l) {
        - if (nodeName.equals(name)) {
        + if (nodeName.equals(name) || "*".equals(name)) {
                    l.add(this);
                }

                Node child = getFirstChild();
                while (child != null) {
                    ((IIOMetadataNode)child).getElementsByTagName(name, l);
                    child = child.getNextSibling();
                }
            }

        (2) The specification of org.w3c.dom.NodeList.item(int index) states:

        >Returns the indexth item in the collection. If index is greater than or equal to the number of nodes in the list, this returns null.

        In the class javax.imageio.metadata.IIONodeList, which implements the above interface, the range check has a trivial typo which means it throws an unexpected IndexOutOfBoundsException if index equals the number of nodes. This is offending code and fix:

            public Node item(int index) {
        - if (index < 0 || index > nodes.size()) {
        + if (index < 0 || index >= nodes.size()) {
                    return null;
                }
                return (Node)nodes.get(index);
            }


        REPRODUCIBILITY :
        This bug can be reproduced always.

        ---------- BEGIN SOURCE ----------
        import java.awt.image.BufferedImage;
        import java.io.ByteArrayInputStream;
        import java.io.ByteArrayOutputStream;
        import java.io.IOException;
        import java.util.ArrayList;
        import javax.imageio.ImageIO;
        import javax.imageio.ImageReader;
        import javax.imageio.metadata.IIOMetadata;
        import javax.imageio.metadata.IIOMetadataFormatImpl;
        import javax.imageio.stream.ImageInputStream;
        import javax.imageio.stream.MemoryCacheImageInputStream;
        import org.w3c.dom.Element;
        import org.w3c.dom.NodeList;

        public class ImageMetadataNodeBugs {
            public static void main(String[] args) throws IOException {
                // Generate some trivial image and save it to a temporary array
                ByteArrayOutputStream tmp = new ByteArrayOutputStream();
                ImageIO.write(new BufferedImage(1, 1, BufferedImage.TYPE_INT_RGB), "gif", tmp);
                
                // Read it back in
                ImageInputStream in = new MemoryCacheImageInputStream(
                    new ByteArrayInputStream(tmp.toByteArray()));
                ImageReader reader = ImageIO.getImageReaders(in).next();
                reader.setInput(in);
                
                // Retrieve standard image metadata tree
                IIOMetadata meta = reader.getImageMetadata(0);
                if (meta == null || !meta.isStandardMetadataFormatSupported())
                    throw new Error("Test failure: Missing metadata");
                Element root = (Element)meta.getAsTree(IIOMetadataFormatImpl.standardMetadataFormatName);
                
                ArrayList<String> problems = new ArrayList<>();
                
                // Test getElementsByTagName("*")
                if (root.getElementsByTagName("*").getLength() == 0)
                    problems.add("getElementsByTagName(\"*\") doesn't return anything");
                
                // Test IIONodeList.item()
                try {
                    NodeList nodeList = root.getElementsByTagName(root.getFirstChild().getNodeName());
                    if (!(nodeList.item(-1) == null))
                        problems.add("nodeList.item(-1) should be null");
                    if (!(nodeList.item(0) != null))
                        problems.add("nodeList.item(0) should be non-null");
                    if (!(nodeList.item(nodeList.getLength() - 1) != null))
                        problems.add("nodeList.item(length - 1) should be non-null");
                    if (!(nodeList.item(nodeList.getLength()) == null))
                        problems.add("nodeList.item(length) should be null");
                } catch (IndexOutOfBoundsException e) {
                    problems.add("nodeList.item throws unexpected IOOBE");
                }
                
                System.out.println("Result: " + (problems.isEmpty() ? "PASS" : "FAIL"));
                for (String p : problems) System.out.println("- " + p);
            }
        }
        ---------- END SOURCE ----------

              jdv Jayathirth D V
              webbuggrp Webbug Group
              Votes:
              0 Vote for this issue
              Watchers:
              6 Start watching this issue

                Created:
                Updated:
                Resolved: