Commit graph

5 commits

Author SHA1 Message Date
Stephen Dennis
af97bce20c fix(digest): resolve digest()/hmac() names via EVP_MD_fetch on OpenSSL 3.0+ (#1961)
digest(<name>) and hmac(...,<name>) resolved algorithm names with the legacy
EVP_get_digestbyname(). On OpenSSL 3.0 that does not resolve hyphenated aliases
(e.g. "sha-1") until the default provider has been lazily loaded by an earlier
successful digest. In threaded netmux that warm-up straddles TC005's two cand()
branches, so smoke went red 4/4 on OpenSSL 3.0.13 (Debian 12 / Ubuntu 22.04 /
RHEL 9), while newer OpenSSL (3.6.2) resolves the alias cold and passes.

Use the provider-native EVP_MD_fetch(NULL, name, NULL) on OpenSSL 3.0+
(non-LibreSSL), which resolves aliases deterministically from a cold process,
and free the fetched EVP_MD. Keep EVP_get_digestbyname() on pre-3.0 / LibreSSL,
where it returns a static const and the lazy-provider behavior does not occur.
Gated on OPENSSL_VERSION_NUMBER rather than AC_CHECK_FUNCS to avoid regenerating
configure with autoconf 2.71 vs the tree's required 2.73 (#1477); EVP_MD_fetch
is inherently a 3.0 API so the version guard is semantically exact.

Also fix an EVP_MD_CTX leak in fun_digest on the unsupported-name path (it
returned after EVP_MD_CTX_new() without freeing the context).

Verified on OpenSSL 3.0.13 (Kagura): reverting just these two files gives
TC005 FAIL 3/3; with the fix TC005 PASS 4/4 and full smoke ALL 1588 PASSED.
digest(sha-1)/hmac(...,sha-1) resolve from a cold process; sha_1/bogus still
rejected. Needs 3.6.2 no-regression confirmation on the box that already passes.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-02 13:22:07 -06:00
Stephen Dennis
e7eb6ec76d nls: route literal #-1 softcode tokens through S_ (#1475)
Mechanical hygiene under the opt-in M_() design: replace T("#-1…") and
T("#-2…") with S_() so softcode ABI tokens are obvious in source and
cannot enter a player catalog. ~400 call sites across engine, exp3,
mail, and driver. Assembled/library-spliced diagnostics (plan §4.2)
are unchanged where they are not a single literal.
2026-07-27 01:00:55 +00:00
Stephen Dennis
44268e7157 fix: json(array/object) emit whole-tail elements; use split_token
fun_json's array and object branches walked their space-separated
input with next_token(), which only advances a pointer and never
NUL-terminates the token it just passed. Each element handed to
safe_str() therefore dragged the entire remaining tail with it:
json(array,a b c) produced [a b c,b c,c], and json(object,...) broke
even at a single key-value pair. Both branches now use split_token(),
the in-place-terminating helper every other list-processing function
already uses.

Also fixes a second defect on the object branch's error path: the
ODD NUMBER OF ELEMENTS reset was *bufc = buff, rewinding to the start
of the entire evaluation buffer and silently discarding any output
evaluated before the call. The reset now rewinds to the function's own
entry position.

Extends json_fn.mux TC001 with the array/object construction coverage
whose absence let this go unnoticed: multi-element arrays (bare and
quoted), one- and two-pair objects, an isjson() validity check, and a
prefix-preservation assertion that pins the buffer-reset fix.

Closes #931.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-17 13:22:10 -06:00
Stephen Dennis
013b797a32 Add url_escape() and url_unescape() functions (RFC 3986)
url_escape() percent-encodes all bytes except unreserved characters
(A-Z, a-z, 0-9, -, _, ., ~).  url_unescape() decodes %XX sequences
and treats + as space for form-urlencoded compatibility.

- 3 smoke test cases (435/435 pass)
- Help text for both functions

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-09 22:45:47 -06:00
Stephen Dennis
7f9e8cb060 Add web integration functions: encode64, decode64, hmac, isjson, json, json_query, json_mod
Tier 1 web parity features identified in server surveys (Penn, Rhost):
- encode64()/decode64(): standard base64 encoding/decoding
- hmac(): HMAC via OpenSSL (default sha256, any digest() algo)
- isjson(): native RFC 8259 JSON validator with optional type check
- json(): JSON construction (string/number/boolean/null/array/object)
- json_query(): JSON queries via SQLite JSON1 (type/size/get/keys/values/exists)
- json_mod(): JSON modification via SQLite JSON1 (set/insert/replace/remove/patch)

New file funcweb.cpp in engine.so. 16 smoke tests (427/427 passing).
Help entries for all 7 functions.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-09 21:59:23 -06:00