468,463 Members | 1,978 Online
Bytes | Developer Community
New Post

Home Posts Topics Members FAQ

Post your question to a community of 468,463 developers. It's quick & easy.

why the usage of gets() is dangerous.

Hi all,

Whenever I use the gets() function, the gnu c compiler gives a
warning that it is dangerous to use gets(). why...?

regards,
jayapal.
Nov 16 '07 #1
104 4551
In <2f**********************************@n20g2000hsh. googlegroups.comjayapal <ja********@gmail.comwrites:
Whenever I use the gets() function, the gnu c compiler gives a
warning that it is dangerous to use gets(). why...?
gets() does not allow you limit the amount of input, which means it
can potentially overflow the buffer into which the input is placed.

--
John Gordon A is for Amy, who fell down the stairs
go****@panix.com B is for Basil, assaulted by bears
-- Edward Gorey, "The Gashlycrumb Tinies"

Nov 16 '07 #2
On Nov 16, 10:10 pm, John Gordon <gor...@panix.comwrote:
gets() does not allow you limit the amount of input, which means it
can potentially overflow the buffer into which the input is placed.
Can u explain the differences b/w the scanf() and gets() ..?

Thanks,
Jayapal
Nov 16 '07 #3
jayapal <ja********@gmail.comwrites:
On Nov 16, 10:10 pm, John Gordon <gor...@panix.comwrote:
>gets() does not allow you limit the amount of input, which means it
can potentially overflow the buffer into which the input is placed.

Can u explain the differences b/w the scanf() and gets() ..?
Presumably you mean for string input? Using 'scanf("%[^\n]", buf)'
has the same problem as 'gets'. But scanf can be saved (just about)
since it permits a bounded input operation:

char buf[100];
...
if (scanf("%99[^\n]", buf) == 1) ...

--
Ben.
Nov 16 '07 #4
jayapal wrote:
Hi all,

Whenever I use the gets() function, the gnu c compiler gives a
warning that it is dangerous to use gets(). why...?

regards,
jayapal.
That function is deprecated and will disappear shortly.
Its usage is not recommended because there is no way to
limit the input that it will receive, and it can overflow
the input buffer.

--
jacob navia
jacob at jacob point remcomp point fr
logiciels/informatique
http://www.cs.virginia.edu/~lcc-win32
Nov 16 '07 #5
CJ
On 16 Nov 2007 at 18:41, jacob navia wrote:
jayapal wrote:
>Hi all,

Whenever I use the gets() function, the gnu c compiler gives a
warning that it is dangerous to use gets(). why...?

regards,
jayapal.

That function is deprecated and will disappear shortly.
Its usage is not recommended because there is no way to
limit the input that it will receive, and it can overflow
the input buffer.
This sort of absolute prohibition on gets() is completely wrong-headed.
It's completely fine to use gets(), as long as you use it properly. To
use it properly, *you* need to be in control of the data that gets()
reads. For throwaway utility routines this will often be the case, and
there's no problem using gets() in this case.

Nov 16 '07 #6
In article <sl*******************@nospam.com>, CJ <no****@nospam.comwrote:
>This sort of absolute prohibition on gets() is completely wrong-headed.
It's completely fine to use gets(), as long as you use it properly. To
use it properly, *you* need to be in control of the data that gets()
reads. For throwaway utility routines this will often be the case, and
there's no problem using gets() in this case.
Except that throwaway code has an annoying habit of not getting thrown
away. If you make a habit of using gets in your throwaway code, sooner
or later it WILL escape into the wild, and once that happens it's only
a matter of time before it becomes an exploitable bug.
dave

Nov 16 '07 #7
jayapal wrote, On 16/11/07 17:18:
On Nov 16, 10:10 pm, John Gordon <gor...@panix.comwrote:
>gets() does not allow you limit the amount of input, which means it
can potentially overflow the buffer into which the input is placed.

Can u explain the differences b/w the scanf() and gets() ..?
Please don't use contractions like "u" for "you" or "b/w" for "between".
They make it far harder to read your posts. For example, a lot of people
will be more likely to read "b/w" as "black and white" then "between"
and then have to work out what you actually meant.

As to your question, it is almost easier to say what the similarities
are. The main similarity is that they both get input from stdin, after
that they are very different. gets just keep reading input in to the
memory you provide a pointer to until either a newline is encountered or
your program crashes. scanf reads input as specified by the format
specifier you provide. With work, scanf *can* be used safely (although
it is not easy for a novice) but it is virtually impossible to use gets
safely and it definitely cannot be used safely for user input.

I would recommend you learn to use fgets and getc and build your input
routines using these function and separate passing. You can use sscanf
for the passing if you like, although you have to be careful, since it
is not as hard to use sscanf correctly as it is to use scanf or fscanf
correctly.
--
Flash Gordon
Nov 16 '07 #8
CJ said:
On 16 Nov 2007 at 18:41, jacob navia wrote:
>jayapal wrote:
>>Hi all,

Whenever I use the gets() function, the gnu c compiler gives a
warning that it is dangerous to use gets(). why...?

regards,
jayapal.

That function is deprecated and will disappear shortly.
Its usage is not recommended because there is no way to
limit the input that it will receive, and it can overflow
the input buffer.

This sort of absolute prohibition on gets() is completely wrong-headed.
No, it isn't. (Even a stopped clock is right twice a day.) There is never a
good reason to use the gets function.
It's completely fine to use gets(), as long as you use it properly.
To use it properly, precede it with an 'f', and modify the syntax of the
call accordingly.
To
use it properly, *you* need to be in control of the data that gets()
reads. For throwaway utility routines this will often be the case, and
there's no problem using gets() in this case.
That would be fine, if it were not for the facts that (a) you're not
necessarily as much in control of the data as you think you are, and (b)
throwaway routines have a bad habit of not being thrown away.

--
Richard Heathfield <http://www.cpax.org.uk>
Email: -http://www. +rjh@
Google users: <http://www.cpax.org.uk/prg/writings/googly.php>
"Usenet is a strange place" - dmr 29 July 1999
Nov 16 '07 #9
On Nov 16, 10:04 pm, jayapal <jayapal...@gmail.comwrote:
Hi all,

Whenever I use the gets() function, the gnu c compiler gives a
warning that it is dangerous to use gets(). why...?
gets is very very dangerous. Handle with care :):)
It has buffer related worries.(Expects newline in its pocket to
work without causing any harm !)

Karthik Balaguru
Nov 16 '07 #10
On Nov 16, 9:04 am, jayapal <jayapal...@gmail.comwrote:
Hi all,

Whenever I use the gets() function, the gnu c compiler gives a
warning that it is dangerous to use gets(). why...?
For the same reason that failure to read the C-FAQ is dangerous.
Because you will look like a nincompoop due to the omission of common
sense.

12.23: Why does everyone say not to use gets()?

A: Unlike fgets(), gets() cannot be told the size of the buffer
it's to read into, so it cannot be prevented from overflowing
that buffer. As a general rule, always use fgets(). See
question 7.1 for a code fragment illustrating the replacement
of
gets() with fgets().

References: Rationale Sec. 4.9.7.2; H&S Sec. 15.7 p. 356.
Nov 16 '07 #11
On Nov 16, 9:04 am, jayapal <jayapal...@gmail.comwrote:
Whenever I use the gets() function, the gnu c compiler gives a
warning that it is dangerous to use gets(). why...?
No set of program control can prevent gets() from having undefined
behavior. In fact, basically all C compilers implement gets() to have
undefined behavior. Because of this, the function has been slated to
be deprecated in the next C standard. I have made a safe
implementation of gets() that you can find as the first example here:

http://www.pobox.com/~qed/userInput.html

Please feel free to use it in lieu of the upcoming standard which will
make its usage obsolete.

--
Paul Hsieh
http://www.pobox.com/~qed/
http://bstring.sf.net/
Nov 16 '07 #12
Paul Hsieh wrote On 11/16/07 14:43,:
On Nov 16, 9:04 am, jayapal <jayapal...@gmail.comwrote:
>>Whenever I use the gets() function, the gnu c compiler gives a
warning that it is dangerous to use gets(). why...?


No set of program control can prevent gets() from having undefined
behavior. In fact, basically all C compilers implement gets() to have
undefined behavior. Because of this, the function has been slated to
be deprecated in the next C standard. I have made a safe
implementation of gets() that you can find as the first example here:

http://www.pobox.com/~qed/userInput.html

Please feel free to use it in lieu of the upcoming standard which will
make its usage obsolete.
Isn't there a buffer overrun vulnerability in the
fgetstralloc() function? Look carefully at the second
argument of the first call to getInputFrag().

--
Er*********@sun.com
Nov 16 '07 #13


CJ wrote:
On 16 Nov 2007 at 18:41, jacob navia wrote:
jayapal wrote:
Hi all,

Whenever I use the gets() function, the gnu c compiler gives a
warning that it is dangerous to use gets(). why...?

regards,
jayapal.
That function is deprecated and will disappear shortly.
Its usage is not recommended because there is no way to
limit the input that it will receive, and it can overflow
the input buffer.

This sort of absolute prohibition on gets() is completely wrong-headed.
It's completely fine to use gets(), as long as you use it properly. To
use it properly, *you* need to be in control of the data that gets()
reads.
Keep in mind, of course, that there's absolutely nothing you can do
within strictly conforming C code that would give you the kind of
control you need to have to use gets() safely. The safety of such
usage depends upon something outside the C standard, and more likely
than not, something outside of the program itself.

It's trivial to replace any call to gets() with a similar call to
fgets() with minor modifications to the surrounding code, and that
change is sufficient to completely avoid the buffer overruns. I don't
know of any legitimate reason for not doing so.
Nov 16 '07 #14
CJ
On 16 Nov 2007 at 20:47, ja*********@verizon.net wrote:
>

CJ wrote:
>On 16 Nov 2007 at 18:41, jacob navia wrote:
jayapal wrote:
Hi all,

Whenever I use the gets() function, the gnu c compiler gives a
warning that it is dangerous to use gets(). why...?

regards,
jayapal.

That function is deprecated and will disappear shortly.
Its usage is not recommended because there is no way to
limit the input that it will receive, and it can overflow
the input buffer.

This sort of absolute prohibition on gets() is completely wrong-headed.
It's completely fine to use gets(), as long as you use it properly. To
use it properly, *you* need to be in control of the data that gets()
reads.

Keep in mind, of course, that there's absolutely nothing you can do
within strictly conforming C code that would give you the kind of
control you need to have to use gets() safely. The safety of such
usage depends upon something outside the C standard, and more likely
than not, something outside of the program itself.

It's trivial to replace any call to gets() with a similar call to
fgets() with minor modifications to the surrounding code, and that
change is sufficient to completely avoid the buffer overruns. I don't
know of any legitimate reason for not doing so.
It's much more typing!

Nov 16 '07 #15
jacob navia <ja***@nospam.comwrites:
jayapal wrote:
>Whenever I use the gets() function, the gnu c compiler gives a
warning that it is dangerous to use gets(). why...?

That function is deprecated and will disappear shortly.
It is not listed in the current C standard as deprecated.
--
"A lesson for us all: Even in trivia there are traps."
--Eric Sosman
Nov 16 '07 #16
On Fri, 16 Nov 2007 13:06:52 -0800, Ben Pfaff wrote:
jacob navia <ja***@nospam.comwrites:
>jayapal wrote:
>>Whenever I use the gets() function, the gnu c compiler gives a warning
that it is dangerous to use gets(). why...?

That function is deprecated and will disappear shortly.

It is not listed in the current C standard as deprecated.
http://open-std.org/JTC1/SC22/WG14/www/docs/dr_332.htm

The status from the summary page is "closed, published in TC 3", and you
can find the added paragraph in n1256. Admittedly, I'm not sure if TC 3
is official just yet.

However, of course being deprecated does not mean it will actually be
removed any time soon.
Nov 16 '07 #17
On Nov 16, 12:20 pm, Eric Sosman <Eric.Sos...@sun.comwrote:
Paul Hsieh wrote On 11/16/07 14:43,:
On Nov 16, 9:04 am, jayapal <jayapal...@gmail.comwrote:
>Whenever I use the gets() function, the gnu c compiler gives a
warning that it is dangerous to use gets(). why...?
No set of program control can prevent gets() from having undefined
behavior. In fact, basically all C compilers implement gets() to have
undefined behavior. Because of this, the function has been slated to
be deprecated in the next C standard. I have made a safe
implementation of gets() that you can find as the first example here:
http://www.pobox.com/~qed/userInput.html
Please feel free to use it in lieu of the upcoming standard which will
make its usage obsolete.

Isn't there a buffer overrun vulnerability in the
fgetstralloc() function? Look carefully at the second
argument of the first call to getInputFrag().
Its 64. getInputFrag(*,64,*,*,*) never writes to more than 64 chars
(the extra '\0' only comes when the input is <= 64 in length; unlike
strncat, this is ok because the length read is always explicitly
returned), and the buffer passed (char blk[64]) in is 64 chars in
length. So ... what am I missing?

--
Paul Hsieh
http://www.pobox.com/~qed/
http://bstring.sf.net/
Nov 16 '07 #18
jacob navia wrote:
jayapal wrote:
>Whenever I use the gets() function, the gnu c compiler gives a
warning that it is dangerous to use gets(). why...?

That function is deprecated and will disappear shortly.
Its usage is not recommended because there is no way to
limit the input that it will receive, and it can overflow
the input buffer.
It's true that gets() has been declared obsolescent and deprecated.
This is reflected in TC3 and in the latest standard draft, n1256.pdf.
This just happened within the last couple of months.

But please don't make the mistake of thinking that it "will disappear
shortly". It has not been removed from the C99 standard. In fact, any
conforming C99 implementation *must* provide gets(), undefined behavior
and all (though any implementation is free to warn about it).

Deprecation means that it will most likely be removed from the *next* C
standard, which is still a number of years away. Consider that the C99
standard is 8 years old, and still has not been fully implemented by the
vast majority of compilers. It will likely be decades, if ever, before
a significant number of implementations conform to a new C20YZ standard.
And even then, compilers will be free to continue to provide it in a
non-conforming mode, perhaps for backward compatibility.

I'm afraid that gets() is going to be around for a very long time. It's
still up to each of us, as programmers, to avoid using it.

jacob, if you really thing gets() will "disappear shortly", I'd be
interested in your reasoning.

--
Keith Thompson (The_Other_Keith) <ks***@mib.org>
Looking for software development work in the San Diego area.
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Nov 16 '07 #19
Keith Thompson wrote:
jacob navia wrote:
>jayapal wrote:
>>Whenever I use the gets() function, the gnu c compiler gives a
warning that it is dangerous to use gets(). why...?

That function is deprecated and will disappear shortly.
Its usage is not recommended because there is no way to
limit the input that it will receive, and it can overflow
the input buffer.

It's true that gets() has been declared obsolescent and deprecated. This
is reflected in TC3 and in the latest standard draft, n1256.pdf. This
just happened within the last couple of months.

But please don't make the mistake of thinking that it "will disappear
shortly". It has not been removed from the C99 standard. In fact, any
conforming C99 implementation *must* provide gets(), undefined behavior
and all (though any implementation is free to warn about it).

Deprecation means that it will most likely be removed from the *next* C
standard, which is still a number of years away. Consider that the C99
standard is 8 years old, and still has not been fully implemented by the
vast majority of compilers. It will likely be decades, if ever, before
a significant number of implementations conform to a new C20YZ standard.
And even then, compilers will be free to continue to provide it in a
non-conforming mode, perhaps for backward compatibility.

I'm afraid that gets() is going to be around for a very long time. It's
still up to each of us, as programmers, to avoid using it.

jacob, if you really thing gets() will "disappear shortly", I'd be
interested in your reasoning.
Nothing, just hopes that now that is deprecated, people will
stop using it, and it will disappear in a few years.

--
jacob navia
jacob at jacob point remcomp point fr
logiciels/informatique
http://www.cs.virginia.edu/~lcc-win32
Nov 16 '07 #20
"Paul Hsieh" <we******@gmail.comwrote in message
On Nov 16, 9:04 am, jayapal <jayapal...@gmail.comwrote:
>Whenever I use the gets() function, the gnu c compiler gives a
warning that it is dangerous to use gets(). why...?

No set of program control can prevent gets() from having undefined
behavior. In fact, basically all C compilers implement gets() to have
undefined behavior.
Undefined behaviour means "undefined by the standard". It is possible,
though rather difficult, to implement a safe gets(), that is to say one that
always terminates the program with an error message if the buffer is
exceeded.

What is not possible to is implement is a safe fgets(), that is to say, one
that can be used safely given the limitations of the average human
programmer.

--
Free games and programming goodies.
http://www.personal.leeds.ac.uk/~bgy1mm

Nov 16 '07 #21
Paul Hsieh wrote On 11/16/07 16:53,:
On Nov 16, 12:20 pm, Eric Sosman <Eric.Sos...@sun.comwrote:
>>Paul Hsieh wrote On 11/16/07 14:43,:
>>>On Nov 16, 9:04 am, jayapal <jayapal...@gmail.comwrote:
>>>>Whenever I use the gets() function, the gnu c compiler gives a
warning that it is dangerous to use gets(). why...?
>>>No set of program control can prevent gets() from having undefined
behavior. In fact, basically all C compilers implement gets() to have
undefined behavior. Because of this, the function has been slated to
be deprecated in the next C standard. I have made a safe
implementation of gets() that you can find as the first example here:
>> http://www.pobox.com/~qed/userInput.html
>>>Please feel free to use it in lieu of the upcoming standard which will
make its usage obsolete.

Isn't there a buffer overrun vulnerability in the
fgetstralloc() function? Look carefully at the second
argument of the first call to getInputFrag().


Its 64. getInputFrag(*,64,*,*,*) never writes to more than 64 chars
(the extra '\0' only comes when the input is <= 64 in length; unlike
strncat, this is ok because the length read is always explicitly
returned), and the buffer passed (char blk[64]) in is 64 chars in
length. So ... what am I missing?
Nothing, I guess. I must have been confused by the
convoluted style. (Well, if it confuses me then it *must*
be convoluted, right?)

Still seems an awfully arcane way to skip and count
characters, though.

--
Er*********@sun.com
Nov 16 '07 #22
Malcolm McLean said:

<snip>
It is possible,
though rather difficult, to implement a safe gets(), that is to say one
that always terminates the program with an error message if the buffer is
exceeded.
Show me.
What is not possible to is implement is a safe fgets(), that is to say,
one that can be used safely given the limitations of the average human
programmer.
The fgets function is very easy to use safely.

--
Richard Heathfield <http://www.cpax.org.uk>
Email: -http://www. +rjh@
Google users: <http://www.cpax.org.uk/prg/writings/googly.php>
"Usenet is a strange place" - dmr 29 July 1999
Nov 16 '07 #23
In article <sl*******************@nospam.com>, CJ <no****@nospam.comwrote:
>On 16 Nov 2007 at 20:47, ja*********@verizon.net wrote:
>It's trivial to replace any call to gets() with a similar call to
fgets() with minor modifications to the surrounding code, and that
change is sufficient to completely avoid the buffer overruns. I don't
know of any legitimate reason for not doing so.

It's much more typing!
If that's what you're worried about, why aren't you using Perl?
dave

Nov 16 '07 #24

"Richard Heathfield" <rj*@see.sig.invalidwrote in message
>It is possible,
though rather difficult, to implement a safe gets(), that is to say one
that always terminates the program with an error message if the buffer is
exceeded.

Show me.
We'll declare that pointer cosist of three values - the address, the start
of the object, and the end of the object.
Now in the write to array code we specify that if the address execceds the
end of the object, the program is to terminate with an error meaage.

With this device we have a perfectly safe gets() fucntion. It cannot return
an incorrect string, or corrupt another variable, or put little elves on
screen. It can only fill the buffer correctly or report that it has been
exceeded.
>
>What is not possible to is implement is a safe fgets(), that is to say,
one that can be used safely given the limitations of the average human
programmer.

The fgets function is very easy to use safely.
Time after time it has been shown that this is not the case. Very often
people treat incomplete reads as full lines. So if the line contains a drug
dose your fgets() - enabled machine might deliver only one tenth of the
amount needed, given an off by one line length error.
--
Free games and programming goodies.
http://www.personal.leeds.ac.uk/~bgy1mm

Nov 16 '07 #25
Malcolm McLean said:
>
"Richard Heathfield" <rj*@see.sig.invalidwrote in message
>>It is possible,
though rather difficult, to implement a safe gets(), that is to say one
that always terminates the program with an error message if the buffer
is exceeded.

Show me.
We'll declare that pointer cosist of three values - the address, the
start of the object, and the end of the object.
I look forward to your reference implementation.

<snip>
>>What is not possible to is implement is a safe fgets(), that is to say,
one that can be used safely given the limitations of the average human
programmer.

The fgets function is very easy to use safely.
Time after time it has been shown that this is not the case.
You can misuse *anything* if you try hard enough. You have to try
reasonably hard to misuse fgets, whereas to misuse gets you only need call
it.
Very often
people treat incomplete reads as full lines.
Very often people drive at 40 in a 30. That does not mean it is difficult
to drive at 30.

--
Richard Heathfield <http://www.cpax.org.uk>
Email: -http://www. +rjh@
Google users: <http://www.cpax.org.uk/prg/writings/googly.php>
"Usenet is a strange place" - dmr 29 July 1999
Nov 16 '07 #26
On Fri, 16 Nov 2007 23:19:12 +0000, Malcolm McLean wrote:
"Richard Heathfield" <rj*@see.sig.invalidwrote in message
>>It is possible,
though rather difficult, to implement a safe gets(), that is to say
one that always terminates the program with an error message if the
buffer is exceeded.

Show me.
We'll declare that pointer cosist of three values - the address, the
start of the object, and the end of the object.
So, in

struct S {
char c[10];
int i;
} s;

does a pointer to s.c store the end as &s.c[10]? Or does it store the end
as &s + 1? If the former, there are cases where it's simply not clear at
all where the buffer ends. If the latter, it doesn't prevent writing past
the end of the buffer.

I do agree that bounded pointers would be useful, but C being what it is,
I don't believe it's possible to make it completely safe.
Nov 16 '07 #27
"Harald van Dijk" <tr*****@gmail.comwrote in message
On Fri, 16 Nov 2007 23:19:12 +0000, Malcolm McLean wrote:
>"Richard Heathfield" <rj*@see.sig.invalidwrote in message
>>>It is possible,
though rather difficult, to implement a safe gets(), that is to say
one that always terminates the program with an error message if the
buffer is exceeded.

Show me.
We'll declare that pointer cosist of three values - the address, the
start of the object, and the end of the object.

So, in

struct S {
char c[10];
int i;
} s;

does a pointer to s.c store the end as &s.c[10]? Or does it store the end
as &s + 1? If the former, there are cases where it's simply not clear at
all where the buffer ends. If the latter, it doesn't prevent writing past
the end of the buffer.
A pointer to s.c would have to store the end as &s.c[10].
It is illegal to convert from a struct S * to a char *, except in the niggly
case of a char or char array being the first member, in which case it must
have the same address as the whole struct. So the compiler does in fact have
to be very clever.

however char *ptr = (char *) (void *) &s;

is I think still illegal. So you cannot defeat the system with a intricate
list of void * intermediates.
--
Free games and programming goodies.
http://www.personal.leeds.ac.uk/~bgy1mm

Nov 17 '07 #28
On Sat, 17 Nov 2007 00:28:43 +0000, Malcolm McLean wrote:
"Harald van Dijk" <tr*****@gmail.comwrote in message
>On Fri, 16 Nov 2007 23:19:12 +0000, Malcolm McLean wrote:
>>"Richard Heathfield" <rj*@see.sig.invalidwrote in message
It is possible,
though rather difficult, to implement a safe gets(), that is to say
one that always terminates the program with an error message if the
buffer is exceeded.

Show me.

We'll declare that pointer cosist of three values - the address, the
start of the object, and the end of the object.

So, in

struct S {
char c[10];
int i;
} s;

does a pointer to s.c store the end as &s.c[10]? Or does it store the
end as &s + 1? If the former, there are cases where it's simply not
clear at all where the buffer ends. If the latter, it doesn't prevent
writing past the end of the buffer.
A pointer to s.c would have to store the end as &s.c[10].
Okay, so then you can't get back the original &s?

struct S {
char c[10];
int i;
} s[2];

char *p = &s[1].c[0];

The range for p would be &s[1].c[0] through &s[1].c[10], but I don't
believe there's anything non-standard about casting p to struct S *, and
subtracting 1. (With a stricter reading of the standard, you might need
to cast p to char(*)[10], and only then to struct S, but this doesn't
change anything important.)
It is illegal
to convert from a struct S * to a char *,
It's allowed for two reasons here. Firstly, *any* object can be addressed
as an array of char. Given int i, ((char *) &i) through (char *) &i +
sizeof i are all valid pointers. Given struct S s, (char *) &s + sizeof s
are all valid pointers. The second reason you mention below.
except in the niggly case of a
char or char array being the first member, in which case it must have
the same address as the whole struct. So the compiler does in fact have
to be very clever.
It has to be able to construct data that is no longer available.
however char *ptr = (char *) (void *) &s;

is I think still illegal. So you cannot defeat the system with a
intricate list of void * intermediates.
Well, this specific example is legal, but I think I get the point you're
making here, and I agreed already that bounded pointers, even while not
perfect, are useful.
Nov 17 '07 #29
jacob navia wrote:
Keith Thompson wrote:
[...]
>I'm afraid that gets() is going to be around for a very long time.
It's still up to each of us, as programmers, to avoid using it.

jacob, if you really thing gets() will "disappear shortly", I'd be
interested in your reasoning.

Nothing, just hopes that now that is deprecated, people will
stop using it, and it will disappear in a few years.
Alas, hoping won't make it happen. As I said, any implementation that
claims to conform to any C standard, up to and including C99, *must*
provide gets().

--
Keith Thompson (The_Other_Keith) <ks***@mib.org>
Looking for software development work in the San Diego area.
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Nov 17 '07 #30

CJ <no****@nospam.comwrote in message
news:sl*******************@nospam.com...
On 16 Nov 2007 at 20:47, ja*********@verizon.net wrote:

It's trivial to replace any call to gets() with a similar call to
fgets() with minor modifications to the surrounding code, and that
change is sufficient to completely avoid the buffer overruns. I don't
know of any legitimate reason for not doing so.

It's much more typing!
Leading to increased carpal tunnel syndrome!

Here's how to avoid some of the typing:

#define GET_INPUT_STRING(string_array) \
get_input_string(string_array,sizeof(string_array) )

char *get_input_string(char *string_array,int array_size) {
int string_size;

GetInput :

fgets(string_array,array_size,stdin);

string_size=strlen(string_array);

if(string_array[string_size-1]!='\n') {
fflush(stdin); /* NOT PORTABLE!!! */
printf
("\nCAUTION: input too long, should be less than %d characters",
array_size);
printf("\nTry again: ");
goto GetInput;
}

else string_array[string_size-1]='\0';

return string_array;
}

Stick that in a little library that you link into all the programs that
require getting standard input (along with some automatic menu
generation routines, etc.), and if GET_INPUT_STRING is too much
typing you can just call it GIS() or something. The only problems
are: 1) you could wind up in an endless user idiocy loop, but it
beats crashing your program when the same idiot types too much
stuff into gets(), and 2) the fflush(stdin) works for my compiler but
of course is not guaranteed for yours...

---
William Ernest Reid

Nov 17 '07 #31
"Harald van Dijk" <tr*****@gmail.comwrote in message
>
>It is illegal
to convert from a struct S * to a char *,

It's allowed for two reasons here. Firstly, *any* object can be addressed
as an array of char. Given int i, ((char *) &i) through (char *) &i +
sizeof i are all valid pointers. Given struct S s, (char *) &s + sizeof s
are all valid pointers. The second reason you mention below.
I nodded. Yes, it is illegal to convert from type x * to type y *, except

when x or y is void.
when y is unsigned char - char yes and no, you may trap when you dereference
the pointer.
when y is the first member of a struct of type x.
when y is a struct of which x is the first member.
>
[ problem is ]
struct S s[2];
char *ptr = &s1.firstmember;
struct S *ptr2 = (struct S *) ptr;
ptr2--;
>
It has to be able to construct data that is no longer available.
I think you have managed to defeat it using the last rule. We can give the
ptr2 the bounds of s[1], not easily but not with too many problems. However
it is virtually impossible to give it the bounds of s. You'd have to store a
fourth pointer with every pointer giving the "mother" object. It becomes
totally unwieldy.

--
Free games and programming goodies.
http://www.personal.leeds.ac.uk/~bgy1mm

Nov 17 '07 #32
Malcolm McLean wrote, On 16/11/07 23:19:
>
"Richard Heathfield" <rj*@see.sig.invalidwrote in message
>>It is possible,
though rather difficult, to implement a safe gets(), that is to say one
that always terminates the program with an error message if the
buffer is
exceeded.

Show me.
We'll declare that pointer cosist of three values - the address, the
start of the object, and the end of the object.
Now in the write to array code we specify that if the address execceds
the end of the object, the program is to terminate with an error meaage.

With this device we have a perfectly safe gets() fucntion. It cannot
return an incorrect string, or corrupt another variable, or put little
elves on screen. It can only fill the buffer correctly or report that it
has been exceeded.
However, unless you manage to get all hosted C implementations changed
to use this it is *still* not safe to call gets because your code might
be ported to an implementation that does not do this.
>>What is not possible to is implement is a safe fgets(), that is to say,
one that can be used safely given the limitations of the average human
programmer.

The fgets function is very easy to use safely.
Time after time it has been shown that this is not the case. Very often
people treat incomplete reads as full lines. So if the line contains a
drug dose your fgets() - enabled machine might deliver only one tenth of
the amount needed, given an off by one line length error.
As pointed out the last time you raised this example:
1) It would get spotted in a properly performed code review
2) It would get caught by properly done testing

So it would not hit production like that. Input validation is one of the
basics of safety-critical programming, it is even one of the basics in
writing SW for non-critical test equipment!

In any case, that people can use a function incorrectly does not mean it
cannot be used correctly easily.

Now let us take your use of gets with an implementation guaranteed to
abort the program in to a similar situation...

The drug dispenser reads a file on a regular basis to check what it
should be dispensing. At 3AM it come across an over-length line and the
program abort. The patient then does not get the drugs keeping him/her
alive and dies.

So by using a "safe" gets you have just made it impossible to safely
handle out-of-range input whereas it is easy to do with fgets.
--
Flash Gordon
Nov 17 '07 #33
jayapal wrote:
>
Whenever I use the gets() function, the gnu c compiler gives a
warning that it is dangerous to use gets(). why...?
Because it cannot be used safely. There is no length control. Two
possible replacements for it are fgets() (a C standard function)
and ggets() (a non-standard function). ggets is available in
source form, with no restrictions, as ggets.zip at:

<http://cbfalconer.home.att.net/download/>

--
Chuck F (cbfalconer at maineline dot net)
<http://cbfalconer.home.att.net>
Try the download section.

--
Posted via a free Usenet account from http://www.teranews.com

Nov 17 '07 #34
Malcolm McLean wrote:
>
.... snip ...
>
Undefined behaviour means "undefined by the standard". It is
possible, though rather difficult, to implement a safe gets(),
that is to say one that always terminates the program with an
error message if the buffer is exceeded.
Consider yourself challenged to post the appropriate code, in
standard C.

--
Chuck F (cbfalconer at maineline dot net)
<http://cbfalconer.home.att.net>
Try the download section.

--
Posted via a free Usenet account from http://www.teranews.com

Nov 17 '07 #35
Malcolm McLean wrote:
"Richard Heathfield" <rj*@see.sig.invalidwrote:
>>It is possible, though rather difficult, to implement a safe
gets(), that is to say one that always terminates the program
with an error message if the buffer is exceeded.

Show me.

We'll declare that pointer cosist of three values - the address,
the start of the object, and the end of the object. Now in the
write to array code we specify that if the address execceds the
end of the object, the program is to terminate with an error
meaage.
No good. Pointers do not necessarily contain those components.
You have to make it safe within the guarantees provided by the C
standard.

--
Chuck F (cbfalconer at maineline dot net)
<http://cbfalconer.home.att.net>
Try the download section.

--
Posted via a free Usenet account from http://www.teranews.com

Nov 17 '07 #36
On Fri, 16 Nov 2007 19:56:39 -0500, CBFalconer wrote:
Malcolm McLean wrote:
>>
... snip ...
>>
Undefined behaviour means "undefined by the standard". It is possible,
though rather difficult, to implement a safe gets(), that is to say one
that always terminates the program with an error message if the buffer
is exceeded.

Consider yourself challenged to post the appropriate code, in standard
C.
gets is a standard library function. Standard library functions need not
be written in standard C, and may make use of highly implementation-
specific features.

If you disagree, please give even just a single example of an
implementation of fopen or longjmp written purely in standard C.
Nov 17 '07 #37
CBFalconer wrote:
Malcolm McLean wrote:
>"Richard Heathfield" <rj*@see.sig.invalidwrote:
>>>It is possible, though rather difficult, to implement a safe
gets(), that is to say one that always terminates the program
with an error message if the buffer is exceeded.
Show me.
We'll declare that pointer cosist of three values - the address,
the start of the object, and the end of the object. Now in the
write to array code we specify that if the address execceds the
end of the object, the program is to terminate with an error
meaage.

No good. Pointers do not necessarily contain those components.
You have to make it safe within the guarantees provided by the C
standard.
No, he doesn't. You're asking for more than Malcolm claimed.

Malcolm didn't claim that it could be made safe within the gaurantees
provided by the C standard. His claim is a much more modest one,
that it's possible for a (hypothetical) C implementation to provide a
"safe" gets() function, and I believe he's correct.

His solution requires the use of "fat pointers", which are not
widely implemented but are reasonably well understood. In such an
implementation, the char* parameter to gets() provides information
about the size of the buffer to which it points. (Portable C code
cannot make use of this information, but gets() needn't be implemented
in portable C.) If the size of the input line exceeds the size of the
buffer, the behavior is undefined. This means the implementation is
free to do whatever it likes, including terminating the program with
an error message (or discarding the remainder of the line, or leaving
the remainder of the line on the input stream).

I know of no C implementations that actually use fat pointers; even if
there were, the possibility of making gets() safe in one implementation
does no good for code that is to be used with other implementations.

I believe Malcolm's claim as stated is correct. It's not particularly
useful, but he didn't claim that it was; I believe it was merely an
intellectual excercise, not a serious proposal.
--
Keith Thompson (The_Other_Keith) <ks***@mib.org>
Looking for software development work in the San Diego area.
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Nov 17 '07 #38
Harald van Dijk writes:
>Sat, 17 Nov 2007 00:28:43 +0000, Malcolm McLean wrote:
>>>We'll declare that pointer cosist of three values - the address, the
start of the object, and the end of the object.
(..)
struct S {
char c[10];
int i;
} s;
(...)
A pointer to s.c would have to store the end as &s.c[10].

Okay, so then you can't get back the original &s?
If I remember correctly, (struct S *)s.c is indeed undefined. Or it
is defined but ((struct S *)s.c)->i and (struct S *)s.c + 1 are not.
Probably for similar reasons that the 'struct hack' is undefined.

--
Regards,
Hallvard
Nov 17 '07 #39
On Sat, 17 Nov 2007 23:21:19 +0100, Hallvard B Furuseth wrote:
Harald van Dijk writes:
>>Sat, 17 Nov 2007 00:28:43 +0000, Malcolm McLean wrote:
>>>>We'll declare that pointer cosist of three values - the address, the
start of the object, and the end of the object.
(..)
struct S {
char c[10];
int i;
} s;
(...)
A pointer to s.c would have to store the end as &s.c[10].

Okay, so then you can't get back the original &s?

If I remember correctly, (struct S *)s.c is indeed undefined. Or it is
defined but ((struct S *)s.c)->i and (struct S *)s.c + 1 are not.
Probably for similar reasons that the 'struct hack' is undefined.
Quoting from 6.7.2.1p13:
"A pointer to a structure object, suitably converted, points to its
initial member (or if that member is a bit-field, then to the unit in
which it resides), and vice versa."

The "and vice versa" means that a pointer to the initial member of a
structure can be converted back to a pointer to that structure object,
does it not? Technically, the initial member of the structure is an array
of char, not a char, but I believe I addressed that in my previous
message.
Nov 17 '07 #40

"Flash Gordon" <sp**@flash-gordon.me.ukwrote in message
The drug dispenser reads a file on a regular basis to check what it should
be dispensing. At 3AM it come across an over-length line and the program
abort. The patient then does not get the drugs keeping him/her alive and
dies.

So by using a "safe" gets you have just made it impossible to safely
handle out-of-range input whereas it is easy to do with fgets.
The computer blows a fuse. The patient dies. No different to aborting with
an error message. All safety critical systems have to consider the
possibility of components failing. As long as they fail, it should be OK.
The danger comes when they work wrongly.

--
Free games and programming goodies.
http://www.personal.leeds.ac.uk/~bgy1mm

Nov 17 '07 #41
Malcolm McLean wrote, On 17/11/07 23:11:
>
"Flash Gordon" <sp**@flash-gordon.me.ukwrote in message
>The drug dispenser reads a file on a regular basis to check what it
should be dispensing. At 3AM it come across an over-length line and
the program abort. The patient then does not get the drugs keeping
him/her alive and dies.

So by using a "safe" gets you have just made it impossible to safely
handle out-of-range input whereas it is easy to do with fgets.
The computer blows a fuse. The patient dies. No different to aborting
with an error message.
The big difference is that one can easily be avoided in SW by the simple
expedient of ignoring your advice and using fgets instead of gets.
All safety critical systems have to consider the
possibility of components failing.
They also have to minimise the probability of any given component
failing. Part of doing this is doing your best to avoid the SW failing,
and part of that is using not using gets, another part is testing
out-of-bounds input which will catch incorrect usage of fgets.
As long as they fail, it should be
OK. The danger comes when they work wrongly.
Which is an excellent reason for not using gets.

I assume that as you did not object to my points about fgets being safe
to use in a safety critical application you agree that it is safe? If
not why did you snip my points without addressing them?
--
Flash Gordon
Nov 18 '07 #42
jayapal wrote:
John Gordon <gor...@panix.comwrote:
>gets() does not allow you limit the amount of input, which means it
can potentially overflow the buffer into which the input is placed.

Can u explain the differences b/w the scanf() and gets() ..?
u hasn't posted here for some time. And black is basically the
lack of illumination, while white requires illumination. That
handles b/w. scanf() and gets() are specified in the C standard.

--
Chuck F (cbfalconer at maineline dot net)
<http://cbfalconer.home.att.net>
Try the download section.
--
Posted via a free Usenet account from http://www.teranews.com

Nov 18 '07 #43
$)CHarald van D)&k wrote:
On Fri, 16 Nov 2007 19:56:39 -0500, CBFalconer wrote:
>Malcolm McLean wrote:
>>>
... snip ...
>>>
Undefined behaviour means "undefined by the standard". It is
possible, though rather difficult, to implement a safe gets(),
that is to say one that always terminates the program with an
error message if the buffer is exceeded.

Consider yourself challenged to post the appropriate code, in
standard C.

gets is a standard library function. Standard library functions
need not be written in standard C, and may make use of highly
implementation-specific features.

If you disagree, please give even just a single example of an
implementation of fopen or longjmp written purely in standard C.
Need not, not must not. gets() (and any replacement) can be
written in standard C and fully satisfy all the specifications. As
evidenced by my ggets() and others.

I wish the library had been divided into things implementable
within the language, and things requiring extensions. Although
actually doing it might have been a horrendous task, and it is now
too late to try.

--
Chuck F (cbfalconer at maineline dot net)
<http://cbfalconer.home.att.net>
Try the download section.

--
Posted via a free Usenet account from http://www.teranews.com

Nov 18 '07 #44

"CBFalconer" <cb********@yahoo.comwrote in message
Need not, not must not. gets() (and any replacement) can be
written in standard C and fully satisfy all the specifications. As
evidenced by my ggets() and others.
On top of fgetc().
>
I wish the library had been divided into things implementable
within the language, and things requiring extensions. Although
actually doing it might have been a horrendous task, and it is now
too late to try.
The standard library fits into a small book. I don't think it would take
more than a few minutes to go through ticking each one.

assert (portable)
the isxxxx character macros (portable*)
tolower (portable*)
toupper (portable*)
math.h functions (portable but)
setjmp (compiler-specific)
longjmp (compiler-specific)
stdarg,h (compiler-specific)
stdio.h - all functions that take a FILE parameter need system calls, as do
those whicht ake an implicit stdin / stdout.
sprintf, vsprintf - (portable with one niggle)
remove, rename, tmpname - (system call)
tmpfile - interesting one. Needs either a malloc(0 call or access tot he
filesystem.
atof, atoi, atol, strtod, strtol, strtoul (portable)
rand, srand (portable)
malloc family (in reality system, but theoretically portable except for a
niggle)
abort, exit (system / compiler-specific|)
atexit - (portable)
system - (system)
getenv - (system)
bsearch, qsort - (portable)
abs, labs - (portable)
div, ldiv - (anyone heard of these? compiler-specific)
string functions - (portable, in reality compiler-specific)
clock - (system)
time - (system)
difftime, mktime, ctime, gmtime, localtime, strftime - (portable as logn as
you know the internal time structure)

There, more or less done it.

The problem is the division doesn't really work. sqrt() was originally a
portable function. Now most larger machines have dedicated root-finding
hardware, which in practise you must use.
tolower and toupper, and the isxxxx macros can be written in C, but to
implement with any efficiency you need to know the execution character
encoding.
Some functions, like longjmp(), do not need to make system calls, but cannot
be implemented without an intimate knowledge of the compiler. sprinf() can
be written completely portably, except for the %p field. The string
functions can be portable, in reality you'd want to take advantage of the
alignment. malloc() realistically needs a system call on all but the
smallest machines that run only one program, but you can write using a
global arena, except that there is no cast iron way of ensuring correct
alignment in portable C.

--
Free games and programming goodies.
http://www.personal.leeds.ac.uk/~bgy1mm

Nov 18 '07 #45
"Richard Heathfield" <rj*@see.sig.invalidwrote in message
Keith Thompson said:
>Programmers don't really
need to know how standard library functions are implemented, or at least
shouldn't depend on such knowledge.

Precisely my point. And yet they would have to depend on such knowledge >
if they wished to use the proposed "safe gets".
You mean to say that you don't trust your compiler vendor to provide a safe
function, if such can be implemented?

--
Free games and programming goodies.
http://www.personal.leeds.ac.uk/~bgy1mm
Nov 18 '07 #46
Keith Thompson wrote:
CBFalconer wrote:
.... snip ...
>
>I wish the library had been divided into things implementable
within the language, and things requiring extensions. Although
actually doing it might have been a horrendous task, and it is
now too late to try.

What would be the benefit of this division? Programmers don't
really need to know how standard library functions are implemented,
or at least shouldn't depend on such knowledge. Implementers can
figure out easily enough which functions can be implemented in
standard C, but are allowed to use non-standard C for greater
efficiency, or for any other reason.
Oh? Then why the frantic efforts right here on c.l.c to implement
sizeof? To cast pointers to integers? etc. Some of these
'possibilities' have fairly subtle impediments.

--
Chuck F (cbfalconer at maineline dot net)
<http://cbfalconer.home.att.net>
Try the download section.

--
Posted via a free Usenet account from http://www.teranews.com

Nov 18 '07 #47
Malcolm McLean wrote:
"Richard Heathfield" <rj*@see.sig.invalidwrote in message
>Keith Thompson said:
>>Programmers don't really
need to know how standard library functions are implemented, or at least
shouldn't depend on such knowledge.

Precisely my point. And yet they would have to depend on such
knowledge if they wished to use the proposed "safe gets".
You mean to say that you don't trust your compiler vendor to provide a
safe function, if such can be implemented?
Implementing a safe gets() would require "fat pointers", which would
have substantial performance effects on the entire implementation
(unless there's hardware support). A "safe" gets() is theoretically
possible, but not realistic. I trust my compiler vendor to be aware of
that -- and I trust myself not to use gets() in the first place.

--
Keith Thompson (The_Other_Keith) <ks***@mib.org>
Looking for software development work in the San Diego area.
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Nov 18 '07 #48
In article <47**************@yahoo.com>,
CBFalconer <cb********@maineline.netwrote:
>Oh? Then why the frantic efforts right here on c.l.c to implement
sizeof?
As far as I can tell, most recent questions about this seem to be the
result of one particular C programming course, in India.

-- Richard
--
"Consideration shall be given to the need for as many as 32 characters
in some alphabets" - X3.4, 1963.
Nov 18 '07 #49
CBFalconer wrote:
Keith Thompson wrote:
>CBFalconer wrote:
... snip ...
>>I wish the library had been divided into things implementable
within the language, and things requiring extensions. Although
actually doing it might have been a horrendous task, and it is
now too late to try.
What would be the benefit of this division? Programmers don't
really need to know how standard library functions are implemented,
or at least shouldn't depend on such knowledge. Implementers can
figure out easily enough which functions can be implemented in
standard C, but are allowed to use non-standard C for greater
efficiency, or for any other reason.

Oh? Then why the frantic efforts right here on c.l.c to implement
sizeof? To cast pointers to integers? etc. Some of these
'possibilities' have fairly subtle impediments.
Um, what does trying to re-implement the sizeof operator (which is a
fairly useless thing to do) have to do with implementing standard
library functions?

Sure, there are subtleties in the implementation of standard library
functions. I just don't see how dividing them as you suggest is helpful
or relevant.

What problem would such a division solve?

--
Keith Thompson (The_Other_Keith) <ks***@mib.org>
Looking for software development work in the San Diego area.
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Nov 18 '07 #50

This discussion thread is closed

Replies have been disabled for this discussion.

By using this site, you agree to our Privacy Policy and Terms of Use.