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
bin
orbit
libraries. 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 table
block, 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
.nse
to 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/sh
shebang 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.