Skip to content

Commit

Permalink
Remove upper bound on how many bytes/characters can be read
Browse files Browse the repository at this point in the history
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 7dbc4e6
Show file tree
Hide file tree
Showing 2 changed files with 80 additions and 15 deletions.
Expand Up @@ -5,6 +5,7 @@
import dan200.computercraft.api.lua.LuaException; import dan200.computercraft.api.lua.LuaException;


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


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

private final InputStream m_stream; private final InputStream m_stream;


public BinaryInputHandle( InputStream reader ) public BinaryInputHandle( InputStream reader )
Expand Down Expand Up @@ -45,16 +48,46 @@ public Object[] callMethod( @Nonnull ILuaContext context, int method, @Nonnull O
if( args.length > 0 && args[ 0 ] != null ) if( args.length > 0 && args[ 0 ] != null )
{ {
int count = getInt( args, 0 ); 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 ]; // Read the initial set of bytes, failing if none are read.
count = m_stream.read( bytes ); int read = m_stream.read( buffer, 0, Math.min( buffer.length, count ) );
if( count < 0 ) return null; if( read == -1 ) return null;
if( count < bytes.length ) bytes = Arrays.copyOf( bytes, count );
return new Object[] { bytes }; 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 else
{ {
Expand Down
Expand Up @@ -6,10 +6,12 @@
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
import java.io.*; import java.io.*;


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


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

private final BufferedReader m_reader; private final BufferedReader m_reader;


public EncodedInputHandle( BufferedReader reader ) public EncodedInputHandle( BufferedReader reader )
Expand Down Expand Up @@ -111,15 +113,45 @@ public Object[] callMethod( @Nonnull ILuaContext context, int method, @Nonnull O
try try
{ {
int count = optInt( args, 0, 1 ); 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 ) catch( IOException e )
{ {
Expand Down

0 comments on commit 7dbc4e6

Please sign in to comment.