Skip to content

MultiInputStream produces stack overflow #2996

@jkoroid

Description

@jkoroid

Using guava-23.0 (and earlier versions), com.google.common.io.MultiInputStream produces a stack overflow when it is given sufficiently many empty ByteSource instances.

Test cases that reproduce the behavior:

import java.io.InputStream;
import java.util.List;

import org.junit.Before;
import org.junit.Test;

import com.google.common.collect.Lists;
import com.google.common.io.ByteSource;

public class MultiInputStreamTest {

  /** Adjust this according to the thread stack size. */
  private static final int LARGE_ENOUGH_FOR_CURRENT_STACK_SIZE = 1000000;

  private ByteSource       concatenated;

  public @Before void setup() throws Exception {
    final List<ByteSource> emptySources = Lists.newArrayList();
    for (int i = 0; i < LARGE_ENOUGH_FOR_CURRENT_STACK_SIZE; i++) {
      emptySources.add(ByteSource.empty());
    }
    // produce a ConcatenatedByteSource which in turn produces
    // a MultiInputStream
    concatenated = ByteSource.concat(emptySources);
  }

  public @Test void stackOverflowErrorOnEmptySources1() throws Exception {
    try (InputStream in = concatenated.openStream()) {
      in.read();
    }
  }

  public @Test void stackOverflowErrorOnEmptySources2() throws Exception {
    try (InputStream in = concatenated.openStream()) {
      in.read(new byte[1], 0, 1);
    }
  }

}

The condensed exception stack traces produced by the respective test case (which appear to be truncated):

$ uniq -c stack1
   1 java.lang.StackOverflowError
   1 	at com.google.common.io.ByteSource$ByteArrayByteSource.openStream(ByteSource.java:574)
   1 	at com.google.common.io.MultiInputStream.advance(MultiInputStream.java:65)
   1 	at com.google.common.io.MultiInputStream.read(MultiInputStream.java:89)
1021 	at com.google.common.io.MultiInputStream.read(MultiInputStream.java:90)
$ uniq -c stack2
   1 java.lang.StackOverflowError
   1 	at com.google.common.io.MultiInputStream.close(MultiInputStream.java:52)
   1 	at com.google.common.io.MultiInputStream.advance(MultiInputStream.java:63)
   1 	at com.google.common.io.MultiInputStream.read(MultiInputStream.java:102)
1021 	at com.google.common.io.MultiInputStream.read(MultiInputStream.java:103)

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions