Using this regular expression, '\(\w*\)\s*=\s*\1\s*\.\.', found and
replaced many string concatenation-reassignments. These can cause
performance issues, since a new string gets allocated for each
reassignment. In many cases, the replacement is simply a single string,
wrapped across lines with the '\z' escape, which consumes a newline and
whitespace following it. In other cases, a table is used to hold the
substrings until the final string is built with a single table.concat
operation (same technique used in stdnse.strbuf).
Also, some string-building loops of this form:
s = ""
for i = 1, 100, 1 do
s = s .. "\0"
end
were replaced with this much faster and cleaner version:
s = string.rep("\0", 100)
for lib in nselib/*.lua*; do l=${lib#*/}; l=${l%.lua*}; find . -name \
\*.lua -o -name \*.nse | xargs grep -l "require .$l\>" | xargs grep \
-c "\<$l\." | grep ':0$' | awk -F: '{print "'$l'", $1}'; done
Did not remove calls to stdnse.silent_require since these can be used to
abort script execution if OpenSSL is not included, even if the script
does not directly call openssl.* (perhaps it uses comm.tryssl instead,
for instance).
Also did not remove require "strict", since that library is special and
modifies the environment.
stdnse.print_debug accepts a format string and arguments, making
string.format redundant in calls of this form:
stdnse.print_debug(1, string.format("%s: error", SCRIPT_NAME))
stdnse.print_debug(("length %d"):format(#tab))
These can be rewritten as:
stdnse.print_debug(1, "%s: error", SCRIPT_NAME)
stdnse.print_debug("length %d", #tab)
Mostly in documentation (the description field, for instance), but also
some long literal strings. Lua 5.2 introduces a string escape, "\z",
which escapes any amount of subsequent whitespace, including newlines.
This can be used to wrap string literals without upsetting indentation.
http://www.lua.org/manual/5.2/manual.html#3.1
The example uses of nmap.receive_buf() were missing the second
parameter, keeppattern. Also referenced the match library from
nmap.receive_buf's NSEdoc to avoid reimplementations of buffered
sockets.
Mostly found with:
for i in nselib/*.lua scripts/*.nse; do
echo $(perl -lne 'BEGIN{$a=$p=0}next unless $_;/^(\s*)/;' \
-e '$l=length$1;next if$l==$p;$a+=(abs($l-$p)-$a)/$.;' \
-e '$p=$l;END{print$a}' $i) $i
done | sort -nr
And indented with: https://gist.github.com/bonsaiviking/8845871
whois-ip.nse was particularly mangled (probably my fault due to using
vim's built-in indentation script, but it could be structured better)
Only FD_SET and FD_CLR were available. Added a FD_ISSET equivalent.
Implemented them as static inline instead of macros for consistency.
These functions abort() if the FD number is higher than FD_SETSIZE
(except on windows where no check is performed).
From this thread: http://seclists.org/nmap-dev/2014/q1/105
* Extensions now better supported in tls.lua
* ssl-enum-ciphers sends all EC options to ensure servers reply with
supported EC suites
* tls.lua supports multiple messages of a single type within 1 record
* tls.record_buffer will read an entire TLS record into a buffer
* ssl-date and tls-nextprotoneg updated to use tls.record_buffer
This wasn't using Nmap's included libpcap if no options were specified,
instead compiling nsock without pcap support if no libpcap could be
found (which breaks Nmap)
string.gsub returns 2 values, the new string and the number of
replacements made. It also has a 4th argument, the number of
replacements to make. So when you use the return value of gsub as the
3rd argument, and no replacements were made, it instructs the next call
to not make any replacements. Thanks to Ron Bowes for reporting this
issue.
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 <nse_main.lua:1293>
[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
"%%%%".