7058700: Unexpected exceptions and timeouts in SF2 parser code
authorserb
Thu, 31 Jul 2014 21:09:52 +0100
changeset 26022 45e78fc2279f
parent 26021 847033cb0339
child 26023 bdcfc40fbce5
7058700: Unexpected exceptions and timeouts in SF2 parser code Reviewed-by: prr, pchelko
jdk/src/share/classes/com/sun/media/sound/RIFFReader.java
jdk/src/share/classes/com/sun/media/sound/SF2Soundbank.java
--- a/jdk/src/share/classes/com/sun/media/sound/RIFFReader.java	Thu Jul 31 23:00:24 2014 +0400
+++ b/jdk/src/share/classes/com/sun/media/sound/RIFFReader.java	Thu Jul 31 21:09:52 2014 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2007, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 2014, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -39,21 +39,20 @@
     private long filepointer = 0;
     private final String fourcc;
     private String riff_type = null;
-    private long ckSize = 0;
+    private long ckSize = Integer.MAX_VALUE;
     private InputStream stream;
-    private long avail;
+    private long avail = Integer.MAX_VALUE;
     private RIFFReader lastiterator = null;
 
     public RIFFReader(InputStream stream) throws IOException {
 
-        if (stream instanceof RIFFReader)
-            root = ((RIFFReader)stream).root;
-        else
+        if (stream instanceof RIFFReader) {
+            root = ((RIFFReader) stream).root;
+        } else {
             root = this;
+        }
 
         this.stream = stream;
-        avail = Integer.MAX_VALUE;
-        ckSize = Integer.MAX_VALUE;
 
         // Check for RIFF null paddings,
         int b;
@@ -75,9 +74,12 @@
         fourcc[0] = (byte) b;
         readFully(fourcc, 1, 3);
         this.fourcc = new String(fourcc, "ascii");
-        ckSize = readUnsignedInt();
-
-        avail = this.ckSize;
+        final long size = readUnsignedInt();
+        if (size > Integer.MAX_VALUE) {
+            throw new RIFFInvalidDataException("Chunk size too big");
+        }
+        ckSize = size;
+        avail = size;
 
         if (getFormat().equals("RIFF") || getFormat().equals("LIST")) {
             byte[] format = new byte[4];
@@ -118,19 +120,23 @@
     }
 
     public int read() throws IOException {
-        if (avail == 0)
+        if (avail == 0) {
             return -1;
+        }
         int b = stream.read();
-        if (b == -1)
+        if (b == -1) {
+            avail = 0;
             return -1;
+        }
         avail--;
         filepointer++;
         return b;
     }
 
     public int read(byte[] b, int offset, int len) throws IOException {
-        if (avail == 0)
+        if (avail == 0) {
             return -1;
+        }
         if (len > avail) {
             int rlen = stream.read(b, offset, (int)avail);
             if (rlen != -1)
@@ -139,8 +145,10 @@
             return rlen;
         } else {
             int ret = stream.read(b, offset, len);
-            if (ret == -1)
+            if (ret == -1) {
+                avail = 0;
                 return -1;
+            }
             avail -= ret;
             filepointer += ret;
             return ret;
@@ -191,8 +199,10 @@
             return len;
         } else {
             long ret = stream.skip(n);
-            if (ret == -1)
+            if (ret == -1) {
+                avail = 0;
                 return -1;
+            }
             avail -= ret;
             filepointer += ret;
             return ret;
@@ -210,8 +220,13 @@
     }
 
     // Read ASCII chars from stream
-    public String readString(int len) throws IOException {
-        byte[] buff = new byte[len];
+    public String readString(final int len) throws IOException {
+        final byte[] buff;
+        try {
+            buff = new byte[len];
+        } catch (final OutOfMemoryError oom) {
+            throw new IOException("Length too big", oom);
+        }
         readFully(buff);
         for (int i = 0; i < buff.length; i++) {
             if (buff[i] == 0) {
--- a/jdk/src/share/classes/com/sun/media/sound/SF2Soundbank.java	Thu Jul 31 23:00:24 2014 +0400
+++ b/jdk/src/share/classes/com/sun/media/sound/SF2Soundbank.java	Thu Jul 31 21:09:52 2014 +0100
@@ -276,6 +276,9 @@
                     count--;
                 }
 
+                if (presets_bagNdx.isEmpty()) {
+                    throw new RIFFInvalidDataException();
+                }
                 int offset = presets_bagNdx.get(0);
                 // Offset should be 0 (but just case)
                 for (int i = 0; i < offset; i++) {
@@ -360,6 +363,9 @@
                     count--;
                 }
 
+                if (instruments_bagNdx.isEmpty()) {
+                    throw new RIFFInvalidDataException();
+                }
                 int offset = instruments_bagNdx.get(0);
                 // Offset should be 0 (but just case)
                 for (int i = 0; i < offset; i++) {
@@ -401,6 +407,9 @@
                     modulator.amount = chunk.readShort();
                     modulator.amountSourceOperator = chunk.readUnsignedShort();
                     modulator.transportOperator = chunk.readUnsignedShort();
+                    if (i < 0 || i >= instruments_splits_gen.size()) {
+                        throw new RIFFInvalidDataException();
+                    }
                     SF2LayerRegion split = instruments_splits_gen.get(i);
                     if (split != null)
                         split.modulators.add(modulator);
@@ -424,7 +433,8 @@
                     sample.name = chunk.readString(20);
                     long start = chunk.readUnsignedInt();
                     long end = chunk.readUnsignedInt();
-                    sample.data = sampleData.subbuffer(start * 2, end * 2, true);
+                    if (sampleData != null)
+                        sample.data = sampleData.subbuffer(start * 2, end * 2, true);
                     if (sampleData24 != null)
                         sample.data24 = sampleData24.subbuffer(start, end, true);
                     /*
@@ -462,6 +472,9 @@
                     int sampleid = split.generators.get(
                             SF2LayerRegion.GENERATOR_SAMPLEID);
                     split.generators.remove(SF2LayerRegion.GENERATOR_SAMPLEID);
+                    if (sampleid < 0 || sampleid >= samples.size()) {
+                        throw new RIFFInvalidDataException();
+                    }
                     split.sample = samples.get(sampleid);
                 } else {
                     globalsplit = split;
@@ -488,6 +501,9 @@
                     int instrumentid = split.generators.get(
                             SF2InstrumentRegion.GENERATOR_INSTRUMENT);
                     split.generators.remove(SF2LayerRegion.GENERATOR_INSTRUMENT);
+                    if (instrumentid < 0 || instrumentid >= layers.size()) {
+                        throw new RIFFInvalidDataException();
+                    }
                     split.layer = layers.get(instrumentid);
                 } else {
                     globalsplit = split;