From d6288c5280176160f2776a68c0a2dbb2f483a185 Mon Sep 17 00:00:00 2001 From: david Date: Mon, 27 Jan 2014 22:56:29 +0000 Subject: [PATCH] Escape '%' in arguments to Thread:d. A user reported this crash when scanning a target whose name contained the '%' character: NSE: Script Engine Scan Aborted. An error was thrown by the engine: nse_main.lua:322: invalid capture index stack traceback: [C]: in function 'gsub' nse_main.lua:322: in function 'd' nse_main.lua:377: in function 'start' nse_main.lua:912: in function 'run' nse_main.lua:1390: in function [C]: in ? I'm not sure how a name with '%' got resolved, but I was able to reproduce the crash by adding this line to /etc/hosts: 127.0.0.1 a%40b and then running ./nmap --script=banner a%40b -d --top-ports 5 The gsub function recognizes "%d", where d is a digit, as a capture index. The constructed string is then passed to print_debug, which is like printf. Therefore we escape every occurrence of "%" twice, to get "%%%%". --- nse_main.lua | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/nse_main.lua b/nse_main.lua index b7cae0635..b64b57e7d 100644 --- a/nse_main.lua +++ b/nse_main.lua @@ -315,12 +315,16 @@ do -- Changes "%THREAD" with an appropriate identifier for the debug level function Thread:d (fmt, ...) local against = against_name(self.host, self.port); + local function replace(fmt, pattern, repl) + -- Escape each % twice: once for gsub, and once for print_debug. + return gsub(fmt, pattern, gsub(repl, "%%", "%%%%%%%%")); + end if debugging() > 1 then - fmt = gsub(fmt, "%%THREAD_AGAINST", self.info..against); - fmt = gsub(fmt, "%%THREAD", self.info); + fmt = replace(fmt, "%%THREAD_AGAINST", self.info..against); + fmt = replace(fmt, "%%THREAD", self.info); else - fmt = gsub(fmt, "%%THREAD_AGAINST", self.short_basename..against); - fmt = gsub(fmt, "%%THREAD", self.short_basename); + fmt = replace(fmt, "%%THREAD_AGAINST", self.short_basename..against); + fmt = replace(fmt, "%%THREAD", self.short_basename); end print_debug(1, fmt, ...); end