You are viewing a plain text version of this content. The canonical link for it is here.
Posted to server-dev@james.apache.org by ba...@apache.org on 2008/07/17 16:03:00 UTC
svn commit: r677582 - in /james/mime4j/branches/streams-refactoring/src:
main/java/org/apache/james/mime4j/ test/java/org/apache/james/mime4j/
test/java/org/apache/james/mime4j/message/
Author: bago
Date: Thu Jul 17 07:02:59 2008
New Revision: 677582
URL: http://svn.apache.org/viewvc?rev=677582&view=rev
Log:
Fix for infinite loop on very long boundary (MIME4J-55)
Patch provided by Oleg Kalnichevski.
Modified:
james/mime4j/branches/streams-refactoring/src/main/java/org/apache/james/mime4j/BufferedLineReaderInputStream.java
james/mime4j/branches/streams-refactoring/src/main/java/org/apache/james/mime4j/MimeBoundaryInputStream.java
james/mime4j/branches/streams-refactoring/src/main/java/org/apache/james/mime4j/MimeEntity.java
james/mime4j/branches/streams-refactoring/src/test/java/org/apache/james/mime4j/MimeBoundaryInputStreamTest.java
james/mime4j/branches/streams-refactoring/src/test/java/org/apache/james/mime4j/message/MessageParserTest.java
Modified: james/mime4j/branches/streams-refactoring/src/main/java/org/apache/james/mime4j/BufferedLineReaderInputStream.java
URL: http://svn.apache.org/viewvc/james/mime4j/branches/streams-refactoring/src/main/java/org/apache/james/mime4j/BufferedLineReaderInputStream.java?rev=677582&r1=677581&r2=677582&view=diff
==============================================================================
--- james/mime4j/branches/streams-refactoring/src/main/java/org/apache/james/mime4j/BufferedLineReaderInputStream.java (original)
+++ james/mime4j/branches/streams-refactoring/src/main/java/org/apache/james/mime4j/BufferedLineReaderInputStream.java Thu Jul 17 07:02:59 2008
@@ -28,7 +28,7 @@
*/
public class BufferedLineReaderInputStream extends LineReaderInputStream {
- private final byte[] buffer;
+ private byte[] buffer;
private int bufpos;
private int buflen;
@@ -46,6 +46,21 @@
this.buflen = 0;
}
+ private void expand(int newlen) {
+ byte newbuffer[] = new byte[newlen];
+ int len = this.buflen - this.bufpos;
+ if (len > 0) {
+ System.arraycopy(this.buffer, this.bufpos, newbuffer, this.bufpos, len);
+ }
+ this.buffer = newbuffer;
+ }
+
+ public void ensureCapacity(int len) {
+ if (len > this.buffer.length) {
+ expand(len);
+ }
+ }
+
public int fillBuffer() throws IOException {
// compact the buffer if necessary
if (this.bufpos > 0) {
@@ -253,6 +268,10 @@
return this.buflen - this.bufpos;
}
+ public int capacity() {
+ return this.buffer.length;
+ }
+
public int skip(int n) {
int chunk = Math.min(n, this.buflen - this.bufpos);
this.bufpos += chunk;
Modified: james/mime4j/branches/streams-refactoring/src/main/java/org/apache/james/mime4j/MimeBoundaryInputStream.java
URL: http://svn.apache.org/viewvc/james/mime4j/branches/streams-refactoring/src/main/java/org/apache/james/mime4j/MimeBoundaryInputStream.java?rev=677582&r1=677581&r2=677582&view=diff
==============================================================================
--- james/mime4j/branches/streams-refactoring/src/main/java/org/apache/james/mime4j/MimeBoundaryInputStream.java (original)
+++ james/mime4j/branches/streams-refactoring/src/main/java/org/apache/james/mime4j/MimeBoundaryInputStream.java Thu Jul 17 07:02:59 2008
@@ -49,7 +49,10 @@
public MimeBoundaryInputStream(BufferedLineReaderInputStream inbuffer, String boundary)
throws IOException {
super(inbuffer);
- this.buffer = (BufferedLineReaderInputStream) in;
+ if (inbuffer.capacity() <= boundary.length()) {
+ throw new IllegalArgumentException("Boundary is too long");
+ }
+ this.buffer = inbuffer;
this.eof = false;
this.limit = -1;
this.atBoundary = false;
Modified: james/mime4j/branches/streams-refactoring/src/main/java/org/apache/james/mime4j/MimeEntity.java
URL: http://svn.apache.org/viewvc/james/mime4j/branches/streams-refactoring/src/main/java/org/apache/james/mime4j/MimeEntity.java?rev=677582&r1=677581&r2=677582&view=diff
==============================================================================
--- james/mime4j/branches/streams-refactoring/src/main/java/org/apache/james/mime4j/MimeEntity.java (original)
+++ james/mime4j/branches/streams-refactoring/src/main/java/org/apache/james/mime4j/MimeEntity.java Thu Jul 17 07:02:59 2008
@@ -162,10 +162,17 @@
}
private void createMimeStream() throws IOException {
+ String boundary = body.getBoundary();
+ int bufferSize = 2 * boundary.length();
+ if (bufferSize < 4096) {
+ bufferSize = 4096;
+ }
if (mimeStream != null) {
- mimeStream = new MimeBoundaryInputStream(new BufferedLineReaderInputStream(mimeStream, 4 * 1024), body.getBoundary());
+ mimeStream = new MimeBoundaryInputStream(
+ new BufferedLineReaderInputStream(mimeStream, bufferSize), boundary);
} else {
- mimeStream = new MimeBoundaryInputStream(inbuffer, body.getBoundary());
+ inbuffer.ensureCapacity(bufferSize);
+ mimeStream = new MimeBoundaryInputStream(inbuffer, boundary);
}
dataStream = new LineReaderInputStreamAdaptor(mimeStream);
}
Modified: james/mime4j/branches/streams-refactoring/src/test/java/org/apache/james/mime4j/MimeBoundaryInputStreamTest.java
URL: http://svn.apache.org/viewvc/james/mime4j/branches/streams-refactoring/src/test/java/org/apache/james/mime4j/MimeBoundaryInputStreamTest.java?rev=677582&r1=677581&r2=677582&view=diff
==============================================================================
--- james/mime4j/branches/streams-refactoring/src/test/java/org/apache/james/mime4j/MimeBoundaryInputStreamTest.java (original)
+++ james/mime4j/branches/streams-refactoring/src/test/java/org/apache/james/mime4j/MimeBoundaryInputStreamTest.java Thu Jul 17 07:02:59 2008
@@ -36,26 +36,26 @@
* @version $Id: MimeBoundaryInputStreamTest.java,v 1.2 2004/10/02 12:41:11 ntherning Exp $
*/
public class MimeBoundaryInputStreamTest extends TestCase {
-
- public void testBasicReading() throws IOException {
+
+ public void testBasicReading() throws IOException {
String text = "Line 1\r\nLine 2\r\n--boundary\r\n" +
- "Line 3\r\nLine 4\r\n--boundary--";
-
- ByteArrayInputStream bis = new ByteArrayInputStream(text.getBytes("US-ASCII"));
-
- BufferedLineReaderInputStream buffer = new BufferedLineReaderInputStream(bis, 4096);
-
- MimeBoundaryInputStream mime1 = new MimeBoundaryInputStream(buffer, "boundary");
- assertEquals("Line 1\r\nLine 2", read(mime1, 5));
-
- assertFalse(mime1.isLastPart());
-
- MimeBoundaryInputStream mime2 = new MimeBoundaryInputStream(buffer, "boundary");
- assertEquals("Line 3\r\nLine 4", read(mime2, 5));
-
- assertTrue(mime2.isLastPart());
- }
-
+ "Line 3\r\nLine 4\r\n--boundary--";
+
+ ByteArrayInputStream bis = new ByteArrayInputStream(text.getBytes("US-ASCII"));
+
+ BufferedLineReaderInputStream buffer = new BufferedLineReaderInputStream(bis, 4096);
+
+ MimeBoundaryInputStream mime1 = new MimeBoundaryInputStream(buffer, "boundary");
+ assertEquals("Line 1\r\nLine 2", read(mime1, 5));
+
+ assertFalse(mime1.isLastPart());
+
+ MimeBoundaryInputStream mime2 = new MimeBoundaryInputStream(buffer, "boundary");
+ assertEquals("Line 3\r\nLine 4", read(mime2, 5));
+
+ assertTrue(mime2.isLastPart());
+ }
+
public void testLenientLineDelimiterReading() throws IOException {
String text = "Line 1\r\nLine 2\n--boundary\n" +
"Line 3\r\nLine 4\n--boundary--\n";
@@ -75,92 +75,92 @@
assertTrue(mime2.isLastPart());
}
- public void testBasicReadingSmallBuffer1() throws IOException {
- String text = "yadayadayadayadayadayadayadayadayadayadayadayadayadayadayadayada\r\n--boundary\r\n" +
- "blahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblah\r\n--boundary--";
-
- ByteArrayInputStream bis = new ByteArrayInputStream(text.getBytes("US-ASCII"));
-
- BufferedLineReaderInputStream buffer = new BufferedLineReaderInputStream(bis, 20);
-
- MimeBoundaryInputStream mime1 = new MimeBoundaryInputStream(buffer, "boundary");
- assertEquals("yadayadayadayadayadayadayadayadayadayadayadayadayadayadayadayada",
- read(mime1, 10));
-
- assertFalse(mime1.isLastPart());
-
- MimeBoundaryInputStream mime2 = new MimeBoundaryInputStream(buffer, "boundary");
- assertEquals("blahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblah",
- read(mime2, 10));
-
- assertTrue(mime2.isLastPart());
- }
-
- public void testBasicReadingSmallBuffer2() throws IOException {
- String text = "yadayadayadayadayadayadayadayadayadayadayadayadayadayadayadayada\r\n--boundary\r\n" +
- "blahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblah\r\n--boundary--";
-
- ByteArrayInputStream bis = new ByteArrayInputStream(text.getBytes("US-ASCII"));
-
- BufferedLineReaderInputStream buffer = new BufferedLineReaderInputStream(bis, 20);
-
- MimeBoundaryInputStream mime1 = new MimeBoundaryInputStream(buffer, "boundary");
-
- assertEquals("yadayadayadayadayadayadayadayadayadayadayadayadayadayadayadayada",
- read(mime1, 25));
-
- assertFalse(mime1.isLastPart());
-
- MimeBoundaryInputStream mime2 = new MimeBoundaryInputStream(buffer, "boundary");
- assertEquals("blahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblah",
- read(mime2, 25));
-
- assertTrue(mime2.isLastPart());
- }
-
- public void testBasicReadingByOneByte() throws IOException {
- String text = "Line 1\r\nLine 2\r\n--boundary\r\n" +
- "Line 3\r\nLine 4\r\n--boundary--";
-
- ByteArrayInputStream bis = new ByteArrayInputStream(text.getBytes("US-ASCII"));
-
- BufferedLineReaderInputStream buffer = new BufferedLineReaderInputStream(bis, 4096);
-
- MimeBoundaryInputStream mime1 = new MimeBoundaryInputStream(buffer, "boundary");
- assertEquals("Line 1\r\nLine 2", readByOneByte(mime1));
-
- assertFalse(mime1.isLastPart());
-
- MimeBoundaryInputStream mime2 = new MimeBoundaryInputStream(buffer, "boundary");
- assertEquals("Line 3\r\nLine 4", readByOneByte(mime2));
-
- assertTrue(mime2.isLastPart());
+ public void testBasicReadingSmallBuffer1() throws IOException {
+ String text = "yadayadayadayadayadayadayadayadayadayadayadayadayadayadayadayada\r\n--boundary\r\n" +
+ "blahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblah\r\n--boundary--";
+
+ ByteArrayInputStream bis = new ByteArrayInputStream(text.getBytes("US-ASCII"));
+
+ BufferedLineReaderInputStream buffer = new BufferedLineReaderInputStream(bis, 20);
+
+ MimeBoundaryInputStream mime1 = new MimeBoundaryInputStream(buffer, "boundary");
+ assertEquals("yadayadayadayadayadayadayadayadayadayadayadayadayadayadayadayada",
+ read(mime1, 10));
+
+ assertFalse(mime1.isLastPart());
+
+ MimeBoundaryInputStream mime2 = new MimeBoundaryInputStream(buffer, "boundary");
+ assertEquals("blahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblah",
+ read(mime2, 10));
+
+ assertTrue(mime2.isLastPart());
+ }
+
+ public void testBasicReadingSmallBuffer2() throws IOException {
+ String text = "yadayadayadayadayadayadayadayadayadayadayadayadayadayadayadayada\r\n--boundary\r\n" +
+ "blahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblah\r\n--boundary--";
+
+ ByteArrayInputStream bis = new ByteArrayInputStream(text.getBytes("US-ASCII"));
+
+ BufferedLineReaderInputStream buffer = new BufferedLineReaderInputStream(bis, 20);
+
+ MimeBoundaryInputStream mime1 = new MimeBoundaryInputStream(buffer, "boundary");
+
+ assertEquals("yadayadayadayadayadayadayadayadayadayadayadayadayadayadayadayada",
+ read(mime1, 25));
+
+ assertFalse(mime1.isLastPart());
+
+ MimeBoundaryInputStream mime2 = new MimeBoundaryInputStream(buffer, "boundary");
+ assertEquals("blahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblah",
+ read(mime2, 25));
+
+ assertTrue(mime2.isLastPart());
+ }
+
+ public void testBasicReadingByOneByte() throws IOException {
+ String text = "Line 1\r\nLine 2\r\n--boundary\r\n" +
+ "Line 3\r\nLine 4\r\n--boundary--";
+
+ ByteArrayInputStream bis = new ByteArrayInputStream(text.getBytes("US-ASCII"));
+
+ BufferedLineReaderInputStream buffer = new BufferedLineReaderInputStream(bis, 4096);
+
+ MimeBoundaryInputStream mime1 = new MimeBoundaryInputStream(buffer, "boundary");
+ assertEquals("Line 1\r\nLine 2", readByOneByte(mime1));
+
+ assertFalse(mime1.isLastPart());
+
+ MimeBoundaryInputStream mime2 = new MimeBoundaryInputStream(buffer, "boundary");
+ assertEquals("Line 3\r\nLine 4", readByOneByte(mime2));
+
+ assertTrue(mime2.isLastPart());
}
/**
- * Tests that a CRLF immediately preceding a boundary isn't included in
- * the stream.
+ * Tests that a CRLF immediately preceding a boundary isn't included in
+ * the stream.
*/
- public void testCRLFPrecedingBoundary() throws IOException {
- String text = "Line 1\r\nLine 2\r\n--boundary\r\n" +
- "Line 3\r\nLine 4\r\n\r\n--boundary\r\n";
-
- ByteArrayInputStream bis = new ByteArrayInputStream(text.getBytes("US-ASCII"));
-
- BufferedLineReaderInputStream buffer = new BufferedLineReaderInputStream(bis, 4096);
-
- MimeBoundaryInputStream mime1 = new MimeBoundaryInputStream(buffer, "boundary");
- assertEquals("Line 1\r\nLine 2", read(mime1, 5));
-
- assertFalse(mime1.isLastPart());
-
- MimeBoundaryInputStream mime2 = new MimeBoundaryInputStream(buffer, "boundary");
- assertEquals("Line 3\r\nLine 4\r\n", read(mime2, 5));
-
- assertFalse(mime2.isLastPart());
+ public void testCRLFPrecedingBoundary() throws IOException {
+ String text = "Line 1\r\nLine 2\r\n--boundary\r\n" +
+ "Line 3\r\nLine 4\r\n\r\n--boundary\r\n";
+
+ ByteArrayInputStream bis = new ByteArrayInputStream(text.getBytes("US-ASCII"));
+
+ BufferedLineReaderInputStream buffer = new BufferedLineReaderInputStream(bis, 4096);
+
+ MimeBoundaryInputStream mime1 = new MimeBoundaryInputStream(buffer, "boundary");
+ assertEquals("Line 1\r\nLine 2", read(mime1, 5));
+
+ assertFalse(mime1.isLastPart());
+
+ MimeBoundaryInputStream mime2 = new MimeBoundaryInputStream(buffer, "boundary");
+ assertEquals("Line 3\r\nLine 4\r\n", read(mime2, 5));
+
+ assertFalse(mime2.isLastPart());
}
- private String readByOneByte(InputStream is) throws IOException {
+ private String readByOneByte(InputStream is) throws IOException {
StringBuffer sb = new StringBuffer();
int b = 0;
while ((b = is.read()) != -1) {
@@ -168,18 +168,18 @@
}
return sb.toString();
}
-
- private String read(InputStream is, int bufsize) throws IOException {
- StringBuffer sb = new StringBuffer();
- int l;
- byte[] tmp = new byte[bufsize];
- while ((l = is.read(tmp)) != -1) {
- for (int i = 0; i < l; i++) {
- sb.append((char) tmp[i]);
- }
- }
- return sb.toString();
- }
+
+ private String read(InputStream is, int bufsize) throws IOException {
+ StringBuffer sb = new StringBuffer();
+ int l;
+ byte[] tmp = new byte[bufsize];
+ while ((l = is.read(tmp)) != -1) {
+ for (int i = 0; i < l; i++) {
+ sb.append((char) tmp[i]);
+ }
+ }
+ return sb.toString();
+ }
/**
* Tests that a stream containing only a boundary is empty.
@@ -188,18 +188,18 @@
String text = "--boundary\r\n";
ByteArrayInputStream bis = new ByteArrayInputStream(text.getBytes());
- BufferedLineReaderInputStream buffer = new BufferedLineReaderInputStream(bis, 4096);
-
+ BufferedLineReaderInputStream buffer = new BufferedLineReaderInputStream(bis, 4096);
+
MimeBoundaryInputStream stream =
- new MimeBoundaryInputStream(buffer, "boundary");
+ new MimeBoundaryInputStream(buffer, "boundary");
assertEquals(-1, stream.read());
text = "\r\n--boundary\r\n";
bis = new ByteArrayInputStream(text.getBytes());
- buffer = new BufferedLineReaderInputStream(bis, 4096);
+ buffer = new BufferedLineReaderInputStream(bis, 4096);
stream =
- new MimeBoundaryInputStream(buffer, "boundary");
+ new MimeBoundaryInputStream(buffer, "boundary");
assertEquals(-1, stream.read());
}
@@ -210,11 +210,11 @@
String text = "--boundary--\r\n";
ByteArrayInputStream bis = new ByteArrayInputStream(text.getBytes());
- BufferedLineReaderInputStream buffer = new BufferedLineReaderInputStream(bis, 4096);
+ BufferedLineReaderInputStream buffer = new BufferedLineReaderInputStream(bis, 4096);
MimeBoundaryInputStream stream =
- new MimeBoundaryInputStream(buffer, "boundary");
+ new MimeBoundaryInputStream(buffer, "boundary");
assertEquals(-1, stream.read());
- assertTrue(stream.isLastPart());
+ assertTrue(stream.isLastPart());
}
/**
@@ -224,16 +224,16 @@
String text = "Line 1\r\n\r\n--boundaryyada\r\n";
ByteArrayInputStream bis = new ByteArrayInputStream(text.getBytes());
- BufferedLineReaderInputStream buffer = new BufferedLineReaderInputStream(bis, 4096);
+ BufferedLineReaderInputStream buffer = new BufferedLineReaderInputStream(bis, 4096);
MimeBoundaryInputStream stream =
- new MimeBoundaryInputStream(buffer, "boundary");
- assertEquals("Line 1\r\n", read(stream, 100));
+ new MimeBoundaryInputStream(buffer, "boundary");
+ assertEquals("Line 1\r\n", read(stream, 100));
text = "--boundaryyada\r\n";
bis = new ByteArrayInputStream(text.getBytes());
- buffer = new BufferedLineReaderInputStream(bis, 4096);
- stream = new MimeBoundaryInputStream(buffer, "boundary");
+ buffer = new BufferedLineReaderInputStream(bis, 4096);
+ stream = new MimeBoundaryInputStream(buffer, "boundary");
assertEquals(-1, stream.read());
}
@@ -330,4 +330,17 @@
assertEquals(-1, instream.readLine(linebuf));
}
+ public void testboundaryLongerThanBuffer() throws IOException {
+ String text = "--looooooooooooooooooooooooooong-boundary\r\n";
+
+ ByteArrayInputStream bis = new ByteArrayInputStream(text.getBytes());
+ BufferedLineReaderInputStream buffer = new BufferedLineReaderInputStream(bis, 10);
+
+ try {
+ new MimeBoundaryInputStream(buffer, "looooooooooooooooooooooooooong-boundary");
+ fail("IllegalArgumentException should have been thrown");
+ } catch (IllegalArgumentException expected) {
+ }
+ }
+
}
Modified: james/mime4j/branches/streams-refactoring/src/test/java/org/apache/james/mime4j/message/MessageParserTest.java
URL: http://svn.apache.org/viewvc/james/mime4j/branches/streams-refactoring/src/test/java/org/apache/james/mime4j/message/MessageParserTest.java?rev=677582&r1=677581&r2=677582&view=diff
==============================================================================
--- james/mime4j/branches/streams-refactoring/src/test/java/org/apache/james/mime4j/message/MessageParserTest.java (original)
+++ james/mime4j/branches/streams-refactoring/src/test/java/org/apache/james/mime4j/message/MessageParserTest.java Thu Jul 17 07:02:59 2008
@@ -20,14 +20,7 @@
package org.apache.james.mime4j.message;
import org.apache.commons.io.IOUtils;
-import org.apache.james.mime4j.EOLConvertingInputStream;
import org.apache.james.mime4j.field.Field;
-import org.apache.james.mime4j.message.BinaryBody;
-import org.apache.james.mime4j.message.Body;
-import org.apache.james.mime4j.message.Entity;
-import org.apache.james.mime4j.message.Message;
-import org.apache.james.mime4j.message.Multipart;
-import org.apache.james.mime4j.message.TextBody;
import org.apache.james.mime4j.util.CharsetUtil;
import org.apache.log4j.BasicConfigurator;
@@ -90,10 +83,7 @@
System.out.println("Parsing " + f.getName());
- InputStream in = new EOLConvertingInputStream(new BufferedInputStream(
- new FileInputStream(f))); //,
-
- Message m = new Message(in);
+ Message m = new Message(new FileInputStream(f));
String prefix = f.getName().substring(0, f.getName().length() - 4);
String xmlFileName = fileName.substring(0, fileName.length() - 4)
@@ -104,8 +94,7 @@
+ "_decoded.mime4j.xml";
String expected = null;
try {
- expected = IOUtils.toString(
- new FileInputStream(xmlFileName), "ISO8859-1");
+ expected = IOUtils.toString(new FileInputStream(xmlFileName), "ISO8859-1");
} catch (FileNotFoundException ex) {
writeToFile(result, mime4jFileName);
fail("Test file not found. Generated the expected result with mime4j prefix: "+ex.getMessage());
---------------------------------------------------------------------
To unsubscribe, e-mail: server-dev-unsubscribe@james.apache.org
For additional commands, e-mail: server-dev-help@james.apache.org