Why is it dangerous?

R

Richard

Nick Keighley said:
hardly. Much web based software does not have total control
of its inputs. Compilers don't have TCOI. Even if the other end of

The dont use gets in this case.

You seem to think I am advocating it when the input is not DEFINED. I am
not.
 
B

Barry Schwarz

This is a hardy annual.
Of course fgets() can be used safely, but won't be. For instance Richard
Heathfield posted a dangerous use of fgets() in this very thread. It will
give the wrong answer if the user enters a string of over 2000 characters.

Any code that does not check the status of "service requests" is
dangerous. But this is a result of sloppy programming. It is not an
inherent property of the request itself as a call to gets() is.
Of course it is not dangerous in a little exercise program that doesn't do
anything, but then neither is gets().

I guess on your system undefined behavior can never do any harm.
To use fgets() safely you must check for the newline. If it is not present a
buffer overflow occurred. So you must then take action against the buffer to

Actually, a buffer overflow was prevented.
ensure that the next read doesn't get the remainder of the previous line.

The recommended action should be either:

Whatever the program needs to do to obtain the remainder of
the line so the input can be processed as intended .

Reject the input with appropriate notification to the user and
suitable follow-on action
 
S

santosh

Antoninus said:
CBFalconer said:
Correction: That omits many useful tests. I suggest:
gcc -W -Wall -ansi -pedantic
for better error detection.

I would also recommend:
[...]
-Wpointer-arith

This is redundant, since it's already enabled by -pedantic.

This is not mentioned in my gcc documentation. Looking it up on the
Web... yes I see you're right. Must have been added recently.
 
S

santosh

Malcolm said:
if I enter

"My name is Rumplewumple ... stiltskin"
and the program comes back

"You entered My name is Rumplewumple ... stilt"

Then I might well object that that's my cousin. Which is potentially
dangerous, depending on what the program is being used for.

If the integrity of your data is valuable, you have to program
carefully. Simple isn't it. In such situations using fgets()
simplistically is not good enough, but it's still *better* than gets.
It's a question of getting data a little wrong or overrunning buffers
with *any* consequences from an immediate crash (lucky you) to altering
valuable data elsewhere.

There is no debate whether gets or fgets is safer. The latter is
*always* the safer option. If you want a line getting function with the
interface of gets, then it's easy enough to write your own.
 
S

santosh

Antoninus said:
True. The world might also be destroyed in a nuclear holocaust while
your throwaway program is reading its non-life-critical data, so why
take the risk of programming at all? Drink a beer, get laid, and wait
for the mushroom cloud to take you.

I'd use fgets even for a "throwaway" program because it's really as easy
to use and I won't have to worry about carefully deleting the sources
later.
 
C

CBFalconer

Malcolm said:
.... snip ...

if I enter
"My name is Rumplewumple ... stiltskin"
and the program comes back
"You entered My name is Rumplewumple ... stilt"

Then I might well object that that's my cousin. Which is potentially
dangerous, depending on what the program is being used for.

If that happens you have made an error in writing the program. It
is simple to avoid any such result while using fgets.
 
B

Ben Bacarisse

CBFalconer said:
santosh said:
Harald said:
santosh wrote:
CBFalconer wrote:

Correction: That omits many useful tests. I suggest:

gcc -W -Wall -ansi -pedantic

for better error detection.

I would also recommend:
[...]
-Wwrite-strings

I would not, since it deliberately makes the compiler nonconforming.
For those that understand in what ways, it can be useful, but they
can find the option themselves. CBFalconer included that option in
his recommendations recently, and I'm glad he dropped it.

Thanks for that. I do remember that subthread now, but I passed over
it, being pressed for time. Now, to the Google Groups archive...

I didn't drop it. I conceded your 'non-standard' point. I
maintain that, for new code, including it will result in better
code, and maintain conformity. It may object to some actually
conforming code.

So it seems you did not accept *my* point of a program that requires a
diagnostic which -Wwrite-strings suppresses.
 
C

CBFalconer

Ben said:
.... snip ...


So it seems you did not accept *my* point of a program that
requires a diagnostic which -Wwrite-strings suppresses.

No. I consider the chance of a complex program trying to write to
a non-writable string is more likely than the case you brought up
(which I have absent-mindedly forgotten). And, if I need it, I am
quite capable of remove -Wwrite-strings from the command for a
particular compilation.
 
D

Doug Miller

Any code that does not check the status of "service requests" is
dangerous. But this is a result of sloppy programming. It is not an
inherent property of the request itself as a call to gets() is.

Since gets() returns the same indication both when the input overflows the
buffer allocated for it, and when it doesn't -- thus necessarily precluding
the possibility of any such status check -- it could be argued that the use of
gets() constitutes "sloppy programming" in and of itself.
I guess on your system undefined behavior can never do any harm.


Actually, a buffer overflow was prevented.


The recommended action should be either:

Whatever the program needs to do to obtain the remainder of
the line so the input can be processed as intended .

Reject the input with appropriate notification to the user and
suitable follow-on action
Exactly so.
 
C

CBFalconer

santosh said:
Antoninus said:
santosh said:
CBFalconer wrote:

Correction: That omits many useful tests. I suggest:
gcc -W -Wall -ansi -pedantic
for better error detection.

I would also recommend:
[...]
-Wpointer-arith

This is redundant, since it's already enabled by -pedantic.

This is not mentioned in my gcc documentation. Looking it up on the
Web... yes I see you're right. Must have been added recently.

I am running gcc 3.2.1, dated 2002, and that option is available.
 
B

Ben Bacarisse

CBFalconer said:
No. I consider the chance of a complex program trying to write to
a non-writable string is more likely than the case you brought up
(which I have absent-mindedly forgotten). And, if I need it, I am
quite capable of remove -Wwrite-strings from the command for a
particular compilation.

I think we have crossed wires. I use that option. I think it useful
and I know you can remove it when you need to (as I can). It is just
that you seemed to be suggesting that it did not break conformity,
only that it objected to some conforming code. People (particularly
learners) should know that it silently allows some programs though
that should have a constraint diagnosed.
 
K

Keith Thompson

CBFalconer said:
santosh said:
Antoninus said:
santosh wrote:
CBFalconer wrote:

Correction: That omits many useful tests. I suggest:
gcc -W -Wall -ansi -pedantic
for better error detection.

I would also recommend:
[...]
-Wpointer-arith

This is redundant, since it's already enabled by -pedantic.

This is not mentioned in my gcc documentation. Looking it up on the
Web... yes I see you're right. Must have been added recently.

I am running gcc 3.2.1, dated 2002, and that option is available.

The question wasn't whether it's available, it was whether
"-Wpointer-arith" is enabled by "-pedantic".

In any case, it would be a good question for gnu.gcc.help.
 
J

James Dow Allen

a_03.c:(.text+0x4d): warning: the `gets' function is dangerous
and should [never] be used.
...
Of course, this is nonsense. There is a perfectly safe way to use
gets(), namely by being in control of what appears on stdin.

Heresy! I'm surprised no one launched a diatribe here
against Mr. Twink, so let me offer a diatribe in support!


Six comments on gets().


First, some history. (Some c.l.c'ers weren't
even alive at the time of the infamous Internet
Worm.)

The infamous worm was complex enough to attempt
exploitation of at least 4 different security loopholes,
but just one of the loopholes was ubiquitous enough
to make it necessary and sufficient for the Worm's
"success." That loophole was the dangerous use
of gets() in a program (fingerd) usually run with
superuser authority. It was the exploits of the
Internet Worm that led to the deprecations against
gets(). (The exploiter, IIRC, wasn't a larcenous
"black hat", but rather a "gray hat" who deliberately
aroused the Unix community from its apathy about
such bugs.)

The fingerd->gets() exploit was not trivial.
The overrun buffer was an automatic variable just
below a procedure frame, whose return-address was
modified to point to executable code within the overrun
buffer. That code loaded and ran another program
(misnamed 'sh' or 'csh') which, among other things,
executed the 'fake finger' program to exploit the
fingerd->gets() bug on still other machines.

The detailed steps of this exploit get elided in the
retelling, and programmers are left with the take-home
lesson: use gets() and the Russian mob will take
over your machine and the rest of the world.
One doesn't have to be a gets() enthusiast to note
fingerd's special nature, and that the claim that
all gets() usage risks catastrophe is confused.


Second, a confession.

Whenever I build the Index to the Fabulous Pedigree
http://fabpedigree.com/altix.htm
I do several hundred thousand gets()'s, but none of
them are "dangerous". I live with a few "dangerous"
messages during the build (although I'm sure the pedants
would prefer that each of the several hundred thousand
gets()'s produced its own such message. :)
Perhaps there's a way to disable gcc's "dangerous"
message but, in keeping with the FSF philosophy, I'm
sure the cure is worse than the disease, something like
setenv IM_AN_UNREPENTANT_MORONIC_ASSHOLE


Third, a boast:

Since another of my "eccentric" codings, in private
throw-away code, is to *not* test malloc()'s return for
zero (failure leads to a core dump, which is what I want
anyway(*)), I'm sure that many in this ng believe that
James Dow Allen's code is buggy! I do not believe
this is the case. When I was rehired after a year to
add new support to a complete OS I wrote as a contractor
I was pleased to note that no changes had been found
necessary to my delivered code. Code reliability
doesn't require ingenuity (indeed the two may be
inversely related!); it requires conscientiousness
and avoiding the cheap substitution of dogma for thought.

AFAIK, I've never used gets() in code I've delivered
to a customer. (This is partly because most of my delivered
code has been OS or standalone, with any stdio library
calls unavailable.) I do use gets() sometimes, on
private code, when the gets()'ed string was itself
machine-produced. The gets() buffer is usually at least
ten times as large as the longest machine-produced
string. The executables are protected from the
Internet by an Impenetrable Firewall. If someone does
break into my house, intending computer mischief,
I'd be surprised if his mischief needed to invoke gets().

The gets() deprecators aren't wrong; indeed I'll cheerfully
concede that their position is more defensible than mine!
But I'm happy to take a Devil's Advocate position to
encourage critical thinking when I see the preposterous and
dogmatic over-generalizations which become so routine in
this ng. Is gets() a *potential* source of bugs? Obviously.
But I'd love to organize a wager, between me and one of
the pedants, on whose code contains more *actual* bugs.

* - Detractors will argue that what I *should* want to
do is spend hours writing a diagnostic for such malloc()
failures! In fact I don't want to do anything about them
since the smallish malloc()'s I use to build the website
Aren't Going To Fail(tm). (The pedants will respond to
this with some nonsense about how the website building
may be ported, some day, to the limited-memory chip
inside my car's fuel injection system !)


Fourth, a peeve:

fgets() preserves LineFeeds, gets() discards them.
Either behavior is fine (an application whose
stringency requires special treatment of an
"unterminated last line" probably will avoid
fgets() for other reasons anyway), but similarly-named
functions *SHOULD BEHAVE SIMILARLY*.
Assuming gets() came first and it was too late to
redefine it, fgets() should have either handled LineFeeds
the same, or have been given an obviously different name.
Whoever created the disparity in these similarly-named
functions should have done to him what Jesse J. secretly
claimed to want to do to Obama.

I *might* have changed from gets() to fgets() on some
of my private code if it weren't for the above nit.
(And yes, I *do* know how to do
if (*s == '\n') *s = 0;
in C.)


Fifth, an oft-overlooked truism:

Programming (and much real-world activity) involves
compromise between thoroughness and convenience.
strncpy(), for example, can do everything(*) strcpy()
can do, *except*, when properly coded, overrun a buffer.
In other words, the *only* reason to ever use strcpy()
(besides deliberately creating a security loophole!)
is the convenience of a 2-argument function call compared
with a 3-argument call. (* -- yes, strcpy() doesn't
null-pad. Any c.l.c'er ever write code that relied
on the *non*-padding?)

Thoroughness is not wrong, *BUT YOU SHOULD SPEND YOUR
THOROUGHNESS WISELY*. The original Hubbell Telescope
program spent $10,000 studying whether or not to do a
$3 Million test. Meanwhile the flaw, that showed up
post-launch, could have been found with a simple $50 test.
I'll bet some engineer would have done the $50 test
if not dizzied by the testing paperwork requirements
dictated by pedants.


Finally, let's note that programming and lawyerism
are different crafts.

The Authorities(tm) who post so pedantically in this
ng are often not completely wrong, but their pretentious
comments about gets() show confused thinking. In
particular, I wonder if some of them are law school
dropouts.

When I mention the gets()'s that I use, in private,
behind my Impenetrable Firewall(tm), on strings generated
by my own Bugfree Software(tm), they never acknowledge
that some gets()'s are less dangerous than others
but instead reject "safe" usages of gets() based on
pipe(fd);
dup2(fd[0], 0);
write(fd[1], "Hello world\n", 13);
printf("%s\n", gets(buff));
on grounds that the semantics of pipe(), etc. are *not
guaranteed* by the C Standard(tm).

If anyone has trouble understanding the absurdity and
hypocrisy of this legalistic view, I refer them to answers
previously given, here in the ng.

Hope this helps, :)
James Hussein Allen
 
S

Serve Lau

"James Dow Allen" <[email protected]> schreef in bericht
a_03.c:(.text+0x4d): warning: the `gets' function is dangerous
and should [never] be used.
...
Of course, this is nonsense. There is a perfectly safe way to use
gets(), namely by being in control of what appears on stdin.
The infamous worm was complex enough to attempt
exploitation of at least 4 different security loopholes,
but just one of the loopholes was ubiquitous enough
to make it necessary and sufficient for the Worm's
"success."
That loophole was the dangerous use
of gets() in a program (fingerd) usually run with
superuser authority.

The story of the internet worm doesnt make Twink's statement less true.
fingerd was not in control of stdin, so yes it could be exploited. Twink
said that gets can be used safely when you are in control of stdin.
 
F

Flash Gordon

James Dow Allen wrote, On 11/08/08 09:38:
a_03.c:(.text+0x4d): warning: the `gets' function is dangerous
and should [never] be used.
...
Of course, this is nonsense. There is a perfectly safe way to use
gets(), namely by being in control of what appears on stdin.

Heresy! I'm surprised no one launched a diatribe here
against Mr. Twink, so let me offer a diatribe in support!

Six comments on gets().


First, some history. (Some c.l.c'ers weren't
even alive at the time of the infamous Internet
Worm.)

Others were.

Perhaps there's a way to disable gcc's "dangerous"
message but, in keeping with the FSF philosophy, I'm
sure the cure is worse than the disease, something like
setenv IM_AN_UNREPENTANT_MORONIC_ASSHOLE

I suspect the only way to disable it is to do a custom build of gcc.

The gets() deprecators aren't wrong; indeed I'll cheerfully
concede that their position is more defensible than mine!
But I'm happy to take a Devil's Advocate position to
encourage critical thinking when I see the preposterous and
dogmatic over-generalizations which become so routine in
this ng. Is gets() a *potential* source of bugs? Obviously.
But I'd love to organize a wager, between me and one of
the pedants, on whose code contains more *actual* bugs.

I'll wager that the number of usages of gets posted to this group where
the input is not under compete control of the poster (a student is not
in control of what his/her instructor types in) is over a hundred times
more than the number of usages where it is under the posters control.
Actually, I suspect the only safe gets usages posted to this group are
posted specifically to point out that with guarantees beyond the scope
of C you can use it safely. Even on the occasions where input is under
my complete control I would use something else.
* - Detractors will argue that what I *should* want to
do is spend hours writing a diagnostic for such malloc()
failures! In fact I don't want to do anything about them
since the smallish malloc()'s I use to build the website
Aren't Going To Fail(tm). (The pedants will respond to

Actually I would not suggest spending hours on it. As it is for personal
use and you are confident it won't fail and would probably just want the
program to abort if it did you could spend a small amount of time
writing a small wrapper that checks the return value and aborts the
program with a failure message if the allocation fails. Not something I
would recommend for general programming, but better than not checking
the value and, if done at the start, will not even cost you 5 minutes.

I *might* have changed from gets() to fgets() on some
of my private code if it weren't for the above nit.
(And yes, I *do* know how to do
if (*s == '\n') *s = 0;
in C.)

So write a wrapper function (or macro) that does this. Or (if
appropriate) you could get it to emit a diagnostic if an overlong line
is encountered.

Finally, let's note that programming and lawyerism
are different crafts.

Reviewing code is another craft different from both of those.
The Authorities(tm) who post so pedantically in this
ng are often not completely wrong, but their pretentious
comments about gets() show confused thinking.

I disagree. I've seen more bugs more crashes of SW due to doing things
similar to calling gets (writing and using a function which takes user
input with no protection against over-long input) than I've seen safe
uses of gets. Generally when someone posts code here using gets it shows
that they have not even considered the possibility of buffer overflows,
and in such situations surely pointing out the possibility of a buffer
overflow is appropriate?
In
particular, I wonder if some of them are law school
dropouts.

I suspect none of them are.
When I mention the gets()'s that I use, in private,
behind my Impenetrable Firewall(tm), on strings generated
by my own Bugfree Software(tm), they never acknowledge
that some gets()'s are less dangerous than others
but instead reject "safe" usages of gets() based on

I've worked on safety-critical SW (as in real possibility of a person
being killed if it goes wrong) and on SW where a crash would at most
make someone mutter something, so I think I am aware that in some
situations a potential (or real) bug is more serious than in other
situations.

If anyone has trouble understanding the absurdity and
hypocrisy of this legalistic view, I refer them to answers
previously given, here in the ng.

I don't consider the view to be hypocritical since I don't use gets in
my code (not even in throw-away code) and if I found it used in code I
was reviewing then I would reject that code.

Also see comments above on the likelihood of someone being aware of the
issues with gets when they post code here that uses it.
Hope this helps, :)
James Hussein Allen

Here is another argument against using gets. It has now been deprecated
so you are limiting portability if you use it. After all, what with it
being deprecated it might not be available in implementations in 50
years time! ;-)
 
E

Edward A. Falk

if you can NOT define the input then I would agree. ...

Can you truly define the input? Can you guarantee that even if the code
is used in controlled conditions now, that it will NEVER be used under
different conditions?

Maybe you can, but by the time you've taken the time to do a proper
security audit of your code and all the ways it would ever be used,
it would be simpler to switch to fgets().
 
A

Antoninus Twink

Something about this fascination with gets() reminds me of the
complaints one hears from people who dislike wearing safety belts when
driving.

Not really.

Usually these "complaints" are just the observation that
self-determination is a pretty fundamental liberty that we should have
in a free society. The state has *no damn business* telling me what I
should or shouldn't do in the privacy of my own car, when it doesn't
affect anyone's safety but my own.

Although Heathfield clearly would love to be the dictator of the world,
actually he isn't, and no one's trying to prevent anyone using gets() by
force of law.

So the sitations aren't really comparable.
 
A

Antoninus Twink

Can you truly define the input? Can you guarantee that even if the code
is used in controlled conditions now, that it will NEVER be used under
different conditions?

Yes, I believe I can.

$ alias throwaway="rm -f"
$ throwaway throwaway-program throwaway-program.c

Or, what part of "throwaway" don't you understand?
 
W

Willem

Antoninus Twink wrote:
) Usually these "complaints" are just the observation that
) self-determination is a pretty fundamental liberty that we should have
) in a free society. The state has *no damn business* telling me what I
) should or shouldn't do in the privacy of my own car, when it doesn't
) affect anyone's safety but my own.

Suppose you're driving along and an oncoming car suddenly veers ondy your
lane, hitting you head-on. Wearing a seatbelt would save your life, but
that is your choice, right ? You're the only one harmed by not wearing it,
right ?

Wrong.

The person driviong that other car would, if you were killed, have the
very traumatic experience of having caused your death, as opposed to just
causing you some injuries had you worn your seatbelt.

So by choosing not to wear your seatbelt you put others in danger of being
traumatized by your death.


SaSW, Willem
--
Disclaimer: I am in no way responsible for any of the statements
made in the above text. For all I know I might be
drugged or something..
No I'm not paranoid. You all think I'm paranoid, don't you !
#EOT
 

Ask a Question

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

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

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,576
Members
45,054
Latest member
LucyCarper

Latest Threads

Top