Skip to content
Permalink
Browse files

Remove upper bound on how many bytes/characters can be read

The limit was added to prevent people creating arbitrarily large buffers
(for instance, handle.read(2^31) would create a 2GB char array). For
"large" counts, we now read in blocks of size 8192, adding to an
extendable buffer.
  • Loading branch information...
SquidDev committed Apr 23, 2018
1 parent 914df8b commit 7dbc4e64556b4bbc8af7e0cc403cb1d6d30fdb32
@@ -5,6 +5,7 @@
import dan200.computercraft.api.lua.LuaException;

import javax.annotation.Nonnull;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Arrays;
@@ -13,6 +14,8 @@

public class BinaryInputHandle extends HandleGeneric
{
private static final int BUFFER_SIZE = 8192;

private final InputStream m_stream;

public BinaryInputHandle( InputStream reader )
@@ -45,16 +48,46 @@ public BinaryInputHandle( InputStream reader )
if( args.length > 0 && args[ 0 ] != null )
{
int count = getInt( args, 0 );
if( count <= 0 || count >= 1024 * 16 )
if( count < 0 )
{
throw new LuaException( "Count out of range" );
// Whilst this may seem absurd to allow reading 0 bytes, PUC Lua it so
// it seems best to remain somewhat consistent.
throw new LuaException( "Cannot read a negative number of bytes" );
}
else if( count <= BUFFER_SIZE )
{
// If we've got a small count, then allocate that and read it.
byte[] bytes = new byte[ count ];
int read = m_stream.read( bytes );

if( read < 0 ) return null;
if( read < count ) bytes = Arrays.copyOf( bytes, read );
return new Object[] { bytes };
}
else
{
byte[] buffer = new byte[ BUFFER_SIZE ];

byte[] bytes = new byte[ count ];
count = m_stream.read( bytes );
if( count < 0 ) return null;
if( count < bytes.length ) bytes = Arrays.copyOf( bytes, count );
return new Object[] { bytes };
// Read the initial set of bytes, failing if none are read.
int read = m_stream.read( buffer, 0, Math.min( buffer.length, count ) );
if( read == -1 ) return null;

ByteArrayOutputStream out = new ByteArrayOutputStream( read );
count -= read;
out.write( buffer, 0, read );

// Otherwise read until we either reach the limit or we no longer consume
// the full buffer.
while( read >= buffer.length && count > 0 )
{
read = m_stream.read( buffer, 0, Math.min( BUFFER_SIZE, count ) );
if( read == -1 ) break;
count -= read;
out.write( buffer, 0, read );
}

return new Object[] { out.toByteArray() };
}
}
else
{
@@ -6,10 +6,12 @@
import javax.annotation.Nonnull;
import java.io.*;

import static dan200.computercraft.core.apis.ArgumentHelper.*;
import static dan200.computercraft.core.apis.ArgumentHelper.optInt;

public class EncodedInputHandle extends HandleGeneric
{
private static final int BUFFER_SIZE = 8192;

private final BufferedReader m_reader;

public EncodedInputHandle( BufferedReader reader )
@@ -111,15 +113,45 @@ private static BufferedReader makeReader( InputStream stream, String encoding )
try
{
int count = optInt( args, 0, 1 );
if( count <= 0 || count >= 1024 * 16 )
if( count < 0 )
{
// Whilst this may seem absurd to allow reading 0 characters, PUC Lua it so
// it seems best to remain somewhat consistent.
throw new LuaException( "Cannot read a negative number of characters" );
}
else if( count <= BUFFER_SIZE )
{
// If we've got a small count, then allocate that and read it.
char[] chars = new char[ count ];
int read = m_reader.read( chars );

return read < 0 ? null : new Object[] { new String( chars, 0, read ) };
}
else
{
throw new LuaException( "Count out of range" );
// If we've got a large count, read in bunches of 8192.
char[] buffer = new char[ BUFFER_SIZE ];

// Read the initial set of characters, failing if none are read.
int read = m_reader.read( buffer, 0, Math.min( buffer.length, count ) );
if( read == -1 ) return null;

StringBuilder out = new StringBuilder( read );
count -= read;
out.append( buffer, 0, read );

// Otherwise read until we either reach the limit or we no longer consume
// the full buffer.
while( read >= BUFFER_SIZE && count > 0 )
{
read = m_reader.read( buffer, 0, Math.min( BUFFER_SIZE, count ) );
if( read == -1 ) break;
count -= read;
out.append( buffer, 0, read );
}

return new Object[] { out.toString() };
}
char[] bytes = new char[ count ];
count = m_reader.read( bytes );
if( count < 0 ) return null;
String str = new String( bytes, 0, count );
return new Object[] { str };
}
catch( IOException e )
{

0 comments on commit 7dbc4e6

Please sign in to comment.
You can’t perform that action at this time.