[PATCH v2] libio: Fix fmemopen_write on appending condition

Rocket Ma marocketbd@gmail.com
Tue Mar 24 17:36:01 GMT 2026


Adhemerval Zanella Netto <adhemerval.zanella@linaro.org> 于2026年3月24日周二 22:39写道:
> This test is missing a Copyright and I think it should be placed on stdio-common/
> subfolder.

Copyright added. I don't think it should be placed in stdio-common.
Since this bug is directly from
libio/fmemopen.c, place it in stdio-common would be confusing.

> We prefer to use support/check.h macros.

Done.

> > +
> > +static int
> > +do_test (void)
> > +{
> > +  char buf[5] = "1";
> > +  FILE *fp = fmemopen (buf, 4, "a+");
> > +  tst_assert (fp != NULL);
> > +  tst_assert (fseek (fp, 3, SEEK_SET) == 0);
> > +  tst_assert (fwrite ("XXXX", 1, 4, fp) > 0);
>
> This test does not really stress the issue, it works regardless of the patch
> is applied or not.  We need also to check if the string does have the XXX append
> on it:
>
> static int
> do_test (void)
> {
>   char buf[5] = "1";
>   FILE *fp = xfmemopen (buf, 4, "a+");
>   TEST_COMPARE (fseek (fp, 3, SEEK_SET), 0);
>   TEST_VERIFY (fwrite ("XXXX", 1, 4, fp) > 0);
>   int r = fclose (fp);
>   printf ("r=%d errno=%s\n", r, strerrorname_np (errno));
>   TEST_COMPARE_STRING (buf, "1XXX");
>
>   return 0;
> }
>

I sebuf to NULL so fwrite could immediately write to underlying buf, then
we can compare it with "1XXX" immediately.

> > +
> > +  return 0;
> > +}
> > +
> > +#include <support/test-driver.c>
> > diff --git a/libio/fmemopen.c b/libio/fmemopen.c
> > index f2ae1338d3..cdc3a3476e 100644
> > --- a/libio/fmemopen.c
> > +++ b/libio/fmemopen.c
> > @@ -71,7 +71,7 @@ fmemopen_write (void *cookie, const char *b, size_t s)
> >
> >    if (pos + s > c->size)
> >      {
> > -      if ((size_t) (c->pos + addnullc) >= c->size)
> > +      if ((size_t) (pos + addnullc) >= c->size)
> >       {
> >         __set_errno (ENOSPC);
> >         return 0;
>
> I think this does not fully fix the issue, since the fwrite below
> will still return 4 where I would expect 3 bytes are written
> (buf becomes "1XXX"), the null terminator attempt lands at size = 4
> (boundary, not within the array).

Please see Bug 34006 (https://sourceware.org/bugzilla/show_bug.cgi?id=34006),
before considering that, I think we need to discuss on a consistent behavior of
fwrite.

> Unfortunately, the current glibc implementation only calls
> fmemopen_write at flush, and thus the fclose above will fail without
> setting the errno. At least with current code we properly fail with
> ENOSPC in such cases.
>
> I think we will need to proper fix the fwrite return code before,
> so fflush/fclose does not fail in this case.

But the "buf" is buffered by stdio... Currently it should be able to
fail when no one byte can
be written in fflush; then for fclose, I'm not sure when closing a
normal FILE, flushing rest buffer
to underlying fd, what if write failed, for example, lack of space?
Will fclose fail then? If so,
we can consider handle this case.


More information about the Libc-alpha mailing list