Bug 63057 - *Cell.setCellValue(String/RichTextString) is not exception-safe
Summary: *Cell.setCellValue(String/RichTextString) is not exception-safe
Status: RESOLVED FIXED
Alias: None
Product: POI
Classification: Unclassified
Component: SS Common (show other bugs)
Version: 4.0.x-dev
Hardware: PC All
: P2 normal (vote)
Target Milestone: ---
Assignee: POI Developers List
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2019-01-04 09:48 UTC by gallon.fizik@gmail.com
Modified: 2019-01-04 10:10 UTC (History)
0 users



Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description gallon.fizik@gmail.com 2019-01-04 09:48:00 UTC
In all three implementations of Cell, in setCellValue(String) and setCellValue(RichTextString) cell is convertyed to STRING before all checks have passed (or failed). That is, if the passed string exceeds the maximum length defined by the spreadsheet version, the method wil throw but the cell contents will have changed.

The fix is simple: perform all checks before any invasive operation.

testcase:

@Test
public void setStringCellValue_ifThrows_shallNotChangeCell() {
    Cell cell = _testDataProvider.createWorkbook().createSheet().createRow(0).createCell(0);

    final double value = 2.78;
    cell.setCellValue(value);
    assertEquals(CellType.NUMERIC, cell.getCellType());

    int badLength = cell.getSheet().getWorkbook().getSpreadsheetVersion().getMaxTextLength() + 1;
    String badStringValue = new String(new byte[badLength]);

    try {
        cell.setCellValue(badStringValue);
    } catch (IllegalArgumentException e) {
        // no-op, expected to throw but we need to assert something more
    }

    assertEquals(CellType.NUMERIC, cell.getCellType()); // <- fails
    assertEquals(value, cell.getNumericCellValue(), 0); // <- fails, obviously
}
Comment 1 gallon.fizik@gmail.com 2019-01-04 10:07:50 UTC
My bad, this only applies to SXSSFCell.

Also this in setCellValue(String):
if(_value.getType()==CellType.FORMULA)
  if(_value instanceof NumericFormulaValue) {
    ((NumericFormulaValue) _value).setPreEvaluatedValue(Double.parseDouble(value));
  }
  ...
}

never happens because it is preceded by resetting the internal value to a [Formula]StringValue, so I removed it.
Comment 2 gallon.fizik@gmail.com 2019-01-04 10:10:59 UTC
Fixed in r1850342