From 937d2cbd25b967195ee81c74a43fa3ae4fd2d703 Mon Sep 17 00:00:00 2001 From: Peter Hancock Date: Mon, 22 Aug 2011 15:14:54 +0000 Subject: [PATCH] Fixed a bug in AFP where an ArrayOutofBoundsException is throwqn when embedding a Page Segment. git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@1160298 13f79535-47bb-0310-9956-ffa450edef68 --- build.xml | 1 + .../apache/fop/afp/util/AFPResourceUtil.java | 60 +++++------ status.xml | 4 + .../fop/afp/AFPResourceUtilTestCase.java | 100 ++++++++++++++++++ .../java/org/apache/fop/afp/AFPTestSuite.java | 1 + .../fop/afp/expected_named_resource.afp | Bin 0 -> 21494 bytes .../org/apache/fop/afp/expected_resource.afp | Bin 0 -> 21511 bytes 7 files changed, 134 insertions(+), 32 deletions(-) create mode 100644 test/java/org/apache/fop/afp/AFPResourceUtilTestCase.java create mode 100644 test/java/org/apache/fop/afp/expected_named_resource.afp create mode 100644 test/java/org/apache/fop/afp/expected_resource.afp diff --git a/build.xml b/build.xml index 1dd2ca689..c1828a144 100644 --- a/build.xml +++ b/build.xml @@ -738,6 +738,7 @@ list of possible build targets. + diff --git a/src/java/org/apache/fop/afp/util/AFPResourceUtil.java b/src/java/org/apache/fop/afp/util/AFPResourceUtil.java index 979376b3e..538f2b880 100644 --- a/src/java/org/apache/fop/afp/util/AFPResourceUtil.java +++ b/src/java/org/apache/fop/afp/util/AFPResourceUtil.java @@ -92,10 +92,13 @@ public final class AFPResourceUtil { throws UnsupportedEncodingException { //The first 8 bytes of the field data represent the resource name byte[] nameBytes = new byte[8]; - System.arraycopy(field.getData(), 0, nameBytes, 0, 8); - String asciiName; - asciiName = new String(nameBytes, AFPConstants.EBCIDIC_ENCODING); - return asciiName; + + byte[] fieldData = field.getData(); + if (fieldData.length < 8) { + throw new IllegalArgumentException("Field data does not contain a resource name"); + } + System.arraycopy(fieldData, 0, nameBytes, 0, 8); + return new String(nameBytes, AFPConstants.EBCIDIC_ENCODING); } /** @@ -128,12 +131,13 @@ public final class AFPResourceUtil { public static void copyNamedResource(String name, final InputStream in, final OutputStream out) throws IOException { final MODCAParser parser = new MODCAParser(in); - Collection resourceNames = new java.util.HashSet(); + Collection resourceNames = new java.util.HashSet(); //Find matching "Begin" field final UnparsedStructuredField fieldBegin; while (true) { - UnparsedStructuredField field = parser.readNextStructuredField(); + final UnparsedStructuredField field = parser.readNextStructuredField(); + if (field == null) { throw new IOException("Requested resource '" + name + "' not found. Encountered resource names: " + resourceNames); @@ -142,8 +146,10 @@ public final class AFPResourceUtil { if (field.getSfTypeCode() != TYPE_CODE_BEGIN) { //0xA8=Begin continue; //Not a "Begin" field } - String resourceName = getResourceName(field); + final String resourceName = getResourceName(field); + resourceNames.add(resourceName); + if (resourceName.equals(name)) { if (LOG.isDebugEnabled()) { LOG.debug("Start of requested structured field found:\n" @@ -170,45 +176,35 @@ public final class AFPResourceUtil { if (wrapInResource) { ResourceObject resourceObject = new ResourceObject(name) { protected void writeContent(OutputStream os) throws IOException { - copyStructuredFields(name, fieldBegin, parser, out); + copyNamedStructuredFields(name, fieldBegin, parser, out); } }; resourceObject.setType(ResourceObject.TYPE_PAGE_SEGMENT); resourceObject.writeToStream(out); } else { - copyStructuredFields(name, fieldBegin, parser, out); + copyNamedStructuredFields(name, fieldBegin, parser, out); } } - private static void copyStructuredFields(String name, UnparsedStructuredField fieldBegin, - MODCAParser parser, OutputStream out) throws IOException { - boolean inRequestedResource; + private static void copyNamedStructuredFields(final String name, + UnparsedStructuredField fieldBegin, MODCAParser parser, + OutputStream out) throws IOException { - //The "Begin" field first - out.write(MODCAParser.CARRIAGE_CONTROL_CHAR); - fieldBegin.writeTo(out); - UnparsedStructuredField field; + UnparsedStructuredField field = fieldBegin; - //Then the rest of the fields until the corresponding "End" field - inRequestedResource = true; - do { - field = parser.readNextStructuredField(); + while (true) { if (field == null) { - break; //Unexpected EOF - } - - if (field.getSfTypeCode() == TYPE_CODE_END) { - String resourceName = getResourceName(field); - if (resourceName.equals(name)) { - inRequestedResource = false; //Signal end of loop - } + throw new IOException("Ending structured field not found for resource " + name); } out.write(MODCAParser.CARRIAGE_CONTROL_CHAR); field.writeTo(out); - } while (inRequestedResource); - if (inRequestedResource) { - throw new IOException("Ending structured field not found for resource " + name); + + if (field.getSfTypeCode() == TYPE_CODE_END + && fieldBegin.getSfCategoryCode() == field.getSfCategoryCode() + && name.equals(getResourceName(field))) { + break; + } + field = parser.readNextStructuredField(); } } - } diff --git a/status.xml b/status.xml index 2295a4f60..340030f22 100644 --- a/status.xml +++ b/status.xml @@ -60,6 +60,10 @@ documents. Example: the fix of marks layering will be such a case when it's done. --> + + Fixed a bug in AFP where an ArrayOutofBoundsException is throwqn when embedding a Page + Segment. + Added support for 128bit encryption in PDF output. Based on work by Michael Rubin. diff --git a/test/java/org/apache/fop/afp/AFPResourceUtilTestCase.java b/test/java/org/apache/fop/afp/AFPResourceUtilTestCase.java new file mode 100644 index 000000000..da3e023a4 --- /dev/null +++ b/test/java/org/apache/fop/afp/AFPResourceUtilTestCase.java @@ -0,0 +1,100 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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. + */ + +/* $Id$ */ + +package org.apache.fop.afp; + +import java.io.ByteArrayOutputStream; +import java.io.InputStream; +import java.util.Arrays; + +import junit.framework.TestCase; + +import org.apache.commons.io.IOUtils; + +import org.apache.fop.afp.util.AFPResourceUtil; + +/** + * Tests the {@link AFPResourceUtil} class. + */ +public class AFPResourceUtilTestCase extends TestCase { + + private static final String RESOURCE_FILENAME = "expected_resource.afp"; + + private static final String NAMED_RESOURCE_FILENAME = "expected_named_resource.afp"; + + private static final String PSEG = "XFEATHER"; + + /** + * Tests copyResourceFile() + * @throws Exception - + */ + public void testCopyResourceFile() throws Exception { + + final ByteArrayOutputStream baos = new ByteArrayOutputStream(); + + InputStream in = null; + + try { + in = getClass().getResourceAsStream(RESOURCE_FILENAME); + AFPResourceUtil.copyResourceFile(in, baos); + } finally { + in.close(); + } + + byte[] expectedBytes = null; + + try { + in = getClass().getResourceAsStream(RESOURCE_FILENAME); + expectedBytes = IOUtils.toByteArray(in); + } finally { + in.close(); + } + + assertTrue(Arrays.equals(expectedBytes, baos.toByteArray())); + + } + + /** + * Tests copyNamedResource() + * @throws Exception - + */ + public void testCopyNamedResource() throws Exception { + final ByteArrayOutputStream baos = new ByteArrayOutputStream(); + + InputStream in = null; + + try { + in = getClass().getResourceAsStream(RESOURCE_FILENAME); + AFPResourceUtil.copyNamedResource(PSEG, in, baos); + } finally { + in.close(); + } + + byte[] expectedBytes = null; + + try { + in = getClass().getResourceAsStream(NAMED_RESOURCE_FILENAME); + expectedBytes = IOUtils.toByteArray(in); + } finally { + in.close(); + } + + assertTrue(Arrays.equals(expectedBytes, baos.toByteArray())); + } +} diff --git a/test/java/org/apache/fop/afp/AFPTestSuite.java b/test/java/org/apache/fop/afp/AFPTestSuite.java index c32eab6ea..cb57a92ed 100644 --- a/test/java/org/apache/fop/afp/AFPTestSuite.java +++ b/test/java/org/apache/fop/afp/AFPTestSuite.java @@ -38,6 +38,7 @@ public class AFPTestSuite { TestSuite suite = new TestSuite("Test suite for FOP's AFP classes"); //$JUnit-BEGIN$ suite.addTest(new TestSuite(IncludeObjectTestCase.class)); + suite.addTest(new TestSuite(AFPResourceUtilTestCase.class)); //$JUnit-END$ return suite; } diff --git a/test/java/org/apache/fop/afp/expected_named_resource.afp b/test/java/org/apache/fop/afp/expected_named_resource.afp new file mode 100644 index 0000000000000000000000000000000000000000..9fe45c38835927348d30c1d01b1ef59674e87d2d GIT binary patch literal 21494 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