An open API service indexing awesome lists of open source software.

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

Awesome Lists containing this project

README

        

# niffy - NIF testing harness

> ... an ad hoc, informally-specified, bug-ridden, slow implementation
> of 1% of Erlang

This 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) malodorous

nifty 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 .