Bug 53147 - Reordering and removing sheet causes internal data inconsistency
Summary: Reordering and removing sheet causes internal data inconsistency
Status: RESOLVED DUPLICATE of bug 50083
Alias: None
Product: POI
Classification: Unclassified
Component: HSSF (show other bugs)
Version: 3.8-FINAL
Hardware: All All
: P2 normal (vote)
Target Milestone: ---
Assignee: POI Developers List
Depends on:
Reported: 2012-04-25 13:45 UTC by recyclebin5385
Modified: 2012-04-26 13:20 UTC (History)
0 users

test code and patch (2.42 KB, application/zip)
2012-04-25 13:45 UTC, recyclebin5385

Note You need to log in before you can comment on or make changes to this bug.
Description recyclebin5385 2012-04-25 13:45:56 UTC
Created attachment 28683 [details]
test code and patch

I changed the order of sheets in a workbook by invoking method setSheetOrder(String, int) of class org.apache.poi.hssf.usermodel.HSSFWorkbook and removed one sheet by invoking method removeSheetAt(int).
Then I tried to save the workbook by invoking method write(OutputStream).
But a strange Exception was thrown and I could not save the workbook.
Below is the stack trace.

java.lang.IllegalArgumentException: calculated end index (2231) is out of allowable range (2204..2228)
	at org.apache.poi.util.LittleEndianByteArrayOutputStream.<init>(LittleEndianByteArrayOutputStream.java:41)
	at org.apache.poi.hssf.record.StandardRecord.serialize(StandardRecord.java:45)
	at org.apache.poi.hssf.usermodel.HSSFWorkbook$SheetRecordCollector.serialize(HSSFWorkbook.java:1259)
	at org.apache.poi.hssf.usermodel.HSSFWorkbook.getBytes(HSSFWorkbook.java:1305)
	at org.apache.poi.hssf.usermodel.HSSFWorkbook.write(HSSFWorkbook.java:1205)
	at Test1.main(Test1.java:13)

I looked into the source code and found that method org.apache.poi.hssf.model.InternalWorkbook#removeSheet(int) destroys the consistency of internal data.

Here is part of the source code in that method.

        if (boundsheets.size() > sheetIndex) {
            records.remove(records.getBspos() - (boundsheets.size() - 1) + sheetIndex);

The code is intended to remove the same instance from both of fields "boundsheets" and "records".
This works only if the orders of elements are the same in both fields, but once method setSheetOrder(String, int) is called, only "boundsheets" is reordered and the precondition is not valid anymore.

This causes different result in calculating the size of the serialized data between method InternalWorkbook#serialize(int, byte[]) and InternalWorkbook#getSize() (returns wrong result).
When getSize() returns a value less than the true serialized data size, POI fails to allocate enough size of buffer and the exception shown above occurs.

I will attach a zip file including a test code and a patch to fix the bug.
Comment 1 recyclebin5385 2012-04-26 13:20:48 UTC

*** This bug has been marked as a duplicate of bug 50083 ***