[libapache-poi-java] 02/03: Fixed CVE-2014-9527: Infinite loop on corrupted PPT file (Closes: #775171)

Emmanuel Bourg ebourg-guest at moszumanska.debian.org
Mon Jan 12 15:49:02 UTC 2015


This is an automated email from the git hooks/post-receive script.

ebourg-guest pushed a commit to branch wheezy-security
in repository libapache-poi-java.

commit 2f17b68f027204eeb32fdaf1dc641ef76eac4134
Author: Emmanuel Bourg <ebourg at apache.org>
Date:   Mon Jan 12 16:44:25 2015 +0100

    Fixed CVE-2014-9527: Infinite loop on corrupted PPT file (Closes: #775171)
---
 debian/changelog                      |   1 +
 debian/patches/07_CVE-2014-9527.patch | 146 ++++++++++++++++++++++++++++++++++
 debian/patches/series                 |   1 +
 3 files changed, 148 insertions(+)

diff --git a/debian/changelog b/debian/changelog
index f6ae44f..6f0da30 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,5 +1,6 @@
 libapache-poi-java (3.6+dfsg-2+deb7u1) UNRELEASED; urgency=medium
 
+  * Fixed CVE-2014-9527: Infinite loop on corrupted PPT file (Closes: #775171)
   * Moved the package to Git
 
  -- Emmanuel Bourg <ebourg at apache.org>  Mon, 12 Jan 2015 12:22:30 +0100
diff --git a/debian/patches/07_CVE-2014-9527.patch b/debian/patches/07_CVE-2014-9527.patch
new file mode 100644
index 0000000..2dc33f7
--- /dev/null
+++ b/debian/patches/07_CVE-2014-9527.patch
@@ -0,0 +1,146 @@
+Description: Fix an infinite loop on corrupted PPT file (CVE-2014-9527).
+ This patch can be dropped after upgrading to Apache POI 3.11 or later.
+Origin: backport, http://svn.apache.org/r1643680
+Bug: https://issues.apache.org/bugzilla/show_bug.cgi?id=57272
+--- a/src/scratchpad/src/org/apache/poi/hslf/HSLFSlideShow.java
++++ b/src/scratchpad/src/org/apache/poi/hslf/HSLFSlideShow.java
+@@ -30,6 +30,9 @@
+ import java.util.Hashtable;
+ import java.util.Iterator;
+ import java.util.List;
++import java.util.Map;
++import java.util.NavigableMap;
++import java.util.TreeMap;
+ 
+ import org.apache.poi.POIDocument;
+ import org.apache.poi.hslf.exceptions.CorruptPowerPointFileException;
+@@ -41,6 +44,7 @@
+ import org.apache.poi.poifs.filesystem.DirectoryNode;
+ import org.apache.poi.poifs.filesystem.DocumentEntry;
+ import org.apache.poi.poifs.filesystem.DocumentInputStream;
++import org.apache.poi.poifs.filesystem.Entry;
+ import org.apache.poi.poifs.filesystem.POIFSFileSystem;
+ import org.apache.poi.util.LittleEndian;
+ import org.apache.poi.util.POILogFactory;
+@@ -227,42 +231,66 @@
+ 	}
+ 
+     private Record[] read(byte[] docstream, int usrOffset){
+-        ArrayList lst = new ArrayList();
+-        HashMap offset2id = new HashMap();
++        //sort found records by offset.
++        //(it is not necessary but SlideShow.findMostRecentCoreRecords() expects them sorted)
++        NavigableMap<Integer,Record> records = new TreeMap<Integer,Record>(); // offset -> record
++        Map<Integer,Integer> persistIds = new HashMap<Integer,Integer>(); // offset -> persistId
++        initRecordOffsets(docstream, usrOffset, records, persistIds);
++
++        for (Map.Entry<Integer,Record> entry : records.entrySet()) {
++            Integer offset = entry.getKey();
++            Record record = entry.getValue();
++            Integer persistId = persistIds.get(offset);
++            if (record == null) {
++                // all plain records have been already added,
++                // only new records need to be decrypted (tbd #35897)
++                record = Record.buildRecordAtOffset(docstream, offset);
++                entry.setValue(record);
++            }
++
++            if (record instanceof PersistRecord) {
++                ((PersistRecord)record).setPersistId(persistId);
++            }
++        }
++
++        return records.values().toArray(new Record[records.size()]);
++    }
++
++    private void initRecordOffsets(byte[] docstream, int usrOffset, NavigableMap<Integer,Record> recordMap, Map<Integer,Integer> offset2id) {
+         while (usrOffset != 0){
+             UserEditAtom usr = (UserEditAtom) Record.buildRecordAtOffset(docstream, usrOffset);
+-            lst.add(Integer.valueOf(usrOffset));
+-            int psrOffset = usr.getPersistPointersOffset();
++            recordMap.put(usrOffset, usr);
+ 
++            int psrOffset = usr.getPersistPointersOffset();
+             PersistPtrHolder ptr = (PersistPtrHolder)Record.buildRecordAtOffset(docstream, psrOffset);
+-            lst.add(Integer.valueOf(psrOffset));
+-            Hashtable entries = ptr.getSlideLocationsLookup();
+-            for (Iterator it = entries.keySet().iterator(); it.hasNext(); ) {
+-                Integer id = (Integer)it.next();
+-                Integer offset = (Integer)entries.get(id);
++            recordMap.put(psrOffset, ptr);
+ 
+-                lst.add(offset);
++            for(Object entry : ptr.getSlideLocationsLookup().entrySet()) {
++                Integer offset = (Integer) ((Map.Entry) entry).getValue();
++                Integer id = (Integer) ((Map.Entry) entry).getKey();
++                recordMap.put(offset, null); // reserve a slot for the record
+                 offset2id.put(offset, id);
+             }
+ 
+             usrOffset = usr.getLastUserEditAtomOffset();
+-        }
+-        //sort found records by offset.
+-        //(it is not necessary but SlideShow.findMostRecentCoreRecords() expects them sorted)
+-        Object a[] = lst.toArray();
+-        Arrays.sort(a);
+-        Record[] rec = new Record[lst.size()];
+-        for (int i = 0; i < a.length; i++) {
+-            Integer offset = (Integer)a[i];
+-            rec[i] = Record.buildRecordAtOffset(docstream, offset.intValue());
+-            if(rec[i] instanceof PersistRecord) {
+-                PersistRecord psr = (PersistRecord)rec[i];
+-                Integer id = (Integer)offset2id.get(offset);
+-                psr.setPersistId(id.intValue());
++
++            // check for corrupted user edit atom and try to repair it
++            // if the next user edit atom offset is already known, we would go into an endless loop
++            if (usrOffset > 0 && recordMap.containsKey(usrOffset)) {
++                // a user edit atom is usually located 36 byte before the smallest known record offset
++                usrOffset = recordMap.firstKey()-36;
++                // check that we really are located on a user edit atom
++                int ver_inst = LittleEndian.getUShort(docstream, usrOffset);
++                int type = LittleEndian.getUShort(docstream, usrOffset+2);
++                int len = LittleEndian.getInt(docstream, usrOffset+4);
++                if (ver_inst == 0 && type == 4085 && (len == 0x1C || len == 0x20)) {
++                    logger.log(POILogger.WARN, "Repairing invalid user edit atom");
++                    usr.setLastUserEditAtomOffset(usrOffset);
++                } else {
++                    throw new CorruptPowerPointFileException("Powerpoint document contains invalid user edit atom");
++                }
+             }
+         }
+-
+-        return rec;
+     }
+ 
+ 	/**
+@@ -291,17 +319,23 @@
+         _pictures = new ArrayList<PictureData>();
+ 
+ 		byte[] pictstream;
++        // if the presentation doesn't contain pictures - will use a null set instead
++        boolean containsPictures = false;
++        Iterator<Entry> entries = directory.getEntries();
++        while (entries.hasNext()) {
++            Entry entry = entries.next();
++            if ("Pictures".equals(entry.getName())) {
++                containsPictures = true;
++                break;
++            }
++        }
++        if (!containsPictures) return;
+ 
+-		try {
+ 			DocumentEntry entry = (DocumentEntry)directory.getEntry("Pictures");
+ 			pictstream = new byte[entry.getSize()];
+ 			DocumentInputStream is = directory.createDocumentInputStream("Pictures");
+ 			is.read(pictstream);
+-		} catch (FileNotFoundException e){
+-			// Silently catch exceptions if the presentation doesn't
+-			//  contain pictures - will use a null set instead
+-			return;
+-		}
++			is.close();
+ 
+         int pos = 0;
+ 		// An empty picture record (length 0) will take up 8 bytes
diff --git a/debian/patches/series b/debian/patches/series
index 6183ff7..c9338a7 100644
--- a/debian/patches/series
+++ b/debian/patches/series
@@ -2,3 +2,4 @@
 02_classpath.patch
 03_no_ooxml.patch
 04_jar_names.patch
+07_CVE-2014-9527.patch

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-java/libapache-poi-java.git



More information about the pkg-java-commits mailing list