Skip to content

review and refactor c code for simplicity and security#1175

Merged
jaromil merged 24 commits intomasterfrom
c-source-review
Apr 2, 2026
Merged

review and refactor c code for simplicity and security#1175
jaromil merged 24 commits intomasterfrom
c-source-review

Conversation

@jaromil
Copy link
Copy Markdown
Member

@jaromil jaromil commented Apr 1, 2026

High priority findings

  • High: buffered stdout/stderr writes report overflow but still write past the configured end. That happens in src/zen_io.c:88, src/zen_io.c:143, and src/
    zen_io.c:177. Those branches should return immediately after the error instead of continuing into memcpy.
  • High: the binding executor has two fixed-buffer bugs. line_alloc() allocates B64decoded_len(len) bytes and then writes a terminator at line[reallen] in src/
    zencode-exec.c:61, so it needs +1. The config path also appends ",logfmt=json" with strcat() in src/zencode-exec.c:123 after a truncation check in src/zencode-
    exec.c:114 that can never catch a too-long fgets() result.
  • High: the X.509 helpers treat DER slices as C strings. src/zen_x509.c:138 and src/zen_x509.c:279 use %s on binary certificate data, and src/zen_x509.c:283 uses
    sprintf() unnecessarily. This is an over-read/overflow risk and also misparses embedded NULs and ASN.1 long-form lengths.
  • High: native runtime state is still effectively global. src/zenroom.c:62, src/zenroom.c:65, src/zen_octet.h:69, and src/zen_error.h:32 hide allocator/context
    ownership behind global singletons and macro-redefined malloc/free. That hurts readability, makes the VM non-reentrant, and complicates maintenance.
  • High: the logging helper macro is unsafe. src/zen_error.c:60 passes a va_list to _err() as if it were normal variadic arguments, and callers like src/
    zen_error.c:185 return early without va_end(). NULL-context logging is therefore undefined behavior today.
  • High: both Zcash import guards are inverted. src/zen_ecp.c:417 and src/zen_ecp2.c:676 use SAFE_GOTO with a predicate that describes the invalid case, so valid
    headers fall into the error path.
  • Medium-high: zen_init() has several error-path ownership problems. src/zenroom.c:176 does not check malloc, src/zenroom.c:217 leaks ZZ on config-parse failure,
    src/zenroom.c:232 does not check RNG allocation, and src/zenroom.c:288 can return after Lua state creation without lua_close().
  • Medium: RNG-seed validation skips the last 4 hex characters. In src/zen_config.c:124 len is reduced by 4, then the validation loop starts at 4 and stops at
    that reduced bound in src/zen_config.c:131. The copy at src/zen_config.c:140 still takes the full payload.
  • Medium: time_arg() ignores its n parameter for scalar inputs and always reads slot 1 in src/zen_time.c:89 and src/zen_time.c:110. That is a correctness bug and
    makes the helper misleading.
  • Medium: big:bytes() is wrong for values whose bit length is not divisible by 8. src/zen_big.c:870 computes ceil(_bitsize(d)/8) after integer division, so 9
    bits still reports 1 byte.
  • Medium: class metatable naming can overflow. src/lua_functions.c:86 seeds a 512-byte buffer with "zenroom.", then src/lua_functions.c:87 appends up to 511 more
    bytes with strncat().
  • Medium: the Longfellow bridge silently truncates inputs and passes octet buffers where the external API expects C strings. See src/zen_longfellow.c:140, src/
    zen_longfellow.c:147, and the direct const char * calls at src/zen_longfellow.c:271 and src/zen_longfellow.c:345. This boundary needs explicit length checks
    and NUL-terminated staging buffers.
  • Medium: api_hash has an unsafe cleanup path. tmp.val is never initialized before the first possible goto end in src/api_hash.c:159, but it is conditionally
    freed at src/api_hash.c:210.
  • Medium: zen_parse.c still relies on static scratch storage in src/zen_parse.c:39. That is easy to replace with a stack buffer and would remove another hidden
    shared state point.
  • Medium: zen_io.c has a dead Emscripten branch due to a typo in src/zen_io.c:182 (_EMSCRIPTEN instead of EMSCRIPTEN).

Lower-Priority Cleanup

  • Low: src/zen_hash.h:35 and src/zen_hash.h:38 define _SHA3_256 twice.
  • Low: src/zen_hash.c:75 and the repeated strncpy() calls below it never force NUL termination of h->name, and the local ht is effectively dead.
  • Low: src/randombytes.c:218 and src/randombytes.c:227 leak the Linux fd on some failure exits. src/randombytes.c:109 still uses legacy CryptoAPI on Windows.
  • Low: src/encoding.c:589 and src/encoding.c:610 implement BIP39 lookup with fixed magic sizes and a linear 2048-word scan. It is correct enough, but not
    especially clear or efficient.
  • Low: there is repeated near-identical code for raw writes/logging in src/zen_io.c:51 and src/zen_error.c:46. One shared helper would simplify maintenance.

@jaromil jaromil merged commit 0e5f0c7 into master Apr 2, 2026
33 checks passed
@jaromil jaromil deleted the c-source-review branch April 2, 2026 03:40
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant