1
0
mirror of https://github.com/SquidDev-CC/CC-Tweaked synced 2024-12-12 11:10:29 +00:00

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.
This commit is contained in:
SquidDev 2018-04-23 16:41:00 +01:00
parent 914df8b0c7
commit 7dbc4e6455
2 changed files with 80 additions and 15 deletions

View File

@ -5,6 +5,7 @@ import dan200.computercraft.api.lua.ILuaContext;
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 @@ import static dan200.computercraft.core.apis.ArgumentHelper.getInt;
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 class BinaryInputHandle extends HandleGeneric
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 );
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 };
if( read < 0 ) return null;
if( read < count ) bytes = Arrays.copyOf( bytes, read );
return new Object[] { bytes };
}
else
{
byte[] buffer = new byte[ BUFFER_SIZE ];
// 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
{

View File

@ -6,10 +6,12 @@ import dan200.computercraft.api.lua.LuaException;
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 @@ public class EncodedInputHandle extends HandleGeneric
try
{
int count = optInt( args, 0, 1 );
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 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
{
// 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 )
{