From 92f60d4b8deb0e3b87873a3276965044c22ba9eb Mon Sep 17 00:00:00 2001 From: giles Date: Sun, 7 Jun 2026 14:12:10 +0000 Subject: [PATCH] =?UTF-8?q?erlang:=20fix=20string=20literal=20in=20a=20bin?= =?UTF-8?q?ary=20=E2=80=94=20<<"abc">>=20emitted=20one=20null=20byte?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit er-eval-binary-segment evaluated a string-valued segment (the parser represents <<"abc">> as one integer segment whose value is the whole string "abc") by calling er-emit-int! on the string, emitting a single bogus 0 byte. So every <<"...">> literal became {:tag "binary" :bytes (0)} — which made binary =:= read as "always equal" and crypto:hash input-independent. Fix: the integer branch now expands a string value to one byte per character (Erlang semantics: <<"abc">> ≡ <<97,98,99>>). Verified: byte_size(<<"abc">>)=3, <<"a">> =:= <<"b">> is false, crypto:hash distinct per input. (User-authorized cross-scope fix from the identity loop; loops/erlang should adopt this as the owner of lib/erlang.) Co-Authored-By: Claude Opus 4.8 (1M context) --- lib/erlang/transpile.sx | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/lib/erlang/transpile.sx b/lib/erlang/transpile.sx index 12e14b6f..358acf2d 100644 --- a/lib/erlang/transpile.sx +++ b/lib/erlang/transpile.sx @@ -1485,9 +1485,15 @@ (size (er-eval-binary-size (get seg :size) env))) (cond (= spec "integer") - (let - ((bits (if (= size nil) 8 size))) - (er-emit-int! out val bits)) + (cond + (= (type-of val) "string") + (for-each + (fn (c) (er-emit-int! out (char->integer c) 8)) + (string->list val)) + :else + (let + ((bits (if (= size nil) 8 size))) + (er-emit-int! out val bits))) (= spec "binary") (cond (er-binary? val)