From f38aeac2d455a62e4d3a63f49894819af91c7e35 Mon Sep 17 00:00:00 2001 From: BigDataDZ <76271875+BigDataDZ@users.noreply.github.com> Date: Wed, 9 Sep 2026 11:47:30 +0800 Subject: [PATCH] fix: fill crash on a stray '}' before a template placeholder Signed-off-by: BigDataDZ <76271875+BigDataDZ@users.noreply.github.com> --- .../executor/ExcelWriteFillExecutor.java | 5 +- .../sheet/fill/FillWithStraySuffixTest.java | 65 +++++++++++++++++++ 2 files changed, 69 insertions(+), 1 deletion(-) create mode 100644 fesod-sheet/src/test/java/org/apache/fesod/sheet/fill/FillWithStraySuffixTest.java diff --git a/fesod-sheet/src/main/java/org/apache/fesod/sheet/write/executor/ExcelWriteFillExecutor.java b/fesod-sheet/src/main/java/org/apache/fesod/sheet/write/executor/ExcelWriteFillExecutor.java index fb743c8f1..c18f5f890 100644 --- a/fesod-sheet/src/main/java/org/apache/fesod/sheet/write/executor/ExcelWriteFillExecutor.java +++ b/fesod-sheet/src/main/java/org/apache/fesod/sheet/write/executor/ExcelWriteFillExecutor.java @@ -555,7 +555,10 @@ private String prepareData( } int suffixIndex = -1; while (suffixIndex == -1 && startIndex < length) { - suffixIndex = value.indexOf(FILL_SUFFIX, startIndex + 1); + // A stray '}' before the placeholder is literal text, so the matching suffix must be + // searched after the '{' — searching from startIndex alone could return an earlier '}' + // and invert the substring bounds below. + suffixIndex = value.indexOf(FILL_SUFFIX, Math.max(startIndex + 1, prefixIndex + 1)); if (suffixIndex < 0) { break out; } diff --git a/fesod-sheet/src/test/java/org/apache/fesod/sheet/fill/FillWithStraySuffixTest.java b/fesod-sheet/src/test/java/org/apache/fesod/sheet/fill/FillWithStraySuffixTest.java new file mode 100644 index 000000000..f11cd00db --- /dev/null +++ b/fesod-sheet/src/test/java/org/apache/fesod/sheet/fill/FillWithStraySuffixTest.java @@ -0,0 +1,65 @@ +/* + * 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.fesod.sheet.fill; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.util.HashMap; +import java.util.Map; +import org.apache.fesod.sheet.FesodSheet; +import org.apache.fesod.sheet.testkit.Tags; +import org.apache.fesod.sheet.testkit.base.AbstractExcelTest; +import org.apache.fesod.sheet.testkit.enums.ExcelFormat; +import org.apache.poi.ss.usermodel.Row; +import org.apache.poi.ss.usermodel.Sheet; +import org.apache.poi.xssf.usermodel.XSSFWorkbook; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Tag; +import org.junit.jupiter.api.Test; + +@Tag(Tags.ROUND_TRIP) +public class FillWithStraySuffixTest extends AbstractExcelTest { + + @Test + void fillTemplateWithStraySuffixBeforePlaceholder() throws Exception { + File template = createTempFile(ExcelFormat.XLSX); + try (XSSFWorkbook workbook = new XSSFWorkbook()) { + Sheet sheet = workbook.createSheet("Sheet0"); + Row row = sheet.createRow(0); + // The stray '}' before the '{name}' placeholder is literal text, not a placeholder suffix. + row.createCell(0).setCellValue("a}b{name}"); + try (FileOutputStream out = new FileOutputStream(template)) { + workbook.write(out); + } + } + + File outFile = createTempFile(ExcelFormat.XLSX); + Map data = new HashMap<>(); + data.put("name", "filled"); + + FesodSheet.write(outFile).withTemplate(template).sheet().doFill(data); + + try (XSSFWorkbook workbook = new XSSFWorkbook(new FileInputStream(outFile))) { + String value = workbook.getSheetAt(0).getRow(0).getCell(0).getStringCellValue(); + Assertions.assertEquals("a}bfilled", value); + } + } +}