On Mon, Feb 24, 2025 at 6:13 PM Solar Designer <so...@openwall.com> wrote:

> Hi Dmitry,
>
> Thank you for taking a look at this.
>
> On Mon, Feb 24, 2025 at 05:57:13PM +0100, Dmitry Belyavskiy wrote:
> > On Sat, Feb 22, 2025 at 4:27???AM Solar Designer <so...@openwall.com>
> wrote:
> > > +++ openssh-8.7p1-43.el9-tree.krb5-ssh_asprintf_append/auth-krb5.c
> > > 2025-02-21 03:37:13.106465704 +0000
> > > @@ -309,13 +309,14 @@ ssh_asprintf_append(char **dsc, const ch
> > >         i = vasprintf(&src, fmt, ap);
> > >         va_end(ap);
> > >
> > > -       if (i == -1 || src == NULL)
> > > +       if (i == -1)
> > >                 return -1;
> > >
> > >         old = *dsc;
> > >
> > >         i = asprintf(dsc, "%s%s", *dsc, src);
> > > -       if (i == -1 || src == NULL) {
> > > +       if (i == -1) {
> > > +               *dsc = old;
> > >                 free(src);
> > >                 return -1;
> > >         }
> > >
> > > This is in RH-added Kerberos support code.  The issue was that if the
> > > second asprintf() call failed, it'd leave *dsc undefined, yet the
> caller
> > > of this function would free() memory via that pointer.  In practice,
> > > glibc would either leave the pointer unchanged or reset it to NULL
> > > (varying by glibc version and specific error condition), both of which
> > > are safe to free().  Yet resetting "*dsc = old;" should be safer, and
> > > should avoid the memory leak that happens if *dsc got reset to NULL.
> > > That memory leak shouldn't have mattered anyway because it'd only occur
> > > when the process already has trouble allocating more memory here.
> > >
> > > The "src == NULL" checks are dropped because the first one shouldn't
> > > matter if asprintf() behaves correctly and wouldn't help if it does not
> > > (as src isn't initialized to NULL before the call), the second one
> > > is wrong (was probably meant to check *dsc, not src), and further code
> > > in this same source file relies on asprintf() return value anyway.
> >
> > I'm not sure that the check for the  src == NULL should be removed at
> least
> > for the 1st branch.
>
> It's OK to keep it.  This really shouldn't matter.
>
> > Unfortunately I came across implementations that caused segfault on
> passing
> > NULL pointers to sprintf-like functions.
>
> Of course, we shouldn't pass NULL pointers to sprintf-like functions.
> But if the first asprintf() call returns other than -1, the pointer is
> supposed to be non-NULL.  And if we somehow don't trust asprintf()
> return value (even though it's standardized, unlike what happens to the
> pointer on error), then the check for NULL is insufficient because the
> pointer may as well remain uninitialized (formally it's undefined), so
> you'd need to start by "src = NULL;" before the first asprintf() call
> for this defensive programming to make sense.  And the second "src ==
> NULL" check is redundant with the first (not reached if src is NULL).
>

Ah. Fair point, I missed that src is freshly allocated. Yes, you are
correct.


-- 
Dmitry Belyavskiy

Reply via email to