Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
ruanhaishen
redis
Commits
93a74949
Commit
93a74949
authored
Apr 13, 2012
by
antirez
Browse files
Merge branch 'strict.lua' into unstable
parents
c18405c9
13a21caa
Changes
2
Hide whitespace changes
Inline
Side-by-side
src/scripting.c
View file @
93a74949
...
@@ -412,6 +412,43 @@ void luaLoadLibraries(lua_State *lua) {
...
@@ -412,6 +412,43 @@ void luaLoadLibraries(lua_State *lua) {
#endif
#endif
}
}
/* This function installs metamethods in the global table _G that prevent
* the creation of globals accidentally.
*
* It should be the last to be called in the scripting engine initialization
* sequence, because it may interact with creation of globals. */
void
scriptingEnableGlobalsProtection
(
lua_State
*
lua
)
{
char
*
s
[
32
];
sds
code
=
sdsempty
();
int
j
=
0
;
/* strict.lua from: http://metalua.luaforge.net/src/lib/strict.lua.html.
* Modified to be adapted to Redis. */
s
[
j
++
]
=
"local mt = {}
\n
"
;
s
[
j
++
]
=
"setmetatable(_G, mt)
\n
"
;
s
[
j
++
]
=
"mt.__newindex = function (t, n, v)
\n
"
;
s
[
j
++
]
=
" if debug.getinfo(2) then
\n
"
;
s
[
j
++
]
=
" local w = debug.getinfo(2,
\"
S
\"
).what
\n
"
;
s
[
j
++
]
=
" if w ~=
\"
main
\"
and w ~=
\"
C
\"
then
\n
"
;
s
[
j
++
]
=
" error(
\"
Script attempted to create global variable '
\"
..tostring(n)..
\"
'
\"
, 2)
\n
"
;
s
[
j
++
]
=
" end
\n
"
;
s
[
j
++
]
=
" end
\n
"
;
s
[
j
++
]
=
" rawset(t, n, v)
\n
"
;
s
[
j
++
]
=
"end
\n
"
;
s
[
j
++
]
=
"mt.__index = function (t, n)
\n
"
;
s
[
j
++
]
=
" if debug.getinfo(2) and debug.getinfo(2,
\"
S
\"
).what ~=
\"
C
\"
then
\n
"
;
s
[
j
++
]
=
" error(
\"
Script attempted to access unexisting global variable '
\"
..tostring(n)..
\"
'
\"
, 2)
\n
"
;
s
[
j
++
]
=
" end
\n
"
;
s
[
j
++
]
=
" return rawget(t, n)
\n
"
;
s
[
j
++
]
=
"end
\n
"
;
s
[
j
++
]
=
NULL
;
for
(
j
=
0
;
s
[
j
]
!=
NULL
;
j
++
)
code
=
sdscatlen
(
code
,
s
[
j
],
strlen
(
s
[
j
]));
luaL_loadbuffer
(
lua
,
code
,
sdslen
(
code
),
"@enable_strict_lua"
);
lua_pcall
(
lua
,
0
,
0
,
0
);
sdsfree
(
code
);
}
/* Initialize the scripting environment.
/* Initialize the scripting environment.
* It is possible to call this function to reset the scripting environment
* It is possible to call this function to reset the scripting environment
* assuming that we call scriptingRelease() before.
* assuming that we call scriptingRelease() before.
...
@@ -488,7 +525,7 @@ void scriptingInit(void) {
...
@@ -488,7 +525,7 @@ void scriptingInit(void) {
" if b == false then b = '' end
\n
"
" if b == false then b = '' end
\n
"
" return a<b
\n
"
" return a<b
\n
"
"end
\n
"
;
"end
\n
"
;
luaL_loadbuffer
(
lua
,
compare_func
,
strlen
(
compare_func
),
"cmp_func_def"
);
luaL_loadbuffer
(
lua
,
compare_func
,
strlen
(
compare_func
),
"
@
cmp_func_def"
);
lua_pcall
(
lua
,
0
,
0
,
0
);
lua_pcall
(
lua
,
0
,
0
,
0
);
}
}
...
@@ -501,6 +538,11 @@ void scriptingInit(void) {
...
@@ -501,6 +538,11 @@ void scriptingInit(void) {
server
.
lua_client
->
flags
|=
REDIS_LUA_CLIENT
;
server
.
lua_client
->
flags
|=
REDIS_LUA_CLIENT
;
}
}
/* Lua beginners ofter don't use "local", this is likely to introduce
* subtle bugs in their code. To prevent problems we protect accesses
* to global variables. */
scriptingEnableGlobalsProtection
(
lua
);
server
.
lua
=
lua
;
server
.
lua
=
lua
;
}
}
...
@@ -634,7 +676,7 @@ int luaCreateFunction(redisClient *c, lua_State *lua, char *funcname, robj *body
...
@@ -634,7 +676,7 @@ int luaCreateFunction(redisClient *c, lua_State *lua, char *funcname, robj *body
funcdef
=
sdscatlen
(
funcdef
,
body
->
ptr
,
sdslen
(
body
->
ptr
));
funcdef
=
sdscatlen
(
funcdef
,
body
->
ptr
,
sdslen
(
body
->
ptr
));
funcdef
=
sdscatlen
(
funcdef
,
" end"
,
4
);
funcdef
=
sdscatlen
(
funcdef
,
" end"
,
4
);
if
(
luaL_loadbuffer
(
lua
,
funcdef
,
sdslen
(
funcdef
),
"
func definition
"
))
{
if
(
luaL_loadbuffer
(
lua
,
funcdef
,
sdslen
(
funcdef
),
"
@user_script
"
))
{
addReplyErrorFormat
(
c
,
"Error compiling script (new function): %s
\n
"
,
addReplyErrorFormat
(
c
,
"Error compiling script (new function): %s
\n
"
,
lua_tostring
(
lua
,
-
1
));
lua_tostring
(
lua
,
-
1
));
lua_pop
(
lua
,
1
);
lua_pop
(
lua
,
1
);
...
...
tests/unit/scripting.tcl
View file @
93a74949
...
@@ -219,6 +219,38 @@ start_server {tags {"scripting"}} {
...
@@ -219,6 +219,38 @@ start_server {tags {"scripting"}} {
list
[
r eval
{
return redis.sha1hex
(
''
)}
0
]
\
list
[
r eval
{
return redis.sha1hex
(
''
)}
0
]
\
[
r eval
{
return redis.sha1hex
(
'Pizza & Mandolino'
)}
0
]
[
r eval
{
return redis.sha1hex
(
'Pizza & Mandolino'
)}
0
]
}
{
da39a3ee5e6b4b0d3255bfef95601890afd80709 74822d82031af7493c20eefa13bd07ec4fada82f
}
}
{
da39a3ee5e6b4b0d3255bfef95601890afd80709 74822d82031af7493c20eefa13bd07ec4fada82f
}
test
{
Globals protection reading an undeclared global variable
}
{
catch
{
r eval
{
return a
}
0
}
e
set e
}
{
*ERR*attempted to access unexisting global*
}
test
{
Globals protection setting an undeclared global*
}
{
catch
{
r eval
{
a=10
}
0
}
e
set e
}
{
*ERR*attempted to create global*
}
test
{
Test an example script DECR_IF_GT
}
{
set decr_if_gt
{
local current
current = redis.call
(
'get',KEYS
[
1
])
if not current then return nil end
if current > ARGV
[
1
]
then
return redis.call
(
'decr',KEYS
[
1
])
else
return redis.call
(
'get',KEYS
[
1
])
end
}
r set foo 5
set res
{}
lappend res
[
r eval $decr_if_gt 1 foo 2
]
lappend res
[
r eval $decr_if_gt 1 foo 2
]
lappend res
[
r eval $decr_if_gt 1 foo 2
]
lappend res
[
r eval $decr_if_gt 1 foo 2
]
lappend res
[
r eval $decr_if_gt 1 foo 2
]
set res
}
{
4 3 2 2 2
}
}
}
start_server
{
tags
{
"scripting repl"
}}
{
start_server
{
tags
{
"scripting repl"
}}
{
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment