Sophie

Sophie

distrib > Mageia > 5 > i586 > by-pkgid > 816d49666a8972b88637859ce5c9eee0 > files > 2

apache-poi-3.10.1-3.mga5.src.rpm

diff -Nru poi-3.10.1/src/scratchpad/src/org/apache/poi/hslf/HSLFSlideShow.java poi-3.10.1.CVE-2014-9527/src/scratchpad/src/org/apache/poi/hslf/HSLFSlideShow.java
--- poi-3.10.1/src/scratchpad/src/org/apache/poi/hslf/HSLFSlideShow.java	2014-08-13 16:05:33.000000000 +0200
+++ poi-3.10.1.CVE-2014-9527/src/scratchpad/src/org/apache/poi/hslf/HSLFSlideShow.java	2015-02-14 16:11:13.481868934 +0100
@@ -20,16 +20,16 @@
 import java.io.ByteArrayInputStream;
 import java.io.ByteArrayOutputStream;
 import java.io.FileInputStream;
-import java.io.FileNotFoundException;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
 import java.util.ArrayList;
-import java.util.Arrays;
 import java.util.HashMap;
 import java.util.Hashtable;
 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;
@@ -81,7 +81,7 @@
 
     // Embedded objects stored in storage records in the document stream, lazily populated.
     private ObjectData[] _objects;
-
+    
     /**
 	 * Returns the underlying POIFSFileSystem for the document
 	 *  that is open.
@@ -195,6 +195,9 @@
 		// Look for any other streams
 		readOtherStreams();
 	}
+	
+	
+	
 	/**
 	 * Constructs a new, empty, Powerpoint document.
 	 */
@@ -269,41 +272,67 @@
         _records = read(_docstream, (int)currentUser.getCurrentEditOffset());
 	}
 
-    private Record[] read(byte[] docstream, int usrOffset){
-        ArrayList<Integer> lst = new ArrayList<Integer>();
-        HashMap<Integer,Integer> offset2id = new HashMap<Integer,Integer>();
+	private Record[] read(byte[] docstream, int usrOffset){
+        //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(usrOffset);
+            recordMap.put(usrOffset, usr);
+            
             int psrOffset = usr.getPersistPointersOffset();
-
             PersistPtrHolder ptr = (PersistPtrHolder)Record.buildRecordAtOffset(docstream, psrOffset);
-            lst.add(psrOffset);
-            Hashtable<Integer,Integer> entries = ptr.getSlideLocationsLookup();
-            for(Integer id : entries.keySet()) {
-                Integer offset = entries.get(id);
-                lst.add(offset);
+            recordMap.put(psrOffset, ptr);
+            
+            for(Map.Entry<Integer,Integer> entry : ptr.getSlideLocationsLookup().entrySet()) {
+                Integer offset = entry.getValue();
+                Integer id = 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)
-        Integer a[] = lst.toArray(new Integer[lst.size()]);
-        Arrays.sort(a);
-        Record[] rec = new Record[lst.size()];
-        for (int i = 0; i < a.length; i++) {
-            Integer offset = a[i];
-            rec[i] = Record.buildRecordAtOffset(docstream, offset.intValue());
-            if(rec[i] instanceof PersistRecord) {
-                PersistRecord psr = (PersistRecord)rec[i];
-                Integer id = offset2id.get(offset);
-                psr.setPersistId(id.intValue());
-            }
-        }
 
-        return rec;
+            // 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");
+                }
+            }
+        }       
     }
 
 	/**
@@ -324,34 +353,30 @@
 	private void readOtherStreams() {
 		// Currently, there aren't any
 	}
-
 	/**
 	 * Find and read in pictures contained in this presentation.
 	 * This is lazily called as and when we want to touch pictures.
 	 */
+    @SuppressWarnings("unused")
 	private void readPictures() throws IOException {
         _pictures = new ArrayList<PictureData>();
 
-		byte[] pictstream;
-
-		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;
-		}
+        // if the presentation doesn't contain pictures - will use a null set instead
+        if (!directory.hasEntry("Pictures")) return;
+        
+		DocumentEntry entry = (DocumentEntry)directory.getEntry("Pictures");
+		byte[] pictstream = new byte[entry.getSize()];
+		DocumentInputStream is = directory.createDocumentInputStream(entry);
+		is.read(pictstream);
+		is.close();
 
+		
         int pos = 0;
 		// An empty picture record (length 0) will take up 8 bytes
         while (pos <= (pictstream.length-8)) {
             int offset = pos;
-
+            
             // Image signature
-            @SuppressWarnings("unused")
             int signature = LittleEndian.getUShort(pictstream, pos);
             pos += LittleEndian.SHORT_SIZE;
             // Image type + 0xF018