Author: fanningpj
Date: Mon Jun 29 13:18:52 2026
New Revision: 1935709

Log:
uard short handle string in XsbReader.readHandle. Thanks to aizu-m. This closes 
#73

Added:
   
xmlbeans/trunk/src/test/java/org/apache/xmlbeans/impl/schema/XsbReaderHandleTest.java
Modified:
   xmlbeans/trunk/src/main/java/org/apache/xmlbeans/impl/schema/XsbReader.java

Modified: 
xmlbeans/trunk/src/main/java/org/apache/xmlbeans/impl/schema/XsbReader.java
==============================================================================
--- xmlbeans/trunk/src/main/java/org/apache/xmlbeans/impl/schema/XsbReader.java 
Mon Jun 29 12:45:04 2026        (r1935708)
+++ xmlbeans/trunk/src/main/java/org/apache/xmlbeans/impl/schema/XsbReader.java 
Mon Jun 29 13:18:52 2026        (r1935709)
@@ -437,10 +437,20 @@ class XsbReader {
             return null;
         }
 
+        if (handle.isEmpty()) {
+            throw new SchemaTypeLoaderException("Cannot resolve handle " + 
handle, typeSystem.getName(), _handle, SchemaTypeLoaderException.BAD_HANDLE);
+        }
+
         if (handle.charAt(0) != '_') {
             return typeSystem.getTypePool().refForHandle(handle);
         }
 
+        // every '_'-prefixed handle is a 4-char tag ("_BI_", "_XT_", ...) 
plus a
+        // payload; charAt(2) and forPretty(handle, 4) below read past a 
shorter one
+        if (handle.length() < 4) {
+            throw new SchemaTypeLoaderException("Cannot resolve handle " + 
handle, typeSystem.getName(), _handle, SchemaTypeLoaderException.BAD_HANDLE);
+        }
+
         switch (handle.charAt(2)) {
             case 'I': // _BI_ - built-in schema type system
                 SchemaType st = (SchemaType) 
BuiltinSchemaTypeSystem.get().resolveHandle(handle);

Added: 
xmlbeans/trunk/src/test/java/org/apache/xmlbeans/impl/schema/XsbReaderHandleTest.java
==============================================================================
--- /dev/null   00:00:00 1970   (empty, because file is newly added)
+++ 
xmlbeans/trunk/src/test/java/org/apache/xmlbeans/impl/schema/XsbReaderHandleTest.java
       Mon Jun 29 13:18:52 2026        (r1935709)
@@ -0,0 +1,67 @@
+/*   Licensed to the Apache Software Foundation (ASF) under one or more
+ *   contributor license agreements.  See the NOTICE file distributed with
+ *   this work for additional information regarding copyright ownership.
+ *   The ASF licenses this file to You under the Apache License, Version 2.0
+ *   (the "License"); you may not use this file except in compliance with
+ *   the License.  You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *   Unless required by applicable law or agreed to in writing, software
+ *   distributed under the License is distributed on an "AS IS" BASIS,
+ *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *   See the License for the specific language governing permissions and
+ *   limitations under the License.
+ */
+
+package org.apache.xmlbeans.impl.schema;
+
+import org.apache.xmlbeans.SchemaTypeLoaderException;
+import org.apache.xmlbeans.impl.util.LongUTFDataInputStream;
+import org.junit.jupiter.api.Test;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.DataOutputStream;
+import java.lang.reflect.Field;
+
+import static org.junit.jupiter.api.Assertions.assertThrows;
+
+public class XsbReaderHandleTest {
+
+    // Builds an XsbReader whose next readString() returns the given component
+    // handle, exactly as a crafted/corrupt .xsb would supply it.
+    private static XsbReader readerForHandle(String handle) throws Exception {
+        XsbReader reader = new XsbReader(new SchemaTypeSystemImpl("test"), 
"h");
+
+        Field poolF = XsbReader.class.getDeclaredField("_stringPool");
+        poolF.setAccessible(true);
+        SchemaTypeSystemImpl.StringPool pool = 
(SchemaTypeSystemImpl.StringPool) poolF.get(reader);
+        int code = pool.codeForString(handle);
+
+        ByteArrayOutputStream bos = new ByteArrayOutputStream();
+        DataOutputStream dos = new DataOutputStream(bos);
+        dos.writeShort(code); // readString -> readUnsignedShortOrInt -> 
stringForCode(code)
+        dos.flush();
+
+        Field inputF = XsbReader.class.getDeclaredField("_input");
+        inputF.setAccessible(true);
+        inputF.set(reader, new LongUTFDataInputStream(new 
ByteArrayInputStream(bos.toByteArray())));
+
+        return reader;
+    }
+
+    @Test
+    void rejectsEmptyHandle() throws Exception {
+        // an empty handle used to throw StringIndexOutOfBoundsException at 
handle.charAt(0)
+        XsbReader reader = readerForHandle("");
+        assertThrows(SchemaTypeLoaderException.class, reader::readHandle);
+    }
+
+    @Test
+    void rejectsShortUnderscoreHandle() throws Exception {
+        // "_X" starts with '_' but is too short for handle.charAt(2)
+        XsbReader reader = readerForHandle("_X");
+        assertThrows(SchemaTypeLoaderException.class, reader::readHandle);
+    }
+}


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to