bug#79194: Fwd: bug#79194: Segfault with 0 byte symbol

a aa <[email protected]> Mon, 11 Aug 2025 23:41:38 +0000
Newsgroups gmane.lisp.guile.bugs
Message-ID <CAN=a0HqstxdgZGby0hS72sgWLT0jZH7yxiWNeWvC=szizDf1-A@mail.gmail.com>
--000000000000c0f111063c1f77f8
Content-Type: multipart/alternative; boundary="000000000000c0f110063c1f77f6"

--000000000000c0f110063c1f77f6
Content-Type: text/plain; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable

---------- Forwarded message ---------
From: a aa <[email protected]>
Date: Mon, Aug 11, 2025 at 11:40=E2=80=AFPM
Subject: Re: bug#79194: Segfault with 0 byte symbol
To: Tomas Volf <[email protected]>


Hello, Tomas <[email protected]>

> You wrote "handle 0 byte *strings*" (emphasis mine).  That is not what
> you are doing.  NULL is not a "0 byte string".  "" (almost) is.  Or a
> char* can be.  But not NULL.

The string "" does not have 0 bytes in utf8. It has 1 byte for the null
terminator,
which is still reading out of bounds when providing 0 for its length.

I probably should have mentioned this in the first message, but I
experienced
this issue in rust which doesn't use null terminated strings so the example
wasn't
exactly accurate.

    rustc -lguile-3.0 main.rs

or if you don't have rust

    c++ main.cpp `pkg-config --cflags --libs guile-3.0`

> Both work fine.  You cannot just send a null pointer to a function that
> is supposed to take a string and expect it to work.  So I do not think
> it is valid to declare this to be an "incorrect behaviour", maybe
> "unexpected" (by you) would be better description.

The function does not take a string, it takes an array of utf8 codepoints
so the function
should not expect the pointer to have a null terminator.

On Sun, Aug 10, 2025 at 2:34=E2=80=AFPM Tomas Volf <[email protected]> wrote:

> Hi,
>
> a aa <[email protected]> writes:
>
> > Hello,
> >
> > how to reproduce:
> > cc main.c `pkg-config --libs --cflags guile-3.0` && ./a.out
> >
> > incorrect behaviour:
> > The second parameter for scm_from_utf8_symboln should be how many bytes
> are
> > pointed to by the pointer however the pointer still gets read if the
> length
> > is zero. Being able to handle 0 byte strings is expected since replacin=
g
> > the call from scm_from_utf8_symboln to scm_from_utf8_stringn will not
> have
> > a segfault and the documentation for this function does not mention bei=
ng
> > unable to handle 0 byte strings.
>
> Well, the scm_from_utf8_symboln is just not documented at all, so I am
> not sure how you have determined that the "documentation for this
> function does no mention ...".  But let us ignore that for a moment.
>
> You wrote "handle 0 byte *strings*" (emphasis mine).  That is not what
> you are doing.  NULL is not a "0 byte string".  "" (almost) is.  Or a
> char* can be.  But not NULL.
>
> >
> > [..]
> >
> > #include <libguile.h>
> >
> > void* inner_main(void*) {
> >   SCM sym =3D scm_from_utf8_symboln(NULL, 0);
>
> The line should be
>
>     SCM sym =3D scm_from_utf8_symboln("", 0);
>
> or
>
>     const char zero_str[] =3D {};
>     SCM sym =3D scm_from_utf8_symboln(zero_str, 0);
>
> Both work fine.  You cannot just send a null pointer to a function that
> is supposed to take a string and expect it to work.  So I do not think
> it is valid to declare this to be an "incorrect behaviour", maybe
> "unexpected" (by you) would be better description.
>
> Tomas
>
> --
> There are only two hard things in Computer Science:
> cache invalidation, naming things and off-by-one errors.
>

--000000000000c0f110063c1f77f6
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr"><br><br><div class=3D"gmail_quote gmail_quote_container"><=
div dir=3D"ltr" class=3D"gmail_attr">---------- Forwarded message ---------=
<br>From: <b class=3D"gmail_sendername" dir=3D"auto">a aa</b> <span dir=3D"=
auto">&lt;<a href=3D"mailto:[email protected]">[email protected]</a>&gt=
;</span><br>Date: Mon, Aug 11, 2025 at 11:40=E2=80=AFPM<br>Subject: Re: bug=
#79194: Segfault with 0 byte symbol<br>To: Tomas Volf &lt;~@<a href=3D"http=
://wolfsden.cz">wolfsden.cz</a>&gt;<br></div><br><br><div dir=3D"ltr">Hello=
, Tomas &lt;~@<a href=3D"http://wolfsden.cz" target=3D"_blank">wolfsden.cz<=
/a>&gt;<div><br>&gt;=C2=A0You wrote &quot;handle 0 byte *strings*&quot; (em=
phasis mine).=C2=A0 That is not what<br>&gt; you are doing.=C2=A0 NULL is n=
ot a &quot;0 byte string&quot;.=C2=A0 &quot;&quot; (almost) is.=C2=A0 Or a<=
br>&gt; char* can be.=C2=A0 But not NULL.<br><br></div><div>The string &quo=
t;&quot; does not have 0 bytes in utf8. It has 1 byte for the null terminat=
or,<br></div><div>which is still reading out of bounds when providing 0 for=
 its length.<br></div><div><br></div><div>I probably should have mentioned =
this in the first message, but I experienced<br>this issue in rust which do=
esn&#39;t use null terminated strings so the example wasn&#39;t<br></div><d=
iv>exactly accurate.</div><div><br></div><div>=C2=A0 =C2=A0 rustc -lguile-3=
.0 <a href=3D"http://main.rs" target=3D"_blank">main.rs</a><br><br></div><d=
iv>or if you don&#39;t have rust<br><br></div><div>=C2=A0 =C2=A0 c++ main.c=
pp `pkg-config --cflags --libs guile-3.0`</div><div><br>&gt; Both work fine=
.=C2=A0 You cannot just send a null pointer to a function that<br>&gt; is s=
upposed to take a string and expect it to work.=C2=A0 So I do not think<br>=
&gt; it is valid to declare this to be an &quot;incorrect behaviour&quot;, =
maybe<br></div><div>&gt; &quot;unexpected&quot; (by you) would be better de=
scription.<br></div><div><br></div><div>The function does not take a string=
, it takes an array of utf8 codepoints so the function<br></div><div>should=
 not expect the pointer to have a null terminator.</div></div><br><div clas=
s=3D"gmail_quote"><div dir=3D"ltr" class=3D"gmail_attr">On Sun, Aug 10, 202=
5 at 2:34=E2=80=AFPM Tomas Volf &lt;~@<a href=3D"http://wolfsden.cz" target=
=3D"_blank">wolfsden.cz</a>&gt; wrote:<br></div><blockquote class=3D"gmail_=
quote" style=3D"margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,=
204);padding-left:1ex">Hi,<br>
<br>
a aa &lt;<a href=3D"mailto:[email protected]" target=3D"_blank">lgray3420=
@gmail.com</a>&gt; writes:<br>
<br>
&gt; Hello,<br>
&gt;<br>
&gt; how to reproduce:<br>
&gt; cc main.c `pkg-config --libs --cflags guile-3.0` &amp;&amp; ./a.out<br=
>
&gt;<br>
&gt; incorrect behaviour:<br>
&gt; The second parameter for scm_from_utf8_symboln should be how many byte=
s are<br>
&gt; pointed to by the pointer however the pointer still gets read if the l=
ength<br>
&gt; is zero. Being able to handle 0 byte strings is expected since replaci=
ng<br>
&gt; the call from scm_from_utf8_symboln to scm_from_utf8_stringn will not =
have<br>
&gt; a segfault and the documentation for this function does not mention be=
ing<br>
&gt; unable to handle 0 byte strings.<br>
<br>
Well, the scm_from_utf8_symboln is just not documented at all, so I am<br>
not sure how you have determined that the &quot;documentation for this<br>
function does no mention ...&quot;.=C2=A0 But let us ignore that for a mome=
nt.<br>
<br>
You wrote &quot;handle 0 byte *strings*&quot; (emphasis mine).=C2=A0 That i=
s not what<br>
you are doing.=C2=A0 NULL is not a &quot;0 byte string&quot;.=C2=A0 &quot;&=
quot; (almost) is.=C2=A0 Or a<br>
char* can be.=C2=A0 But not NULL.<br>
<br>
&gt;<br>
&gt; [..]<br>
&gt;<br>
&gt; #include &lt;libguile.h&gt;<br>
&gt;<br>
&gt; void* inner_main(void*) {<br>
&gt;=C2=A0 =C2=A0SCM sym =3D scm_from_utf8_symboln(NULL, 0);<br>
<br>
The line should be<br>
<br>
=C2=A0 =C2=A0 SCM sym =3D scm_from_utf8_symboln(&quot;&quot;, 0);<br>
<br>
or<br>
<br>
=C2=A0 =C2=A0 const char zero_str[] =3D {};<br>
=C2=A0 =C2=A0 SCM sym =3D scm_from_utf8_symboln(zero_str, 0);<br>
<br>
Both work fine.=C2=A0 You cannot just send a null pointer to a function tha=
t<br>
is supposed to take a string and expect it to work.=C2=A0 So I do not think=
<br>
it is valid to declare this to be an &quot;incorrect behaviour&quot;, maybe=
<br>
&quot;unexpected&quot; (by you) would be better description.<br>
<br>
Tomas<br>
<br>
-- <br>
There are only two hard things in Computer Science:<br>
cache invalidation, naming things and off-by-one errors.<br>
</blockquote></div>
</div></div>

--000000000000c0f110063c1f77f6--

--000000000000c0f111063c1f77f8
Content-Type: text/x-rust; charset="US-ASCII"; name="main.rs"
Content-Disposition: attachment; filename="main.rs"
Content-Transfer-Encoding: base64
Content-ID: <f_me7q5fpm0>
X-Attachment-Id: f_me7q5fpm0

dXNlIHN0ZDo6ewogICAgZmZpOjp7Y19jaGFyLCBjX3ZvaWR9LAogICAgcHRyLAp9OwoKZXh0ZXJu
ICJDIiB7CiAgICBmbiBzY21fd2l0aF9ndWlsZSgKICAgICAgICBfOiBPcHRpb248dW5zYWZlIGV4
dGVybiAiQyIgZm4oXzogKm11dCBjX3ZvaWQpIC0+ICptdXQgY192b2lkPiwKICAgICAgICBfOiAq
bXV0IGNfdm9pZCwKICAgICkgLT4gKm11dCBjX3ZvaWQ7CiAgICBmbiBzY21fZnJvbV91dGY4X3N5
bWJvbG4oXzogKmNvbnN0IGNfY2hhciwgXzogdXNpemUpIC0+ICptdXQgY192b2lkOwp9Cgp1bnNh
ZmUgZXh0ZXJuICJDIiBmbiBpbm5lcl9tYWluKF86ICptdXQgY192b2lkKSAtPiAqbXV0IGNfdm9p
ZCB7CiAgICBsZXQgc3RyID0gIiI7CiAgICB1bnNhZmUgewogICAgICAgIHNjbV9mcm9tX3V0Zjhf
c3ltYm9sbihzdHIuYXNfcHRyKCkuY2FzdCgpLCBzdHIubGVuKCkpOwogICAgfQoKICAgIHB0cjo6
bnVsbF9tdXQoKQp9CgpmbiBtYWluKCkgewogICAgdW5zYWZlIHsKICAgICAgICBzY21fd2l0aF9n
dWlsZShTb21lKGlubmVyX21haW4pLCBwdHI6Om51bGxfbXV0KCkpOwogICAgfQp9Cg==
--000000000000c0f111063c1f77f8
Content-Type: text/x-c-code; charset="US-ASCII"; name="main.cpp"
Content-Disposition: attachment; filename="main.cpp"
Content-Transfer-Encoding: base64
Content-ID: <f_me7q5o9y1>
X-Attachment-Id: f_me7q5o9y1

I2luY2x1ZGUgPGxpYmd1aWxlLmg+CiNpbmNsdWRlIDx2ZWN0b3I+Cgp2b2lkKiBpbm5lcl9tYWlu
KHZvaWQqKSB7CiAgc3RkOjp2ZWN0b3I8Y2hhcj4gcmF3X3plcm9fdXRmOF9zdHIgPSB7fTsKICBT
Q00gc3ltID0gc2NtX2Zyb21fdXRmOF9zeW1ib2xuKHJhd196ZXJvX3V0Zjhfc3RyLmRhdGEoKSwg
cmF3X3plcm9fdXRmOF9zdHIuc2l6ZSgpKTsKICAKICByZXR1cm4gTlVMTDsKfQoKaW50IG1haW4o
dm9pZCkgewogIHNjbV93aXRoX2d1aWxlKGlubmVyX21haW4sIE5VTEwpOwoKICByZXR1cm4gMDsK
fQo=
--000000000000c0f111063c1f77f8--