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 5fc26e44e9 refactor hssf limit code (#1115)
5fc26e44e9 is described below
commit 5fc26e44e95caa43ef5686e0de5eb4042333a2ef
Author: PJ Fanning <[email protected]>
AuthorDate: Thu Jun 4 19:11:36 2026 +0100
refactor hssf limit code (#1115)
* refactor hssf limit code
* refactor
* revert some changes
* Update IOUtils.java
* Update poi-integration-exceptions.csv
* Update poi-integration-exceptions.csv
---
.../poi/hssf/extractor/OldExcelExtractor.java | 2 +-
.../org/apache/poi/hssf/record/CFRule12Record.java | 8 +--
.../org/apache/poi/hssf/record/DConRefRecord.java | 3 +-
.../hssf/record/EmbeddedObjectRefSubRecord.java | 3 +-
.../apache/poi/hssf/record/EscherAggregate.java | 3 +-
.../apache/poi/hssf/record/FtCblsSubRecord.java | 5 +-
.../poi/hssf/record/GroupMarkerSubRecord.java | 3 +-
.../apache/poi/hssf/record/HyperlinkRecord.java | 3 +-
.../poi/hssf/record/NoteStructureSubRecord.java | 5 +-
.../org/apache/poi/hssf/record/OldLabelRecord.java | 3 +-
.../org/apache/poi/hssf/record/OldSheetRecord.java | 3 +-
.../apache/poi/hssf/record/OldStringRecord.java | 4 +-
.../org/apache/poi/hssf/record/RecordFactory.java | 3 +-
.../apache/poi/hssf/record/RecordInputStream.java | 3 +-
.../java/org/apache/poi/hssf/record/SubRecord.java | 3 +-
.../apache/poi/hssf/record/WriteAccessRecord.java | 11 ++--
.../hssf/record/aggregates/SharedValueManager.java | 16 ++++--
.../org/apache/poi/hssf/record/common/ExtRst.java | 3 +-
.../hssf/record/crypto/Biff8DecryptingStream.java | 3 +-
.../apache/poi/hssf/usermodel/HSSFWorkbook.java | 9 +++-
.../main/java/org/apache/poi/util/ArrayUtil.java | 16 +++---
poi/src/main/java/org/apache/poi/util/IOUtils.java | 63 +++++++++++++++-------
test-data/poi-integration-exceptions.csv | 6 +--
23 files changed, 109 insertions(+), 72 deletions(-)
diff --git
a/poi/src/main/java/org/apache/poi/hssf/extractor/OldExcelExtractor.java
b/poi/src/main/java/org/apache/poi/hssf/extractor/OldExcelExtractor.java
index 10ab25f188..99f9581865 100644
--- a/poi/src/main/java/org/apache/poi/hssf/extractor/OldExcelExtractor.java
+++ b/poi/src/main/java/org/apache/poi/hssf/extractor/OldExcelExtractor.java
@@ -305,7 +305,7 @@ public class OldExcelExtractor implements POITextExtractor {
break;
default:
- ris.readFully(IOUtils.safelyAllocate(ris.remaining(),
HSSFWorkbook.getMaxRecordLength()));
+
ris.readFully(HSSFWorkbook.safelyAllocate(ris.remaining()));
}
}
diff --git a/poi/src/main/java/org/apache/poi/hssf/record/CFRule12Record.java
b/poi/src/main/java/org/apache/poi/hssf/record/CFRule12Record.java
index 2b0fb59c5e..0c04ab12f9 100644
--- a/poi/src/main/java/org/apache/poi/hssf/record/CFRule12Record.java
+++ b/poi/src/main/java/org/apache/poi/hssf/record/CFRule12Record.java
@@ -33,6 +33,7 @@ import org.apache.poi.hssf.record.common.ExtendedColor;
import org.apache.poi.hssf.record.common.FtrHeader;
import org.apache.poi.hssf.record.common.FutureRecord;
import org.apache.poi.hssf.usermodel.HSSFSheet;
+import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.formula.Formula;
import org.apache.poi.ss.formula.ptg.Ptg;
import org.apache.poi.ss.usermodel.ConditionalFormattingThreshold.RangeType;
@@ -42,7 +43,6 @@ import org.apache.poi.util.IOUtils;
import org.apache.poi.util.LittleEndianOutput;
import static org.apache.logging.log4j.util.Unbox.box;
-import static org.apache.poi.hssf.usermodel.HSSFWorkbook.getMaxRecordLength;
/**
* Conditional Formatting v12 Rule Record (0x087A).
@@ -121,7 +121,7 @@ public final class CFRule12Record extends CFRuleBase
implements FutureRecord {
priority = 0;
template_type = getConditionType();
template_param_length = 16;
- template_params = IOUtils.safelyAllocate(template_param_length,
getMaxRecordLength());
+ template_params = HSSFWorkbook.safelyAllocate(template_param_length);
}
/**
@@ -265,7 +265,7 @@ public final class CFRule12Record extends CFRuleBase
implements FutureRecord {
} else {
long len = readFormatOptions(in);
if (len < ext_formatting_length) {
- ext_formatting_data =
IOUtils.safelyAllocate(ext_formatting_length-len, getMaxRecordLength());
+ ext_formatting_data =
HSSFWorkbook.safelyAllocate(ext_formatting_length-len);
in.readFully(ext_formatting_data);
}
}
@@ -281,7 +281,7 @@ public final class CFRule12Record extends CFRuleBase
implements FutureRecord {
template_type = in.readUShort();
template_param_length = in.readByte();
if (template_param_length == 0 || template_param_length == 16) {
- template_params = IOUtils.safelyAllocate(template_param_length,
getMaxRecordLength());
+ template_params =
HSSFWorkbook.safelyAllocate(template_param_length);
in.readFully(template_params);
} else {
LOG.atWarn().log("CF Rule v12 template params length should be 0
or 16, found {}", box(template_param_length));
diff --git a/poi/src/main/java/org/apache/poi/hssf/record/DConRefRecord.java
b/poi/src/main/java/org/apache/poi/hssf/record/DConRefRecord.java
index 74a6dee371..c72ea13083 100644
--- a/poi/src/main/java/org/apache/poi/hssf/record/DConRefRecord.java
+++ b/poi/src/main/java/org/apache/poi/hssf/record/DConRefRecord.java
@@ -26,7 +26,6 @@ import java.util.function.Supplier;
import org.apache.commons.io.input.UnsynchronizedByteArrayInputStream;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.util.GenericRecordUtil;
-import org.apache.poi.util.IOUtils;
import org.apache.poi.util.LittleEndianOutput;
import org.apache.poi.util.RecordFormatException;
import org.apache.poi.util.StringUtil;
@@ -157,7 +156,7 @@ public class DConRefRecord extends StandardRecord {
// single-byte, 1 if double-byte.
final int byteLength = charCount * (charType + 1);
- path = IOUtils.safelyAllocate(byteLength,
HSSFWorkbook.getMaxRecordLength());
+ path = HSSFWorkbook.safelyAllocate(byteLength);
inStream.readFully(path);
// If it's a self reference, the last one or two bytes (depending on
char type) are the
diff --git
a/poi/src/main/java/org/apache/poi/hssf/record/EmbeddedObjectRefSubRecord.java
b/poi/src/main/java/org/apache/poi/hssf/record/EmbeddedObjectRefSubRecord.java
index e5db7b6e67..53930b3b8b 100644
---
a/poi/src/main/java/org/apache/poi/hssf/record/EmbeddedObjectRefSubRecord.java
+++
b/poi/src/main/java/org/apache/poi/hssf/record/EmbeddedObjectRefSubRecord.java
@@ -31,7 +31,6 @@ import org.apache.poi.ss.formula.ptg.Ptg;
import org.apache.poi.ss.formula.ptg.Ref3DPtg;
import org.apache.poi.ss.formula.ptg.RefPtg;
import org.apache.poi.util.GenericRecordUtil;
-import org.apache.poi.util.IOUtils;
import org.apache.poi.util.LittleEndianConsts;
import org.apache.poi.util.LittleEndianInput;
import org.apache.poi.util.LittleEndianInputStream;
@@ -201,7 +200,7 @@ public final class EmbeddedObjectRefSubRecord extends
SubRecord {
if (size == 0) {
return EMPTY_BYTE_ARRAY;
}
- byte[] result = IOUtils.safelyAllocate(size,
HSSFWorkbook.getMaxRecordLength());
+ byte[] result = HSSFWorkbook.safelyAllocate(size);
in.readFully(result);
return result;
}
diff --git a/poi/src/main/java/org/apache/poi/hssf/record/EscherAggregate.java
b/poi/src/main/java/org/apache/poi/hssf/record/EscherAggregate.java
index fc6d8270b9..d4a882b243 100644
--- a/poi/src/main/java/org/apache/poi/hssf/record/EscherAggregate.java
+++ b/poi/src/main/java/org/apache/poi/hssf/record/EscherAggregate.java
@@ -364,7 +364,8 @@ public final class EscherAggregate extends
AbstractEscherHolderRecord {
// Determine buffer size
List<EscherRecord> records = getEscherRecords();
int rawEscherSize = getEscherRecordSize(records);
- byte[] buffer = IOUtils.safelyAllocate(rawEscherSize,
MAX_RECORD_LENGTH);
+ byte[] buffer = IOUtils.safelyAllocate(rawEscherSize,
MAX_RECORD_LENGTH,
+ "EscherAggregate.setMaxRecordLength()");
final List<Integer> spEndingOffsets = new ArrayList<>();
int pos = 0;
for (EscherRecord e : records) {
diff --git a/poi/src/main/java/org/apache/poi/hssf/record/FtCblsSubRecord.java
b/poi/src/main/java/org/apache/poi/hssf/record/FtCblsSubRecord.java
index c849ec4f8f..6f4a7e9751 100644
--- a/poi/src/main/java/org/apache/poi/hssf/record/FtCblsSubRecord.java
+++ b/poi/src/main/java/org/apache/poi/hssf/record/FtCblsSubRecord.java
@@ -20,8 +20,8 @@ package org.apache.poi.hssf.record;
import java.util.Map;
import java.util.function.Supplier;
+import org.apache.poi.util.ArrayUtil;
import org.apache.poi.util.GenericRecordUtil;
-import org.apache.poi.util.IOUtils;
import org.apache.poi.util.LittleEndianInput;
import org.apache.poi.util.LittleEndianOutput;
import org.apache.poi.util.RecordFormatException;
@@ -57,7 +57,8 @@ public final class FtCblsSubRecord extends SubRecord {
throw new RecordFormatException("Unexpected size (" + size + ")");
}
//just grab the raw data
- byte[] buf = IOUtils.safelyAllocate(size, ENCODED_SIZE);
+ ArrayUtil.strictAllocateCheck(size, ENCODED_SIZE);
+ byte[] buf = new byte[size];
in.readFully(buf);
reserved = buf;
}
diff --git
a/poi/src/main/java/org/apache/poi/hssf/record/GroupMarkerSubRecord.java
b/poi/src/main/java/org/apache/poi/hssf/record/GroupMarkerSubRecord.java
index 64c751a22d..da991817d6 100644
--- a/poi/src/main/java/org/apache/poi/hssf/record/GroupMarkerSubRecord.java
+++ b/poi/src/main/java/org/apache/poi/hssf/record/GroupMarkerSubRecord.java
@@ -22,7 +22,6 @@ import java.util.function.Supplier;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.util.GenericRecordUtil;
-import org.apache.poi.util.IOUtils;
import org.apache.poi.util.LittleEndianInput;
import org.apache.poi.util.LittleEndianOutput;
@@ -52,7 +51,7 @@ public final class GroupMarkerSubRecord extends SubRecord {
}
GroupMarkerSubRecord(LittleEndianInput in, int size, int cmoOt) {
- byte[] buf = IOUtils.safelyAllocate(size,
HSSFWorkbook.getMaxRecordLength());
+ byte[] buf = HSSFWorkbook.safelyAllocate(size);
in.readFully(buf);
reserved = buf;
}
diff --git a/poi/src/main/java/org/apache/poi/hssf/record/HyperlinkRecord.java
b/poi/src/main/java/org/apache/poi/hssf/record/HyperlinkRecord.java
index a27a9ab82a..4bb17bdbb5 100644
--- a/poi/src/main/java/org/apache/poi/hssf/record/HyperlinkRecord.java
+++ b/poi/src/main/java/org/apache/poi/hssf/record/HyperlinkRecord.java
@@ -35,7 +35,6 @@ import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.util.GenericRecordUtil;
import org.apache.poi.util.HexRead;
-import org.apache.poi.util.IOUtils;
import org.apache.poi.util.LittleEndianInput;
import org.apache.poi.util.LittleEndianOutput;
import org.apache.poi.util.RecordFormatException;
@@ -389,7 +388,7 @@ public final class HyperlinkRecord extends StandardRecord {
int len = in.readInt();
- byte[] path_bytes = IOUtils.safelyAllocate(len,
HSSFWorkbook.getMaxRecordLength());
+ byte[] path_bytes = HSSFWorkbook.safelyAllocate(len);
in.readFully(path_bytes);
_address = new String(path_bytes, StringUtil.UTF8);
diff --git
a/poi/src/main/java/org/apache/poi/hssf/record/NoteStructureSubRecord.java
b/poi/src/main/java/org/apache/poi/hssf/record/NoteStructureSubRecord.java
index e15e05a92f..4dc31ff1e1 100644
--- a/poi/src/main/java/org/apache/poi/hssf/record/NoteStructureSubRecord.java
+++ b/poi/src/main/java/org/apache/poi/hssf/record/NoteStructureSubRecord.java
@@ -20,8 +20,8 @@ package org.apache.poi.hssf.record;
import java.util.Map;
import java.util.function.Supplier;
+import org.apache.poi.util.ArrayUtil;
import org.apache.poi.util.GenericRecordUtil;
-import org.apache.poi.util.IOUtils;
import org.apache.poi.util.LittleEndianInput;
import org.apache.poi.util.LittleEndianOutput;
import org.apache.poi.util.RecordFormatException;
@@ -68,7 +68,8 @@ public final class NoteStructureSubRecord extends SubRecord {
throw new RecordFormatException("Unexpected size (" + size + ")");
}
//just grab the raw data
- byte[] buf = IOUtils.safelyAllocate(size, ENCODED_SIZE);
+ ArrayUtil.strictAllocateCheck(size, ENCODED_SIZE);
+ byte[] buf = new byte[size];
in.readFully(buf);
reserved = buf;
}
diff --git a/poi/src/main/java/org/apache/poi/hssf/record/OldLabelRecord.java
b/poi/src/main/java/org/apache/poi/hssf/record/OldLabelRecord.java
index 66fa67f9a9..ad30b9a8aa 100644
--- a/poi/src/main/java/org/apache/poi/hssf/record/OldLabelRecord.java
+++ b/poi/src/main/java/org/apache/poi/hssf/record/OldLabelRecord.java
@@ -24,7 +24,6 @@ import org.apache.logging.log4j.Logger;
import org.apache.poi.logging.PoiLogManager;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.util.GenericRecordUtil;
-import org.apache.poi.util.IOUtils;
import org.apache.poi.util.RecordFormatException;
import static org.apache.logging.log4j.util.Unbox.box;
@@ -59,7 +58,7 @@ public final class OldLabelRecord extends OldCellRecord {
}
// Can only decode properly later when you know the codepage
- field_5_bytes = IOUtils.safelyAllocate(field_4_string_len,
HSSFWorkbook.getMaxRecordLength());
+ field_5_bytes = HSSFWorkbook.safelyAllocate(field_4_string_len);
in.read(field_5_bytes, 0, field_4_string_len);
if (in.remaining() > 0) {
diff --git a/poi/src/main/java/org/apache/poi/hssf/record/OldSheetRecord.java
b/poi/src/main/java/org/apache/poi/hssf/record/OldSheetRecord.java
index 24f67bf8b9..cd1cc9e7db 100644
--- a/poi/src/main/java/org/apache/poi/hssf/record/OldSheetRecord.java
+++ b/poi/src/main/java/org/apache/poi/hssf/record/OldSheetRecord.java
@@ -25,7 +25,6 @@ import org.apache.poi.common.usermodel.GenericRecord;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.util.GenericRecordJsonWriter;
import org.apache.poi.util.GenericRecordUtil;
-import org.apache.poi.util.IOUtils;
import org.apache.poi.util.RecordFormatException;
/**
@@ -62,7 +61,7 @@ public final class OldSheetRecord implements GenericRecord {
}
}
}
- field_5_sheetname = IOUtils.safelyAllocate(field_4_sheetname_length,
HSSFWorkbook.getMaxRecordLength());
+ field_5_sheetname =
HSSFWorkbook.safelyAllocate(field_4_sheetname_length);
in.read(field_5_sheetname, 0, field_4_sheetname_length);
}
diff --git a/poi/src/main/java/org/apache/poi/hssf/record/OldStringRecord.java
b/poi/src/main/java/org/apache/poi/hssf/record/OldStringRecord.java
index 91a00265ff..96ecdd0fbb 100644
--- a/poi/src/main/java/org/apache/poi/hssf/record/OldStringRecord.java
+++ b/poi/src/main/java/org/apache/poi/hssf/record/OldStringRecord.java
@@ -27,8 +27,6 @@ import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.util.CodePageUtil;
import org.apache.poi.util.GenericRecordJsonWriter;
import org.apache.poi.util.GenericRecordUtil;
-import org.apache.poi.util.IOUtils;
-
/**
* Biff2 - Biff 4 Label Record (0x0007 / 0x0207) - read only support for
@@ -57,7 +55,7 @@ public final class OldStringRecord implements GenericRecord {
}
// Can only decode properly later when you know the codepage
- field_2_bytes = IOUtils.safelyAllocate(field_1_string_len,
HSSFWorkbook.getMaxRecordLength());
+ field_2_bytes = HSSFWorkbook.safelyAllocate(field_1_string_len);
in.read(field_2_bytes, 0, field_1_string_len);
}
diff --git a/poi/src/main/java/org/apache/poi/hssf/record/RecordFactory.java
b/poi/src/main/java/org/apache/poi/hssf/record/RecordFactory.java
index f0f1c42f82..8d4ff09b19 100644
--- a/poi/src/main/java/org/apache/poi/hssf/record/RecordFactory.java
+++ b/poi/src/main/java/org/apache/poi/hssf/record/RecordFactory.java
@@ -199,7 +199,8 @@ public final class RecordFactory {
while ((record = recStream.nextRecord()) != null) {
records.add(record);
- IOUtils.safelyAllocateCheck(records.size(), MAX_NUMBER_OF_RECORDS);
+ IOUtils.safelyAllocateCheck(records.size(), MAX_NUMBER_OF_RECORDS,
+ "RecordFactory.setMaxNumberOfRecords");
}
return records;
diff --git
a/poi/src/main/java/org/apache/poi/hssf/record/RecordInputStream.java
b/poi/src/main/java/org/apache/poi/hssf/record/RecordInputStream.java
index 561768f32b..2ca1740f89 100644
--- a/poi/src/main/java/org/apache/poi/hssf/record/RecordInputStream.java
+++ b/poi/src/main/java/org/apache/poi/hssf/record/RecordInputStream.java
@@ -25,7 +25,6 @@ import
org.apache.commons.io.output.UnsynchronizedByteArrayOutputStream;
import org.apache.poi.hssf.record.crypto.Biff8DecryptingStream;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.poifs.crypt.EncryptionInfo;
-import org.apache.poi.util.IOUtils;
import org.apache.poi.util.Internal;
import org.apache.poi.util.LittleEndianConsts;
import org.apache.poi.util.LittleEndianInput;
@@ -437,7 +436,7 @@ public final class RecordInputStream implements
LittleEndianInput {
if (size ==0) {
return EMPTY_BYTE_ARRAY;
}
- byte[] result = IOUtils.safelyAllocate(size,
HSSFWorkbook.getMaxRecordLength());
+ byte[] result = HSSFWorkbook.safelyAllocate(size);
readFully(result);
return result;
}
diff --git a/poi/src/main/java/org/apache/poi/hssf/record/SubRecord.java
b/poi/src/main/java/org/apache/poi/hssf/record/SubRecord.java
index ca16540ec8..07e57f5ef8 100644
--- a/poi/src/main/java/org/apache/poi/hssf/record/SubRecord.java
+++ b/poi/src/main/java/org/apache/poi/hssf/record/SubRecord.java
@@ -167,7 +167,8 @@ public abstract class SubRecord implements Duplicatable,
GenericRecord {
public UnknownSubRecord(LittleEndianInput in, int size, int sid) {
_sid = sid;
- byte[] buf = IOUtils.safelyAllocate(size, MAX_RECORD_LENGTH);
+ byte[] buf = IOUtils.safelyAllocate(size, MAX_RECORD_LENGTH,
+ "SubRecord.setMaxRecordLength");
in.readFully(buf);
_data = buf;
}
diff --git
a/poi/src/main/java/org/apache/poi/hssf/record/WriteAccessRecord.java
b/poi/src/main/java/org/apache/poi/hssf/record/WriteAccessRecord.java
index 712693554c..2a93a11d52 100644
--- a/poi/src/main/java/org/apache/poi/hssf/record/WriteAccessRecord.java
+++ b/poi/src/main/java/org/apache/poi/hssf/record/WriteAccessRecord.java
@@ -23,10 +23,10 @@ import java.util.Arrays;
import java.util.Map;
import java.util.function.Supplier;
+import org.apache.poi.util.ArrayUtil;
import org.apache.poi.util.BitField;
import org.apache.poi.util.BitFieldFactory;
import org.apache.poi.util.GenericRecordUtil;
-import org.apache.poi.util.IOUtils;
import org.apache.poi.util.LittleEndian;
import org.apache.poi.util.LittleEndianOutput;
import org.apache.poi.util.RecordFormatException;
@@ -83,7 +83,8 @@ public final class WriteAccessRecord extends StandardRecord {
if (in.isEncrypted()) {
// WPS Office seems to generate files with this record
unencrypted (#66115)
// Libre Office/Excel can read those, but Excel will convert
those back to encrypted
- data = IOUtils.safelyAllocate(in.remaining(), STRING_SIZE);
+ ArrayUtil.strictAllocateCheck(in.remaining(), STRING_SIZE);
+ data = new byte[in.remaining()];
in.readPlain(data, 0, data.length);
int i = data.length;
// PAD_CHAR is filled for every byte even for UTF16 strings
@@ -97,7 +98,8 @@ public final class WriteAccessRecord extends StandardRecord {
// String header looks wrong (probably missing)
// OOO doc says this is optional anyway.
byteCnt = 3 + in.remaining();
- data = IOUtils.safelyAllocate(byteCnt, DATA_SIZE);
+ ArrayUtil.strictAllocateCheck(byteCnt, DATA_SIZE);
+ data = new byte[byteCnt];
LittleEndian.putUShort(data, 0, nChars);
LittleEndian.putByte(data, 2, is16BitFlag);
in.readFully(data, 3, byteCnt-3);
@@ -105,7 +107,8 @@ public final class WriteAccessRecord extends StandardRecord
{
}
} else {
// the normal case ...
- data = IOUtils.safelyAllocate(in.remaining(), STRING_SIZE);
+ ArrayUtil.strictAllocateCheck(in.remaining(), STRING_SIZE);
+ data = new byte[in.remaining()];
in.readFully(data);
if (UTF16FLAG.isSet(is16BitFlag)) {
// the spec only allows up to 109 bytes for the string in this
record, but it seems some broken
diff --git
a/poi/src/main/java/org/apache/poi/hssf/record/aggregates/SharedValueManager.java
b/poi/src/main/java/org/apache/poi/hssf/record/aggregates/SharedValueManager.java
index 44763597cb..ab72bdfe89 100644
---
a/poi/src/main/java/org/apache/poi/hssf/record/aggregates/SharedValueManager.java
+++
b/poi/src/main/java/org/apache/poi/hssf/record/aggregates/SharedValueManager.java
@@ -31,7 +31,7 @@ import org.apache.poi.hssf.record.TableRecord;
import org.apache.poi.ss.formula.ptg.ExpPtg;
import org.apache.poi.hssf.util.CellRangeAddress8Bit;
import org.apache.poi.ss.util.CellReference;
-import org.apache.poi.util.IOUtils;
+import org.apache.poi.util.ArrayUtil;
/**
* Manages various auxiliary records while constructing a
@@ -43,7 +43,16 @@ import org.apache.poi.util.IOUtils;
* </ul>
*/
public final class SharedValueManager {
- private static final int MAX_NUMBER_AGGS = 10_000;
+ private static final int DEFAULT_MAX_NUMBER_AGGS = 10_000;
+ private static int MAX_NUMBER_AGGS = DEFAULT_MAX_NUMBER_AGGS;
+
+ public static void setMaxNumberOfFormulaRecordAggregates(int
maxNumberOfFormulaRecordAggregates) {
+ MAX_NUMBER_AGGS = maxNumberOfFormulaRecordAggregates;
+ }
+
+ public static int getMaxNumberOfFormulaRecordAggregates() {
+ return MAX_NUMBER_AGGS;
+ }
private static final class SharedFormulaGroup {
private final SharedFormulaRecord _sfr;
@@ -68,7 +77,8 @@ public final class SharedValueManager {
// ensure we do not try to initialize a very large amount of
formula-record-aggregates
int allocateSize = width * height;
- IOUtils.safelyAllocateCheck(allocateSize, MAX_NUMBER_AGGS);
+ ArrayUtil.safelyAllocateCheck(allocateSize, MAX_NUMBER_AGGS,
+
"SharedValueManager.setMaxNumberOfFormulaRecordAggregates");
_frAggs = new FormulaRecordAggregate[allocateSize];
_numberOfFormulas = 0;
diff --git a/poi/src/main/java/org/apache/poi/hssf/record/common/ExtRst.java
b/poi/src/main/java/org/apache/poi/hssf/record/common/ExtRst.java
index d798b0cc39..9e6c13ac0a 100644
--- a/poi/src/main/java/org/apache/poi/hssf/record/common/ExtRst.java
+++ b/poi/src/main/java/org/apache/poi/hssf/record/common/ExtRst.java
@@ -28,7 +28,6 @@ import org.apache.poi.common.usermodel.GenericRecord;
import org.apache.poi.hssf.record.cont.ContinuableRecordOutput;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.util.GenericRecordUtil;
-import org.apache.poi.util.IOUtils;
import org.apache.poi.util.Internal;
import org.apache.poi.util.LittleEndianInput;
import org.apache.poi.util.StringUtil;
@@ -125,7 +124,7 @@ public class ExtRst implements Comparable<ExtRst>,
GenericRecord {
LOG.atWarn().log("ExtRst overran by {} bytes",
box(-extraDataLength));
extraDataLength = 0;
}
- extraData = IOUtils.safelyAllocate(extraDataLength,
HSSFWorkbook.getMaxRecordLength());
+ extraData = HSSFWorkbook.safelyAllocate(extraDataLength);
for(int i=0; i<extraData.length; i++) {
extraData[i] = in.readByte();
}
diff --git
a/poi/src/main/java/org/apache/poi/hssf/record/crypto/Biff8DecryptingStream.java
b/poi/src/main/java/org/apache/poi/hssf/record/crypto/Biff8DecryptingStream.java
index 63ed8e1fad..112d02c0e9 100644
---
a/poi/src/main/java/org/apache/poi/hssf/record/crypto/Biff8DecryptingStream.java
+++
b/poi/src/main/java/org/apache/poi/hssf/record/crypto/Biff8DecryptingStream.java
@@ -25,7 +25,6 @@ import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.poifs.crypt.ChunkedCipherInputStream;
import org.apache.poi.poifs.crypt.Decryptor;
import org.apache.poi.poifs.crypt.EncryptionInfo;
-import org.apache.poi.util.IOUtils;
import org.apache.poi.util.Internal;
import org.apache.poi.util.LittleEndian;
import org.apache.poi.util.LittleEndianConsts;
@@ -44,7 +43,7 @@ public final class Biff8DecryptingStream implements
BiffHeaderInput, LittleEndia
public Biff8DecryptingStream(InputStream in, int initialOffset,
EncryptionInfo info) throws RecordFormatException {
try {
- byte[] initialBuf = IOUtils.safelyAllocate(initialOffset,
HSSFWorkbook.getMaxRecordLength());
+ byte[] initialBuf = HSSFWorkbook.safelyAllocate(initialOffset);
InputStream stream;
if (initialOffset == 0) {
stream = in;
diff --git a/poi/src/main/java/org/apache/poi/hssf/usermodel/HSSFWorkbook.java
b/poi/src/main/java/org/apache/poi/hssf/usermodel/HSSFWorkbook.java
index 9862b38d5d..50a9efc74f 100644
--- a/poi/src/main/java/org/apache/poi/hssf/usermodel/HSSFWorkbook.java
+++ b/poi/src/main/java/org/apache/poi/hssf/usermodel/HSSFWorkbook.java
@@ -244,6 +244,10 @@ public final class HSSFWorkbook extends POIDocument
implements Workbook {
return ioMaxSize < 0 ? MAX_IMAGE_LENGTH : Math.min(MAX_IMAGE_LENGTH,
ioMaxSize);
}
+ public static byte[] safelyAllocate(long len) {
+ return IOUtils.safelyAllocate(len, MAX_RECORD_LENGTH,
"HSSFWorkbook.setMaxRecordLength()");
+ }
+
/**
* Creates new HSSFWorkbook from scratch (start here!)
*/
@@ -1670,7 +1674,7 @@ public final class HSSFWorkbook extends POIDocument
implements Workbook {
if (sid == BoundSheetRecord.sid) {
// special case for the field_1_position_of_BOF
(=lbPlyPos) field of
// the BoundSheet8 record which must be unencrypted
- byte[] bsrBuf = IOUtils.safelyAllocate(len,
MAX_RECORD_LENGTH);
+ byte[] bsrBuf = safelyAllocate(len);
plain.readFully(bsrBuf);
os.writePlain(bsrBuf, 0, 4);
os.write(bsrBuf, 4, len - 4);
@@ -2078,7 +2082,8 @@ public final class HSSFWorkbook extends POIDocument
implements Workbook {
case PICTURE_TYPE_WMF:
// remove first 22 bytes if file starts with the WMF placeable
header
if (FileMagic.valueOf(pictureData) == FileMagic.WMF) {
- pictureData = IOUtils.safelyClone(pictureData, 22,
pictureData.length - 22, getMaxImageLength());
+ pictureData = IOUtils.safelyClone(pictureData, 22,
pictureData.length - 22,
+ getMaxImageLength(),
"HSSFWorkbook.setMaxImageLength()");
}
// fall through
case PICTURE_TYPE_EMF:
diff --git a/poi/src/main/java/org/apache/poi/util/ArrayUtil.java
b/poi/src/main/java/org/apache/poi/util/ArrayUtil.java
index 504b80e625..ce86100d88 100644
--- a/poi/src/main/java/org/apache/poi/util/ArrayUtil.java
+++ b/poi/src/main/java/org/apache/poi/util/ArrayUtil.java
@@ -17,7 +17,6 @@
package org.apache.poi.util;
-
import java.util.Arrays;
/**
@@ -96,15 +95,18 @@ public final class ArrayUtil {
* @throws RecordFormatException if the length is negative or too long
*/
public static void safelyAllocateCheck(long length, int maxLength, String
limitMethod) {
- if (length < 0L) {
- throw new RecordFormatException("Can't allocate an array of length
< 0, but had " + length + " and " + maxLength);
- }
- if (length > (long)Integer.MAX_VALUE) {
- throw new RecordFormatException("Can't allocate an array > " +
Integer.MAX_VALUE);
- }
+ IOUtils.globalLengthChecks(length);
if (length > maxLength) {
IOUtils.throwRFE(length, maxLength, limitMethod);
}
}
+ public static void strictAllocateCheck(long length, int maxLength) {
+ IOUtils.globalLengthChecks(length);
+ if (length > maxLength) {
+ IOUtils.throwStrictLimitRFE(length, maxLength);
+ }
+ }
+
+
}
diff --git a/poi/src/main/java/org/apache/poi/util/IOUtils.java
b/poi/src/main/java/org/apache/poi/util/IOUtils.java
index bc36232251..733bcb1c56 100644
--- a/poi/src/main/java/org/apache/poi/util/IOUtils.java
+++ b/poi/src/main/java/org/apache/poi/util/IOUtils.java
@@ -232,9 +232,7 @@ public final class IOUtils {
* @since 5.4.1
*/
public static byte[] toByteArray(InputStream stream, final long length,
final int maxLength) throws IOException {
- if (length > Integer.MAX_VALUE) {
- throwRFE(length, maxLength);
- }
+ globalLengthChecks(length);
return toByteArray(stream, Math.toIntExact(length),
maxLength, true, length != Integer.MAX_VALUE);
}
@@ -613,12 +611,7 @@ public final class IOUtils {
* @throws RecordFormatException if the length is negative or too long
*/
public static void safelyAllocateCheck(long length, int maxLength) {
- if (length < 0L) {
- throw new RecordFormatException("Can't allocate an array of length
< 0, but had " + length + " and " + maxLength);
- }
- if (length > (long)Integer.MAX_VALUE) {
- throw new RecordFormatException("Can't allocate an array > " +
Integer.MAX_VALUE);
- }
+ globalLengthChecks(length);
checkLength(length, maxLength);
}
@@ -634,27 +627,36 @@ public final class IOUtils {
* @throws RecordFormatException if the length is negative or too long
*/
public static void safelyAllocateCheck(long length, int maxLength, String
limitMethod) {
- if (length < 0L) {
- throw new RecordFormatException("Can't allocate an array of length
< 0, but had " + length + " and " + maxLength);
- }
- if (length > (long)Integer.MAX_VALUE) {
- throw new RecordFormatException("Can't allocate an array > " +
Integer.MAX_VALUE);
- }
+ globalLengthChecks(length);
checkLength(length, maxLength, limitMethod);
}
public static byte[] safelyClone(byte[] src, int offset, int length, int
maxLength) {
+ return safelyClone(src, offset, length, maxLength, null);
+ }
+
+ public static byte[] safelyClone(byte[] src, int offset, int length,
+ int maxLength, String limitMethod) {
if (src == null) {
return null;
}
if (offset < 0 || length < 0 || maxLength < 0) {
- throw new RecordFormatException("Invalid offset/length specified: "
- + "offset: " + offset + ", length: " + length + ",
maxLength: " + maxLength);
+ if (limitMethod == null) {
+ throw new RecordFormatException(String.format(Locale.ROOT,
"Invalid offset/length specified: " +
+ "offset: %d, length: %d, maxLength: %d", offset,
length, maxLength));
+ }
+ throw new RecordFormatException(String.format(Locale.ROOT,
"Invalid offset/length specified: " +
+ "offset: %d, length: %d, maxLength: %d.%n" +
+ "You can set a higher override value with %s.", offset,
length, maxLength, limitMethod));
}
int realLength = Math.min(src.length - offset, length);
- safelyAllocateCheck(realLength, maxLength);
+ if (limitMethod == null) {
+ safelyAllocateCheck(realLength, maxLength);
+ } else {
+ safelyAllocateCheck(realLength, maxLength, limitMethod);
+ }
return Arrays.copyOfRange(src, offset, offset+realLength);
}
@@ -705,7 +707,15 @@ public final class IOUtils {
", but the maximum length for this record type is %,d.%n" +
"If the file is not corrupt and not large, please open an
issue on bugzilla to request %n" +
"increasing the maximum allowable size for this record
type.%n" +
- "You can set a higher override value with %s", length,
maxLength, limitMethod));
+ "You can set a higher override value with %s.", length,
maxLength, limitMethod));
+ }
+
+ // no override available for the limit
+ static void throwStrictLimitRFE(long length, int maxLength) {
+ throw new RecordFormatException(String.format(Locale.ROOT, "Tried to
allocate an array of length %,d" +
+ ", but the maximum length for this record type is %,d.%n" +
+ "If the file is not corrupt and not large, please open an
issue on bugzilla to request %n" +
+ "increasing the maximum allowable size for this record
type.%n", length, maxLength));
}
private static void throwRecordTruncationException(final int maxLength) {
@@ -713,6 +723,19 @@ public final class IOUtils {
"for this record type is %,d.%n" +
"If the file is not corrupt and not large, please open an
issue on bugzilla to request %n" +
"increasing the maximum allowable size for this record
type.%n" +
- "You can set a higher override value with
IOUtils.setByteArrayMaxOverride()", maxLength));
+ "You can set a higher override value with
IOUtils.setByteArrayMaxOverride().", maxLength));
+ }
+
+ static void globalLengthChecks(long length) {
+ if (length < 0L) {
+ throw new RecordFormatException(String.format(Locale.ROOT,
+ "Tried to allocate an array with negative length; %d was
requested.",
+ length));
+ }
+ if (length > (long)Integer.MAX_VALUE) {
+ throw new RecordFormatException(String.format(Locale.ROOT,
+ "Tried to allocate an array with length greater than max
allowed int (%d); %d was requested.",
+ Integer.MAX_VALUE, length));
+ }
}
}
diff --git a/test-data/poi-integration-exceptions.csv
b/test-data/poi-integration-exceptions.csv
index f38fec98ff..d70a72058d 100644
--- a/test-data/poi-integration-exceptions.csv
+++ b/test-data/poi-integration-exceptions.csv
@@ -187,8 +187,8 @@
slideshow/clusterfuzz-testcase-minimized-POIHSLFFuzzer-6710128412590080.ppt,"han
slideshow/clusterfuzz-testcase-minimized-POIHSLFFuzzer-6710128412590080.ppt,extract,HPSF,,java.lang.IllegalArgumentException,Had
unexpected type of entry for name,
slideshow/clusterfuzz-testcase-minimized-POIHSLFFuzzer-6710128412590080.ppt,additional,HPSF,,java.lang.IllegalStateException,Buffer
overrun,
slideshow/clusterfuzz-testcase-minimized-POIHSLFFuzzer-6710128412590080.ppt,handle,HPSF,,org.opentest4j.AssertionFailedError,expected:
<true> but was: <false>,
-diagram/clusterfuzz-testcase-minimized-POIHDGFFuzzer-5947849161179136.vsd,extract,"HDGF,HPSF",,org.apache.poi.util.RecordFormatException,Can't
allocate an array > 2147483647,
-diagram/clusterfuzz-testcase-minimized-POIHDGFFuzzer-5947849161179136.vsd,handle,HDGF,,org.apache.poi.util.RecordFormatException,Can't
allocate an array > 2147483647,
+diagram/clusterfuzz-testcase-minimized-POIHDGFFuzzer-5947849161179136.vsd,extract,"HDGF,HPSF",,org.apache.poi.util.RecordFormatException,Tried
to allocate an array with length greater than max allowed int (2147483647);
2450525952 was requested.,
+diagram/clusterfuzz-testcase-minimized-POIHDGFFuzzer-5947849161179136.vsd,handle,HDGF,,org.apache.poi.util.RecordFormatException,Tried
to allocate an array with length greater than max allowed int (2147483647);
2450525952 was requested.,
diagram/clusterfuzz-testcase-minimized-POIHDGFFuzzer-5947849161179136.vsd,"handle,additional",HPSF,,java.util.NoSuchElementException,Can't
read past the end of the stream,
hsmf/clusterfuzz-testcase-minimized-POIHSMFFuzzer-4735011465854976.msg,extract,"HSMF,HPSF",,java.lang.IllegalArgumentException,ChunkId
and type of chunk did not match,
hsmf/clusterfuzz-testcase-minimized-POIHSMFFuzzer-4735011465854976.msg,handle,HSMF,,java.lang.IllegalArgumentException,ChunkId
and type of chunk did not match,
@@ -404,5 +404,5 @@
slideshow/clusterfuzz-testcase-minimized-POIXSLFFuzzer-6435650376957952.pptx,han
slideshow/clusterfuzz-testcase-minimized-POIXSLFFuzzer-6435650376957952.pptx,extract,"XSLF,OPC",,java.lang.IllegalStateException,org.apache.poi.ooxml.POIXMLException,
slideshow/clusterfuzz-testcase-minimized-POIFileHandlerFuzzer-6466833057382400.emf,"handle,extract",HEMF,,org.apache.poi.util.RecordFormatException,java.lang.IllegalStateException:
Unexpected end-of-file,
slideshow/clusterfuzz-testcase-minimized-POIHSLFFuzzer-4983252485210112.ppt,"handle,additional",HPSF,,java.lang.IndexOutOfBoundsException,Block
21 not found,
-slideshow/clusterfuzz-testcase-minimized-POIHSLFFuzzer-4983252485210112.ppt,handle,HSLF,,org.apache.poi.util.RecordFormatException,"Can't
allocate an array of length < 0, but had -1579150891 and 1000000",
+slideshow/clusterfuzz-testcase-minimized-POIHSLFFuzzer-4983252485210112.ppt,handle,HSLF,,org.apache.poi.util.RecordFormatException,Tried
to allocate an array with negative length; -1579150891 was requested.,
slideshow/clusterfuzz-testcase-minimized-POIFileHandlerFuzzer-6060921738035200.wmf,handle,HWMF,,java.lang.IllegalStateException,invalid
wmf file
\ No newline at end of file
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]