Nmap/Code Standards
From SecWiki
< Nmap
Nmap is a large codebase. To keep things manageable, please follow these standards.
Contents
Style guidance
Uniform coding style makes hunting bugs easier, and it makes causing bugs harder.
All languages
- Whitespace is limited to the space (" ", ASCII 0x20) and newline ("\n", ASCII 0x0a). This means:
- Unix-style line endings ("\n", not "\r\n" or anything else)
- No tabs. Ever.
- No trailing whitespace
- Readable code
- Expressive, but not over-long variable names
- Effective use of whitespace (around operators, after commas, etc.)
- See Python style guidance for more ideas
- Keep lines under 80 columns
- UTF-8 encoded source
- Single newline at EOF - this does NOT mean an empty line, just that the final byte in the file should be 0x0A.
C/C++
- Indent with 2 spaces.
- Prefer all lowercase function and variable names, separate terms with underscores. C++ classes should be CamelCase.
- All macro names must be uppercase, no exception.
- No space before parenthesis in function calls
- Opening braces are at the end of the line both for functions and blocks.
- switch/case have one level of indentation for the cases, and another one for the corresponding blocks
- Wrap at 80 columns, unless it gets ugly
Lua
- Indent with 2 spaces.
- All variables and functions declared
local. (Exception for names exported from NSE libraries) - NSEdoc when appropriate.
- No semicolons.
- Always use explicit endianness in format strings for string.pack and string.unpack
- Scripts should support Nmap structured output.
- Do not use the deprecated
binorbitlibraries. Use Lua 5.3 string packing and bitwise operators instead.
NSEdoc best-practices
- All exported (non-local) functions and data structures in a library need NSEdoc.
- You can use NSEdoc on "private" functions, too, but introduce it with
--;instead of---to indicate private documentation.
- You can use NSEdoc on "private" functions, too, but introduce it with
- The first paragraph of a NSEdoc block should be a 1-line summary only.
- Document tables (as arguments or return values) in a separate
@class tableblock, using @name and @see to associate them. - @see doesn't work inline. It needs to be on a line by itself.
- @see can be used in scripts to link to related scripts, but you must append
.nseto the name of the script.
- @see can be used in scripts to link to related scripts, but you must append
- For object methods (e.g. Comm.receive), use @name Class.methodname, otherwise only methodname is used.
Python
Follow PEP 8.
Shell
Use POSIX shell language, not Bash. Not picky on which version (SUSv4, POSIX.1, whatever).
- Scripts should use
#!/bin/shshebang line.
Tools to help
- pep8 tool - https://pypi.python.org/pypi/pep8
- lua-format - Script written by Patrick Donnelly to format Lua programs. Included in Nmap under docs/style/
- lua.vim - Indentation vimscript for auto-indenting: https://gist.github.com/bonsaiviking/8845871
- commit hooks - If you are using git or git-svn, you can use this one: https://gist.github.com/dmiller-nmap/04d166bdd7872993fedb50db7fe90ac5
- check script - Does most of the same checks as the git hooks, but can be run independently and without git with some tweaks: https://gist.github.com/dmiller-nmap/5e0c5b5524d0a594e38785d3cdc8dc07
Sample .vimrc
function SetNmapPrefs ()
"Get the full dirname of the edited file and
"Check whether we are in an Nmap source tree
if expand('%:p:h') =~ "/nmap"
"Set this to the location of nmap-private-dev, if you want
let nmap_private_dev = "/home/miller/nmap/nmap-m/nmap-private-dev"
"proper indentation
set nocindent
set autoindent
set smartindent
set copyindent
let ext = expand('%:e')
" *.nse and *.luadoc are Lua
if ext == "nse" || ext == "luadoc"
set ft=lua
endif
"PEP 8 specifies 4 spaces for indentation
if &filetype == "python"
set tabstop=4
set softtabstop=4
set shiftwidth=4
else
"Indent is 2 spaces, no tabs
set tabstop=2
set softtabstop=2
set shiftwidth=2
endif
set expandtab
set smarttab
"Complain about trailing whitespace and tab indentation
let b:ws = matchadd("SpellBad", '\s\+$')
"Tabs are fine to indent in Makefiles
if &filetype != "make"
let b:tabs = matchadd("SpellBad", '^\s*\t\+')
endif
"Source the service-probes syntax highlighting
if nmap_private_dev != "" && expand('%:t') == "nmap-service-probes"
execute("source " . nmap_private_dev . "fp/sv-highlight.vim")
endif
endif
endfunction
au BufRead,BufNewFile * call SetNmapPrefs()
Converting existing code
- Keep formatting commits separate from code-changing commits
- Strive for whitespace-only commits for changing indentation (diff -w or diff -b show no changes)
- If using lua-format, do a whitespace-only indentation commit first, to keep the lua-format changes visible.

