From 1823459ab0219a856a46f27b574d3240a90b94df Mon Sep 17 00:00:00 2001 From: Glen Stampoultzis Date: Sun, 19 Sep 2004 02:26:30 +0000 Subject: [PATCH] Bugzilla Bug 27929 - finally :-) git-svn-id: https://svn.apache.org/repos/asf/jakarta/poi/trunk@353599 13f79535-47bb-0310-9956-ffa450edef68 --- .../org/apache/poi/hssf/record/ObjRecord.java | 2 +- .../org/apache/poi/hssf/record/SubRecord.java | 22 ++++- .../apache/poi/hssf/record/TestSubRecord.java | 98 +++++++++++++++++++ 3 files changed, 117 insertions(+), 5 deletions(-) create mode 100644 src/testcases/org/apache/poi/hssf/record/TestSubRecord.java diff --git a/src/java/org/apache/poi/hssf/record/ObjRecord.java b/src/java/org/apache/poi/hssf/record/ObjRecord.java index 75d594fea..2380c0803 100644 --- a/src/java/org/apache/poi/hssf/record/ObjRecord.java +++ b/src/java/org/apache/poi/hssf/record/ObjRecord.java @@ -98,7 +98,7 @@ public class ObjRecord short subRecordSize = LittleEndian.getShort(data, pos + 2); Record subRecord = SubRecord.createSubRecord(subRecordSid, subRecordSize, data, pos + 4); subrecords.add(subRecord); - pos += 4 + subRecordSize; + pos += subRecord.getRecordSize(); } } diff --git a/src/java/org/apache/poi/hssf/record/SubRecord.java b/src/java/org/apache/poi/hssf/record/SubRecord.java index f04863f06..d680a47d8 100644 --- a/src/java/org/apache/poi/hssf/record/SubRecord.java +++ b/src/java/org/apache/poi/hssf/record/SubRecord.java @@ -42,19 +42,33 @@ abstract public class SubRecord { Record r = null; + short adjustedSize = size; + if ( size < 0 ) + { + adjustedSize = 0; + } + else if ( offset + size > data.length ) + { + adjustedSize = (short) ( data.length - offset ); + if ( adjustedSize > 4 ) + { + adjustedSize -= 4; + } + } + switch ( subRecordSid ) { case CommonObjectDataSubRecord.sid: - r = new CommonObjectDataSubRecord( subRecordSid, size, data, offset ); + r = new CommonObjectDataSubRecord( subRecordSid, adjustedSize, data, offset ); break; case GroupMarkerSubRecord.sid: - r = new GroupMarkerSubRecord( subRecordSid, size, data, offset ); + r = new GroupMarkerSubRecord( subRecordSid, adjustedSize, data, offset ); break; case EndSubRecord.sid: - r = new EndSubRecord( subRecordSid, size, data, offset ); + r = new EndSubRecord( subRecordSid, adjustedSize, data, offset ); break; default: - r = new UnknownRecord( subRecordSid, size, data, offset ); + r = new UnknownRecord( subRecordSid, adjustedSize, data, offset ); } return r; diff --git a/src/testcases/org/apache/poi/hssf/record/TestSubRecord.java b/src/testcases/org/apache/poi/hssf/record/TestSubRecord.java new file mode 100644 index 000000000..3385cb911 --- /dev/null +++ b/src/testcases/org/apache/poi/hssf/record/TestSubRecord.java @@ -0,0 +1,98 @@ +/* ==================================================================== + Copyright 2002-2004 Apache Software Foundation + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + + +package org.apache.poi.hssf.record; + + +import junit.framework.TestCase; + +/** + * Tests Subrecord components of an OBJ record. Test data taken directly + * from a real Excel file. + * + * @author Michael Zalewski (zalewski@optonline.net) + */ +public class TestSubRecord + extends TestCase +{ + /* + The following is a dump of the OBJ record corresponding to an auto-filter + drop-down list. The 3rd subrecord beginning at offset 0x002e (type=0x0013) + does not conform to the documentation, because the length field is 0x1fee, + which is longer than the entire OBJ record. + + 00000000 15 00 12 00 14 00 01 00 01 21 00 00 00 00 3C 13 .........!....<. Type=0x15 Len=0x0012 ftCmo + 00000010 F4 03 00 00 00 00 + 0C 00 14 00 00 00 00 00 00 00 ................ Type=0x0c Len=0x0014 ftSbs + 00000020 00 00 00 00 01 00 08 00 00 00 10 00 00 00 + 13 00 ................ Type=0x13 Len=0x1FEE ftLbsData + 00000030 EE 1F 00 00 08 00 08 00 01 03 00 00 0A 00 14 00 ................ + 00000040 6C 00 + 00 00 00 00 l..... Type=0x00 Len=0x0000 ftEnd + */ + + byte[] dataAutoFilter = new byte[]{ + // ftCmo + (byte) 0x15, (byte) 0x00, (byte) 0x12, (byte) 0x00, (byte) 0x14, (byte) 0x00, (byte) 0x01, (byte) 0x00 + , (byte) 0x01, (byte) 0x00, (byte) 0x01, (byte) 0x21, (byte) 0x00, (byte) 0x00, (byte) 0x3c, (byte) 0x13 + , (byte) 0xf4, (byte) 0x03, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00 + + // ftSbs (currently UnknownSubrecord) + , (byte) 0x0c, (byte) 0x00 + , (byte) 0x14, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00 + , (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x01, (byte) 0x00, (byte) 0x08, (byte) 0x00 + , (byte) 0x00, (byte) 0x00, (byte) 0x10, (byte) 0x00, (byte) 0x00, (byte) 0x00 + + // ftLbsData (currently UnknownSubrecord) + , (byte) 0x13, (byte) 0x00 + , (byte) 0xee, (byte) 0x1f, (byte) 0x00, (byte) 0x00, (byte) 0x08, (byte) 0x00, (byte) 0x08, (byte) 0x00 + , (byte) 0x01, (byte) 0x03, (byte) 0x00, (byte) 0x00, (byte) 0x0a, (byte) 0x00, (byte) 0x14, (byte) 0x00 + , (byte) 0x6c, (byte) 0x00 + + // ftEnd + , (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00 + }; + + public TestSubRecord( String name ) + { + super( name ); + } + + public void testParseCmo() + { + Record r = SubRecord.createSubRecord( (short) 0x0015, (short) 0x0012, dataAutoFilter, 0x0000 ); + assertEquals( "ftCmo is 22 bytes", 22, r.getRecordSize() ); + assertEquals( "ftCmo is a CommonObjectDataSubRecord" + , "org.apache.poi.hssf.record.CommonObjectDataSubRecord" + , r.getClass().getName() ); + } + + public void testParseAutoFilterLbsData() + { + Record r = SubRecord.createSubRecord( (short) 0x0013, (short) 0x1fee, dataAutoFilter, 0x0032 ); + assertEquals( "ftLbsData is 20 bytes", 20, r.getRecordSize() ); + } + + public void testParseEnd() + { + Record r = SubRecord.createSubRecord( (short) 0x0000, (short) 0x0000, dataAutoFilter, 0x0046 ); + assertEquals( "ftEnd is 4 bytes", 4, r.getRecordSize() ); + assertEquals( "ftEnd is a EndSubRecord" + , "org.apache.poi.hssf.record.EndSubRecord" + , r.getClass().getName() ); + } +}