Deutsch   English   Français   Italiano  
<86zfijygzi.fsf@linuxsc.com>

View for Bookmarking (what is this?)
Look up another Usenet article

Path: ...!eternal-september.org!feeder3.eternal-september.org!news.eternal-september.org!eternal-september.org!.POSTED!not-for-mail
From: Tim Rentsch <tr.17687@z991.linuxsc.com>
Newsgroups: comp.lang.c
Subject: Re: Buffer contents well-defined after fgets() reaches EOF ?
Date: Mon, 17 Feb 2025 21:11:29 -0800
Organization: A noiseless patient Spider
Lines: 90
Message-ID: <86zfijygzi.fsf@linuxsc.com>
References: <vo9g74$fu8u$1@dont-email.me> <vo9hlo$g0to$1@dont-email.me> <vo9khf$ggd4$1@dont-email.me> <vobf3h$sefh$2@dont-email.me> <vobjdt$t5ka$1@dont-email.me> <vobro1$u9fa$1@dont-email.me> <vobu9b$12bi8$1@dont-email.me> <voc9d7$13pam$2@dont-email.me> <vodi7t$1b6at$1@dont-email.me> <voe7kp$1f0us$3@dont-email.me> <voegdf$1hbn6$1@dont-email.me> <voel5v$1kp3m$1@dont-email.me> <vog3lp$1sd7k$1@dont-email.me> <87msesnnwa.fsf@nosuchdomain.example.com> <vogkn3$1vo3l$2@dont-email.me> <87bjv8nj8g.fsf@nosuchdomain.example.com>
MIME-Version: 1.0
Content-Type: text/plain; charset=us-ascii
Injection-Date: Tue, 18 Feb 2025 06:11:30 +0100 (CET)
Injection-Info: dont-email.me; posting-host="9d1d7b6626b34534d8c8589d87cd0ec0";
	logging-data="1657108"; mail-complaints-to="abuse@eternal-september.org";	posting-account="U2FsdGVkX18xWX74iHnrtigETLcxwGRwKygIGMFoWrQ="
User-Agent: Gnus/5.11 (Gnus v5.11) Emacs/22.4 (gnu/linux)
Cancel-Lock: sha1:nVk3Qc/XxzrjNcW0s5AkTn3nPBw=
	sha1:SZz6SHuv6t2jLfzYu5cSBYGYMGQ=
Bytes: 4078

Keith Thompson <Keith.S.Thompson+u@gmail.com> writes:

> James Kuyper <jameskuyper@alumni.caltech.edu> writes:
>
>> On 2/11/25 16:59, Keith Thompson wrote:
>>
>>> James Kuyper <jameskuyper@alumni.caltech.edu> writes:
>>
>> ...
>>
>>>> I just tried it, using gcc and found that fgets() does set the
>>>> first byte of the buffer to a null character.  Therefore, it
>>>> doesn't conform to the requirements of the standard.  That's not
>>>> particularly surprising - calling fgets with useless arguments
>>>> isn't something that I'd expect to be a high priority on their
>>>> pre-delivery tests.
>>>
>>> As you know, gcc doesn't implement fgets().  Were you using GNU lib
>>
>> .
>> Yes.  To be specific, Ubuntu GLIBC 2.35-0ubuntu3.9.
>>
>> Here's my test code:
>>
>> #include <stdio.h>
>> #include <stdlib.h>
>> int main(int argc, char *argv[])
>> {
>> char fill = 1;
>> char buffer = fill;
>> char *retval = NULL;
>> FILE *infile;
>> if(argc < 2)
>> infile = stdin;
>> else{
>> infile = fopen(argv[1], "r");
>> if(!infile)
>> {
>> perror(argv[1]);
>> return EXIT_FAILURE;
>> }
>> }
>>
>> while((retval = fgets(&buffer, 1, infile)) == &buffer)
>> {
>> printf("%ld:'%u'\n", ftell(infile), (unsigned)buffer);
>> buffer = fill++;
>> }
>> if(ferror(infile))
>> perror("fgets");
>>
>> printf("%p!=%p ferror:%d feof:%d '%c'\n",
>> (void*)&buffer, (void*)retval,
>> ferror(infile), feof(infile), buffer);
>> }
>>
>> Note that if fgets() works as it should, that's an infinite loop,
>> since no data is read in, and therefore there's no movement through
>> the input file.  I wrote code that executes after the infinite loop
>> just to cover the possibility that it doesn't work that way.
>
> I get an infinite loop with both glibc and musl on Ubuntu, and under
> Termux on Android (Bionic library implementation):
>
> $ ./jk < /dev/null | head -n 3
> 0:'0'
> 0:'0'
> 0:'0'
> $ echo hello | ./jk | head -n 3
> -1:'0'
> -1:'0'
> -1:'0'
> $
>
> With newlib on Cygwin, there is no infinite loop:
>
> $ ./jk.exe < /dev/null
> 0x7ffffcc17!=0x0 ferror:0 feof:0 ''
> $ echo hello | ./jk.exe
> 0x7ffffcc17!=0x0 ferror:0 feof:0 ''
> $

I have an amusing footnote to these trials.

I wrote a short program to test fgets() under varying length
arguments.  Compiling with gcc on Ubuntu, I was surprised to
discover the behavior of fgets() with a length argument of 1
depended on the the optimization setting of the compiler -
using -O0 gave a different result than -O1.  Compiling with clang
gave the same result under both optimization settings.