https://github.com/tokenrove/niffy
NIF testing harness
https://github.com/tokenrove/niffy
afl-fuzz c erlang nif testing valgrind
Last synced: about 1 month ago
JSON representation
NIF testing harness
- Host: GitHub
- URL: https://github.com/tokenrove/niffy
- Owner: tokenrove
- License: gpl-3.0
- Created: 2015-10-06T17:29:37.000Z (over 9 years ago)
- Default Branch: master
- Last Pushed: 2019-03-27T10:57:22.000Z (about 6 years ago)
- Last Synced: 2025-03-19T09:40:56.945Z (about 1 month ago)
- Topics: afl-fuzz, c, erlang, nif, testing, valgrind
- Language: C
- Size: 144 KB
- Stars: 32
- Watchers: 4
- Forks: 2
- Open Issues: 8
-
Metadata Files:
- Readme: README.md
- License: COPYING
Awesome Lists containing this project
README
# niffy - NIF testing harness
> ... an ad hoc, informally-specified, bug-ridden, slow implementation
> of 1% of ErlangThis is a very simple harness to allow running NIFs under valgrind and
other debugging tools without all the machinery of building a special
version of the runtime.It allows you to load a NIF and invoke its functions with arbitrary
Erlang terms (or, at least, some subset of acceptable Erlang terms).Very little of the ERTS is implemented, so it's likely that your NIF
will break in other ways if it's dependent on much of Erlang.## Etymology
From WordNet (r) 3.0 (2006) [wn]:
> niffy
> adj 1: (British informal) malodorousnifty was already taken.
## Caveats
- allocates lots of memory and doesn't free it
- isn't character encoding aware (no UTF-8 support)
- much of the NIF API is still unimplemented## License
[GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html)
## Building
Requires [ragel](http://www.colm.net/open-source/ragel/), and the
header files you'd use to compile a NIF. Run `make all` to build
everything.## Usage
### Simple
You have a compiled NIF shared object `nif.so` and want to call some
of its functions under valgrind:```
$ valgrind niffy nif.so <
Port = open_port({spawn_executable, "/usr/bin/valgrind"},
[{args, ["--error-exitcode=42", "--",
"../niffy/niffy", "./priv/my_nif.so", "-q"]},
binary, stream, exit_status,
{line, 1024}]),
Port ! {self(), {command, <<"_ = niffy:load_nif(my_nif, []).\n">>}},
erlang:trace_pattern({my_nif, '_', '_'}, true, []),
erlang:trace(all, true, [call]),
loop(Port).loop(Port) ->
receive
{trace, _, call, {Module, Function, Arguments}} ->
Port ! {self(), {command, format_mfa(Module, Function, Arguments)}},
loop(Port);
{_Port, {exit_status, Status}} ->
io:format("niffy exited with code ~p~n", [Status])
end.
```In more complex situations, you may need to handle certain calls
(those that return a non-printable term, for example) and rewrite them
to the form `Handle = my_nif:creation_call(Args).`, and suitably
replace later arguments that containing that non-printable term with
`Handle`. An example should soon be included here, but until then,
feel free to contact me about it.## Alternatives
As an alternative to niffy, you could build a valgrind-enabled OTP,
[using this recipe](https://gist.github.com/gburd/4157112).## Contact
niffy is maintained by Julian Squires .