From 0c02382673d2dde4715a548bf856e82ca070eb53 Mon Sep 17 00:00:00 2001 From: James Roseborough Date: Fri, 18 Jul 2008 01:22:00 +0000 Subject: [PATCH] Improve argument type checkign on string libraries. --- src/core/org/luaj/lib/StringLib.java | 77 +++++++++++++++------------- src/test/errors/stringlibargs.lua | 23 ++++++--- 2 files changed, 55 insertions(+), 45 deletions(-) diff --git a/src/core/org/luaj/lib/StringLib.java b/src/core/org/luaj/lib/StringLib.java index ab04eec2..14d30261 100644 --- a/src/core/org/luaj/lib/StringLib.java +++ b/src/core/org/luaj/lib/StringLib.java @@ -26,6 +26,7 @@ import org.luaj.vm.LNumber; import org.luaj.vm.LString; import org.luaj.vm.LTable; import org.luaj.vm.LValue; +import org.luaj.vm.Lua; import org.luaj.vm.LuaState; @@ -152,21 +153,21 @@ public class StringLib extends LFunction { * @param vm the calling vm */ static void byte_( LuaState vm ) { - LString ls = vm.tolstring(2); - int l = ls.length(); - final int top = vm.gettop(); - int i = posrelat( ( top >= 3 ) ? vm.tointeger(3) : 1, l ); - int j = posrelat( ( top >= 4 ) ? vm.tointeger(4) : i, l ); + LString s = vm.checklstring(2); + int l = s.m_length; + int posi = posrelat( vm.optint(3,1), l ); + int pose = posrelat( vm.optint(4,posi), l ); vm.resettop(); - if ( i <= 0 ) - i = 1; - if ( j > l ) - j = l; - if ( i > j ) - return; - int n = j - i + 1; - for ( int k=0; k < n; k++ ) - vm.pushinteger( ls.luaByte(k+i-1) ); + int n,i; + if (posi <= 0) posi = 1; + if (pose > l) pose = l; + if (posi > pose) return; /* empty interval; return no values */ + n = (int)(pose - posi + 1); + if (posi + n <= pose) /* overflow? */ + vm.error("string slice too long"); + vm.checkstack(n); + for (i=0; i=0 && c<256), a, "invalid value"); + bytes[i] = (byte) c; + } vm.resettop(); vm.pushlstring( bytes ); } @@ -275,8 +279,8 @@ public class StringLib extends LFunction { * as this would prevent the iteration. */ static void gmatch( LuaState vm ) { - LString src = vm.tolstring( 2 ); - LString pat = vm.tolstring( 3 ); + LString src = vm.checklstring( 2 ); + LString pat = vm.checklstring( 3 ); vm.resettop(); vm.pushlvalue( new GMatchAux(vm, src, pat) ); } @@ -354,11 +358,11 @@ public class StringLib extends LFunction { * --> x="lua-5.1.tar.gz" */ static void gsub( LuaState vm ) { - LString src = vm.tolstring(2); + LString src = vm.checklstring(2); final int srclen = src.length(); - LString p = vm.tolstring(3); + LString p = vm.checklstring(3); 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 ) == '^'; 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. */ static void len( LuaState vm ) { - int l = vm.tolstring(2).length(); + int l = vm.checklstring(2).length(); vm.resettop(); 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. */ static void lower( LuaState vm ) { - String s = vm.tostring(2).toLowerCase(); + String s = vm.checkstring(2).toLowerCase(); vm.resettop(); 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. */ static void rep( LuaState vm ) { - LString s = vm.tolstring(2); - int n = vm.tointeger( 3 ); + LString s = vm.checklstring(2); + int n = vm.checkint( 3 ); vm.resettop(); if ( n >= 0 ) { 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. */ static void reverse( LuaState vm ) { - LString s = vm.tolstring(2); + LString s = vm.checklstring(2); int n = s.length(); byte[] b = new byte[n]; for ( int i=0, j=n-1; i= 3 ? vm.tointeger( 3 ) : 1, len ); - int j = posrelat( top >= 4 ? vm.tointeger( 4 ) : -1, len ); + int i = posrelat( vm.checkint( 3 ), len ); + int j = posrelat( vm.optint( 4, -1 ), len ); if ( 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. */ static void upper( LuaState vm ) { - String s = vm.tostring(2).toUpperCase(); + String s = vm.checkstring(2).toUpperCase(); vm.resettop(); vm.pushstring(s); } @@ -510,9 +513,9 @@ public class StringLib extends LFunction { * This utility method implements both string.find and string.match. */ static void str_find_aux( LuaState vm, boolean find ) { - LString s = vm.tolstring(2); - LString pat = vm.tolstring(3); - int init = vm.gettop() >= 4 ? vm.tointeger( 4 ) : 1; + LString s = vm.checklstring(2); + LString pat = vm.checklstring(3); + int init = vm.optint( 4 , 1 ); if ( init > 0 ) { init = Math.min( init - 1, s.length() ); @@ -669,7 +672,7 @@ public class StringLib extends LFunction { vm.pop( 1 ); vm.pushlvalue( ((LTable) repl).luaGetTable( vm, k ) ); } else { - vm.error( "string/function/table expected" ); + vm.error( "bad argument: string/function/table expected" ); return; } diff --git a/src/test/errors/stringlibargs.lua b/src/test/errors/stringlibargs.lua index 32e91062..1467e271 100644 --- a/src/test/errors/stringlibargs.lua +++ b/src/test/errors/stringlibargs.lua @@ -5,7 +5,9 @@ require 'args' -- 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',{notastring,{nil,111}},'bad argument') @@ -53,9 +55,9 @@ local somerepl = {astring,atable,afunction} local notarepl = {nil,aboolean} banner('string.gsub') checkallpass('string.gsub',{somestring,somestring,somerepl,{nil,-1}}) -checkallerrors('string.gsub',{notastring,somestring,somerepl},'bad argument #1') -checkallerrors('string.gsub',{somestring,notastring,somerepl},'bad argument #2') -checkallerrors('string.gsub',{{astring},{astring},notarepl},'bad argument #3') +checkallerrors('string.gsub',{nonstring,somestring,somerepl},'bad argument #1') +checkallerrors('string.gsub',{somestring,nonstring,somerepl},'bad argument #2') +checkallerrors('string.gsub',{{astring},{astring},notarepl},'bad argument') checkallerrors('string.gsub',{{astring},{astring},somerepl,nonnumber},'bad argument #4') -- string.len @@ -72,8 +74,10 @@ checkallerrors('string.lower',{notastring},'bad argument #1') banner('string.match') checkallpass('string.match',{somestring,somestring}) checkallpass('string.match',{somestring,somestring,{nil,-3,3}}) -checkallerrors('string.match',{notastring,somestring},'bad argument #1') -checkallerrors('string.match',{somestring,notastring},'bad argument #2') +checkallerrors('string.match',{},'bad argument #1') +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') -- string.reverse @@ -89,9 +93,12 @@ checkallerrors('string.rep',{somestring,notanumber},'bad argument #2') -- string.sub banner('string.sub') +checkallpass('string.sub',{somestring,somenumber}) checkallpass('string.sub',{somestring,somenumber,somenumber}) -checkallerrors('string.sub',{notastring,somenumber,somenumber},'bad argument #1') -checkallerrors('string.sub',{somestring,notanumber,somenumber},'bad argument #2') +checkallerrors('string.sub',{},'bad argument #1') +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') -- string.upper