The flip: FUNCTION/XFUNCTION/FUN::fun/delim_check and the module
interfaces take `const UTF8 * const fargs[]`. Double-const is
load-bearing: C++ qualification conversion needs const at both pointer
levels, so builder-side `UTF8 *[]` arrays convert implicitly — the
evaluator, the JIT marshaller, and every owner site need zero casts,
and slot reassignment inside bodies becomes a compile error for free.
The conversions: the flip landed first so the compiler enumerated every
violation; this commit is that inventory worked to zero — ~250 sites
across funceval, funceval2, functions, funmath, help, mail, session,
powers, levels, predicates, conf, walkdb, stringutil, timeutil/
date_scan (regenerated, one-line diff), exp3, and mux_main, each
classified per docs/campaign-2136-const-fargs.md's four recipes.
New idioms (functions.h): trim_space_sep_n() — non-destructive trim for
(pointer, length) consumers, so trim-then-scan sites need no copy at
all; FargVec — the argv counterpart of FargCopy for CS_ARGV handlers.
countwords() and DecodeListOfIntegers() rewritten non-destructive.
The flip deleted more than it added: #2157's fun_munge list1 copy, the
engine_com help-topic copy, fun_index's in-place NUL write, and five
const_casts (process_sex x4, sha1_helper). const_cast budget: zero
added.
Trap recorded in the brief: an old-signature definition doesn't fail
the build — it becomes a C++ overload, and the new-signature symbol
stays undefined until dlopen(RTLD_NOW). delim_check, the conn_bridge
bridges, the dbt_spike stub, and exp3::Call were all silently shadowed;
muxscript was the only host that noticed, because netmux's own net.cpp
resolved the flat-namespace lookup. After any signature flip, grep the
old spelling.
Verified: make test EXPECT_CONFIG="jit=yes" (35 passed / 0 failed) and
make test-scenario, including the new tests/scenario/sidefx_fargs.py
that live-probes the class-3 wrappers smoke never touches (pemit/
trigger/link/tel/wipe/destroy).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The non-OpenSSL digest backend is now CNG (BCrypt) with cached
algorithm-provider handles; the FIPS-180 MUX_SHA1_* implementation is
deleted and the tree ships no cryptographic source, matching the
Schannel-for-TLS precedent. A new generalized mux_digest(name, ...)
entry point serves sha1/sha256/sha384/sha512/md5 (case-insensitive,
hyphenated aliases), and fun_digest's non-OpenSSL branch dispatches
through it, so digest(sha256,...) et al. now work on Windows --
digest_fn.mux TC004/TC005 flip from Skipped to Succeeded there via
their existing behavior-probing guards.
Output is byte-identical across the swap: tests/digest (new, wired as
make test-digest and into test-asan) pins the surfaces whose bytes may
never change -- RFC 6455 Sec-WebSocket-Accept (single-part and the
two-part gather websocket.cpp performs), the $SHA1$ salt||password
gather and bare-password $P6H$ shapes from player.cpp, and the sha1()
softcode FIPS vectors -- with every golden value generated by the
openssl(1) CLI as an external oracle. Verified on Windows: homegrown
== oracle == CNG on all six SHA-1 vectors, 17/17 KATs against the CNG
build, full solution build with zero new warnings, smoke ALL 1601
PASSED / 0 failed.
A non-Windows non-OpenSSL platform now hits #error by design:
configure.ac hard-errors without OpenSSL, so no shipped config lands
there, and the homegrown fallback must not silently return.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>