Author: tilman
Date: Mon Dec 15 16:08:11 2025
New Revision: 1930594

Log:
PDFBOX-3882: avoid NPE, move block to the correct location, correct existing 
NPE handling, improve test coverage

Modified:
   pdfbox/trunk/xmpbox/src/main/java/org/apache/xmpbox/xml/DomXmpParser.java
   pdfbox/trunk/xmpbox/src/test/java/org/apache/xmpbox/xml/DomXmpParserTest.java

Modified: 
pdfbox/trunk/xmpbox/src/main/java/org/apache/xmpbox/xml/DomXmpParser.java
==============================================================================
--- pdfbox/trunk/xmpbox/src/main/java/org/apache/xmpbox/xml/DomXmpParser.java   
Mon Dec 15 16:08:06 2025        (r1930593)
+++ pdfbox/trunk/xmpbox/src/main/java/org/apache/xmpbox/xml/DomXmpParser.java   
Mon Dec 15 16:08:11 2025        (r1930594)
@@ -310,8 +310,7 @@ public class DomXmpParser
             ComplexPropertyContainer container = schema.getContainer();
             PropertyType type = checkPropertyDefinition(xmp,
                     new QName(attr.getNamespaceURI(), attr.getLocalName()));
-            
-            // PDFBOX-2318, PDFBOX-6106: Default to text if no type is found
+
             if (type == null)
             {
                 if (strictParsing)
@@ -321,6 +320,7 @@ public class DomXmpParser
                 }
                 else
                 {
+                    // PDFBOX-2318, PDFBOX-6106: Default to text if no type is 
found
                     type = TypeMapping.createPropertyType(Types.Text, 
Cardinality.Simple);
                 }
             }
@@ -1058,18 +1058,11 @@ public class DomXmpParser
                     // Instantiate abstract structured type with hint from 
first element
                     QName attrQName = new QName(attr.getNamespaceURI(), 
attr.getLocalName(), attr.getPrefix());
                     PropertyType ctype = checkPropertyDefinition(xmp, 
attrQName);
-                    // PDFBOX-2318, PDFBOX-6106: Default to text if no type is 
found
+                    // this is the type of the AbstractStructuredType, not of 
the element(s)
                     if (ctype == null)
                     {
-                        if (strictParsing)
-                        {
-                            throw new 
XmpParsingException(ErrorType.InvalidType, "No type defined for {" + 
attr.getNamespaceURI() + "}"
-                                    + attr.getLocalName());
-                        }
-                        else
-                        {
-                            ctype = TypeMapping.createPropertyType(Types.Text, 
Cardinality.Simple);
-                        }
+                        throw new XmpParsingException(ErrorType.NoType,
+                            "Property '" + attrQName.getLocalPart() + "' not 
defined in " + attrQName.getNamespaceURI());
                     }
                     Types tt = ctype.type();
                     ast = instanciateStructured(tm, tt, qName.getLocalPart(), 
attr.getNamespaceURI());
@@ -1085,6 +1078,19 @@ public class DomXmpParser
                 if (ast != null && pm != null && attr.getNamespaceURI() != 
null)
                 {
                     PropertyType type = 
pm.getPropertyType(attr.getLocalName());
+                    if (type == null)
+                    {
+                        if (strictParsing)
+                        {
+                            throw new 
XmpParsingException(ErrorType.InvalidType, "No type defined for {" + 
attr.getNamespaceURI() + "}"
+                                    + attr.getLocalName());
+                        }
+                        else
+                        {
+                            // PDFBOX-2318, PDFBOX-6106: Default to text if no 
type is found
+                            type = TypeMapping.createPropertyType(Types.Text, 
Cardinality.Simple);
+                        }
+                    }
                     AbstractSimpleProperty asp = tm.instanciateSimpleProperty(
                             attr.getNamespaceURI(), attr.getPrefix(), 
attr.getLocalName(),
                             attr.getValue(), type.type());

Modified: 
pdfbox/trunk/xmpbox/src/test/java/org/apache/xmpbox/xml/DomXmpParserTest.java
==============================================================================
--- 
pdfbox/trunk/xmpbox/src/test/java/org/apache/xmpbox/xml/DomXmpParserTest.java   
    Mon Dec 15 16:08:06 2025        (r1930593)
+++ 
pdfbox/trunk/xmpbox/src/test/java/org/apache/xmpbox/xml/DomXmpParserTest.java   
    Mon Dec 15 16:08:11 2025        (r1930594)
@@ -556,6 +556,37 @@ class DomXmpParserTest
         assertEquals("Important subject", subjects.get(0));
         assertEquals("Unimportant subject", subjects.get(1));
     }
+    
+    @Test
+    void testBadAttr() throws XmpParsingException
+    {
+        String s = "<?xml version=\"1.0\" encoding=\"UTF-8\" 
standalone=\"no\"?>\n" +
+                    "<?xpacket begin=\"\" 
id=\"W5M0MpCehiHzreSzNTczkc9d\"?>\n" +
+                    "<x:xmpmeta xmlns:x=\"adobe:ns:meta/\">\n" +
+                    "  <rdf:RDF 
xmlns:rdf=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\";>\n" +
+                    "           <rdf:Description 
xmlns:xmpTPg=\"http://ns.adobe.com/xap/1.0/t/pg/\""; +
+                    "                            
xmlns:stDim=\"http://ns.adobe.com/xap/1.0/sType/Dimensions#\""; +
+                    "                           rdf:about=\"\">\n" +
+                    "                  <xmpTPg:MaxPageSize>\n" +
+                    "                          <rdf:Description stDim:X=\"4\" 
stDim:Y=\"3\" stDim:Z=\"inch\"/>\n" +
+                    "                  </xmpTPg:MaxPageSize>\n" +
+                    "          </rdf:Description>\n" +
+                    "  </rdf:RDF>\n" +
+                    "</x:xmpmeta><?xpacket end=\"r\"?>";
+        XmpParsingException ex = assertThrows(
+                XmpParsingException.class,
+                () -> new 
DomXmpParser().parse(s.getBytes(StandardCharsets.UTF_8)));
+        assertEquals("No type defined for 
{http://ns.adobe.com/xap/1.0/sType/Dimensions#}X";, ex.getMessage());
+        DomXmpParser xmpParser = new DomXmpParser();
+        xmpParser.setStrictParsing(false);
+        XMPMetadata xmp = xmpParser.parse(s.getBytes(StandardCharsets.UTF_8));
+        XMPPageTextSchema pageTextSchema = xmp.getPageTextSchema();
+        DimensionsType dim = (DimensionsType) 
pageTextSchema.getProperty(XMPPageTextSchema.MAX_PAGE_SIZE);
+        assertEquals("DimensionsType{null x null null}", dim.toString());
+        assertEquals("[X=TextType:4]", dim.getProperty("X").toString());
+        assertEquals("[Y=TextType:3]", dim.getProperty("Y").toString());
+        assertEquals("[Z=TextType:inch]", dim.getProperty("Z").toString());
+    }
 
     @Test
     void testBadType() throws XmpParsingException

Reply via email to