[PATCH v2] ungetc: Guarantee single char pushback

Siddhesh Poyarekar siddhesh@sourceware.org
Mon Dec 2 22:22:07 GMT 2024


On 2024-12-02 16:18, Florian Weimer wrote:
> * 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?

Uhmm, I suppose so, so:

if (_IO_vtable_offset (fp) == 0 && ptr != fp->_short_backupbuf)
   ...

> 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.

I'll take a look and clean up.

> 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.

Yes, I just wanted to separate it out from this change.  Would you 
rather prefer that I club the two changes together like I did the first 
time?

>> 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

Eep :/

>> +  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.

Ah, so a *successful* switch after the transient failure; OK I'll add 
that and also see if there are any other combinations to test.

Thanks,
Sid


More information about the Libc-alpha mailing list