Re: [PATCH] Don't segfault when uniquifying hidden tied arrays
Philippe Altherr <[email protected]> Mon, 20 Jul 2026 15:15:58 +0200
| Newsgroups | gmane.comp.shells.zsh.devel |
|---|---|
| Message-ID | <CAGdYchs4StAndjgG9aY1wTf8OvsaWnaJ5ONxRgr23QN6o3UuLQ@mail.gmail.com> |
--000000000000b094b406570ab5c0 Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable On Mon, Jul 20, 2026 at 7:55=E2=80=AFAM Bart Schaefer <schaefer@brasslanter= n.com> wrote: > On Sun, Jul 19, 2026 at 7:28=E2=80=AFPM Philippe Altherr > <[email protected]> wrote: > > > > - (Param) paramtab->getnode(paramtab, pm->ename))) { > > - x =3D (*apm->gsu.a->getfn)(apm); > > + } else if (PM_TYPE(pm->node.flags) =3D=3D PM_SCALAR && pm->ename) = { > > + x =3D *(pm->node.flags & PM_SPECIAL > > + ? (char ***)pm->u.data > > + : ((struct tieddata *)pm->u.data)->arrptr); > > Just checking ... apm->gsu.a->getfn can return the static &nullarray > to guarantee the result is never NULL. > > Are you confident that pm->u.data is never NULL or a pointer to NULL here= ? > pm->u.data is never NULL by constructions. Global special tied scalars like PATH <https://github.com/zsh-users/zsh/blob/3c0372aef88a6b7cc86f0902b1ba3f14a751= 18c9/Src/params.c#L406> are initialized with IPDEF8 <https://github.com/zsh-users/zsh/blob/3c0372aef88a6b7cc86f0902b1ba3f14a751= 18c9/Src/params.c#L401>, which initializes u.data with a pointer to the underlying variable. Similarly, module defined tied scalars, like WATCH <https://github.com/zsh-users/zsh/blob/3c0372aef88a6b7cc86f0902b1ba3f14a751= 18c9/Src/Modules/watch.c#L699>, have their u.data initialized <https://github.com/zsh-users/zsh/blob/3c0372aef88a6b7cc86f0902b1ba3f14a751= 18c9/Src/module.c#L1079>with a pointer to the underlying variable <https://github.com/zsh-users/zsh/blob/3c0372aef88a6b7cc86f0902b1ba3f14a751= 18c9/Src/module.c#L1079> . User defined tied scalars initialize u.data with an instance of tieddata <https://github.com/zsh-users/zsh/blob/3c0372aef88a6b7cc86f0902b1ba3f14a751= 18c9/Src/builtin.c#L2561> whose arrptr points to the u.arr of the tied array <https://github.com/zsh-users/zsh/blob/3c0372aef88a6b7cc86f0902b1ba3f14a751= 18c9/Src/builtin.c#L2558> . The function colonarrgetfn <https://github.com/zsh-users/zsh/blob/3c0372aef88a6b7cc86f0902b1ba3f14a751= 18c9/Src/params.c#L4275> used by special tied scalars assumes that u.data contains a non-NULL char***. The function tiedarrgetfn <https://github.com/zsh-users/zsh/blob/3c0372aef88a6b7cc86f0902b1ba3f14a751= 18c9/Src/params.c#L4302> used by user defined tied scalars assumes that u.data contains a non-NULL struct tieddata * whose arrptr field contains a non-NULL char***. While pm->u.data is never NULL, the value assigned to x may be NULL but that's fine, then the code that follows simply does nothing; the function uniqarray <https://github.com/zsh-users/zsh/blob/3c0372aef88a6b7cc86f0902b1ba3f14a751= 18c9/Src/params.c#L4468> immediately returns if its parameter is NULL. Philippe --000000000000b094b406570ab5c0 Content-Type: text/html; charset="UTF-8" Content-Transfer-Encoding: quoted-printable <div dir=3D"ltr"><div dir=3D"ltr"><span style=3D"background-color:transpare= nt">On Mon, Jul 20, 2026 at 7:55=E2=80=AFAM Bart Schaefer <<a href=3D"ma= ilto:[email protected]">[email protected]</a>> wrote:</s= pan></div><div class=3D"gmail_quote gmail_quote_container"><blockquote clas= s=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-left:1px solid r= gb(204,204,204);padding-left:1ex">On Sun, Jul 19, 2026 at 7:28=E2=80=AFPM P= hilippe Altherr<br> <<a href=3D"mailto:[email protected]" target=3D"_blank">philipp= [email protected]</a>> wrote:<br> ><br> > - (Param) paramtab->getnode(paramtab, pm->ename))) {<br> > - x =3D (*apm->gsu.a->getfn)(apm);<br> > +=C2=A0 =C2=A0 } else if (PM_TYPE(pm->node.flags) =3D=3D PM_SCALAR = && pm->ename) {<br> > + x =3D *(pm->node.flags & PM_SPECIAL<br> > +=C2=A0 =C2=A0 =C2=A0 ? (char ***)pm->u.data<br> > +=C2=A0 =C2=A0 =C2=A0 : ((struct tieddata *)pm->u.data)->arrptr)= ;<br> <br> Just checking ... apm->gsu.a->getfn can return the static &nullar= ray<br> to guarantee the result is never NULL.<br> <br> Are you confident that pm->u.data is never NULL or a pointer to NULL her= e?<br></blockquote><div><br></div><div>pm->u.data is never NULL by const= ructions. Global special tied scalars like <a href=3D"https://github.com/zs= h-users/zsh/blob/3c0372aef88a6b7cc86f0902b1ba3f14a75118c9/Src/params.c#L406= ">PATH</a>=C2=A0are initialized with <a href=3D"https://github.com/zsh-user= s/zsh/blob/3c0372aef88a6b7cc86f0902b1ba3f14a75118c9/Src/params.c#L401">IPDE= F8</a>, which initializes u.data with a pointer to the underlying variable.= Similarly, module defined tied scalars, like <a href=3D"https://github.com= /zsh-users/zsh/blob/3c0372aef88a6b7cc86f0902b1ba3f14a75118c9/Src/Modules/wa= tch.c#L699">WATCH</a>, have their <a href=3D"https://github.com/zsh-users/z= sh/blob/3c0372aef88a6b7cc86f0902b1ba3f14a75118c9/Src/module.c#L1079">u.data= initialized=C2=A0</a><span style=3D"background-color:transparent"><a href= =3D"https://github.com/zsh-users/zsh/blob/3c0372aef88a6b7cc86f0902b1ba3f14a= 75118c9/Src/module.c#L1079">with a pointer to the underlying variable</a>.= =C2=A0</span><span style=3D"background-color:transparent">User defined tied= scalars </span><a href=3D"https://github.com/zsh-users/zsh/blob/3c0372aef8= 8a6b7cc86f0902b1ba3f14a75118c9/Src/builtin.c#L2561" style=3D"background-col= or:transparent">initialize u.data with an instance of tieddata</a><span st= yle=3D"background-color:transparent"> whose=C2=A0</span><a href=3D"https://= github.com/zsh-users/zsh/blob/3c0372aef88a6b7cc86f0902b1ba3f14a75118c9/Src/= builtin.c#L2558" style=3D"background-color:transparent">arrptr points to th= e u.arr of the tied array</a><span style=3D"background-color:transparent">.= </span></div><div><span style=3D"background-color:transparent"><br></span><= /div><div><span style=3D"background-color:transparent">The function=C2=A0<a= href=3D"https://github.com/zsh-users/zsh/blob/3c0372aef88a6b7cc86f0902b1ba= 3f14a75118c9/Src/params.c#L4275">colonarrgetfn</a>=C2=A0used by special tie= d scalars assumes that u.data contains a non-NULL char***.</span></div><div= ><span style=3D"background-color:transparent"><br></span></div><div><span s= tyle=3D"background-color:transparent">The function=C2=A0<a href=3D"https://= github.com/zsh-users/zsh/blob/3c0372aef88a6b7cc86f0902b1ba3f14a75118c9/Src/= params.c#L4302">tiedarrgetfn</a>=C2=A0used by user defined tied scalars ass= umes that u.data contains a non-NULL=C2=A0</span><span style=3D"background-= color:transparent">struct tieddata * whose arrptr field contains a non-NULL= char***.</span></div><div><span style=3D"background-color:transparent"><br= ></span></div><div><span style=3D"background-color:transparent">While pm-&g= t;u.data is never NULL, the value assigned to x may be NULL but that's = fine, then the code that follows simply does nothing; the function=C2=A0</s= pan><span style=3D"background-color:transparent"><a href=3D"https://github.= com/zsh-users/zsh/blob/3c0372aef88a6b7cc86f0902b1ba3f14a75118c9/Src/params.= c#L4468">uniqarray</a>=C2=A0immediately returns if its parameter is NULL.</= span></div><div><span style=3D"background-color:transparent"><br></span></d= iv><div><span style=3D"background-color:transparent">Philippe</span></div><= div><span style=3D"background-color:transparent"><br></span></div></div></d= iv> --000000000000b094b406570ab5c0--