diff --git a/poi/src/main/java/org/apache/poi/poifs/filesystem/Ole10Native.java b/poi/src/main/java/org/apache/poi/poifs/filesystem/Ole10Native.java index fef85f82db2..027500dcb57 100644 --- a/poi/src/main/java/org/apache/poi/poifs/filesystem/Ole10Native.java +++ b/poi/src/main/java/org/apache/poi/poifs/filesystem/Ole10Native.java @@ -290,7 +290,7 @@ private static String readAsciiLen(LittleEndianByteArrayInputStream leis) throws private static String readUtf16(LittleEndianByteArrayInputStream leis) throws IOException { int size = leis.readInt(); - byte[] buf = IOUtils.toByteArray(leis, size * 2, MAX_STRING_LENGTH); + byte[] buf = IOUtils.toByteArray(leis, size * 2L, MAX_STRING_LENGTH); return StringUtil.getFromUnicodeLE(buf, 0, size); } diff --git a/poi/src/test/java/org/apache/poi/poifs/filesystem/TestOle10Native.java b/poi/src/test/java/org/apache/poi/poifs/filesystem/TestOle10Native.java index 7a39eb47797..f33506de6f9 100644 --- a/poi/src/test/java/org/apache/poi/poifs/filesystem/TestOle10Native.java +++ b/poi/src/test/java/org/apache/poi/poifs/filesystem/TestOle10Native.java @@ -17,6 +17,7 @@ Licensed to the Apache Software Foundation (ASF) under one or more package org.apache.poi.poifs.filesystem; +import static org.apache.poi.POITestCase.assertContains; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.core.IsEqual.equalTo; import static org.junit.jupiter.api.Assertions.assertEquals; @@ -33,6 +34,7 @@ Licensed to the Apache Software Foundation (ASF) under one or more import org.apache.commons.io.output.UnsynchronizedByteArrayOutputStream; import org.apache.poi.POIDataSamples; import org.apache.poi.util.IOUtils; +import org.apache.poi.util.LittleEndian; import org.apache.poi.util.RecordFormatException; import org.junit.jupiter.api.Test; @@ -107,4 +109,23 @@ void testOleNativeOOM() throws IOException { } } + @Test + void testOle10NativeUtf16SizeOverflow() { + // command2 declares 0x40000001 UTF-16 chars; the byte count (size * 2) overflows + // a signed int to a negative value that slips past the MAX_STRING_LENGTH cap. + byte[] data = new byte[34]; + LittleEndian.putShort(data, 4, (short) 2); // flags1 -> parsed encoding + data[6] = 'A'; // label (AsciiZ) + data[8] = 'B'; // fileName (AsciiZ) + // flags2, unknown1, ascii command length and data length stay zero + LittleEndian.putInt(data, 22, 0x40000001); // command2 char count + LittleEndian.putInt(data, 0, data.length - 4); // totalSize + + RecordFormatException ex = assertThrows( + RecordFormatException.class, + () -> new Ole10Native(data, 0) + ); + assertContains(ex.getMessage(), "Tried to allocate"); + } + }