Qry : Behaviour of fgets -- ?


S

Sheth Raxit

Machine 1 :
bash-3.00$ uname -a
SunOS <hostname> 5.10 Generic_118822-30 sun4u sparc SUNW,Sun-Fire-280R

bash-3.00$ gcc -v
Reading specs from /usr/local/lib/gcc-lib/sparc-sun-solaris2.8/2.95.3/
specs
gcc version 2.95.3 20010315 (release)


Machine 2:
bash-2.05b$ uname -a
Linux <hostname> 2.4.21-4.EL #1 Fri Oct 3 18:13:58 EDT 2003 i686 i686
i386 GNU/Linux

bash-2.05b$ gcc -v
Reading specs from /usr/lib/gcc-lib/i386-redhat-linux/3.2.3/specs
Configured with: ../configure --prefix=/usr --mandir=/usr/share/man --
infodir=/usr/share/info --enable-shared --enable-threads=posix --
disable-checking --with-system-zlib --enable-__cxa_atexit --host=i386-
redhat-linux
Thread model: posix
gcc version 3.2.3 20030502 (Red Hat Linux 3.2.3-20)



bash-2.05b$ cat fgets_fail_test.c
#include<stdio.h>
#include <string.h>
#include<stdlib.h>

/* Demo fgets failed by Raxit Sheth & Gaurav Gupta */

int main()
{
char spcontent[100],sendrepfile[100];
FILE *spfp=NULL;
memset(sendrepfile,0,100);
strcpy(sendrepfile,"/tmp/filenotexists");
if ((spfp = fopen(sendrepfile, "r")) == (FILE *)NULL)
{
printf("error in opening file %s",sendrepfile);fflush(stdout);
}
memset(spcontent, 0, sizeof(spcontent));

while (fgets(spcontent,40, spfp)!=NULL)
{
printf("The value of spcontent is
[%s]",spcontent);fflush(stdout);;
}
return 0;
}


<simillar core dump occurs on both the system>
bash-2.05b$ gcc -Wall fgets_fail_test.c -o test
bash-2.05b$ ./test
error in opening file /tmp/filenotexistsSegmentation fault (core
dumped)
bash-2.05b$ gdb ./test ./core.27887
GNU gdb Red Hat Linux (5.3.90-0.20030710.40rh)
Copyright 2003 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and
you are
welcome to change it and/or distribute copies of it under certain
conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB. Type "show warranty" for
details.
This GDB was configured as "i386-redhat-linux-gnu"...(no debugging
symbols found)...Using host libthread_db library "/lib/tls/
libthread_db.so.1".

Core was generated by `./test'.
Program terminated with signal 11, Segmentation fault.
Reading symbols from /lib/tls/libc.so.6...(no debugging symbols
found)...done.
Loaded symbols for /lib/tls/libc.so.6
Reading symbols from /lib/ld-linux.so.2...(no debugging symbols
found)...done.
Loaded symbols for /lib/ld-linux.so.2
#0 0xb7506444 in fgets () from /lib/tls/libc.so.6
(gdb) where
#0 0xb7506444 in fgets () from /lib/tls/libc.so.6
#1 0x0804854b in main ()
(gdb) frame 0
#0 0xb7506444 in fgets () from /lib/tls/libc.so.6
(gdb) print errno
Cannot access memory at address 0xb74a7008


char *fgets(char *s, int n, FILE *stream)
Qry : What is the Behaviour if stream is NULL. ?

As per our understanding fgets should return NULL < and internally
gets should put check on stream, if it is not NULL then only should do
additional access of stream.

please ignore if it is known and would be great if you can point out
in the implementation detail.


--Gaurav Gupta & Raxit Sheth
http://www.barcamp.org/BarCampMumbaiOct2007 <----BarCampMumbaiOct2007
 
Ad

Advertisements

K

Kenneth Brody

Sheth Raxit wrote:
[...]
char *fgets(char *s, int n, FILE *stream)
Qry : What is the Behaviour if stream is NULL. ?

As per our understanding fgets should return NULL < and internally
gets should put check on stream, if it is not NULL then only should do
additional access of stream.
[...]

I see no direct reference in the standard to what should happen. The
closest thing I see (and it's not very close) is 7.19.3p4:

The value of a pointer to a FILE object is indeterminate after
the associated file is closed (including the standard text
streams).

However, I can tell you that the system I'm currently on has an
ASSERT(stream != NULL) near the top of fgets(), so it won't allow
such a value.

My guess is that this is UB.

--
+-------------------------+--------------------+-----------------------+
| Kenneth J. Brody | www.hvcomputer.com | #include |
| kenbrody/at\spamcop.net | www.fptech.com | <std_disclaimer.h> |
+-------------------------+--------------------+-----------------------+
Don't e-mail me at: <mailto:[email protected]>
 
J

jacob navia

Sheth said:
Machine 1 :
bash-3.00$ uname -a
SunOS <hostname> 5.10 Generic_118822-30 sun4u sparc SUNW,Sun-Fire-280R

bash-3.00$ gcc -v
Reading specs from /usr/local/lib/gcc-lib/sparc-sun-solaris2.8/2.95.3/
specs
gcc version 2.95.3 20010315 (release)


Machine 2:
bash-2.05b$ uname -a
Linux <hostname> 2.4.21-4.EL #1 Fri Oct 3 18:13:58 EDT 2003 i686 i686
i386 GNU/Linux

bash-2.05b$ gcc -v
Reading specs from /usr/lib/gcc-lib/i386-redhat-linux/3.2.3/specs
Configured with: ../configure --prefix=/usr --mandir=/usr/share/man --
infodir=/usr/share/info --enable-shared --enable-threads=posix --
disable-checking --with-system-zlib --enable-__cxa_atexit --host=i386-
redhat-linux
Thread model: posix
gcc version 3.2.3 20030502 (Red Hat Linux 3.2.3-20)



bash-2.05b$ cat fgets_fail_test.c
#include<stdio.h>
#include <string.h>
#include<stdlib.h>

/* Demo fgets failed by Raxit Sheth & Gaurav Gupta */

int main()
{
char spcontent[100],sendrepfile[100];
FILE *spfp=NULL;
memset(sendrepfile,0,100);
strcpy(sendrepfile,"/tmp/filenotexists");
if ((spfp = fopen(sendrepfile, "r")) == (FILE *)NULL)
{
printf("error in opening file %s",sendrepfile);fflush(stdout);
}
memset(spcontent, 0, sizeof(spcontent));

while (fgets(spcontent,40, spfp)!=NULL)
{
printf("The value of spcontent is
[%s]",spcontent);fflush(stdout);;
}
return 0;
}


<simillar core dump occurs on both the system>
bash-2.05b$ gcc -Wall fgets_fail_test.c -o test
bash-2.05b$ ./test
error in opening file /tmp/filenotexistsSegmentation fault (core
dumped)
bash-2.05b$ gdb ./test ./core.27887
GNU gdb Red Hat Linux (5.3.90-0.20030710.40rh)
Copyright 2003 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and
you are
welcome to change it and/or distribute copies of it under certain
conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB. Type "show warranty" for
details.
This GDB was configured as "i386-redhat-linux-gnu"...(no debugging
symbols found)...Using host libthread_db library "/lib/tls/
libthread_db.so.1".

Core was generated by `./test'.
Program terminated with signal 11, Segmentation fault.
Reading symbols from /lib/tls/libc.so.6...(no debugging symbols
found)...done.
Loaded symbols for /lib/tls/libc.so.6
Reading symbols from /lib/ld-linux.so.2...(no debugging symbols
found)...done.
Loaded symbols for /lib/ld-linux.so.2
#0 0xb7506444 in fgets () from /lib/tls/libc.so.6
(gdb) where
#0 0xb7506444 in fgets () from /lib/tls/libc.so.6
#1 0x0804854b in main ()
(gdb) frame 0
#0 0xb7506444 in fgets () from /lib/tls/libc.so.6
(gdb) print errno
Cannot access memory at address 0xb74a7008


char *fgets(char *s, int n, FILE *stream)
Qry : What is the Behaviour if stream is NULL. ?

As per our understanding fgets should return NULL < and internally
gets should put check on stream, if it is not NULL then only should do
additional access of stream.

please ignore if it is known and would be great if you can point out
in the implementation detail.


--Gaurav Gupta & Raxit Sheth
http://www.barcamp.org/BarCampMumbaiOct2007 <----BarCampMumbaiOct2007

The C99 standard of C says:

7.19.7.2 The fgets function
Synopsis
#include <stdio.h>
char *fgets(char * restrict s, int n, FILE * restrict stream);
Description
The fgets function reads at most one less than the
number of characters specified by n from the stream
pointed to by stream into the array pointed to by s.
No additional characters are read after a new-line
character (which is retained) or after end-of-file.
A null character is written immediately after the
last character read into the array.

Returns
The fgets function returns s if successful. If
end-of-file is encountered and no characters have been
read into the array, the contents of the array remain
unchanged and a null pointer is returned. If a read
error occurs during the operation, the array contents
are indeterminate and a null pointer is returned.
----------------------------------------------------
Nothing is said about

File stream is NULL
int n is <= 0
char *s is NULL
 
B

Bart van Ingen Schenau

Sheth Raxit wrote:

<simillar core dump occurs on both the system>
bash-2.05b$ gcc -Wall fgets_fail_test.c -o test
bash-2.05b$ ./test
error in opening file /tmp/filenotexistsSegmentation fault (core
dumped)
char *fgets(char *s, int n, FILE *stream)
Qry : What is the Behaviour if stream is NULL. ?

Then the behaviour is undefined, meaning that anything can happen
(including a crash as you experienced).
fgets() is defined to read characters from the stream pointed at by the
argument stream, but a null-pointer does not refer to any stream.
As per our understanding fgets should return NULL < and internally
gets should put check on stream, if it is not NULL then only should do
additional access of stream.

Your understanding is incorrect. There is no such requirement for
fgets().
The fgets() implementation may simply assume that all pointers passed
into it are valid. Some may have implemented a precondition check on
this assumption, but that is certainly not universal. And a failed
check may just as easily be regarded as a fatal error.
please ignore if it is known and would be great if you can point out
in the implementation detail.


--Gaurav Gupta & Raxit Sheth

Bart v Ingen Schenau
 
K

Keith Thompson

Sheth Raxit said:
Machine 1 :
bash-3.00$ uname -a [SNIP]
Machine 2:
bash-2.05b$ uname -a
[SNIP]

The details of your system aren't relevant to your problem. (If they
were, comp.lang.c probably wouldn't be the place to ask about it.)
I've redirected followups to comp.lang.c (which probably won't do any
good.)
bash-2.05b$ cat fgets_fail_test.c
#include<stdio.h>
#include <string.h>
#include<stdlib.h>

/* Demo fgets failed by Raxit Sheth & Gaurav Gupta */

int main()
{
char spcontent[100],sendrepfile[100];
FILE *spfp=NULL;
memset(sendrepfile,0,100);
strcpy(sendrepfile,"/tmp/filenotexists");
if ((spfp = fopen(sendrepfile, "r")) == (FILE *)NULL)
{
printf("error in opening file %s",sendrepfile);fflush(stdout);
}
memset(spcontent, 0, sizeof(spcontent));

while (fgets(spcontent,40, spfp)!=NULL)
{
printf("The value of spcontent is
[%s]",spcontent);fflush(stdout);;
}
return 0;
}


<simillar core dump occurs on both the system>
[SNIP]

The formatting of your code makes it difficult to read. Here's a
cleaned-up version:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

/* Demo fgets failed by Raxit Sheth & Gaurav Gupta */

int main()
{
char spcontent[100], sendrepfile[100];
FILE *spfp = NULL;
memset(sendrepfile, 0, 100);
strcpy(sendrepfile, "/tmp/filenotexists");
if ((spfp = fopen(sendrepfile, "r")) == (FILE *)NULL)
{
printf("error in opening file %s", sendrepfile);
fflush(stdout);
}
memset(spcontent, 0, sizeof(spcontent));

while (fgets(spcontent, 40, spfp) != NULL)
{
printf("The value of spcontent is [%s]", spcontent);
fflush(stdout);
}
return 0;
}

You check whether the fopen() call succeeded or not. If it fails, you
print an error message.


You then attempt to read from the file *even if the fopen() call
failed*.

fgets() is not required to check whether its third argument is valid;
it can simply assume that it is. The standard's description (I'll use
'*'s to denote boldface) is:

The *fgets* function reads at most one less than the number of
characters specified by *n* from the stream pointed to by *stream*
into the array pointed to by *s*.

If there is no "stream pointed to by *stream*", then the behavior is
undefined. A segmentation fault is not surprising.

If you fail to open the file, don't try to read from it.

A few other remarks:

You don't use anything from <stdlib.h>.

'int main(void)' is preferred to 'int main()', though both are valid.

Avoid "magic numbers" like 100. Define a symbolic constant so that
you only have to change it in one place. You use a literal 100 in one
memset call, sizeof() in the other.

Both memsets are unnecessary. spcontent and sendrepfile are used to
hold strings; it doesn't matter what's in the array past the
terminating '\0'.

The cast to FILE* is unnecessary (as are most casts); you can just
compare the result of fopen() to NULL.

You print your error message to stdout. Error messages should normally
be written to stderr.

Your outputs should be terminated with '\n' unless you have a specific
reason not to. In particular, you should definitely have a '\n' at
the very end of your program's output.

The fflush(stdout) calls should be on lines by themselves; I almost
didn't notice them before I reformatted your code.

You declare spcontent as an array of 100 characters, but you only
attempt read at most 40 characters into it. Using symbolic constants
(say, '#define MAX_LINE_LENGTH 40') would make it easier to keep these
consistent.

You have a double semicolon on the second fflush() call. It happens
to be harmless, but there's no reason for it.
 
J

Jack Klein

On Thu, 06 Sep 2007 20:27:49 +0200, jacob navia

[snip original post]
The C99 standard of C says:

7.19.7.2 The fgets function
Synopsis
#include <stdio.h>
char *fgets(char * restrict s, int n, FILE * restrict stream);
Description
The fgets function reads at most one less than the
number of characters specified by n from the stream
pointed to by stream into the array pointed to by s.
No additional characters are read after a new-line
character (which is retained) or after end-of-file.
A null character is written immediately after the
last character read into the array.

Returns
The fgets function returns s if successful. If
end-of-file is encountered and no characters have been
read into the array, the contents of the array remain
unchanged and a null pointer is returned. If a read
error occurs during the operation, the array contents
are indeterminate and a null pointer is returned.
----------------------------------------------------
Nothing is said about

File stream is NULL
int n is <= 0
char *s is NULL

I would expect better from an implementer:

"7.1.4 Use of library functions
1 Each of the following statements applies unless explicitly stated
otherwise in the detailed descriptions that follow: If an argument to
a function has an invalid value (such as a value outside the domain of
the function, or a pointer outside the address space of the program,
or a null pointer, or a pointer to non-modifable storage when the
corresponding parameter is not const-qualifed) or a type (after
promotion) not expected by a function with variable number of
arguments, the behavior is undefined."

This makes passing a null pointer to almost all library functions
illegal, without requiring such text in each and every single function
description.

There are several functions that specifically document accepting null
pointers, such as free(), strto..., and a few others. fgets() is not
among them.

--
Jack Klein
Home: http://JK-Technology.Com
FAQs for
comp.lang.c http://c-faq.com/
comp.lang.c++ http://www.parashift.com/c++-faq-lite/
alt.comp.lang.learn.c-c++
http://www.club.cc.cmu.edu/~ajo/docs/FAQ-acllc.html
 
Ad

Advertisements

J

Jack Klein

On Thu, 06 Sep 2007 10:38:55 -0700, Sheth Raxit

[snip]
char *fgets(char *s, int n, FILE *stream)
Qry : What is the Behaviour if stream is NULL. ?

As per our understanding fgets should return NULL < and internally
gets should put check on stream, if it is not NULL then only should do
additional access of stream.

Where does your understanding come from? It is totally incorrect.
please ignore if it is known and would be great if you can point out
in the implementation detail.

Section 7.1.4 paragraph 1 of the C language standard makes it quite
clear that passing a null pointer to a function that does not document
accepting a null pointer is undefined behavior.

--
Jack Klein
Home: http://JK-Technology.Com
FAQs for
comp.lang.c http://c-faq.com/
comp.lang.c++ http://www.parashift.com/c++-faq-lite/
alt.comp.lang.learn.c-c++
http://www.club.cc.cmu.edu/~ajo/docs/FAQ-acllc.html
 
S

Sheth Raxit

Sheth Raxit said:
Machine 1 :
bash-3.00$ uname -a [SNIP]
Machine 2:
bash-2.05b$ uname -a

[SNIP]

The details of your system aren't relevant to your problem. (If they
were, comp.lang.c probably wouldn't be the place to ask about it.)
I've redirected followups to comp.lang.c (which probably won't do any
good.) agree
bash-2.05b$ cat fgets_fail_test.c
#include<stdio.h>
#include <string.h>
#include<stdlib.h>
/* Demo fgets failed by Raxit Sheth & Gaurav Gupta */
int main()
{
char spcontent[100],sendrepfile[100];
FILE *spfp=NULL;
memset(sendrepfile,0,100);
strcpy(sendrepfile,"/tmp/filenotexists");
if ((spfp = fopen(sendrepfile, "r")) == (FILE *)NULL)
{
printf("error in opening file %s",sendrepfile);fflush(stdout);
}
memset(spcontent, 0, sizeof(spcontent));
while (fgets(spcontent,40, spfp)!=NULL)
{
printf("The value of spcontent is
[%s]",spcontent);fflush(stdout);;
}
return 0;
}
<simillar core dump occurs on both the system>

[SNIP]

The formatting of your code makes it difficult to read. Here's a
cleaned-up version:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

/* Demo fgets failed by Raxit Sheth & Gaurav Gupta */

int main()
{
char spcontent[100], sendrepfile[100];
FILE *spfp = NULL;
memset(sendrepfile, 0, 100);
strcpy(sendrepfile, "/tmp/filenotexists");
if ((spfp = fopen(sendrepfile, "r")) == (FILE *)NULL)
{
printf("error in opening file %s", sendrepfile);
fflush(stdout);
}
memset(spcontent, 0, sizeof(spcontent));

while (fgets(spcontent, 40, spfp) != NULL)
{
printf("The value of spcontent is [%s]", spcontent);
fflush(stdout);
}
return 0;

}

You check whether the fopen() call succeeded or not. If it fails, you
print an error message.

You then attempt to read from the file *even if the fopen() call
failed*.
Yes, we know that is incorrect but to re-product the behaviour. i.e.
you can say fgets Test code.
fgets() is not required to check whether its third argument is valid;
it can simply assume that it is. The standard's description (I'll use
'*'s to denote boldface) is:

The *fgets* function reads at most one less than the number of
characters specified by *n* from the stream pointed to by *stream*
into the array pointed to by *s*.

If there is no "stream pointed to by *stream*", then the behavior is
undefined. A segmentation fault is not surprising.

Can not it more useful, if standard suggest to returns the NULL, if
stream is NULL., than of Undefined behaviour. ?

By this, every implementation <conforming to standard> will check
if (fgets==NULL) then Instead of Undefined behaviour, it will return
NULL. <or proper error handling.>

it is like introducing new Test Case for fgets <and i think related
simillar functions.>


All your remarks/suggestion are very much valid, assume our code as
small test program which fails on some platform.

If you fail to open the file, don't try to read from it.
yes,but we are checking currently the behaviour of fgets.
A few other remarks:

You don't use anything from <stdlib.h>.
we have used exit if fopen returns NULL, but intentionally we remove
exit,to check the behaviour of fgets.
[deleted]
--
Keith Thompson (The_Other_Keith) (e-mail address removed) <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"- Hide quoted text -

- Show quoted text -


-Raxit & Gaurav
 
S

Sheth Raxit

Sheth said:
Machine 1 :
bash-3.00$ uname -a
SunOS <hostname> 5.10 Generic_118822-30 sun4u sparc SUNW,Sun-Fire-280R
bash-3.00$ gcc -v
Reading specs from /usr/local/lib/gcc-lib/sparc-sun-solaris2.8/2.95.3/
specs
gcc version 2.95.3 20010315 (release)
Machine 2:
bash-2.05b$ uname -a
Linux <hostname> 2.4.21-4.EL #1 Fri Oct 3 18:13:58 EDT 2003 i686 i686
i386 GNU/Linux
bash-2.05b$ gcc -v
Reading specs from /usr/lib/gcc-lib/i386-redhat-linux/3.2.3/specs
Configured with: ../configure --prefix=/usr --mandir=/usr/share/man --
infodir=/usr/share/info --enable-shared --enable-threads=posix --
disable-checking --with-system-zlib --enable-__cxa_atexit --host=i386-
redhat-linux
Thread model: posix
gcc version 3.2.3 20030502 (Red Hat Linux 3.2.3-20)
bash-2.05b$ cat fgets_fail_test.c
#include<stdio.h>
#include <string.h>
#include<stdlib.h>
/* Demo fgets failed by Raxit Sheth & Gaurav Gupta */
int main()
{
char spcontent[100],sendrepfile[100];
FILE *spfp=NULL;
memset(sendrepfile,0,100);
strcpy(sendrepfile,"/tmp/filenotexists");
if ((spfp = fopen(sendrepfile, "r")) == (FILE *)NULL)
{
printf("error in opening file %s",sendrepfile);fflush(stdout);
}
memset(spcontent, 0, sizeof(spcontent));
while (fgets(spcontent,40, spfp)!=NULL)
{
printf("The value of spcontent is
[%s]",spcontent);fflush(stdout);;
}
return 0;
}
<simillar core dump occurs on both the system>
bash-2.05b$ gcc -Wall fgets_fail_test.c -o test
bash-2.05b$ ./test
error in opening file /tmp/filenotexistsSegmentation fault (core
dumped)
bash-2.05b$ gdb ./test ./core.27887
GNU gdb Red Hat Linux (5.3.90-0.20030710.40rh)
Copyright 2003 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and
you are
welcome to change it and/or distribute copies of it under certain
conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB. Type "show warranty" for
details.
This GDB was configured as "i386-redhat-linux-gnu"...(no debugging
symbols found)...Using host libthread_db library "/lib/tls/
libthread_db.so.1".
Core was generated by `./test'.
Program terminated with signal 11, Segmentation fault.
Reading symbols from /lib/tls/libc.so.6...(no debugging symbols
found)...done.
Loaded symbols for /lib/tls/libc.so.6
Reading symbols from /lib/ld-linux.so.2...(no debugging symbols
found)...done.
Loaded symbols for /lib/ld-linux.so.2
#0 0xb7506444 in fgets () from /lib/tls/libc.so.6
(gdb) where
#0 0xb7506444 in fgets () from /lib/tls/libc.so.6
#1 0x0804854b in main ()
(gdb) frame 0
#0 0xb7506444 in fgets () from /lib/tls/libc.so.6
(gdb) print errno
Cannot access memory at address 0xb74a7008
char *fgets(char *s, int n, FILE *stream)
Qry : What is the Behaviour if stream is NULL. ?
As per our understanding fgets should return NULL < and internally
gets should put check on stream, if it is not NULL then only should do
additional access of stream.
please ignore if it is known and would be great if you can point out
in the implementation detail.
--Gaurav Gupta & Raxit Sheth
http://www.barcamp.org/BarCampMumbaiOct2007<----BarCampMumbaiOct2007

The C99 standard of C says:

7.19.7.2 The fgets function
Synopsis
#include <stdio.h>
char *fgets(char * restrict s, int n, FILE * restrict stream);
Description
The fgets function reads at most one less than the
number of characters specified by n from the stream
pointed to by stream into the array pointed to by s.
No additional characters are read after a new-line
character (which is retained) or after end-of-file.
A null character is written immediately after the
last character read into the array.

Returns
The fgets function returns s if successful. If
end-of-file is encountered and no characters have been
read into the array, the contents of the array remain
unchanged and a null pointer is returned. If a read
error occurs during the operation, the array contents
are indeterminate and a null pointer is returned.
----------------------------------------------------
Nothing is said about

File stream is NULL
int n is <= 0
char *s is NULL- Hide quoted text -
don't you think instead of "not saying" or "saying undefined
behaviour" any additional checks are put itself in std ?
 
S

Sheth Raxit

On Thu, 06 Sep 2007 10:38:55 -0700, Sheth Raxit

[snip]
char *fgets(char *s, int n, FILE *stream)
Qry : What is the Behaviour if stream is NULL. ?
As per our understanding fgets should return NULL < and internally
gets should put check on stream, if it is not NULL then only should do
additional access of stream.

Where does your understanding come from? It is totally incorrect.
please ignore if it is known and would be great if you can point out
in the implementation detail.

Section 7.1.4 paragraph 1 of the C language standard makes it quite
clear that passing a null pointer to a function that does not document
accepting a null pointer is undefined behavior.
 
K

Keith Thompson

Sheth Raxit said:
Can not it more useful, if standard suggest to returns the NULL, if
stream is NULL., than of Undefined behaviour. ?

By this, every implementation <conforming to standard> will check
if (fgets==NULL) then Instead of Undefined behaviour, it will return
NULL. <or proper error handling.>

it is like introducing new Test Case for fgets <and i think related
simillar functions.>

Yes, such a change could be made, but passing a null pointer to fgets
(or to most standard library functions) is only one of a nearly
infinite number of possible errors. fgets() could detect a null
pointer, but it couldn't reasonably detect all possible invalid
arguments. The burden is on the programmer to avoid passing invalid
arguments; fgets() just has to work properly if it the arguments are
valid.

And if the standard committee decided to require fgets() to behave
reasonably with a null pointer argument, it would be literally decades
before all implementations would conform.

[...]
yes,but we are checking currently the behaviour of fgets.

Strictly speaking, you're checking the behavior of one implementation
of fgets.

[...]
 
Ad

Advertisements

K

Keith Thompson

Sheth Raxit said:
don't you think instead of "not saying" or "saying undefined
behaviour" any additional checks are put itself in std ?

No, the behavior is undefined.
 
C

Casper H.S. Dik

Kenneth Brody said:
However, I can tell you that the system I'm currently on has an
ASSERT(stream != NULL) near the top of fgets(), so it won't allow
such a value.
My guess is that this is UB.

Since he's not passing a pointer to a STREAM I'd also say it's UB.

Casper
 
N

Nick Keighley

#include<stdio.h>
#include <string.h>
#include<stdlib.h>

/* Demo fgets failed by Raxit Sheth & Gaurav Gupta */

int main()
{
char spcontent[100],sendrepfile[100];
FILE *spfp=NULL;
memset(sendrepfile,0,100);
strcpy(sendrepfile,"/tmp/filenotexists");

why the strcpy()? why not:-

if ((spfp = fopen ("/tmp/filenotexists", "r")) == NULL)

or initialise sendfilerep when you define it.

char sendrepfile [] = "/tmp/filenotexists";

<snip>


--
Nick Keighley

in comp.lang.c, the very people most capable of making the inference
are those least likely to make it. This newsgroup considers pedantry
to be an art form.
Richard Heathfield
 
S

Sheth Raxit

Since he's not passing a pointer to a STREAM I'd also say it's UB.

Yes It is Undefined Behaviour, But Don't you feel, standard **should**
impose this to return NULL.

I am asking to first make change in standard to have "few Undefined
Behaviour" when platform can handle. Technically platform may return
NULL, and handle this test case. Let me know if i am buffling
something/everything. ?

-Raxit
 
S

Sheth Raxit

#include<stdio.h>
#include <string.h>
#include<stdlib.h>
/* Demo fgets failed by Raxit Sheth & Gaurav Gupta */
int main()
{
char spcontent[100],sendrepfile[100];
FILE *spfp=NULL;
memset(sendrepfile,0,100);
strcpy(sendrepfile,"/tmp/filenotexists");

why the strcpy()? why not:-

This is not a point of Query ? why are we having trouble with strcpy/
individual coding style ?
Is it not confirming to std. ?
ignored
 
Ad

Advertisements

J

jacob navia

Jack said:
On Thu, 06 Sep 2007 20:27:49 +0200, jacob navia

[snip original post]
The C99 standard of C says:

7.19.7.2 The fgets function
Synopsis
#include <stdio.h>
char *fgets(char * restrict s, int n, FILE * restrict stream);
Description
The fgets function reads at most one less than the
number of characters specified by n from the stream
pointed to by stream into the array pointed to by s.
No additional characters are read after a new-line
character (which is retained) or after end-of-file.
A null character is written immediately after the
last character read into the array.

Returns
The fgets function returns s if successful. If
end-of-file is encountered and no characters have been
read into the array, the contents of the array remain
unchanged and a null pointer is returned. If a read
error occurs during the operation, the array contents
are indeterminate and a null pointer is returned.
----------------------------------------------------
Nothing is said about

File stream is NULL
int n is <= 0
char *s is NULL

I would expect better from an implementer:

"7.1.4 Use of library functions
1 Each of the following statements applies unless explicitly stated
otherwise in the detailed descriptions that follow: If an argument to
a function has an invalid value (such as a value outside the domain of
the function, or a pointer outside the address space of the program,
or a null pointer, or a pointer to non-modifable storage when the
corresponding parameter is not const-qualifed) or a type (after
promotion) not expected by a function with variable number of
arguments, the behavior is undefined."

Nothing is said about the return value or behavior of any error.
The behavior is UNDEFINED.

Can't you read?

That is what I said!
This makes passing a null pointer to almost all library functions
illegal, without requiring such text in each and every single function
description.

Errors are illegal. Nice. But nothing is said about
what to do when those situations appear, what is what I was saying
in the first place.

Other parts of the standard are more specified, specifically
the math functions, where every possible return value is specified.

The C library is like 30 years old and it shows...
There are several functions that specifically document accepting null
pointers, such as free(), strto..., and a few others. fgets() is not
among them.

OK. What happens when you actually pass NULL then?
I repeat:
Nothing is said about error handling. It is just

"UNDEFINED".
 
S

Sheth Raxit

Yes, such a change could be made, but passing a null pointer to fgets
(or to most standard library functions) is only one of a nearly
infinite number of possible errors. fgets() could detect a null
pointer, but it couldn't reasonably detect all possible invalid
arguments. The burden is on the programmer to avoid passing invalid
Interesting, !
yes there are many possible way except null pointer, do you think
which is the most frequently occuring ?

Yes after all it is the programmer,
arguments; fgets() just has to work properly if it the arguments are
valid.

And if the standard committee decided to require fgets() to behave
reasonably with a null pointer argument, it would be literally decades
before all implementations would conform.
you may correct, i am really not very much in related to std stuff,
this is what i think should/can be done.
[...]
yes,but we are checking currently the behaviour of fgets.

Strictly speaking, you're checking the behavior of one implementation
of fgets.

yes, i have checked and Behaviour is Undefined for particular
implementation, which might be corrected if std says or implementar
implements.

Let me find some time, if i can try to have patch for some most widely
used platform. <or better if you are reading this, and you are
platform implementor, you may correct this stuff.>
[...]

--
Keith Thompson (The_Other_Keith) (e-mail address removed) <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"- Hide quoted text -

- Show quoted text -

Thanks,
Raxit
http://www.barcamp.org/BarCampMumbaiOct2007<---BarCampMumbaiOct2007
 
C

Casper H.S. Dik

Yes It is Undefined Behaviour, But Don't you feel, standard **should**
impose this to return NULL.

No. The standard should not make it easier for buggy programs to
blunder on.

The implementation is doing you a favour by dumping core for this
particular bit of undefined behaviour. You have a bug in your program
(you invoke undefined behaviour, always a bug). If you had continued
onwards, your codee would not have made a distinction between
"file not found" and "file is empty". Perhaps not relevant for you,
but in other cases this might hide a serious bug in the program.

Casper
 
Ad

Advertisements

J

jacob navia

Casper said:
Yes It is Undefined Behaviour, But Don't you feel, standard **should**
impose this to return NULL.

No. The standard should not make it easier for buggy programs to
blunder on.
[snip]

Casper

Even better would be to specify what to do when one
of the parameters is wrong...
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top