ustring: Handle invalid types in gsub

If the replacement table or function results in a value that isn't a
string or number (or nil), string.gsub raises an error. Have ustring
raise the same error.

Bug: T195326
Change-Id: Ic36f9f5d7adc0c14e7a4a94d3747335107acd8b6
This commit is contained in:
Brad Jorsch 2018-05-22 18:50:00 -04:00
parent 131af4d277
commit 32718af677
3 changed files with 41 additions and 2 deletions

View file

@ -679,7 +679,14 @@ class Scribunto_LuaUstringLibrary extends Scribunto_LuaLibraryBase {
$m = array_shift( $captures );
}
$x = isset( $m['m1'] ) ? $m['m1'] : $m[0];
return isset( $repl[$x] ) ? $repl[$x] : $m[0];
if ( !isset( $repl[$x] ) || $repl[$x] === null ) {
return $m[0];
}
$type = $this->getLuaType( $repl[$x] );
if ( $type !== 'string' && $type !== 'number' ) {
throw new Scribunto_LuaError( "invalid replacement value (a $type)" );
}
return $repl[$x];
};
break;
@ -701,6 +708,10 @@ class Scribunto_LuaUstringLibrary extends Scribunto_LuaLibraryBase {
if ( count( $ret ) === 0 || $ret[0] === null ) {
return $m[0];
}
$type = $this->getLuaType( $ret[0] );
if ( $type !== 'string' && $type !== 'number' ) {
throw new Scribunto_LuaError( "invalid replacement value (a $type)" );
}
return $ret[0];
};
break;

View file

@ -1002,7 +1002,7 @@ function ustring.gsub( s, pattern, repl, n )
ret[#ret + 1] = sub( s, cps, init, m[1] - 1 )
end
local mm = sub( s, cps, m[1], m[2] )
local val
local val, valType
if tp == 1 then
if m[3] then
val = repl( unpack( m, 3 ) )
@ -1034,6 +1034,10 @@ function ustring.gsub( s, pattern, repl, n )
}
val = S.gsub( repl, '%%[%%0-9]', t )
end
valType = type( val )
if valType ~= 'nil' and valType ~= 'string' and valType ~= 'number' then
error( 'invalid replacement value (a ' .. valType .. ')', 2 )
end
ret[#ret + 1] = val or mm
init = m[2] + 1
ct = ct + 1

View file

@ -640,6 +640,30 @@ return testframework.getTestProvider( {
args = { '12345', '[3]', 9 },
expect = { '12945', 1 }
},
{ name = 'gsub: table replacement with a bad type (boolean)', func = mw.ustring.gsub,
args = { 'abc', 'b', { b = true } },
expect = 'invalid replacement value (a boolean)'
},
{ name = 'gsub: table replacement with a bad type (table)', func = mw.ustring.gsub,
args = { 'abc', 'b', { b = {} } },
expect = 'invalid replacement value (a table)'
},
{ name = 'gsub: table replacement with a bad type (function)', func = mw.ustring.gsub,
args = { 'abc', 'b', { b = function () end } },
expect = 'invalid replacement value (a function)'
},
{ name = 'gsub: function replacement with a bad type (boolean)', func = mw.ustring.gsub,
args = { 'abc', 'b', function () return true end },
expect = 'invalid replacement value (a boolean)'
},
{ name = 'gsub: function replacement with a bad type (table)', func = mw.ustring.gsub,
args = { 'abc', 'b', function () return {} end },
expect = 'invalid replacement value (a table)'
},
{ name = 'gsub: function replacement with a bad type (function)', func = mw.ustring.gsub,
args = { 'abc', 'b', function () return function () end end },
expect = 'invalid replacement value (a function)'
},
{ name = 'gcodepoint: basic test', func = mw.ustring.gcodepoint,
args = { str1 },