From 9d5de2a9d1be55fca7c45c4180f25782c1c7302c Mon Sep 17 00:00:00 2001 From: batrick Date: Wed, 15 Jul 2009 15:14:00 +0000 Subject: [PATCH] Added strict library for libraries (and scripts). The module function is replaced so that all NSE modules will have strict declared global checking at runtime. This should catch most developer errors early. Please see [1] for further reference into the problem. [1] http://seclists.org/nmap-dev/2009/q3/0070.html --- nse_main.lua | 2 ++ nselib/strict.lua | 83 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 85 insertions(+) create mode 100644 nselib/strict.lua 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;