Open Source · Apache 2.0

Community & Contributing

Rerius is Apache 2.0, developed in the open. There's no dark-pattern gating here: the CLI, C library, and npm package are the whole project; nothing functional is held back behind an account or a paid tier.

Good first issues Discussions Apache 2.0 license text

Contributing to Rerius

Repository: https://github.com/ECLS-Studio/rerius


Table of Contents#


Code of Conduct#

All contributors are expected to follow the Code of Conduct.


Ways to Contribute#

  • Report bugs: open a bug report
  • Request features: GitHub Discussions or feature request
  • Fix bugs: check issues labelled bug or good first issue
  • Improve decode coverage: add ARM64, x86-64, or RISC-V instructions to the decoders in src/arch/
  • Add architecture support: e.g. MIPS, PowerPC, Thumb-2
  • Improve the decompiler / SSA-NR pass: better lifting patterns, type tagging, call-target resolution
  • Write tests: expand js/test/basic.js
  • Improve documentation: fix inaccuracies, add examples

Security vulnerabilities: report privately: see SECURITY.md. Do not open a public issue or PR for a security bug.


Development Setup#

git clone https://github.com/ECLS-Studio/rerius.git
cd Rerius

# Build CLI and JS addon
make

# Verify
./rerius -h
node js/test/basic.js   # all 27 tests should pass

Termux:

pkg install nodejs clang make git
git clone https://github.com/ECLS-Studio/rerius.git && cd Rerius && make

Submitting a Pull Request#

  1. Fork the repository and create a branch from main: bash git checkout -b fix/cfg-dead-bytes
  2. Make your changes, following the Code Style guide below.
  3. Build cleanly: make clean && make
  4. Run the test suite: node js/test/basic.js
  5. Push and open a PR against main.
  6. Fill in the PR template completely: reviewers will ask for missing context otherwise.

PRs that fail CI or introduce new compiler warnings are not merged.


Code Style#

C (C99, strict)#

/* snake_case for functions and variables */
int dax_cfg_build(dax_binary_t *bin, uint8_t *code, size_t sz, uint64_t base, int func_idx);

/* _t suffix for types */
typedef struct { ... } dax_section_t;

/* ALL_CAPS for macros and enum values */
#define DAX_MAX_SECTIONS 128
typedef enum { SEC_TYPE_CODE, SEC_TYPE_DATA } dax_sec_type_t;

/* Explicit integer types */
uint32_t n;     /* not: unsigned int */
uint64_t addr;  /* not: unsigned long long */

/* Check all heap allocations */
bin->data = calloc(sz, 1);
if (!bin->data) return -1;

/* Return 0 on success, -1 on failure */

Favor self-documenting names over comments that just restate what a line does. That said, module-level and "why" comments are used throughout the codebase (see the header block in src/analysis/dsa.c for the expected style): explain non-obvious algorithm choices and tradeoffs, not what i++ does.

Fault isolation: expected for every new analysis module:

Every public entry point should include dax_guard.h (after dax.h) and open with a guard:

#include "dax.h"
#include "dax_guard.h"

void dax_mymodule(dax_binary_t *bin, dax_opts_t *opts, FILE *out) {
    DAX_GUARD_BIN(bin);              /* returns void on bad bin */
    if (!opts || !out) return;
    /* ... */
}

int dax_mymodule_build(dax_binary_t *bin, int fi) {
    DAX_GUARD_BIN_RET(bin, -1);      /* returns -1 on bad bin */
    DAX_GUARD_FUNC_RET(bin, fi, -1); /* returns -1 on OOB fi */
    /* ... */
}

All loops over dax_binary_t counter fields should have a DAX_MAX_* upper bound:

/* correct */
for (i = 0; i < bin->nfunctions && i < DAX_MAX_FUNCTIONS; i++) { ... }

/* missing the DAX_MAX guard: avoid this */
for (i = 0; i < bin->nfunctions; i++) { ... }

All section offset arithmetic should use the overflow-safe subtraction form:

/* correct */
if (sec->size > bin->size - sec->offset) continue;

/* can overflow on large offset values: avoid this */
if (sec->offset + sec->size > bin->size) continue;

Set the fault flag when aborting early so DAX_RUN_PASS can report it:

if (something_wrong) {
    dax_fault_set("brief reason string");
    return;
}

Avoid adding new external dependencies: no #include beyond what's already used in the codebase, no new npm packages, unless there's a strong reason and it's discussed first in an issue.

Code should compile cleanly under clang -std=c99 -Werror. Avoid non-standard compiler extensions (nested functions, __builtin_* without a portable fallback) so the project keeps building on all supported compilers.

JavaScript#

'use strict';           // always
const / let             // never var
camelCase               // functions and variables
#privateField            // class private fields

Commit Messages#

Use Conventional Commits:

<type>(<scope>): <description>
Type When
feat New feature
fix Bug fix
perf Performance improvement
refactor No behavior change
docs Documentation only
build Makefile, build_js.sh, workflows
test Tests
chore Version bumps, formatting

Examples:

feat(cfg): two-pass builder pre-registers all branch targets
fix(unicode): reject UTF-16LE strings without codepoints > U+02FF
fix(decomp): replace non-portable compiler extension with a static helper
build: add -lm to LDFLAGS for entropy log2()
docs: update CLI_REFERENCE.md with -e -R -V flags

Testing#

Rerius uses a hand-written test suite in js/test/basic.js (27 tests, no external test framework).

# Full test run
node js/test/basic.js

# Test against a specific binary
RERIUS_TEST_BIN=/path/to/binary node js/test/basic.js

# Quick CLI smoke tests
./rerius -x /bin/ls > /dev/null && echo OK
./rerius -e -R -V /bin/ls > /dev/null && echo OK

When contributing:

  • All existing tests must still pass.
  • Add new tests for any new JS API methods.
  • For CFG changes: test against a binary with irregular control flow (computed jumps, jump tables).
  • For Unicode changes: test against a Windows PE binary with UTF-16LE strings.

Adding New Features#

New CLI analysis module#

  1. Create the module under the matching subdirectory (e.g. src/analysis/mymodule.c for a new analysis pass) and implement the analysis function.
  2. Add #include "dax_guard.h" after #include "dax.h" in the new file.
  3. Open every public entry point with DAX_GUARD_BIN(bin) or DAX_GUARD_BIN_RET(bin, retval).
  4. Cap all loops over bin->nfunctions, bin->nsections, etc. with && i < DAX_MAX_*.
  5. Use the overflow-safe sec->size > bin->size - sec->offset form for all section bounds checks.
  6. Declare the function in include/core/dax.h: void dax_mymodule(dax_binary_t *bin, dax_opts_t *opts, FILE *out);
  7. Add a flag to dax_opts_t: int mymodule;
  8. Wire it up in src/cli/main.c using DAX_RUN_PASS("mymodule", opts.color, dax_mymodule(&bin, &opts, stdout));
  9. Add the new source file to SRCS in Makefile and LIB_SRCS in build_js.sh.
  10. Add an N-API wrapper in js/src/rerius_napi.c.
  11. Add the method to js/index.js and its type declaration to js/index.d.ts.
  12. Add an endpoint to js/server/server.js.
  13. Add a panel to js/server/ui.html.
  14. Add tests to js/test/basic.js.
  15. Document the change in CHANGELOG.md, docs/API.md, and docs/CLI_REFERENCE.md.

New architecture#

  1. Add ARCH_NEWARCH to dax_arch_t in include/core/dax.h.
  2. Create include/arch/newarch.h and src/arch/newarch_decode.c.
  3. Add dax_disasm_newarch() in src/arch/disasm.c.
  4. Add dax_classify_newarch() in src/analysis/analysis.c.
  5. Wire it up in src/core/loader.c, src/cli/main.c, and src/analysis/cfg.c.
  6. Add the new source file(s) to the Makefile/build script.

New architecture support is a substantial undertaking: expect it to touch the decoder, classifier, CFG builder, and (if you want CFG/loop/call-graph support) the analysis passes that assume an instruction shape. Open an issue to discuss scope before starting.


License#

By contributing, you agree that your changes will be licensed under the Apache 2.0 License.

On this page
Contributing to Rerius Table of Contents Code of Conduct Ways to Contribute Development Setup Submitting a Pull Request Code Style C (C99, strict) JavaScript Commit Messages Testing Adding New Features New CLI analysis module New architecture License
ESC
↑↓ navigate openesc close