Skip to content

Bug: REPLACE function fails with empty StringBuilder in Replace.cs #1655

@ZagidullinRuslanG

Description

@ZagidullinRuslanG

NPOI Version

v2.7.5

File Type

  • XLSX
  • XLS
  • DOCX
  • XLSM
  • OTHER

Upload the Excel File

Any Excel file (.xls or .xlsx) that contains REPLACE formula will reproduce this issue.

Example formula that triggers the bug:
=REPLACE("Hello World", 7, 5, "NPOI")

Expected result: "Hello NPOI"
Actual result: Application crashes during formula calculation

Reproduce Steps

Open or create any Excel file (.xls or .xlsx) with NPOI
Create a cell with REPLACE formula, for example: =REPLACE("Hello World", 7, 5, "NPOI")
Try to evaluate the formula using cell.CellFormula or workbook calculation
The application crashes with an exception when trying to Remove characters from empty StringBuilder

Code to reproduce:
IWorkbook workbook = new XSSFWorkbook();
ISheet sheet = workbook.CreateSheet("Test");
ICell cell = sheet.CreateRow(0).CreateCell(0);
cell.SetCellFormula("REPLACE("Hello World", 7, 5, "NPOI")");
workbook.GetCreationHelper().CreateFormulaEvaluator().EvaluateAll(); // Crashes here

Issue Description

Critical bug in Replace.cs causing formula evaluation failure
Location: main/SS/Formula/Functions/Text/Replace.cs, lines 59-63
Root Cause:
The EvaluateFunc method creates an empty StringBuilder on line 59 but immediately attempts to remove characters from it on line 63 without first adding the original string (oldStr).
Current buggy code:
using var strBuff = ZString.CreateStringBuilder();
// remove any characters that should be replaced
if (startNum <= oldStr.Length && numChars != 0)
{
strBuff.Remove(startNum - 1, Math.Min(numChars, oldStr.Length - startNum + 1));
}

Fix:
Add one line after creating the StringBuilder to populate it with the original string:

using var strBuff = ZString.CreateStringBuilder();
strBuff.Append(oldStr); // ← ADD THIS LINE
// remove any characters that should be replaced
if (startNum <= oldStr.Length && numChars != 0)
{
strBuff.Remove(startNum - 1, Math.Min(numChars, oldStr.Length - startNum + 1));
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions