This is an automated email from the ASF dual-hosted git repository.

pjfanning pushed a commit to branch trunk
in repository https://gitbox.apache.org/repos/asf/poi.git


The following commit(s) were added to refs/heads/trunk by this push:
     new 152e061292 Prevent crashes when calculating cells on absolute anchors. 
(#1089)
152e061292 is described below

commit 152e061292fd49219c310d2a950be6ea9a20ccb3
Author: Jacobo Aragunde PĂ©rez <[email protected]>
AuthorDate: Tue May 26 19:12:15 2026 +0200

    Prevent crashes when calculating cells on absolute anchors. (#1089)
    
    Absolute anchors in OOXML aren't anchored to cells, they have absolute
    positions in the document. The XSSFClientAnchor has code to calculate
    the cell equivalent, using the absolute position and the cell width and
    height. The same code is used to calculate the second anchor cell in
    one-cell anchors.
    
    For absolute anchors, it takes an empty cell (EMPTY_MARKER) and
    calculates the first anchor cell by compounding it with the anchor
    position, the problem is the empty cell has some null fields that the
    code is not expecting, and it crashes.
    
    We add those null cells and add a test that exercises this use case.
    The same test would crash if run on trunk, with the following
    exception:
    
    java.lang.NullPointerException: Cannot invoke 
"org.apache.xmlbeans.XmlAnySimpleType.getStringValue()" because "coordUnion" is 
null
            at 
org.apache.poi.ooxml/org.apache.poi.ooxml.util.POIXMLUnits.parseLengthInner(POIXMLUnits.java:236)
            at 
org.apache.poi.ooxml/org.apache.poi.ooxml.util.POIXMLUnits.parseLength(POIXMLUnits.java:167)
            at 
org.apache.poi.ooxml/org.apache.poi.xssf.usermodel.XSSFClientAnchor.calcCell(XSSFClientAnchor.java:166)
            at 
org.apache.poi.ooxml/org.apache.poi.xssf.usermodel.XSSFClientAnchor.getCell1(XSSFClientAnchor.java:202)
            at 
org.apache.poi.ooxml/org.apache.poi.xssf.usermodel.XSSFClientAnchor.getCol1(XSSFClientAnchor.java:211)
            at 
org.apache.poi.ooxml/org.apache.poi.xssf.usermodel.TestXSSFDrawing.testAbsoluteAnchor(TestXSSFDrawing.java:938)
---
 .../apache/poi/xssf/usermodel/XSSFClientAnchor.java    |   4 ++--
 .../org/apache/poi/xssf/usermodel/TestXSSFDrawing.java |  17 +++++++++++++++++
 .../spreadsheet/absolute-anchor-over-empty-sheet.xlsx  | Bin 0 -> 21153 bytes
 3 files changed, 19 insertions(+), 2 deletions(-)

diff --git 
a/poi-ooxml/src/main/java/org/apache/poi/xssf/usermodel/XSSFClientAnchor.java 
b/poi-ooxml/src/main/java/org/apache/poi/xssf/usermodel/XSSFClientAnchor.java
index 893e3ec3cd..14502d5e24 100644
--- 
a/poi-ooxml/src/main/java/org/apache/poi/xssf/usermodel/XSSFClientAnchor.java
+++ 
b/poi-ooxml/src/main/java/org/apache/poi/xssf/usermodel/XSSFClientAnchor.java
@@ -163,7 +163,7 @@ public class XSSFClientAnchor extends XSSFAnchor implements 
ClientAnchor {
         int cw = Units.columnWidthToEMU(sheet.getColumnWidth(c));
 
         // start with width - offset, then keep adding column widths until the 
next one puts us over w
-        long wPos = cw - POIXMLUnits.parseLength(cell.xgetColOff());
+        long wPos = cell.xgetColOff() == null ? cw : cw - 
POIXMLUnits.parseLength(cell.xgetColOff());
 
         while (wPos < w) {
             c++;
@@ -176,7 +176,7 @@ public class XSSFClientAnchor extends XSSFAnchor implements 
ClientAnchor {
 
         int rh = Units.toEMU(getRowHeight(sheet, r));
         // start with height - offset, then keep adding row heights until the 
next one puts us over h
-        long hPos = rh - POIXMLUnits.parseLength(cell.xgetRowOff());
+        long hPos = cell.xgetRowOff() == null ? rh : rh - 
POIXMLUnits.parseLength(cell.xgetRowOff());
 
         while (hPos < h) {
             r++;
diff --git 
a/poi-ooxml/src/test/java/org/apache/poi/xssf/usermodel/TestXSSFDrawing.java 
b/poi-ooxml/src/test/java/org/apache/poi/xssf/usermodel/TestXSSFDrawing.java
index 48c3b4478a..a02f21f436 100644
--- a/poi-ooxml/src/test/java/org/apache/poi/xssf/usermodel/TestXSSFDrawing.java
+++ b/poi-ooxml/src/test/java/org/apache/poi/xssf/usermodel/TestXSSFDrawing.java
@@ -925,6 +925,23 @@ class TestXSSFDrawing {
         }
     }
 
+    @Test
+    void testAbsoluteAnchor() throws IOException {
+        try (XSSFWorkbook workbook = 
XSSFTestDataSamples.openSampleWorkbook("absolute-anchor-over-empty-sheet.xlsx"))
 {
+            XSSFSheet sheet = workbook.getSheetAt(0);
+            XSSFDrawing drawing = sheet.getDrawingPatriarch();
+            List<XSSFShape> shapes = drawing.getShapes();
+            assertEquals(1, shapes.size());
+
+            assertTrue(shapes.get(0).getAnchor() instanceof ClientAnchor);
+            ClientAnchor anchor = (ClientAnchor) shapes.get(0).getAnchor();
+            assertEquals(3, anchor.getCol1());
+            assertEquals(38, anchor.getRow1());
+            assertEquals(19, anchor.getCol2());
+            assertEquals(80, anchor.getRow2());
+        }
+    }
+
     private static void checkRewrite(XSSFWorkbook wb) throws IOException {
         XSSFWorkbook wb2 = XSSFTestDataSamples.writeOutAndReadBack(wb);
         assertNotNull(wb2);
diff --git a/test-data/spreadsheet/absolute-anchor-over-empty-sheet.xlsx 
b/test-data/spreadsheet/absolute-anchor-over-empty-sheet.xlsx
new file mode 100644
index 0000000000..a8c3ce1c53
Binary files /dev/null and 
b/test-data/spreadsheet/absolute-anchor-over-empty-sheet.xlsx differ


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

Reply via email to