Improve argument type checkign on string libraries.

This commit is contained in:
James Roseborough
2008-07-18 01:22:00 +00:00
parent 41ed2fa8ad
commit 0c02382673
2 changed files with 55 additions and 45 deletions

View File

@@ -26,6 +26,7 @@ import org.luaj.vm.LNumber;
import org.luaj.vm.LString; import org.luaj.vm.LString;
import org.luaj.vm.LTable; import org.luaj.vm.LTable;
import org.luaj.vm.LValue; import org.luaj.vm.LValue;
import org.luaj.vm.Lua;
import org.luaj.vm.LuaState; import org.luaj.vm.LuaState;
@@ -152,21 +153,21 @@ public class StringLib extends LFunction {
* @param vm the calling vm * @param vm the calling vm
*/ */
static void byte_( LuaState vm ) { static void byte_( LuaState vm ) {
LString ls = vm.tolstring(2); LString s = vm.checklstring(2);
int l = ls.length(); int l = s.m_length;
final int top = vm.gettop(); int posi = posrelat( vm.optint(3,1), l );
int i = posrelat( ( top >= 3 ) ? vm.tointeger(3) : 1, l ); int pose = posrelat( vm.optint(4,posi), l );
int j = posrelat( ( top >= 4 ) ? vm.tointeger(4) : i, l );
vm.resettop(); vm.resettop();
if ( i <= 0 ) int n,i;
i = 1; if (posi <= 0) posi = 1;
if ( j > l ) if (pose > l) pose = l;
j = l; if (posi > pose) return; /* empty interval; return no values */
if ( i > j ) n = (int)(pose - posi + 1);
return; if (posi + n <= pose) /* overflow? */
int n = j - i + 1; vm.error("string slice too long");
for ( int k=0; k < n; k++ ) vm.checkstack(n);
vm.pushinteger( ls.luaByte(k+i-1) ); for (i=0; i<n; i++)
vm.pushinteger(s.luaByte(posi+i-1));
} }
/** /**
@@ -181,10 +182,13 @@ public class StringLib extends LFunction {
* @param vm the calling VM * @param vm the calling VM
*/ */
public static void char_( LuaState vm) { public static void char_( LuaState vm) {
int nargs = vm.gettop()-1; int n = vm.gettop()-1;
byte[] bytes = new byte[nargs]; byte[] bytes = new byte[n];
for ( int i=0; i<nargs; i++ ) for ( int i=0, a=2; i<n; i++, a++ ) {
bytes[i] = (byte)( vm.tointeger(i+2) & 0x0FF ); int c = vm.checkint(a);
vm.argcheck((c>=0 && c<256), a, "invalid value");
bytes[i] = (byte) c;
}
vm.resettop(); vm.resettop();
vm.pushlstring( bytes ); vm.pushlstring( bytes );
} }
@@ -275,8 +279,8 @@ public class StringLib extends LFunction {
* as this would prevent the iteration. * as this would prevent the iteration.
*/ */
static void gmatch( LuaState vm ) { static void gmatch( LuaState vm ) {
LString src = vm.tolstring( 2 ); LString src = vm.checklstring( 2 );
LString pat = vm.tolstring( 3 ); LString pat = vm.checklstring( 3 );
vm.resettop(); vm.resettop();
vm.pushlvalue( new GMatchAux(vm, src, pat) ); vm.pushlvalue( new GMatchAux(vm, src, pat) );
} }
@@ -354,11 +358,11 @@ public class StringLib extends LFunction {
* --> x="lua-5.1.tar.gz" * --> x="lua-5.1.tar.gz"
*/ */
static void gsub( LuaState vm ) { static void gsub( LuaState vm ) {
LString src = vm.tolstring(2); LString src = vm.checklstring(2);
final int srclen = src.length(); final int srclen = src.length();
LString p = vm.tolstring(3); LString p = vm.checklstring(3);
LValue repl = vm.topointer( 4 ); LValue repl = vm.topointer( 4 );
int max_s = ( vm.gettop() >= 5 ? vm.tointeger( 5 ) : srclen + 1 ); int max_s = vm.optint( 5, srclen + 1 );
final boolean anchor = p.length() > 0 && p.charAt( 0 ) == '^'; final boolean anchor = p.length() > 0 && p.charAt( 0 ) == '^';
LBuffer lbuf = new LBuffer( srclen ); LBuffer lbuf = new LBuffer( srclen );
@@ -395,7 +399,7 @@ public class StringLib extends LFunction {
* Embedded zeros are counted, so "a\000bc\000" has length 5. * Embedded zeros are counted, so "a\000bc\000" has length 5.
*/ */
static void len( LuaState vm ) { static void len( LuaState vm ) {
int l = vm.tolstring(2).length(); int l = vm.checklstring(2).length();
vm.resettop(); vm.resettop();
vm.pushinteger( l ); vm.pushinteger( l );
} }
@@ -408,7 +412,7 @@ public class StringLib extends LFunction {
* The definition of what an uppercase letter is depends on the current locale. * The definition of what an uppercase letter is depends on the current locale.
*/ */
static void lower( LuaState vm ) { static void lower( LuaState vm ) {
String s = vm.tostring(2).toLowerCase(); String s = vm.checkstring(2).toLowerCase();
vm.resettop(); vm.resettop();
vm.pushstring( s ); vm.pushstring( s );
} }
@@ -432,8 +436,8 @@ public class StringLib extends LFunction {
* Returns a string that is the concatenation of n copies of the string s. * Returns a string that is the concatenation of n copies of the string s.
*/ */
static void rep( LuaState vm ) { static void rep( LuaState vm ) {
LString s = vm.tolstring(2); LString s = vm.checklstring(2);
int n = vm.tointeger( 3 ); int n = vm.checkint( 3 );
vm.resettop(); vm.resettop();
if ( n >= 0 ) { if ( n >= 0 ) {
final byte[] bytes = new byte[ s.length() * n ]; final byte[] bytes = new byte[ s.length() * n ];
@@ -451,7 +455,7 @@ public class StringLib extends LFunction {
* Returns a string that is the string s reversed. * Returns a string that is the string s reversed.
*/ */
static void reverse( LuaState vm ) { static void reverse( LuaState vm ) {
LString s = vm.tolstring(2); LString s = vm.checklstring(2);
int n = s.length(); int n = s.length();
byte[] b = new byte[n]; byte[] b = new byte[n];
for ( int i=0, j=n-1; i<n; i++, j-- ) for ( int i=0, j=n-1; i<n; i++, j-- )
@@ -472,12 +476,11 @@ public class StringLib extends LFunction {
* returns a suffix of s with length i. * returns a suffix of s with length i.
*/ */
static void sub( LuaState vm ) { static void sub( LuaState vm ) {
final int top = vm.gettop(); final LString s = vm.checklstring(2);
final LString s = vm.tolstring(2);
final int len = s.length(); final int len = s.length();
int i = posrelat( top >= 3 ? vm.tointeger( 3 ) : 1, len ); int i = posrelat( vm.checkint( 3 ), len );
int j = posrelat( top >= 4 ? vm.tointeger( 4 ) : -1, len ); int j = posrelat( vm.optint( 4, -1 ), len );
if ( i < 1 ) if ( i < 1 )
i = 1; i = 1;
@@ -501,7 +504,7 @@ public class StringLib extends LFunction {
* The definition of what a lowercase letter is depends on the current locale. * The definition of what a lowercase letter is depends on the current locale.
*/ */
static void upper( LuaState vm ) { static void upper( LuaState vm ) {
String s = vm.tostring(2).toUpperCase(); String s = vm.checkstring(2).toUpperCase();
vm.resettop(); vm.resettop();
vm.pushstring(s); vm.pushstring(s);
} }
@@ -510,9 +513,9 @@ public class StringLib extends LFunction {
* This utility method implements both string.find and string.match. * This utility method implements both string.find and string.match.
*/ */
static void str_find_aux( LuaState vm, boolean find ) { static void str_find_aux( LuaState vm, boolean find ) {
LString s = vm.tolstring(2); LString s = vm.checklstring(2);
LString pat = vm.tolstring(3); LString pat = vm.checklstring(3);
int init = vm.gettop() >= 4 ? vm.tointeger( 4 ) : 1; int init = vm.optint( 4 , 1 );
if ( init > 0 ) { if ( init > 0 ) {
init = Math.min( init - 1, s.length() ); init = Math.min( init - 1, s.length() );
@@ -669,7 +672,7 @@ public class StringLib extends LFunction {
vm.pop( 1 ); vm.pop( 1 );
vm.pushlvalue( ((LTable) repl).luaGetTable( vm, k ) ); vm.pushlvalue( ((LTable) repl).luaGetTable( vm, k ) );
} else { } else {
vm.error( "string/function/table expected" ); vm.error( "bad argument: string/function/table expected" );
return; return;
} }

View File

@@ -5,7 +5,9 @@ require 'args'
-- string.byte -- string.byte
banner('string.byte') banner('string.byte')
checkallpass('string.byte',{somestring,{nil,ainteger},{nil,ainteger}}) checkallpass('string.byte',{somestring})
checkallpass('string.byte',{somestring,somenumber})
checkallpass('string.byte',{somestring,somenumber,somenumber})
checkallerrors('string.byte',{somestring,{astring,afunction,atable}},'bad argument') checkallerrors('string.byte',{somestring,{astring,afunction,atable}},'bad argument')
checkallerrors('string.byte',{notastring,{nil,111}},'bad argument') checkallerrors('string.byte',{notastring,{nil,111}},'bad argument')
@@ -53,9 +55,9 @@ local somerepl = {astring,atable,afunction}
local notarepl = {nil,aboolean} local notarepl = {nil,aboolean}
banner('string.gsub') banner('string.gsub')
checkallpass('string.gsub',{somestring,somestring,somerepl,{nil,-1}}) checkallpass('string.gsub',{somestring,somestring,somerepl,{nil,-1}})
checkallerrors('string.gsub',{notastring,somestring,somerepl},'bad argument #1') checkallerrors('string.gsub',{nonstring,somestring,somerepl},'bad argument #1')
checkallerrors('string.gsub',{somestring,notastring,somerepl},'bad argument #2') checkallerrors('string.gsub',{somestring,nonstring,somerepl},'bad argument #2')
checkallerrors('string.gsub',{{astring},{astring},notarepl},'bad argument #3') checkallerrors('string.gsub',{{astring},{astring},notarepl},'bad argument')
checkallerrors('string.gsub',{{astring},{astring},somerepl,nonnumber},'bad argument #4') checkallerrors('string.gsub',{{astring},{astring},somerepl,nonnumber},'bad argument #4')
-- string.len -- string.len
@@ -72,8 +74,10 @@ checkallerrors('string.lower',{notastring},'bad argument #1')
banner('string.match') banner('string.match')
checkallpass('string.match',{somestring,somestring}) checkallpass('string.match',{somestring,somestring})
checkallpass('string.match',{somestring,somestring,{nil,-3,3}}) checkallpass('string.match',{somestring,somestring,{nil,-3,3}})
checkallerrors('string.match',{notastring,somestring},'bad argument #1') checkallerrors('string.match',{},'bad argument #1')
checkallerrors('string.match',{somestring,notastring},'bad argument #2') checkallerrors('string.match',{nonstring,somestring},'bad argument #1')
checkallerrors('string.match',{somestring},'bad argument #2')
checkallerrors('string.match',{somestring,nonstring},'bad argument #2')
checkallerrors('string.match',{somestring,somestring,notanumber},'bad argument #3') checkallerrors('string.match',{somestring,somestring,notanumber},'bad argument #3')
-- string.reverse -- string.reverse
@@ -89,9 +93,12 @@ checkallerrors('string.rep',{somestring,notanumber},'bad argument #2')
-- string.sub -- string.sub
banner('string.sub') banner('string.sub')
checkallpass('string.sub',{somestring,somenumber})
checkallpass('string.sub',{somestring,somenumber,somenumber}) checkallpass('string.sub',{somestring,somenumber,somenumber})
checkallerrors('string.sub',{notastring,somenumber,somenumber},'bad argument #1') checkallerrors('string.sub',{},'bad argument #1')
checkallerrors('string.sub',{somestring,notanumber,somenumber},'bad argument #2') checkallerrors('string.sub',{nonstring,somenumber,somenumber},'bad argument #1')
checkallerrors('string.sub',{somestring},'bad argument #2')
checkallerrors('string.sub',{somestring,nonnumber,somenumber},'bad argument #2')
checkallerrors('string.sub',{somestring,somenumber,nonnumber},'bad argument #3') checkallerrors('string.sub',{somestring,somenumber,nonnumber},'bad argument #3')
-- string.upper -- string.upper