diff --git a/nse_main.lua b/nse_main.lua index e534c4d5a..d04c19d8c 100644 --- a/nse_main.lua +++ b/nse_main.lua @@ -88,6 +88,8 @@ do -- Append the nselib directory to the Lua search path package.path = package.path..";"..path.."?.lua"; end +(require "strict")() -- strict global checking + -- NSE_YIELD_VALUE -- This is the table C uses to yield a thread with a unique value to -- differentiate between yields initiated by NSE or regular coroutine yields. diff --git a/nselib/strict.lua b/nselib/strict.lua new file mode 100644 index 000000000..87b22ba59 --- /dev/null +++ b/nselib/strict.lua @@ -0,0 +1,83 @@ +--- Strict Declared Global library. +-- +-- Checks for undeclared global variables during runtime execution. This module +-- places the 'strict' function in the global environment. The strict function +-- allows a script to add runtime checking so that undeclared globals cause +-- an error to be raised. This is useful for finding accidental use of globals +-- when local was intended. +-- A global variable is considered 'declared' if the script makes an assignment +-- to the global name (even nil). +-- +-- @class module +-- @name strict +-- @copyright Copyright© Same as Nmap--See http://nmap.org/book/man-legal.html + +local error = error; +local getfenv = getfenv; +local lmodule = module; +local rawset = rawset; +local rawget = rawget; +local setfenv = setfenv; +local type = type; + +local getinfo = debug.getinfo; + +local function what () + local d = getinfo(3, "S"); + return d and d.what or "C"; +end + +--- The strict function. +-- +-- This function adds runtime checking to the global environment for use of +-- undeclared globals. A global is 'undeclared' if not assigned in the file +-- (script) scope previously. An error will be raised on use of an undeclared +-- global. +function strict () + local _G = getfenv(2); + + local mt = getmetatable(_G) or setmetatable(_G, {}) and getmetatable(_G); + local _newindex, _index = mt.__newindex, mt.__index; + + mt.__declared = {}; + + function mt.__newindex (t, n, v) + if type(_newindex) == "function" then + _newindex(t, n, v); -- hook it + end + if not mt.__declared[n] then + local w = what(); + if w ~= "main" and w ~= "C" then + error("assign to undeclared variable '"..n.."'", 2); + end + mt.__declared[n] = true; + end + rawset(t, n, v); + end + + function mt.__index (t, n) + if type(_index) == "function" then + local v = _index(t, n); -- hook it + if v ~= nil then return v end + else + local v = _index[n]; + if v ~= nil then return v end + end + if not mt.__declared[n] and what() ~= "C" then + error("variable '"..n.."' is not declared", 2); + end + return rawget(t, n); + end +end + +local strict = strict; + +function module (...) + local myenv = getfenv(1); + lmodule(...); + strict(); + setfenv(2, getfenv(1)); + setfenv(1, myenv); +end + +return strict;