|
Home > Archive > Unix Programming > September 2007 > Qry : Behaviour of fgets -- ?
You are viewing an archived Text-only version of the thread.
To view this thread in it's original format and/or if you want to reply to
this thread please [click here]
| Author |
Qry : Behaviour of fgets -- ?
|
|
| Sheth Raxit 2007-09-06, 1:19 pm |
|
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
| |
| Kenneth Brody 2007-09-06, 1:19 pm |
| 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:ThisIsASpamTrap@gmail.com>
| |
| Robert Harris 2007-09-06, 7:20 pm |
| Sheth Raxit wrote:
> 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)
What do you expect this to do if spfp contains the NULL pointer? It is
supposed to contain a pointer to a stream (FILE *) so anything is possible.
Robert
> [snip]
>
> --Gaurav Gupta & Raxit Sheth
> http://www.barcamp.org/BarCampMumbaiOct2007 <----BarCampMumbaiOct2007
>
| |
| jacob navia 2007-09-06, 7:20 pm |
| Sheth Raxit wrote:
> 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
| |
| Keith Thompson 2007-09-06, 7:20 pm |
| Sheth Raxit <raxitsheth2000@gmail.com> writes:
> 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.
--
Keith Thompson (The_Other_Keith) kst-u@mib.org <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"
| |
| Bart van Ingen Schenau 2007-09-06, 7:20 pm |
| Sheth Raxit wrote:
<snip>
> <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)
<snip>
> 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
--
a.c.l.l.c-c++ FAQ: http://www.comeaucomputing.com/learn/faq
c.l.c FAQ: http://www.eskimo.com/~scs/C-faq/top.html
c.l.c++ FAQ: http://www.parashift.com/c++-faq-lite/
| |
| Jack Klein 2007-09-07, 1:20 am |
| On Thu, 06 Sep 2007 20:27:49 +0200, jacob navia
<jacob@jacob.remcomp.fr> wrote in comp.lang.c:
[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
| |
| Jack Klein 2007-09-07, 1:20 am |
| On Thu, 06 Sep 2007 10:38:55 -0700, Sheth Raxit
<raxitsheth2000@gmail.com> wrote in comp.lang.c:
[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
| |
| Sheth Raxit 2007-09-07, 7:24 am |
| On Sep 7, 12:54 am, Keith Thompson <ks...@mib.org> wrote:
> Sheth Raxit <raxitsheth2...@gmail.com> writes:
> [SNIP]
>
> [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
>
>
>
>
>
>
>
>
>
>
> [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) ks...@mib.org <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
| |
| Sheth Raxit 2007-09-07, 7:24 am |
| On Sep 6, 11:27 pm, jacob navia <ja...@jacob.remcomp.fr> wrote:
> Sheth Raxit wrote:
>
>
>
>
>
>
>
>
>
>
>
>
>
>
> 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 ?
>
> - Show quoted text -
| |
| Sheth Raxit 2007-09-07, 7:24 am |
| On Sep 7, 7:24 am, Jack Klein <jackkl...@spamcop.net> wrote:
> On Thu, 06 Sep 2007 10:38:55 -0700, Sheth Raxit
> <raxitsheth2...@gmail.com> wrote in comp.lang.c:
>
> [snip]
>
>
>
> Where does your understanding come from? It is totally incorrect.
>
>
> 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.chttp://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
| |
| Keith Thompson 2007-09-07, 7:24 am |
| Sheth Raxit <raxitsheth2000@gmail.com> writes:
> On Sep 7, 12:54 am, Keith Thompson <ks...@mib.org> wrote:
[...]
>
> 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.
[...]
--
Keith Thompson (The_Other_Keith) kst-u@mib.org <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"
| |
| Keith Thompson 2007-09-07, 7:24 am |
| Sheth Raxit <raxitsheth2000@gmail.com> writes:
[...]
> 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.
--
Keith Thompson (The_Other_Keith) kst-u@mib.org <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"
| |
| Casper H.S. Dik 2007-09-07, 7:24 am |
| Kenneth Brody <kenbrody@spamcop.net> writes:
>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
--
Expressed in this posting are my opinions. They are in no way related
to opinions held by my employer, Sun Microsystems.
Statements on Sun products included here are not gospel and may
be fiction rather than truth.
| |
| Nick Keighley 2007-09-07, 7:24 am |
| On 6 Sep, 18:38, Sheth Raxit <raxitsheth2...@gmail.com> wrote:
<snip>
> #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
| |
| Sheth Raxit 2007-09-07, 7:24 am |
| On Sep 7, 1:08 pm, Casper H.S. Dik <Casper....@Sun.COM> wrote:
> Kenneth Brody <kenbr...@spamcop.net> writes:
>
> 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
>
> Casper
> --
> Expressed in this posting are my opinions. They are in no way related
> to opinions held by my employer, Sun Microsystems.
> Statements on Sun products included here are not gospel and may
> be fiction rather than truth.
| |
| Sheth Raxit 2007-09-07, 7:24 am |
| On Sep 7, 1:36 pm, Nick Keighley <nick_keighley_nos...@hotmail.com>
wrote:
> On 6 Sep, 18:38, Sheth Raxit <raxitsheth2...@gmail.com> wrote:
>
> <snip>
>
>
>
>
> 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
| |
| Sheth Raxit 2007-09-07, 7:24 am |
| On Sep 7, 12:32 pm, Keith Thompson <ks...@mib.org> wrote:
> Sheth Raxit <raxitsheth2...@gmail.com> writes:
> [...]
>
>
>
>
>
>
> 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.
>
> [...]
>
>
>
> 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) ks...@mib.org <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
| |
| jacob navia 2007-09-07, 7:24 am |
| Jack Klein wrote:
> On Thu, 06 Sep 2007 20:27:49 +0200, jacob navia
> <jacob@jacob.remcomp.fr> wrote in comp.lang.c:
>
> [snip original post]
>
>
> 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".
| |
| Casper H.S. Dik 2007-09-07, 7:24 am |
| Sheth Raxit <raxitsheth2000@gmail.com> writes:
>On Sep 7, 1:08 pm, Casper H.S. Dik <Casper....@Sun.COM> wrote:
[vbcol=seagreen]
>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
--
Expressed in this posting are my opinions. They are in no way related
to opinions held by my employer, Sun Microsystems.
Statements on Sun products included here are not gospel and may
be fiction rather than truth.
| |
| Casper H.S. Dik 2007-09-07, 7:24 am |
| jacob navia <jacob@jacob.remcomp.fr> writes:
>Nothing is said about error handling. It is just
>"UNDEFINED".
Yes. And when a programmer invokes "undefined" behaviour
*ANYTHING* can happen.
It's not quite the same as "no errors should happen"; it's
"thou shalt not invoke undefined behaviour".
The reason why this behaviour is undefined and why implementors
are free to ignore this is fairly straight forward:
- it's prohibitively expensive to test for any possible
form of undefined behaviour
Why stop at (FILE *)NULL; why not test for
(FILE *)0x1 or any non-mapped or non-aligned pointer or
pointer not returned by f*open?
- undefined behaviour is only invoked by programs with bugs
in it so why should other programs pay for this?
Dumping core is a good thing; you have a bug, it was caught. Now go
and fix your code.
Casper
--
Expressed in this posting are my opinions. They are in no way related
to opinions held by my employer, Sun Microsystems.
Statements on Sun products included here are not gospel and may
be fiction rather than truth.
| |
| jacob navia 2007-09-07, 7:24 am |
| Casper H.S. Dik wrote:
> Sheth Raxit <raxitsheth2000@gmail.com> writes:
>
>
>
> 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...
| |
| Richard Heathfield 2007-09-07, 7:24 am |
| Casper H.S. Dik said:
<snip>
> The standard should not make it easier for buggy programs to
> blunder on.
Agreed.
> The implementation is doing you a favour by dumping core for this
> particular bit of undefined behaviour.
Agreed.
> You have a bug in your program
Agreed.
> (you invoke undefined behaviour, always a bug).
Here, however, I must beg to differ. There are times when one must
invoke undefined behaviour if one is to get something done.
It is not a bug to point directly at video memory, for example. Yes, to
do this will necessarily make your code non-portable. Yes, you're
leaving behind all the guarantees that the Standard offers. But no, it
is not a bug, if one is deliberately setting out to write that code to
achieve one's goal because the Standard doesn't offer any satisfactory
way to achieve it.
<snip>
--
Richard Heathfield <http://www.cpax.org.uk>
Email: -www. +rjh@
Google users: <http://www.cpax.org.uk/prg/writings/googly.php>
"Usenet is a strange place" - dmr 29 July 1999
| |
| Casper H.S. Dik 2007-09-07, 7:24 am |
| Richard Heathfield <rjh@see.sig.invalid> writes:
>Here, however, I must beg to differ. There are times when one must
>invoke undefined behaviour if one is to get something done.
Such as? You are nopt confusing implementation defined behaviour
with undefined behaviour?
>It is not a bug to point directly at video memory, for example. Yes, to
>do this will necessarily make your code non-portable. Yes, you're
>leaving behind all the guarantees that the Standard offers. But no, it
>is not a bug, if one is deliberately setting out to write that code to
>achieve one's goal because the Standard doesn't offer any satisfactory
>way to achieve it.
Ah, yes, but I would say that such things are covered by
"extensions to the standard" rather than down-right undefined
behaviour.
Casper
--
Expressed in this posting are my opinions. They are in no way related
to opinions held by my employer, Sun Microsystems.
Statements on Sun products included here are not gospel and may
be fiction rather than truth.
| |
| jacob navia 2007-09-07, 7:24 am |
| Casper H.S. Dik wrote:
> jacob navia <jacob@jacob.remcomp.fr> writes:
>
>
>
> Yes. And when a programmer invokes "undefined" behaviour
> *ANYTHING* can happen.
>
> It's not quite the same as "no errors should happen"; it's
> "thou shalt not invoke undefined behaviour".
>
> The reason why this behaviour is undefined and why implementors
> are free to ignore this is fairly straight forward:
>
> - it's prohibitively expensive to test for any possible
> form of undefined behaviour
> Why stop at (FILE *)NULL; why not test for
> (FILE *)0x1 or any non-mapped or non-aligned pointer or
> pointer not returned by f*open?
>
> - undefined behaviour is only invoked by programs with bugs
> in it so why should other programs pay for this?
>
> Dumping core is a good thing; you have a bug, it was caught. Now go
> and fix your code.
>
> Casper
Why error analysis is necessary?
Error analysis means trying to have a defined an in all cases
identical reaction to program errors.
This means that for each function we write, we try to
return a specified error report value if things go wrong.
In the case of fgets this implies:
o Testing for NULL.
o Testing for a bad value of n (<= 0)
o Testing for a NULL value in the receiving buffer.
This means 3 integer comparisons in this case. Compared to the
i/o that fgets is going to do anyway, those 3 integer
comparisons amount to NOTHING.
| |
| Richard Heathfield 2007-09-07, 7:24 am |
| Casper H.S. Dik said:
> Richard Heathfield <rjh@see.sig.invalid> writes:
>
>
> Such as? You are nopt confusing implementation defined behaviour
> with undefined behaviour?
No. Implementation-defined behaviour is behaviour that the Standard
requires the implementation to document. The Standard does not require
any implementation to document the behaviour of:
unsigned char *p = (unsigned char *)0xb8000000UL;
*p++ = 'A';
*p++ = 0x84;
>
> Ah, yes, but I would say that such things are covered by
> "extensions to the standard" rather than down-right undefined
> behaviour.
The behaviour of extensions, as far as I'm aware, is not defined by the
Standard, and therefore is covered by the definition of undefined
behaviour, which (according to my C89 draft) is:
"Undefined behavior --- behavior, upon use of a nonportable or erroneous
program construct, of erroneous data, or of indeterminately-valued
objects, for which the Standard imposes no requirements. Permissible
undefined behavior ranges from ignoring the situation completely with
unpredictable results, to behaving during translation or program
execution in a documented manner characteristic of the environment
(with or without the issuance of a diagnostic message), to terminating
a translation or execution (with the issuance of a diagnostic
message)."
--
Richard Heathfield <http://www.cpax.org.uk>
Email: -www. +rjh@
Google users: <http://www.cpax.org.uk/prg/writings/googly.php>
"Usenet is a strange place" - dmr 29 July 1999
| |
| Chris Dollin 2007-09-07, 7:24 am |
| jacob navia wrote:
> Casper H.S. Dik wrote:
>
> Why error analysis is necessary?
>
> Error analysis means trying to have a defined an in all cases
> identical reaction to program errors.
>
> This means that for each function we write, we try to
> return a specified error report value if things go wrong.
>
> In the case of fgets this implies:
> o Testing for NULL.
> o Testing for a bad value of n (<= 0)
> o Testing for a NULL value in the receiving buffer.
o Testing for a bad value of n (> maximum possible line length)
o Testing that the non-null buffer points to a legal C object
containing at least the `n` characters required
o Testing that the non-null stream points to a legal C object
> This means 3 integer comparisons in this case. Compared to the
> i/o that fgets is going to do anyway, those 3 integer
> comparisons amount to NOTHING.
If you're /serious/ about checking for errors, "3 integer comparisions"
is a substantial underestimate.
--
Chris "serious about frivolity" Dollin
Hewlett-Packard Limited registered no:
registered office: Cain Road, Bracknell, Berks RG12 1HN 690597 England
| |
| Rainer Weikusat 2007-09-07, 7:24 am |
| jacob navia <jacob@jacob.remcomp.fr> writes:
> Casper H.S. Dik wrote:
>
> Why error analysis is necessary?
>
> Error analysis means trying to have a defined an in all cases
> identical reaction to program errors.
>
> This means that for each function we write, we try to
> return a specified error report value if things go wrong.
>
> In the case of fgets this implies:
> o Testing for NULL.
> o Testing for a bad value of n (<= 0)
> o Testing for a NULL value in the receiving buffer.
>
> This means 3 integer comparisons in this case.
Not completely. It means that a subroutine which is not supposed to be
separated from the remaining code by a 'protection boundary' (like a
system call) performs on average at least three useless comparisons per
invocation. What makes them especially useless is that user mode code
cannot a priory (meaning before using it) determine if a specific pointer
is valid, which basically means the at least two of these comparisons
have no purpose for the 'normal case' (arguments are valid) and cannot
(easily) detect a majority of the errors case which are to be
expected. To add insult to injury, the proposed checks are
automatically performed by the memory management hardware on a typical
UNIX(*) system and cause a hardware trap which the kernel handles by
terminating the process and generating a core dumpm which can be used
to determine the exact cause and location of the error.
Thus, the net effect of this idea is to make all programs run a little
slower to complicated debugging somewhat.
Truly brilliant.
| |
| Richard 2007-09-07, 7:24 am |
| Keith Thompson <kst-u@mib.org> writes:
>
> 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.
In addition, sometimes two bugs make a feature. If the behaviour changed
over night after a new compile there might be news bugs which could go
days without being discovered in huge legacy code bases. Never
underestimate the knock on effects of changing code libraries. Even if
it is a "one liner".
| |
| jacob navia 2007-09-07, 7:24 am |
| Richard wrote:
> In addition, sometimes two bugs make a feature. If the behaviour changed
> over night after a new compile there might be news bugs which could go
> days without being discovered in huge legacy code bases. Never
> underestimate the knock on effects of changing code libraries. Even if
> it is a "one liner".
I can't parse that
> If the behaviour changed
> over night after a new compile there might be news bugs which could go
> days without being discovered in huge legacy code bases.
You mean programs that relied on fgets making a segmentation fault
would now work and that would produce new bugs?
???
Please explain
| |
| Sheth Raxit 2007-09-07, 1:32 pm |
| On Sep 7, 2:32 pm, Casper H.S. Dik <Casper....@Sun.COM> wrote:
> Sheth Raxit <raxitsheth2...@gmail.com> writes:
>
>
> No. The standard should not make it easier for buggy programs to
> blunder on.
Is Assert-ing for NULL is better than Undefined Behaviour ?
Good for Buggy program. Good for platform ?
>
> 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
-Raxit
http://www.barcamp.org/BarCampMumbaiOct2007 <----BarCampMumbaiOct2007
> --
> Expressed in this posting are my opinions. They are in no way related
> to opinions held by my employer, Sun Microsystems.
> Statements on Sun products included here are not gospel and may
> be fiction rather than truth.
| |
| Kenneth Brody 2007-09-07, 1:32 pm |
| Richard Heathfield wrote:
>
> Casper H.S. Dik said:
>
>
> No. Implementation-defined behaviour is behaviour that the Standard
> requires the implementation to document. The Standard does not require
> any implementation to document the behaviour of:
>
> unsigned char *p = (unsigned char *)0xb8000000UL;
> *p++ = 'A';
> *p++ = 0x84;
[...]
But, what if your particular implementation does document the
behavior? Yes, as far as the Standard is concerned, it's UB,
but have you really invoked UB on that particular platform?
--
+-------------------------+--------------------+-----------------------+
| Kenneth J. Brody | www.hvcomputer.com | #include |
| kenbrody/at\spamcop.net | www.fptech.com | <std_disclaimer.h> |
+-------------------------+--------------------+-----------------------+
Don't e-mail me at: <mailto:ThisIsASpamTrap@gmail.com>
| |
| Kenneth Brody 2007-09-07, 1:32 pm |
| Jack Klein wrote:
>
> "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.
[...]
I knew there had to be something better than 7.19.3p4's reference to
a closed stream. I looked around 7.19's intro on I/O but didn't see
anything about NULL. I didn't think to go all the way back to 7's
intro.
Thanks.
--
+-------------------------+--------------------+-----------------------+
| Kenneth J. Brody | www.hvcomputer.com | #include |
| kenbrody/at\spamcop.net | www.fptech.com | <std_disclaimer.h> |
+-------------------------+--------------------+-----------------------+
Don't e-mail me at: <mailto:ThisIsASpamTrap@gmail.com>
| |
| Kenneth Brody 2007-09-07, 1:32 pm |
| Keith Thompson wrote:
[...]
> 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.
[...]
Well, then they better get off their lazy butts and get cracking!
:-) <--- For the humor-impaired. (And humour-impaired, as well.)
--
+-------------------------+--------------------+-----------------------+
| Kenneth J. Brody | www.hvcomputer.com | #include |
| kenbrody/at\spamcop.net | www.fptech.com | <std_disclaimer.h> |
+-------------------------+--------------------+-----------------------+
Don't e-mail me at: <mailto:ThisIsASpamTrap@gmail.com>
| |
| Richard Heathfield 2007-09-07, 1:32 pm |
| Kenneth Brody said:
> Richard Heathfield wrote:
<snip>
[vbcol=seagreen]
> [...]
>
> But, what if your particular implementation does document the
> behavior? Yes, as far as the Standard is concerned, it's UB,
> but have you really invoked UB on that particular platform?
Yes, as far as the Standard is concerned. In comp.lang.c, that's what
counts. (I note that this is c/p'd to c.u.p., where they might have a
different opinion!)
--
Richard Heathfield <http://www.cpax.org.uk>
Email: -www. +rjh@
Google users: <http://www.cpax.org.uk/prg/writings/googly.php>
"Usenet is a strange place" - dmr 29 July 1999
| |
| Richard Tobin 2007-09-07, 1:32 pm |
| In article <46E16A28.11552FC4@spamcop.net>,
Kenneth Brody <kenbrody@spamcop.net> wrote:
>But, what if your particular implementation does document the
>behavior? Yes, as far as the Standard is concerned, it's UB,
>but have you really invoked UB on that particular platform?
Yes - undefined behaviour means anything can happen, and the thing
that's happened is the behaviour defined by the implementation.
Behaviour undefined by the standard has been invoked on that platform,
even though it is defined by the implementation.
-- Richard
--
"Consideration shall be given to the need for as many as 32 characters
in some alphabets" - X3.4, 1963.
| |
| Rainer Weikusat 2007-09-07, 1:32 pm |
| richard@cogsci.ed.ac.uk (Richard Tobin) writes:
> In article <46E16A28.11552FC4@spamcop.net>,
> Kenneth Brody <kenbrody@spamcop.net> wrote:
>
> Yes - undefined behaviour means anything can happen,
This statement is untrue (and obvious nonsense for any conceivable
real-world example). Undefined behaviours is 'behaviour [...] upon
which this international standard imposes no requirements'. This means
whatever the behaviour might or might not be is not relevant for
determining if the implementation is conforming to ISO/IEC 9899:1999,
ie follows the requirements imposed by it, or not.
Any statement ascribing properties to areas not defined by the
C-standard is a statement about something which is not part of C, as
defined by this standard.
| |
| Douglas A. Gwyn 2007-09-07, 1:32 pm |
| Sheth Raxit wrote:
> 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.>
No, the stdio implementation is not able to correctly decide
what "proper error handling" should be. When the failure to
open the file is reported to the application by a null-pointer
return from fopen(), the application needs to apply the
proper error recover. In no case would that involve ignoring
the error and proceed to read the non-existent data.
> yes,but we are checking currently the behaviour of fgets.
fgets makes no sense when there is no stream for it to read
from. It is quite properly specified as having undefined
behavior in that case. There is no need to require every
conforming C implementation to perform an additional
validity test on standard library parameters every time a
library function is invoked; that would impose a performance
penalty on nearly *every* application, with potential benefit
only for incorrectly coded applications. You are free to use
an implementation that does perform extra validity tests if
you happen to have one. (There are "malloc" libraries like
that.)
| |
| Jonathan Leffler 2007-09-07, 1:32 pm |
| Rainer Weikusat wrote:
> richard@cogsci.ed.ac.uk (Richard Tobin) writes:
>
> This statement is untrue (and obvious nonsense for any conceivable
> real-world example). Undefined behaviours is 'behaviour [...] upon
> which this international standard imposes no requirements'. This means
> whatever the behaviour might or might not be is not relevant for
> determining if the implementation is conforming to ISO/IEC 9899:1999,
> ie follows the requirements imposed by it, or not.
>
> Any statement ascribing properties to areas not defined by the
> C-standard is a statement about something which is not part of C, as
> defined by this standard.
Read up on 'Nasal Demons' (Google - 4th entry when I looked). In
comp.std.c land, undefined behaviour means exactly that. You invoke it,
and if the program erases every file on your system, there is nothing in
the standard that says "that was the incorrect response to undefined
behaviour". As a QoI (Quality of Implementation) issue, you might be
legitimately chagrined and decide to (a) change compilers and (b) be
more careful, but the ISO C Standard does not say that was the wrong
response to invoking undefined behaviour.
--
Jonathan Leffler #include <disclaimer.h>
Email: jleffler@earthlink.net, jleffler@us.ibm.com
Guardian of DBD::Informix v2007.0826 -- http://dbi.perl.org/
| |
| Douglas A. Gwyn 2007-09-07, 1:32 pm |
| /* mystdio.h */
#include <stdio.h> // just for FILE
extern char *myfgets(char *, int, FILE *);
#undef fgets // in case <stdio.h> defined it
#define fgets myfgets
/* ... and others ... */
/* myfgets.c */
#include <stddef.h> // for size_t
#include <stdio.h>
extern void myverify(void *, size_t);
extern void myerror(const char *);
char *myfgets(char *s, int n, FILE *stream) {
if (n < 1)
myerror("n<1");
myverify(s, n - 1); // may invoke myerror
myverify(stream, sizeof(FILE)); // may invoke myerror
return fgets(s, n, stream);
}
| |
| Douglas A. Gwyn 2007-09-07, 1:32 pm |
| Richard Heathfield wrote:
> The behaviour of extensions, as far as I'm aware, is not defined by the
> Standard, and therefore is covered by the definition of undefined
> behaviour, ...
Yes, extensions are allowed that define (necessarily in an
implementation-dependent way) behavior for what the C standard
has labeled as "undefined behavior". Some other kinds of
extensions, such as extensions to the grammar, require at
least one diagnostic to be produced by a conforming C
implementation when a program uses the extension. The
diagnostic could be "Congratulations on making use of some
of our fine extensions!", although I'd hope for something
along the lines "warning: nonstandard extension used".
| |
| Douglas A. Gwyn 2007-09-07, 1:32 pm |
| Sheth Raxit wrote:
> Is Assert-ing for NULL is better than Undefined Behaviour ?
> Good for Buggy program. Good for platform ?
A failed assert() is generally not a good way of handling an
error, since the application and its supporting libraries are
not given a chance to clean up (flush changes to databases,
etc.). Interrupting the application's procedure in the
middle of some chain of actions could have horrible
consequences. Consider if the error occurs between the
time when the medical equipment starts a pump to inject some
drug into a patient and the time when it stops the pump.
In the case of fgets erroneously called with an invalid
stream pointer, the actual problem is not fgets, it is at an
earlier point in the application where a nonexistent-file
error was not properly handled. Therefore the correct fix
needs to be applied at that earlier point, where suitable
application-controlled steps can be taken to recover from it.
| |
| Rainer Weikusat 2007-09-07, 7:36 pm |
| Jonathan Leffler <jleffler@earthlink.net> writes:
> Rainer Weikusat wrote:
>
> Read up on 'Nasal Demons' (Google - 4th entry when I looked). In
> comp.std.c land, undefined behaviour means exactly that.
Well, I wasn't about writing 'preferred phantasies of comp.std.c
regulars' but about C. And from the perpsective of the standard text,
claiming that
a = 3;
a = ++a;
results in any particular value for a is as wrong as claiming that it
may cause your next door neighbour to turn into a piano. If it may can
be determined empirically and both the answer and the means for
determining it are not part of the C programming language.
| |
| Keith Thompson 2007-09-07, 7:36 pm |
| Rainer Weikusat <rweikusat@mssgmbh.com> writes:
> Jonathan Leffler <jleffler@earthlink.net> writes:
[...][vbcol=seagreen]
>
> Well, I wasn't about writing 'preferred phantasies of comp.std.c
> regulars' but about C. And from the perpsective of the standard text,
> claiming that
>
> a = 3;
> a = ++a;
>
> results in any particular value for a is as wrong as claiming that it
> may cause your next door neighbour to turn into a piano. If it may can
> be determined empirically and both the answer and the means for
> determining it are not part of the C programming language.
We don't claim (except jokingly) that executing those statements
*will* cause demons to fly out of your nose. The claim is merely that
nasal demons are one of the infinitely many behaviors permitted by the
standard. If you compile and run a program containing those
statements and demons in fact do fly out of your nose, you can
certainly complain to your compiler vendor, but you have no basis for
claiming that the compiler violates the standard.
It's entirely possible that we're sometimes insufficiently precise on
that point.
--
Keith Thompson (The_Other_Keith) kst-u@mib.org <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"
| |
| Bart van Ingen Schenau 2007-09-07, 7:36 pm |
| Rainer Weikusat wrote:
> Jonathan Leffler <jleffler@earthlink.net> writes:
>
> Well, I wasn't about writing 'preferred phantasies of comp.std.c
> regulars' but about C. And from the perpsective of the standard text,
> claiming that
>
> a = 3;
> a = ++a;
>
> results in any particular value for a is as wrong as claiming that it
> may cause your next door neighbour to turn into a piano.
The standard does indeed not require that UB causes my next door
neighbour to turn into a piano, but that appears to be exactly the
behaviour of my DeathStation 9000.
Are you claiming that this behaviour is not correct?
Bart v Ingen Schenau
--
a.c.l.l.c-c++ FAQ: http://www.comeaucomputing.com/learn/faq
c.l.c FAQ: http://www.eskimo.com/~scs/C-faq/top.html
c.l.c++ FAQ: http://www.parashift.com/c++-faq-lite/
| |
| kuyper 2007-09-07, 7:36 pm |
| Kenneth Brody wrote:
> Richard Heathfield wrote:
> [...]
>
> But, what if your particular implementation does document the
> behavior? Yes, as far as the Standard is concerned, it's UB,
> but have you really invoked UB on that particular platform?
UB is not "invoked"; that wording carries with it the concept that
there's a particular kind of behavior that is labelled by "UB", and
that using C in the wrong way allows that kind of behavior. That
concept is almost, but not exactly, opposite to the correct way of
thinking about UB.
The correct statement is that such code has behavior that is not
defined by the C standard; a situation which the C standard quite
reasonably labels as "undefined behavior". However, just because
that's the C standard's jargon for such code, doesn't mean that the
behavior is necessarily undefined in the ordinary English sense of the
phrase. The behavior may be perfectly well-defined - by something
other than the C standard. It could be defined by the POSIX standard,
or it could be defined by the particular implementation of C that
you're using, or something else entirely.
Definitions of the behavior which are provided by other sources than
the C standard are off-topic in comp.std.c; I'm not sure about the
policies of the other newsgroups this message is cross-posted to.
However, just because such behavior is off-topic doesn't mean that
it's meaningless, or non-existent, or not worth talking about, as some
other people have implied. It's just not appropriate to talk about
them in comp.std.c.
| |
| CBFalconer 2007-09-07, 7:36 pm |
| jacob navia wrote:
> Jack Klein wrote:
>
.... snip ...
>
> 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!
No you didn't. You quoted something which said a NULL was
returned, without bothering to identify the source of the quote.
Then, in this immediate reply, you got ugly and rude rather than
accepting the accurate correction and a quote from the standard.
--
Chuck F (cbfalconer at maineline dot net)
Available for consulting/temporary embedded and systems.
<http://cbfalconer.home.att.net>
--
Posted via a free Usenet account from http://www.teranews.com
| |
| CBFalconer 2007-09-07, 7:36 pm |
| jacob navia wrote:
> Casper H.S. Dik wrote:
>
.... snip ...
>
> Why error analysis is necessary?
>
> Error analysis means trying to have a defined an in all cases
> identical reaction to program errors.
>
> This means that for each function we write, we try to
> return a specified error report value if things go wrong.
>
> In the case of fgets this implies:
> o Testing for NULL.
> o Testing for a bad value of n (<= 0)
> o Testing for a NULL value in the receiving buffer.
NULLs are allowed in the receiving buffer, and don't matter since
they will either be beyond the line end or overwritten. It helps
to get the objective right before trying to code for it.
One is also allowed to snip obvious signatures, even though the
originator neglected to include a proper sig. marker. There are no
prizes for extreme laziness or rudeness.
--
Chuck F (cbfalconer at maineline dot net)
Available for consulting/temporary embedded and systems.
<http://cbfalconer.home.att.net>
--
Posted via a free Usenet account from http://www.teranews.com
| |
| jacob navia 2007-09-07, 7:36 pm |
| CBFalconer wrote:
> jacob navia wrote:
> ... snip ...
>
> No you didn't. You quoted something which said a NULL was
> returned,
I quoted the standard. That is the "something".
without bothering to identify the source of the quote.
No. I started my message with
[vbcol=seagreen]
[vbcol=seagreen]
No. I did not insult anyone or whatever. You are dreaming things up.
I just wanted to argument that error checking is lacking in many
functions that *could* reasonably have more error returns specified.
This is a valid opinion, and I am free to argue it.
| |
| Keith Thompson 2007-09-07, 7:36 pm |
| CBFalconer <cbfalconer@yahoo.com> writes:
> jacob navia wrote:
[...]
>
> NULLs are allowed in the receiving buffer, and don't matter since
> they will either be beyond the line end or overwritten. It helps
> to get the objective right before trying to code for it.
[...]
Let's be clear what we're talking about.
Here's the declaration of fgets:
char *fgets(char * restrict s, int n, FILE * restrict stream);
You're interpreting jacob's third point to mean null characters ('\0')
in the array pointed to by 's'. I don't believe that's what he meant;
the initial contents of the array are irrelevant, and if he were
talking about null characters he probably wouldn't have used the term
NULL, which is a macro that expands to a null pointer constant.
I think he was referring to checking in fgets whether s == NULL.
That's a reasonable check to make, but it's not required, and it
misses a plethora of other possible invalid values.
As a programmer, of course, I can't depend on any such checks, since
not all implementations perform them, and that's going to remain the
case for a long time. It's still entirely *my* responsibility to
avoid passing invalid arguments to fgets. If the implementation helps
me out by catching certain errors, that's great (unless it imposes too
much of a burden on *correct* calls), but I can't count on it. If I
don't trust myself to get this right, I can always write a wrapper
that checks the arguments before calling fgets.
A side note: Above I referred to "the array pointed to by 's'". Since
's' is a char*, it doesn't point to an array; it points to a char
(which presumably is the first element of an array). The standard
allows a char* to be a "pointer to a string", but there's no such
wording that allows it to be called a "pointer to an array", since a
pointer to an array is a valid and distinct concept. However, the
standard itself refers to the "the array pointed to by s" (C99
7.19.7.2p2). I suppose it's clear enough from context.
--
Keith Thompson (The_Other_Keith) kst-u@mib.org <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"
| |
| Richard Tobin 2007-09-07, 7:36 pm |
| In article <877in2wgfc.fsf@fever.mssgmbh.com>,
Rainer Weikusat <rweikusat@mssgmbh.com> wrote:
[vbcol=seagreen]
>This statement is untrue (and obvious nonsense for any conceivable
>real-world example). Undefined behaviours is 'behaviour [...] upon
>which this international standard imposes no requirements'. This means
>whatever the behaviour might or might not be is not relevant for
>determining if the implementation is conforming to ISO/IEC 9899:1999,
>ie follows the requirements imposed by it, or not.
Ok, let me rephrase it. Undefined behaviour means anything can happen
*without violating the standard*. No real implementation will make
DMR's head explode, but if it did it wouldn't be a standard violation.
-- Richard
--
"Consideration shall be given to the need for as many as 32 characters
in some alphabets" - X3.4, 1963.
| |
| Scott Lurndal 2007-09-08, 1:43 am |
| Keith Thompson <kst-u@mib.org> writes:
[snip]
>As a programmer, of course, I can't depend on any such checks, since
>not all implementations perform them, and that's going to remain the
>case for a long time. It's still entirely *my* responsibility to
>avoid passing invalid arguments to fgets. If the implementation helps
>me out by catching certain errors, that's great (unless it imposes too
>much of a burden on *correct* calls), but I can't count on it. If I
>don't trust myself to get this right, I can always write a wrapper
>that checks the arguments before calling fgets.
Indeed. One may as well expect strcpy to return EFAULT when provided
arguments in which the destination pointer refers to an
unmapped portion of the virtual address space (or a portion mapped
read-only, or a portion to which the process has no access).
This was actually proposed to the X/Open group at one point and was
quickly rejected due to performance and correctness constraints.
scott
| |
| Barry Margolin 2007-09-08, 1:43 am |
| In article <1189149497.959132.199430@22g2000hsm.googlegroups.com>,
Sheth Raxit <raxitsheth2000@gmail.com> wrote:
> don't you think instead of "not saying" or "saying undefined
> behaviour" any additional checks are put itself in std ?
This would be redundant and inefficient. Instead of the programmer
checking the return value of fopen() once, all the I/O functions would
have to check the value of the stream every time.
Consider an inner loop calling fgetc(). This is a very simple
operation, probably only about 5-10 instructions most of the time
(because of buffering -- if there's data in the buffer it just has to
copy one byte and increment the buffer pointer). Adding the NULL check
would slow it down by 20-30%, I suspect.
--
Barry Margolin, barmar@alum.mit.edu
Arlington, MA
*** PLEASE post questions in newsgroups, not directly to me ***
*** PLEASE don't copy me on replies, I'll read them in the group ***
| |
| Joe Wright 2007-09-08, 1:31 pm |
| CBFalconer wrote:
> jacob navia wrote:
> ... snip ...
>
> NULLs are allowed in the receiving buffer, and don't matter since
> they will either be beyond the line end or overwritten. It helps
> to get the objective right before trying to code for it.
>
> One is also allowed to snip obvious signatures, even though the
> originator neglected to include a proper sig. marker. There are no
> prizes for extreme laziness or rudeness.
>
Canonically,
char buff[80];
size_t size = sizeof buff;
while (fgets(buff, size, stream)) {
....
}
fgets will return NULL at EOF or error. The EOF condition is the normal
exit from the while loop.
fgets returns the value buff if it read something. We use strchr to
check for '\n' in buff indicating a complete line.
If the line is incomplete, either the line is longer than buff or it is
the last line of the stream and doesn't terminate with '\n'. To find out
which we use strchr searching for '\0' which will always succeed. If the
NUL is at buff[size-1] we assume the line is longer than buff. If the
NUL occurs earlier we assume an unterminated last line.
For well formed input we have enough information to do 'the right thing'
with the data.
Perversity.
It is apparently legal, if unusual, to have '\0' characters in text
files. fgets makes no exception for these NUL characters. If a too-long
line has a NUL in it, my logic above gets it wrong by assuming an
unterminated last line. Even if the line is terminated with '\n', if it
also contains NUL then using strcpy to move it from buff will fail
miserably.
All because NUL is legal in text streams. Or is it?
--
Joe Wright
"Everything should be made as simple as possible, but not simpler."
--- Albert Einstein ---
| |
| Robert Harris 2007-09-08, 1:31 pm |
| Joe Wright wrote:
> CBFalconer wrote:
> Canonically,
>
> char buff[80];
> size_t size = sizeof buff;
> while (fgets(buff, size, stream)) {
> ....
> }
> fgets will return NULL at EOF or error. The EOF condition is the normal
> exit from the while loop.
>
> fgets returns the value buff if it read something. We use strchr to
> check for '\n' in buff indicating a complete line.
>
> If the line is incomplete, either the line is longer than buff or it is
> the last line of the stream and doesn't terminate with '\n'. To find out
> which we use strchr searching for '\0' which will always succeed. If the
> NUL is at buff[size-1] we assume the line is longer than buff. If the
> NUL occurs earlier we assume an unterminated last line.
>
> For well formed input we have enough information to do 'the right thing'
> with the data.
>
> Perversity.
> It is apparently legal, if unusual, to have '\0' characters in text
> files. fgets makes no exception for these NUL characters. If a too-long
> line has a NUL in it, my logic above gets it wrong by assuming an
> unterminated last line. Even if the line is terminated with '\n', if it
> also contains NUL then using strcpy to move it from buff will fail
> miserably.
>
> All because NUL is legal in text streams. Or is it?
>
A stream is a stream. If there is any possibility of NULs in your
stream, then using fgets will lead to misleading results because it
doesn't return a character count.
Robert
| |
| CBFalconer 2007-09-08, 1:31 pm |
| Joe Wright wrote:
> CBFalconer wrote:
>
> Canonically,
>
> char buff[80];
> size_t size = sizeof buff;
> while (fgets(buff, size, stream)) {
> ....
> }
> fgets will return NULL at EOF or error. The EOF condition is the
> normal exit from the while loop.
>
> fgets returns the value buff if it read something. We use strchr
> to check for '\n' in buff indicating a complete line.
>
> If the line is incomplete, either the line is longer than buff or
> it is the last line of the stream and doesn't terminate with '\n'.
> To find out which we use strchr searching for '\0' which will
> always succeed. If the NUL is at buff[size-1] we assume the line
> is longer than buff. If the NUL occurs earlier we assume an
> unterminated last line.
>
> For well formed input we have enough information to do 'the right
> thing' with the data.
>
> Perversity.
> It is apparently legal, if unusual, to have '\0' characters in
> text files. fgets makes no exception for these NUL characters. If
> a too-long line has a NUL in it, my logic above gets it wrong by
> assuming an unterminated last line. Even if the line is terminated
> with '\n', if it also contains NUL then using strcpy to move it
> from buff will fail miserably.
The constant response to all line lengths thing is easily handled
by ggets. If the NULLs in the line are affecting you, you could
easily modify ggets.zip to ignore them (which may not be the right
cure). See:
<http://cbfalconer.home.att.net/download/>
Barring i/o or malloc failures ggets always returns complete lines,
with the final '\n' removed. The penalty is exercising the malloc
subsystem.
It has been pointed out that ggets is vulnerable to deliberate
interference, since it continues to expand the buffer as long as
input is arriving (without a '\n'). I think this is negligible,
partly because it is hard to provide a continuous input. It
actually doesn't tie up indefinitely, since once the malloc system
refuses to expand it exits with error.
--
Chuck F (cbfalconer at maineline dot net)
Available for consulting/temporary embedded and systems.
<http://cbfalconer.home.att.net>
--
Posted via a free Usenet account from http://www.teranews.com
| |
| Army1987 2007-09-08, 7:24 pm |
| On Sat, 08 Sep 2007 10:03:32 -0400, Joe Wright wrote:
> [...]To find out
> which we use strchr searching for '\0' which will always succeed. If the
> NUL is at buff[size-1] we assume the line is longer than buff.
Doesn't strlen(buf) != size - 1 do the same without looking that
weird?
--
Army1987 (Replace "NOSPAM" with "email")
If you're sending e-mail from a Windows machine, turn off Microsoft's
stupid “Smart Quotes” feature. This is so you'll avoid sprinkling garbage
characters through your mail. -- Eric S. Raymond and Rick Moen
| |
| Keith Thompson 2007-09-08, 7:24 pm |
| Joe Wright <joewwright@comcast.net> writes:
[...]
> Canonically,
>
> char buff[80];
> size_t size = sizeof buff;
> while (fgets(buff, size, stream)) {
> ....
> }
[...]
> If the line is incomplete, either the line is longer than buff or it
> is the last line of the stream and doesn't terminate with '\n'. To
> find out which we use strchr searching for '\0' which will always
> succeed. If the NUL is at buff[size-1] we assume the line is longer
> than buff. If the NUL occurs earlier we assume an unterminated last
> line.
[...]
strchr? Just use strlen.
--
Keith Thompson (The_Other_Keith) kst-u@mib.org <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"
| |
| Keith Thompson 2007-09-08, 7:24 pm |
| CBFalconer <cbfalconer@yahoo.com> writes:
[...]
> It has been pointed out that ggets is vulnerable to deliberate
> interference, since it continues to expand the buffer as long as
> input is arriving (without a '\n'). I think this is negligible,
> partly because it is hard to provide a continuous input.
> actually doesn't tie up indefinitely, since once the malloc system
> refuses to expand it exits with error.
No, it's not hard to provide a continuous input. In fact, it's
trivial, as I've demonstrated:
./my_program < /dev/zero
> It
> actually doesn't tie up indefinitely, since once the malloc system
> refuses to expand it exits with error.
Which is not necessarily benign.
--
Keith Thompson (The_Other_Keith) kst-u@mib.org <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"
| |
| CBFalconer 2007-09-08, 7:24 pm |
| Keith Thompson wrote:
> CBFalconer <cbfalconer@yahoo.com> writes:
> [...]
>
> No, it's not hard to provide a continuous input. In fact, it's
> trivial, as I've demonstrated:
>
> ./my_program < /dev/zero
>
>
> Which is not necessarily benign.
However, this assumes the evildoer has access to the machine, and
can access devices, and can redirect input to access such a device,
etc. etc. I don't think this generally applies.
Actually the suggestion I made earlier in this thread, of making
ggets ignore a zero byte, would foul this attack entirely. Since
ggets is intended to input text this is probably a harmless change
and doesn't affect the .h linkage file in the least.
--
Chuck F (cbfalconer at maineline dot net)
Available for consulting/temporary embedded and systems.
<http://cbfalconer.home.att.net>
--
Posted via a free Usenet account from http://www.teranews.com
| |
| Richard Tobin 2007-09-08, 7:24 pm |
| In article <46E31854.99470D35@yahoo.com>,
CBFalconer <cbfalconer@maineline.net> wrote:
[vbcol=seagreen]
>However, this assumes the evildoer has access to the machine, and
>can access devices, and can redirect input to access such a device,
>etc. etc. I don't think this generally applies.
What kind of input would someone have that *wouldn't* allow them that
kind of access? In the old days they might be sitting at a dumb
terminal, but now almost all remote access is from another computer
that can generate arbitrary data.
On the other hand, most remote access these days is probably through
HTTP, and for that the size of the data is usually known before the
remote application gets hold of it. It can be very big of course.
-- Richard
--
"Consideration shall be given to the need for as many as 32 characters
in some alphabets" - X3.4, 1963.
| |
| Keith Thompson 2007-09-08, 7:24 pm |
| CBFalconer <cbfalconer@yahoo.com> writes:
> Keith Thompson wrote:
>
> However, this assumes the evildoer has access to the machine, and
> can access devices, and can redirect input to access such a device,
> etc. etc. I don't think this generally applies.
Sure it does. On a typical system, if the "evildoer" is able to run
the program at all, he can redirect its input from anywhere he likes.
> Actually the suggestion I made earlier in this thread, of making
> ggets ignore a zero byte, would foul this attack entirely. Since
> ggets is intended to input text this is probably a harmless change
> and doesn't affect the .h linkage file in the least.
That only affects the specific case of reading from /dev/zero (or
something equivalent). You could read from any arbitrary binary file;
depending on the kind of file, it might happen to contain an
arbitrarily long sequence of bytes containing neither '\n' nor '\0'.
And that's just something that can happen entirely by accident. I've
done that kind of thing myself trying to run "less" on a binary file
(it hangs until I kill it from another window). Given a malicious
attacker ("Here, take a look at this file!"), generating arbitrarily
long lines is trivial.
My examples are Unix-specific, but similar problems can occur on other
systems.
--
Keith Thompson (The_Other_Keith) kst-u@mib.org <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"
| |
| CBFalconer 2007-09-09, 1:25 am |
| Keith Thompson wrote:
> CBFalconer <cbfalconer@yahoo.com> writes:
>
> Sure it does. On a typical system, if the "evildoer" is able to run
> the program at all, he can redirect its input from anywhere he likes.
>
>
> That only affects the specific case of reading from /dev/zero (or
> something equivalent). You could read from any arbitrary binary file;
> depending on the kind of file, it might happen to contain an
> arbitrarily long sequence of bytes containing neither '\n' nor '\0'.
>
> And that's just something that can happen entirely by accident. I've
> done that kind of thing myself trying to run "less" on a binary file
> (it hangs until I kill it from another window). Given a malicious
> attacker ("Here, take a look at this file!"), generating arbitrarily
> long lines is trivial.
>
> My examples are Unix-specific, but similar problems can occur on other
> systems.
Generating such a file is a non-trivial exercise, as I discovered
when I created some long lines for ggets testing in the first
place. They have to ban the use of a byte holding numeric 10
everywhere, since this will always create a line ending. I
maintain the routine is no more dangerous than an ordinary program
that reads a file into memory, using malloc to create the storage.
Either can lead to harassment, admittedly, but they cannot form a
security hole. Almost anything that does input can be harassed in
the same general way.
--
Chuck F (cbfalconer at maineline dot net)
Available for consulting/temporary embedded and systems.
<http://cbfalconer.home.att.net>
--
Posted via a free Usenet account from http://www.teranews.com
| |
| Army1987 2007-09-09, 7:33 am |
| On Sat, 08 Sep 2007 21:48:19 +0200, Army1987 wrote:
> On Sat, 08 Sep 2007 10:03:32 -0400, Joe Wright wrote:
>
> Doesn't strlen(buf) != size - 1 do the same without looking that
> weird?
Or better, set buff[size - 1] to a nonzero value, call fgets, and
check whether buff[size - 1] is zero. This takes O(1) time.
--
Army1987 (Replace "NOSPAM" with "email")
If you're sending e-mail from a Windows machine, turn off Microsoft's
stupid “Smart Quotes” feature. This is so you'll avoid sprinkling garbage
characters through your mail. -- Eric S. Raymond and Rick Moen
| |
| Army1987 2007-09-09, 1:30 pm |
| On Fri, 07 Sep 2007 17:38:50 +0000, Douglas A. Gw | | |