Maintaining libio

Florian Weimer fweimer@redhat.com
Wed Apr 19 15:02:00 GMT 2017


On 04/19/2017 04:48 PM, Adhemerval Zanella wrote:
> 
> 
> On 19/04/2017 06:17, Florian Weimer wrote:
>> On 08/08/2016 10:43 PM, Adhemerval Zanella wrote:
>>> @@ -239,14 +254,14 @@ _IO_str_seekoff (_IO_FILE *fp, _IO_off64_t offset, int dir, int mode)
>>>      if (mode == 0 && (fp->_flags & _IO_TIED_PUT_GET))
>>>        mode = (fp->_flags & _IO_CURRENTLY_PUTTING ? _IOS_OUTPUT : _IOS_INPUT);
>>>    +  bool was_writing = (fp->_IO_write_ptr > fp->_IO_write_base
>>> +             || _IO_in_put_mode (fp));
>>> +  if (was_writing)
>>> +    _IO_str_switch_to_get_mode (fp);
>>
>> This patch breaks backwards compatibility with applications which call _IO_str_seekoff directly.  This is an exported function and it was originally intended as a building block for building custom streams, so we cannot change what it does just to fit glibc's internal needs, based on how the function is called from within glibc.
>>
>> But if we apply this standard of backwards compatibility, we cannot make *any* changes to libio (including important security hardening) without copying most of the code first.  We have no tests which check the extended API behavior, and the interface is very much under-documented, too.
>>
>> What should we do here?
> 
> Right, so should we revert the patch, reopen both bugs and rework all libio
> in this case (which might span on multiple releases)? I know that we should
> aim for compatibility where applicable, but I think blindly aim for it even
> for bug/out of conformance cases adds more maintainer burden that actually
> fixes real cases usage.
> 
> For this specific case, the code is clearly buggy when ran a different libc
> for a non-specific gnu extension (open_memstream). Should we still provide
> buggy compat interfaces in this case (as we are still aiming to provide)?

Sorry, I wasn't clear.  The buggy interface is open_memstream.  Fixing 
that is completely fine, no compatibility symbol is required.  But 
_IO_str_seekoff is a completely different, allegedly public interface, 
and the existing callers most expect some concrete behavior from it.

A hypothetical example of the same scenario: posix_fallocate used to 
have a bug that it did not work on O_APPEND descriptors because pwrite64 
ignored the offset for them, as required by POSIX.  We could have fixed 
that by changing pwrite64 not to ignore the write offset, but that's of 
course bogus because the specified semantics for pwrite64 require 
different behavior.

What I'm trying to say is that similar, but undocumented requirements 
might well exist for the _IO_str_seekoff function.  Hence my original 
comment that we'd need to make a copy first, fix the copy, and adjust 
internal callers to use the copy, leaving the original implementation alone.

Things get worse once we start changing struct definitions.  Then we 
basically have to duplicate everything that depends on those structs.

I think that's not a good use of our time because it is very unlikely 
that there are any applications left which use these interfaces. 
Instead, I suggest that we make explicit that the internal libio 
interfaces are unsupported (because they are unsupportable), and remove 
them from the ABI, so that people who have those old binaries get clear 
dynamic linker failures instead of corrupted data.

Thanks,
Florian



More information about the Libc-alpha mailing list