[PATCH v2] ungetc: Guarantee single char pushback

Florian Weimer fweimer@redhat.com
Mon Dec 2 21:18:39 GMT 2024


* Siddhesh Poyarekar:

> diff --git a/libio/genops.c b/libio/genops.c
> index d7e35e67d5..996daf0ad8 100644
> --- a/libio/genops.c
> +++ b/libio/genops.c
> @@ -1,4 +1,5 @@
>  /* Copyright (C) 1993-2024 Free Software Foundation, Inc.
> +   Copyright The GNU Toolchain Authors.
>     This file is part of the GNU C Library.
>  
>     The GNU C Library is free software; you can redistribute it and/or
> @@ -48,6 +49,13 @@ flush_cleanup (void *not_used)
>  }
>  #endif
>  
> +void
> +_IO_free_backup_buf (FILE *fp, char *ptr)
> +{
> +  if (ptr != fp->_short_backupbuf)
> +    free (ptr);
> +}

Shouldn't this check for the availability of the _short_backupbuf field,
too?

And with that in place, it might make sense to update oldfileops.c in
similar places, just in case something weird happens with the vtables
and we end up the old vtables code on new file handles.

For similar reasons, please convert the free calls for wide streams to
_IO_free_backup_buf, too.  We definitely have weird vtable interactions
for those.

> diff --git a/stdio-common/tst-ungetc-nomem.c b/stdio-common/tst-ungetc-nomem.c
> new file mode 100644
> index 0000000000..73b88e2e1c
> --- /dev/null
> +++ b/stdio-common/tst-ungetc-nomem.c

> +    FAIL_EXIT1 ("fwrite failed: 5m\n");

Typo: %m

> +  while (!feof (fp))
> +    {
> +      fail = true;
> +      TEST_COMPARE (ungetc ('y', fp), 'y');
> +      /* This will result in resizing, which should fail.  */
> +      TEST_COMPARE (ungetc ('y', fp), EOF);
> +      fail = false;
> +      TEST_COMPARE (fgetc (fp), 'y');

Hmm.  So ungetc doesn't set the error indicator?  POSIX doesn't mention
it, so it seems okay.

When I mentioned multiple ungetc calls in a row, I meant that first
force a single-byte buffer (with fail = true), and then re-enable malloc
and force switch to a larger buffer with multiple ungetc calls.

Thanks,
Florian



More information about the Libc-alpha mailing list