Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

gets() is dead

8 views
Skip to first unread message

jacob navia

unread,
Apr 24, 2007, 7:02:04 PM4/24/07
to
In the discussion group comp.std.c Mr Gwyn wrote:

< quote >

... gets has been declared an obsolescent feature and
deprecated, as a direct result of my submitting a DR about it
(which originally suggested a less drastic change). (The official
impact awaits wrapping up the latest batch of TCs into a formal
amending document, and getting it approved and published.)

< end quote >

This is a very positive development. After all those discussions,
reason prevailed and we got rid of that wart.

It *is* possible to influence the comitee as it seems.
This is good news.

jacob

Gregor H.

unread,
Apr 24, 2007, 7:13:08 PM4/24/07
to
On Wed, 25 Apr 2007 01:02:04 +0200, jacob navia
<ja...@jacob.remcomp.fr> wrote:

>
> < quote >
>
> ... gets has been declared an obsolescent feature and
> deprecated, as a direct result of my submitting a DR about it
> (which originally suggested a less drastic change). (The official
> impact awaits wrapping up the latest batch of TCs into a formal
> amending document, and getting it approved and published.)
>
> < end quote >
>

R.I.P.


G.

--

E-mail: info<at>simple-line<Punkt>de

Keith Thompson

unread,
Apr 24, 2007, 7:48:55 PM4/24/07
to

It's not dead yet. "Deprecated" merely means that it can be
considered for removal in the next version of the standard (which
presumably will be released some time after C99 actually catches on).
Conforming implementations are still required to support gets().

But this is the first step in getting rid of it.

--
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"

Richard Heathfield

unread,
Apr 25, 2007, 1:37:59 AM4/25/07
to
Keith Thompson said:

<snip>

> Conforming implementations are still required to support gets().
>
> But this is the first step in getting rid of it.

Surely the first step was the continual rage and horror expressed at its
prolonged survival, over a period of many years, by a great many
people, until ISO were embarrassed by their own inadequate explanations
for its continued existence?

Next stop: unmodified %s in scanf.

--
Richard Heathfield
"Usenet is a strange place" - dmr 29/7/1999
http://www.cpax.org.uk
email: rjh at the above domain, - www.

Keith Thompson

unread,
Apr 25, 2007, 5:41:30 AM4/25/07
to
Richard Heathfield <r...@see.sig.invalid> writes:
> Keith Thompson said:
>
> <snip>
>
>> Conforming implementations are still required to support gets().
>>
>> But this is the first step in getting rid of it.
>
> Surely the first step was the continual rage and horror expressed at its
> prolonged survival, over a period of many years, by a great many
> people, until ISO were embarrassed by their own inadequate explanations
> for its continued existence?

Yeah, that too.

Eric Sosman

unread,
Apr 25, 2007, 8:25:22 AM4/25/07
to
Richard Heathfield wrote:
> Keith Thompson said:
>
> <snip>
>
>> Conforming implementations are still required to support gets().
>>
>> But this is the first step in getting rid of it.
>
> Surely the first step was the continual rage and horror expressed at its
> prolonged survival, over a period of many years, by a great many
> people, until ISO were embarrassed by their own inadequate explanations
> for its continued existence?
>
> Next stop: unmodified %s in scanf.

... along with unrestricted "[%", I guess. But there's no
compelling reason to remove either of them from sscanf() ...

--
Eric Sosman
eso...@acm-dot-org.invalid

CBFalconer

unread,
Apr 25, 2007, 8:38:51 AM4/25/07
to
Richard Heathfield wrote:
> Keith Thompson said:
>
> <snip>
>
>> Conforming implementations are still required to support gets().
>>
>> But this is the first step in getting rid of it.
>
> Surely the first step was the continual rage and horror expressed
> at its prolonged survival, over a period of many years, by a great
> many people, until ISO were embarrassed by their own inadequate
> explanations for its continued existence?
>
> Next stop: unmodified %s in scanf.

Not needed, it can be handled. More useful would be inclusion of
generic routines for numerical input from streams without buffers.

--
<http://www.cs.auckland.ac.nz/~pgut001/pubs/vista_cost.txt>
<http://www.securityfocus.com/columnists/423>
<http://www.aaxnet.com/editor/edit043.html>
cbfalconer at maineline.net

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

Al Balmer

unread,
Apr 25, 2007, 11:51:31 AM4/25/07
to
On Wed, 25 Apr 2007 01:13:08 +0200, Gregor H. <nomail@invalid> wrote:

>On Wed, 25 Apr 2007 01:02:04 +0200, jacob navia
><ja...@jacob.remcomp.fr> wrote:
>

You snipped one rather important line:

"In the discussion group comp.std.c Mr Gwyn wrote:"
>>
>> < quote >
>>
>> ... gets has been declared an obsolescent feature and
>> deprecated, as a direct result of my submitting a DR about it
>> (which originally suggested a less drastic change). (The official
>> impact awaits wrapping up the latest batch of TCs into a formal
>> amending document, and getting it approved and published.)
>>
>> < end quote >
>>
>
>R.I.P.
>

Your editing made it appear that this was a quote from Jacob Navia.

Incidentally, I am unable to find this article with a Google Groups
search of comp.std.c. Does anyone have a link?

--
Al Balmer
Sun City, AZ

Tor Rustad

unread,
Apr 25, 2007, 12:23:51 PM4/25/07
to
jacob navia wrote:

[...]



> This is a very positive development. After all those discussions,
> reason prevailed and we got rid of that wart.

These days, there should be no experienced C programmers using gets()
in security sensitive programs anyway, so I don't see the big fuzz about
this.

I have done a number of C code audits in safety-critical systems, and never
seen a single gets(), and didn't expect such a trivial bug either.

Who cares what students use?

I don't.


Richard Heathfield

unread,
Apr 25, 2007, 12:53:23 PM4/25/07
to
Al Balmer said:

<snip>

> Incidentally, I am unable to find this article[*] with a Google Groups


> search of comp.std.c. Does anyone have a link?

Message-ID: <462E7AF8...@null.net>

[* An article by Doug Gwyn in comp.std.c, saying that gets() will be
deprecated in the next Standard.]

Kenny McCormack

unread,
Apr 25, 2007, 12:56:48 PM4/25/07
to
In article <Q4-dnR_aS7s...@telenor.com>,

Tor Rustad <tor...@online.no> wrote:
>jacob navia wrote:
>
>[...]
>
>> This is a very positive development. After all those discussions,
>> reason prevailed and we got rid of that wart.

It's the sort of thing that gets people in this ng hot.

>These days, there should be no experienced C programmers using gets()
>in security sensitive programs anyway, so I don't see the big fuzz about
>this.

I'd have said: no experienced C programmers using gets()
and left it at that. According to the ng regs, everything is "security
sensitive", so including that text is superfluouos.

>I have done a number of C code audits in safety-critical systems, and never
>seen a single gets(), and didn't expect such a trivial bug either.
>
>Who cares what students use?
>
>I don't.

The anal-retentive freaks in this ng obviously do.
They've got nothing else in their lives, that much is clear.

Ben Pfaff

unread,
Apr 25, 2007, 1:03:36 PM4/25/07
to
Richard Heathfield <r...@see.sig.invalid> writes:

> Al Balmer said:
>> Incidentally, I am unable to find this article[*] with a Google Groups
>> search of comp.std.c. Does anyone have a link?
>
> Message-ID: <462E7AF8...@null.net>
>
> [* An article by Doug Gwyn in comp.std.c, saying that gets() will be
> deprecated in the next Standard.]

Indeed, I can't find this via Google. But my local news server
has it. See below:

----------------------------------------------------------------------

From: "Douglas A. Gwyn" <DAG...@null.net>
Subject: Re: security enhacement to C runtime library (XXX_s)
Newsgroups: comp.std.c
Date: Tue, 24 Apr 2007 21:47:36 GMT
Organization: U.S. Army Research Laboratory

webs...@gmail.com wrote:
> On Apr 22, 1:50 pm, "Douglas A. Gwyn" <DAG...@null.net> wrote:
> > The supposed advantage is that buffer overuns are under control,
> > not undefined behavior.
> Now explain to me what can you really in a practical sense do about
> this. If C had exception handling, then you could make a case, but it
> doesn't so? You're going to call exit(-1) instead? I hope you saved
> all your open documents in the program.

Because the behavior is controlled, you can safely save the state
of the work files, etc. Indeed, you can even simulate throwing an
exception by invoking jongjmp to regain control at a convenient
point in the overall algorithm. There are several implementations
of nested exception handling packages in Standard C.

With undefined behavior, you typically get a random crash leaving
data in a corrupted state, or worse yet get exploited by a "hacker"
who uses the overrun for nefarious purposes under *his* control.

> Thus creating a new code synchronization issue. Congratulations. You
> don't have any mathematicians (people who understand what a
> mathematical closure is I mean) or people who have used Ruby, or
> Python on the committee do you?

Sure we do. I know it's hard to believe that smart people could
come to any conclusion different from the one you come up with,
but it happens. Often it is because they are balancing a different
set of trade-offs or at least assigning different weights to them.

> I had major problems that prevented me from considering contributing
> to the ANSI standard:

If you don't participate, how do you expect to impact the outcome?

> 1) You are not open to the idea of *TAKING THINGS OUT* of the standard
> library.

Unless there is really strong justification, altering the behavior
of features which have been relied upon as guaranteed to be supported
on every conforming implementation (including dropping the guarantee
of their existence) does a disservice to the huge amount of existing
code that relies on the guarantees. Therefore, there is *rightly* a
strong predisposition on the part of the standards body to maintain
existing interfaces. However, ...

> 2) You have overtly distorted reality in your C rationale in the past
> to cover up for the embarrassment that is gets().

... actually, gets has been declared an obsolescent feature and


deprecated, as a direct result of my submitting a DR about it
(which originally suggested a less drastic change). (The official
impact awaits wrapping up the latest batch of TCs into a formal
amending document, and getting it approved and published.)

> 3) If I were to propose Bstrlib for inclusion into the standard, and
> it were to be accepted, it would *WORSEN* Bstrlib, because it would be
> included by some/most compiler vendors in a closed-source manner. One
> of Bstrlib's capabilities relies on the fact that it is open source
> (replaceable allocation functions), and the security statement is
> meaningless unless the source is available. So I declined the
> potential wide-spread notoriety and usage I might have gotten for
> Bstrlib if it were accepted (but lets be honest, you guys would not
> have given it a fair shake anyways) in exchange for retaining its
> status for maximal capability.

When submitted appropriately within the process, proposals are taken
quite seriously and are given fair consideration. A lot of what has
been standardized started out as such proposals. Of course, they had
active participants promoting, explaining, and shepherding them.

> 4) When I have made suggestions of proposals in the past I have been
> met with nothing but derision from you people. There was also an
> excellent and really necessary time generalization proposal (I don't
> remember who made it, but it was from a regular here; Dave Tribble
> maybe?). I don't see that proposal in the current TR. Its obvious
> you people just don't care about important capability issues.

I doubt that anything you submitted for consideration by WG14 has
"met with derision". There was in fact an extended time function
proposal that spun off from an earlier proposal which had been found
to have problems too late in the C99 revision process to make it into
the last version of the standard. Tribble has indeed been working to
refine and improve that, although so far as I recall it has not been
proposed as a Work Item, which would be necessary for the committee
to being working on a TR in that regard. Of course it is unrelated
to the buffer-limits TR.

Richard Tobin

unread,
Apr 25, 2007, 1:13:52 PM4/25/07
to
In article <8ftu239tclb1d4pp9...@4ax.com>,

Al Balmer <alba...@att.net> wrote:
>Incidentally, I am unable to find this article with a Google Groups
>search of comp.std.c. Does anyone have a link?

I can't find anything I posted in the last day. I think it must be a
Google problem.

-- Richard
--
"Consideration shall be given to the need for as many as 32 characters
in some alphabets" - X3.4, 1963.

Christopher Benson-Manica

unread,
Apr 25, 2007, 1:27:31 PM4/25/07
to
Tor Rustad <tor...@online.no> wrote:

> Who cares what students use?

Some students graduate. Handing them gets() is like handing them
matches and hoping they don't get anywhere near the flammables.

--
C. Benson Manica | I *should* know what I'm talking about - if I
cbmanica(at)gmail.com | don't, I need to know. Flames welcome.

Charlton Wilbur

unread,
Apr 25, 2007, 1:50:58 PM4/25/07
to
>>>>> "CBM" == Christopher Benson-Manica <at...@faeroes.freeshell.org> writes:

CBM> Some students graduate. Handing them gets() is like handing
CBM> them matches and hoping they don't get anywhere near the
CBM> flammables.

It's considerably easier to deal with recent graduates if you don't
have to beat bad habits out of them before instilling good habits --
and even easier still if they come with good habits instilled.

Charlton


--
Charlton Wilbur
cwi...@chromatico.net

Al Balmer

unread,
Apr 25, 2007, 2:32:11 PM4/25/07
to
On Wed, 25 Apr 2007 16:53:23 +0000, Richard Heathfield
<r...@see.sig.invalid> wrote:

>Al Balmer said:
>
><snip>
>
>> Incidentally, I am unable to find this article[*] with a Google Groups
>> search of comp.std.c. Does anyone have a link?
>
>Message-ID: <462E7AF8...@null.net>
>
>[* An article by Doug Gwyn in comp.std.c, saying that gets() will be
>deprecated in the next Standard.]

Thanks, Richard. I don't usually read the group. For some reason,
Google couldn't find the message, even searching for an exact phrase.
Probably it takes some time to get indexed.

Tor Rustad

unread,
Apr 25, 2007, 2:35:32 PM4/25/07
to
Kenny McCormack wrote:

> In article <Q4-dnR_aS7s...@telenor.com>,
> Tor Rustad <tor...@online.no> wrote:

>>These days, there should be no experienced C programmers using gets()
>>in security sensitive programs anyway, so I don't see the big fuzz about
>>this.
>
> I'd have said: no experienced C programmers using gets()
> and left it at that. According to the ng regs, everything is "security
> sensitive", so including that text is superfluouos.

Well, it's not, there is no problem using gets(), when the programmer
control the input.

For example, when writing a quick-and-short-lived test module, which is
needed only during development.


Default User

unread,
Apr 25, 2007, 3:28:28 PM4/25/07
to
Ben Pfaff wrote:

> Richard Heathfield <r...@see.sig.invalid> writes:
>
> > Al Balmer said:
> >> Incidentally, I am unable to find this article[*] with a Google
> Groups >> search of comp.std.c. Does anyone have a link?
> >
> > Message-ID: <462E7AF8...@null.net>
> >
> > [* An article by Doug Gwyn in comp.std.c, saying that gets() will
> > be deprecated in the next Standard.]
>
> Indeed, I can't find this via Google. But my local news server
> has it. See below:

Google is apparently screwed up today. That's leading many GG users
reposting because they think messages didn't go out.

We're now at the "when Google coughs, usenet gets a cold" state.

Brian

Dave Vandervies

unread,
Apr 25, 2007, 3:25:01 PM4/25/07
to
In article <Xu6dnbvNHM7...@telenor.com>,
Tor Rustad <tor_r...@hotmail.com> wrote:

>Well, it's not, there is no problem using gets(), when the programmer
>control the input.
>
>For example, when writing a quick-and-short-lived test module, which is
>needed only during development.

The problem with that is that quick-and-short-lived code usually isn't.


dave

--
Dave Vandervies dj3v...@csclub.uwaterloo.ca

Should I let the cat walk over the keyboard to select the compiler?
--CBFalconer in comp.lang.c

Christopher Benson-Manica

unread,
Apr 25, 2007, 3:35:33 PM4/25/07
to
Tor Rustad <tor_r...@hotmail.com> wrote:

> Well, it's not, there is no problem using gets(), when the programmer
> control the input.

> For example, when writing a quick-and-short-lived test module, which is
> needed only during development.

I don't agree. Very few things are as quick-and-short-lived as they
are originally intended to be. It isn't a great leap from a simple
test to code that gets e-mailed to someone else to demonstrate that X
is broken to code that someone else may cut and paste without paying
attention. I would suggest that any source file making use of gets()
should be deleted within (at most) five minutes of creation.

Flash Gordon

unread,
Apr 25, 2007, 3:44:55 PM4/25/07
to
Tor Rustad wrote, On 25/04/07 19:35:

The overhead of using fgets is pretty minimal even in that situation.
--
Flash Gordon

Keith Thompson

unread,
Apr 25, 2007, 4:18:47 PM4/25/07
to
CBFalconer <cbfal...@yahoo.com> writes:
> Richard Heathfield wrote:
>> Keith Thompson said:
>>
>> <snip>
>>
>>> Conforming implementations are still required to support gets().
>>>
>>> But this is the first step in getting rid of it.
>>
>> Surely the first step was the continual rage and horror expressed
>> at its prolonged survival, over a period of many years, by a great
>> many people, until ISO were embarrassed by their own inadequate
>> explanations for its continued existence?
>>
>> Next stop: unmodified %s in scanf.
>
> Not needed, it can be handled.
[snip]

I don't know what you mean by this. If you mean that eliminating
unmodified %s in scanf is not needed, can you explain? For example:

char s[N];
scanf("%s", s);

reads a (blank-delimited) word from stdin. If the user types, say,
2*N non-blank characters, it will invoke undefined behavior. How can
this be "handled" (other than by avoiding "%s")?

Ian Collins

unread,
Apr 25, 2007, 5:33:48 PM4/25/07
to
Default User wrote:
>
> Google is apparently screwed up today.

Today? You mean they fixed it before? ;)

--
Ian Collins.

Default User

unread,
Apr 25, 2007, 6:24:29 PM4/25/07
to
Ian Collins wrote:

> Default User wrote:
> >
> > Google is apparently screwed up today.
>
> Today? You mean they fixed it before? ;)

Screwed up worse than usual. It is, or was, failing to display new
posts for its users.

Brian

CBFalconer

unread,
Apr 25, 2007, 10:32:56 PM4/25/07
to
Keith Thompson wrote:
> CBFalconer <cbfal...@yahoo.com> writes:
>> Richard Heathfield wrote:
>>
... snip ...

>>>
>>> Next stop: unmodified %s in scanf.
>>
>> Not needed, it can be handled.
> [snip]
>
> I don't know what you mean by this. If you mean that eliminating
> unmodified %s in scanf is not needed, can you explain? For example:
>
> char s[N];
> scanf("%s", s);
>
> reads a (blank-delimited) word from stdin. If the user types, say,
> 2*N non-blank characters, it will invoke undefined behavior. How
> can this be "handled" (other than by avoiding "%s")?

By not using unmodified %s. That is a user choice. No such
available for gets.

Keith Thompson

unread,
Apr 26, 2007, 12:34:35 AM4/26/07
to
CBFalconer <cbfal...@yahoo.com> writes:
> Keith Thompson wrote:
>> CBFalconer <cbfal...@yahoo.com> writes:
>>> Richard Heathfield wrote:
>>>
> ... snip ...
>>>>
>>>> Next stop: unmodified %s in scanf.
>>>
>>> Not needed, it can be handled.
>> [snip]
>>
>> I don't know what you mean by this. If you mean that eliminating
>> unmodified %s in scanf is not needed, can you explain? For example:
>>
>> char s[N];
>> scanf("%s", s);
>>
>> reads a (blank-delimited) word from stdin. If the user types, say,
>> 2*N non-blank characters, it will invoke undefined behavior. How
>> can this be "handled" (other than by avoiding "%s")?
>
> By not using unmodified %s. That is a user choice. No such
> available for gets.

The suggestion, I think, is to disallow the use of "%s" with scanf.

Disallowing a particular argument value to a function is not as
straightforward as eliminating a function altogether, but the
rationale is the same. gets(..) cannot be used safely;
scanf("%s", ...) cannot be used safely.

Malcolm McLean

unread,
Apr 26, 2007, 1:27:42 AM4/26/07
to

"Keith Thompson" <ks...@mib.org> wrote in message
news:lnejm7g...@nuthaus.mib.org...

> CBFalconer <cbfal...@yahoo.com> writes:
>> Keith Thompson wrote:
>>> CBFalconer <cbfal...@yahoo.com> writes:
>>>> Richard Heathfield wrote:
>>>>
>> ... snip ...
>>>>>
>>>>> Next stop: unmodified %s in scanf.
>>>>
>>>> Not needed, it can be handled.
>>> [snip]
>>>
>>> I don't know what you mean by this. If you mean that eliminating
>>> unmodified %s in scanf is not needed, can you explain? For example:
>>>
>>> char s[N];
>>> scanf("%s", s);
>>>
>>> reads a (blank-delimited) word from stdin. If the user types, say,
>>> 2*N non-blank characters, it will invoke undefined behavior. How
>>> can this be "handled" (other than by avoiding "%s")?
>>
>> By not using unmodified %s. That is a user choice. No such
>> available for gets.
>
> The suggestion, I think, is to disallow the use of "%s" with scanf.
>
> Disallowing a particular argument value to a function is not as
> straightforward as eliminating a function altogether, but the
> rationale is the same. gets(..) cannot be used safely;
> scanf("%s", ...) cannot be used safely.
>
And fgets() is in practise too difficult for any but the best programmers to
use safely.
--
Free games and programming goodies.
http://www.personal.leeds.ac.uk/~bgy1mm

Keith Thompson

unread,
Apr 26, 2007, 2:22:08 AM4/26/07
to
"Malcolm McLean" <regn...@btinternet.com> writes:
> "Keith Thompson" <ks...@mib.org> wrote in message
> news:lnejm7g...@nuthaus.mib.org...
[...]

>> The suggestion, I think, is to disallow the use of "%s" with scanf.
>>
>> Disallowing a particular argument value to a function is not as
>> straightforward as eliminating a function altogether, but the
>> rationale is the same. gets(..) cannot be used safely;
>> scanf("%s", ...) cannot be used safely.
>>
> And fgets() is in practise too difficult for any but the best
> programmers to use safely.

Huh???

fgets() has limitations, but it doesn't pose anything like the danger
of gets() or scanf("%s", ...). It mishandles long lines by leaving
the remainder in the input stream, which is a minor inconvenience
compared to the undefined behavior of gets().

Richard Heathfield

unread,
Apr 26, 2007, 3:04:16 AM4/26/07
to
Keith Thompson said:

> "Malcolm McLean" <regn...@btinternet.com> writes:
<snip>


>> And fgets() is in practise too difficult for any but the best
>> programmers to use safely.
>
> Huh???

Quite. It's a ludicrous claim.

> fgets() has limitations, but it doesn't pose anything like the danger
> of gets() or scanf("%s", ...). It mishandles long lines by leaving
> the remainder in the input stream, which is a minor inconvenience
> compared to the undefined behavior of gets().

What else could fgets do with long lines, other than leave them in the
input stream, if it isn't allowed to call *alloc()?

jaysome

unread,
Apr 26, 2007, 3:13:02 AM4/26/07
to
On Wed, 25 Apr 2007 01:02:04 +0200, jacob navia wrote:

> In the discussion group comp.std.c Mr Gwyn wrote:
>
> < quote >
>

> ... gets has been declared an obsolescent feature and


> deprecated, as a direct result of my submitting a DR about it
> (which originally suggested a less drastic change). (The official
> impact awaits wrapping up the latest batch of TCs into a formal
> amending document, and getting it approved and published.)
>

> < end quote >


>
> This is a very positive development. After all those discussions,
> reason prevailed and we got rid of that wart.
>

> It *is* possible to influence the comitee as it seems.
> This is good news.
>
> jacob

So, I guess the reasoning goes, in C0x or possibly even C1x, we'll all be
relieved of having to deal with gets()?

Will compiler vendors jump on the bandwagon of conforming to the latest
standard and forbid us to use gets(), just like they jumped on the
bandwagon of adopting the now-more-than-8-year-old C99 standard, and
allowed us to use "//" comments and declare variables in-line and use some
great keywords like "restrict"?

And if they do, will we all jump on their bandwagon and switch to their
latest and greatest C0x or C1x compiler--just like we all jumped on the
C99 compiler bandwagon--just so that we can take advantage of the great
feature of deprecating gets()?

I think not.

Although Mr. Gwyn's intentions are laudable, his connection with reality
is arguably questionable, and regrettably about 17 years too late.

Best regards
--
jay

Keith Thompson

unread,
Apr 26, 2007, 3:28:43 AM4/26/07
to
Richard Heathfield <r...@see.sig.invalid> writes:
> Keith Thompson said:
[...]

>> fgets() has limitations, but it doesn't pose anything like the danger
>> of gets() or scanf("%s", ...). It mishandles long lines by leaving
>> the remainder in the input stream, which is a minor inconvenience
>> compared to the undefined behavior of gets().
>
> What else could fgets do with long lines, other than leave them in the
> input stream, if it isn't allowed to call *alloc()?

Well, it could discard them, but that would be dumb.

Richard Bos

unread,
Apr 26, 2007, 6:38:41 AM4/26/07
to
Tor Rustad <tor_r...@hotmail.com> wrote:

> Well, it's not, there is no problem using gets(), when the programmer
> control the input.

s/when/if/.

> For example, when writing a quick-and-short-lived test module, which is
> needed only during development.

You clearly do not have cats, children, _or_ typo-prone fingers.

Richard

Kenny McCormack

unread,
Apr 26, 2007, 8:07:03 AM4/26/07
to
In article <463047a7....@news.xs4all.nl>,

See what I mean about "anal-retentive freaks without lives" ???

webs...@gmail.com

unread,
Apr 26, 2007, 8:27:38 AM4/26/07
to
On Apr 25, 11:35 am, Tor Rustad <tor_rus...@hotmail.com> wrote:
> Kenny McCormack wrote:
> > In article <Q4-dnR_aS7sIHbLbRVnz...@telenor.com>,

As if we need further proof of just how dangerous gets() is. (James
Dow Allen has posted similar sentiments here in the past.) Even the
face of knowing exactly what's wrong with it, people claim its usable.

--
Paul Hsieh
http://www.pobox.com/~qed/
http://bstring.sf.net/

Eric Sosman

unread,
Apr 26, 2007, 8:48:09 AM4/26/07
to
Malcolm McLean wrote:
>
> And fgets() is in practise too difficult for any but the best
> programmers to use safely.

You're setting the "best" bar awfully low.

--
Eric Sosman
eso...@acm-dot-org.invalid

Chris Dollin

unread,
Apr 26, 2007, 8:58:15 AM4/26/07
to
Malcolm McLean wrote:

> And fgets() is in practise too difficult for any but the best programmers to
> use safely.

I think that's absurd. Do you have a reason for this interesting point of view?

--
"Go not to the Drazi for counsel, Unsaid /Babylon 5/
for they will answer both 'green' and 'purple'."

Hewlett-Packard Limited registered no:
registered office: Cain Road, Bracknell, Berks RG12 1HN 690597 England

Richard Heathfield

unread,
Apr 26, 2007, 10:13:48 AM4/26/07
to
Malcolm McLean said:

<snip>

> And fgets() is in practise too difficult for any but the best
> programmers to use safely.

Oh dear. I sure hope I'm a counter-example, because otherwise I've been
using fgets() unsafely for years.

Francin...@googlemail.com

unread,
Apr 26, 2007, 12:53:18 PM4/26/07
to
On Apr 25, 12:02 am, jacob navia <j...@jacob.remcomp.fr> wrote:
> This is a very positive development. After all those discussions,
> reason prevailed and we got rid of that wart.
>
> It *is* possible to influence the comitee as it seems.
> This is good news.

I wouldn't say it's good news. Firstly, it will break a lot of old
code if it's dropped. Secondly, gets() is completely safe *as long as
_you_ control the data passed to it*. Of course it should never be
used in production code, but for private/development/toy code I find
it extremely useful.

> jacob

Eric Sosman

unread,
Apr 26, 2007, 1:17:35 PM4/26/07
to
jaysome wrote On 04/26/07 03:13,:

What part of the quoted text is connected tenuously to
reality? It says that "gets has been declared an obsolescent
feature and deprecated." Do you have a reason to believe
this is an inaccurate description of the state of affairs?

It was you, not Doug Gwyn, who suggested that the action
of the Committee would "relieve" the world of gets(). It was
you, not Gwyn, who described the miraculous consequences of
gets()' forthcoming status. It is you, not Gwyn, who are
peddling fantasy.

--
Eric....@sun.com

Richard Heathfield

unread,
Apr 26, 2007, 1:35:37 PM4/26/07
to
Francin...@googlemail.com said:

> On Apr 25, 12:02 am, jacob navia <j...@jacob.remcomp.fr> wrote:
>> This is a very positive development. After all those discussions,
>> reason prevailed and we got rid of that wart.
>>
>> It *is* possible to influence the comitee as it seems.
>> This is good news.
>
> I wouldn't say it's good news. Firstly, it will break a lot of old
> code if it's dropped.

No, it won't break any old code that was not already broken.

> Secondly, gets() is completely safe *as long as
> _you_ control the data passed to it*.

And you can't guarantee that you do.

Gregor H.

unread,
Apr 26, 2007, 1:33:27 PM4/26/07
to
On 26 Apr 2007 09:53:18 -0700, Francin...@googlemail.com wrote:

>>
>> This is a very positive development. After all those discussions,
>> reason prevailed and we got rid of that wart.
>>
>> It *is* possible to influence the comitee as it seems.
>> This is good news.
>>
> I wouldn't say it's good news. Firstly, it will break a lot of old
> code if it's dropped.
>

Which is rather good news, given that the code you are talking about
makes use of "gets()" --- which is an inherently unsafe function.

>
> Secondly, gets() is completely safe *as long as _you_ control the
> data passed to it*.
>

Hear, hear. Well, sure, a gun is also completely safe as long you do
not aim at people with it.

>
> Of course it should never be used in production code, but for
> private/development/toy code I find it extremely useful.
>

It's extremely idiotic to have such a function in the first place,
even if only interested in "private/development/toy code" ...

Why do you think that

fgets(buffer, MAXBUF, stdin);

is less useful than

gets(buffer);

???


And if you have problems with the '\n' read in into the buffer, then
you might just add the code

char *pszTemp;
if ((pszTemp = strchr(buffer, '\n')) != NULL)
*pszTemp = '\0';

Done.


G.

--

E-mail: info<at>simple-line<Punkt>de

Flash Gordon

unread,
Apr 26, 2007, 1:46:12 PM4/26/07
to
Francin...@googlemail.com wrote, On 26/04/07 17:53:

> On Apr 25, 12:02 am, jacob navia <j...@jacob.remcomp.fr> wrote:
>> This is a very positive development. After all those discussions,
>> reason prevailed and we got rid of that wart.
>>
>> It *is* possible to influence the comitee as it seems.
>> This is good news.
>
> I wouldn't say it's good news.

I and many others here disagree.

> Firstly, it will break a lot of old
> code if it's dropped.

Most people here (even those who have argued for keeping gets) think
that it is only useful for quick throw-away programs (which are not a
problem as they are going to be thrown away anyway) and very specialised
situations (which being very specialised do not occur often and so do
not make up a lot of code). Any other code needs to be fixed anyway, so
the sooner it will not build the better since it will force it to be
fixed or discarded.

> Secondly, gets() is completely safe *as long as
> _you_ control the data passed to it*.

In such a situation you know the size of the buffer you have allocated
so is it really such a big problem to do:
fgets(buffer,sizeof buffer,stdin);
or
fgets(buffer,BUFFER_SIZE,stdin);

You could even write a macro
#define GETS(buffer) fgets(buffer,sizeof buffer,stdin)
which would be suitable for most usage.

> Of course it should never be
> used in production code, but for private/development/toy code I find
> it extremely useful.

See above for easy ways to live without it. If the buffer is not large
enough you are likely to find it easier to debug since the results will
be more predictable, if it is large enough it just means you have to
deal with the newline left in the buffer. So you could do:
#define GETS(buffer) ((fgets(buffer,sizeof buffer,stdin)!=NULL)? \
(buffer[strcspn(buffer,"\n")]=0,buffer):NULL)

Obviously you do not pass a pointer to this macro. It can be used as in:
#include <stdio.h>
#include <string.h>

#define GETS(buffer) ((fgets(buffer,sizeof buffer,stdin)!=NULL)? \
(buffer[strcspn(buffer,"\n")]=0,buffer):NULL)

int main(void)
{
char buf[10];
GETS(buf);
printf("'%s'\n",buf);
GETS(buf);
printf("'%s'\n",buf);
return 0;
}

markg@brenda:~$ gcc -ansi -pedantic -Wall -Wextra -O t.c
markg@brenda:~$ ./a.out

''

''
markg@brenda:~$ ./a.out
1
'1'

''
markg@brenda:~$ ./a.out
12345678
'12345678'

''
markg@brenda:~$ ./a.out
123456789
'123456789'
''
markg@brenda:~$ ./a.out
1234567890
'123456789'
'0'
markg@brenda:~$

Easily good enough for a throwaway program wanting gets type
functionality. I will even hereby grant everyone the permission to use
the code illustrated herein for any code of there own for any purpose
under any license with one exception. If you are publishing my idea
outside Usenet then you need my permission and inside Usenet you need to
acknowledge it as mine unless you can find prior art.
--
Flash Gordon

Richard Heathfield

unread,
Apr 26, 2007, 1:53:19 PM4/26/07
to
Flash Gordon said:

<snip>

> I will even hereby grant everyone the permission to use
> the code illustrated herein for any code of there own for any purpose
> under any license with one exception. If you are publishing my idea
> outside Usenet then you need my permission and inside Usenet you need
> to acknowledge it as mine unless you can find prior art.

Very generous, Flash, but if it's all the same to you, I'll pass. :-)

Flash Gordon

unread,
Apr 26, 2007, 1:52:20 PM4/26/07
to
Eric Sosman wrote, On 26/04/07 18:17:

<snip>

> reality? It says that "gets has been declared an obsolescent
> feature and deprecated." Do you have a reason to believe

I think it would be nice if the standard mandated emitting a diagnostic
for the use of any feature declared in the standard as obsolescent
and/or deprecated. Note that I am NOT saying it should fail to
compile/link, just that a diagnostic should be issued.
--
Flash Gordon

Flash Gordon

unread,
Apr 26, 2007, 1:56:55 PM4/26/07
to
Richard Heathfield wrote, On 26/04/07 18:53:

> Flash Gordon said:
>
> <snip>
>
>> I will even hereby grant everyone the permission to use
>> the code illustrated herein for any code of there own for any purpose
>> under any license with one exception. If you are publishing my idea
>> outside Usenet then you need my permission and inside Usenet you need
>> to acknowledge it as mine unless you can find prior art.
>
> Very generous, Flash, but if it's all the same to you, I'll pass. :-)

I'm sure you have a suitable routine for situations where other might
consider using gets anyway :-)

I would also not be surprised if something similar has been posted in
the past.
--
Flash Gordon

Dave Vandervies

unread,
Apr 26, 2007, 3:08:29 PM4/26/07
to
In article <f0qt88$1kp$1...@rumours.uwaterloo.ca>,
Dave Vandervies <dj3v...@caffeine.csclub.uwaterloo.ca> wrote:

>I don't think that getting required non-fatal warnings for obsolescent
>or deprecated features would be worth creating that distinction in the
>language implementation, especially since most reasonable implementations
^^^^^^^^^^^^^^
>already *do* issue non-fatal warnings for them.

I meant "in the language specification", of course.

But even in this correction it took me three tries to convince my fingers
of that for some reason.


dave

--
Dave Vandervies dj3v...@csclub.uwaterloo.ca
[...]then stick a fake rock on top of the mast to cover the dish. Then the
dish isn't the unslightly thing seen from the road, and there's nothing in
the CCR banning fake aerial rocks. --Peter H. Coffin in the SDM

Dave Vandervies

unread,
Apr 26, 2007, 3:06:48 PM4/26/07
to
In article <kf57g4x...@news.flash-gordon.me.uk>,

The standard makes no distinction between a diagnostic that causes
translation to be aborted and one that allows it to continue. Many
implementations make this distinction between "warnings" and "errors";
when invoked in conforming mode, such an implementation may issue either
a "warning" or an "error" for a syntax error or constraint violation
(and most do some of each), but only a "warning" for diagnostics not
required by the standard.

I don't think that getting required non-fatal warnings for obsolescent
or deprecated features would be worth creating that distinction in the
language implementation, especially since most reasonable implementations

already *do* issue non-fatal warnings for them.

Default User

unread,
Apr 26, 2007, 3:25:07 PM4/26/07
to
Richard Heathfield wrote:

> Malcolm McLean said:
>
> <snip>
>
> > And fgets() is in practise too difficult for any but the best
> > programmers to use safely.
>
> Oh dear. I sure hope I'm a counter-example, because otherwise I've
> been using fgets() unsafely for years.

As he humbly discards the possibility that he's one of the best
programmers.


Brian

Dave Vandervies

unread,
Apr 26, 2007, 3:32:54 PM4/26/07
to
In article <59cckjF...@mid.individual.net>,

I can't speak for him, but I suspect his response to that would be
similar to mine:

I like to think I'm good. If I tried hard enough, I could probably even
dig up supporting evidence for above average. But if I'm "one of the
best", we're all in trouble.

And I, too, have apparently been using fgets unsafely for years.

Malcolm McLean

unread,
Apr 26, 2007, 3:58:00 PM4/26/07
to

"Chris Dollin" <chris....@hp.com> wrote in message
news:f0q7lv$1d0$1...@murdoch.hpl.hp.com...

> Malcolm McLean wrote:
>
>> And fgets() is in practise too difficult for any but the best programmers
>> to
>> use safely.
>
> I think that's absurd. Do you have a reason for this interesting point of
> view?
>
You've provided your own evidence.
You can't articulate why fgets() is dangerous, or why it could be considered
dangerous if you persist in disagreeing with me. A threat you can't
recognise is much more deadly than one that you can.

Charlton Wilbur

unread,
Apr 26, 2007, 4:04:58 PM4/26/07
to
>>>>> "DU" == Default User <defaul...@yahoo.com> writes:

DU> As he humbly discards the possibility that he's one of the
DU> best programmers.

In my case, I have to. I know how inexpert I am, and the notion that
I might be one of the best is truly horrifying.

Charlton


--
Charlton Wilbur
cwi...@chromatico.net

Harald van Dijk

unread,
Apr 26, 2007, 4:16:03 PM4/26/07
to
Richard Heathfield wrote:
> Francin...@googlemail.com said:
>
> > On Apr 25, 12:02 am, jacob navia <j...@jacob.remcomp.fr> wrote:
> >> This is a very positive development. After all those discussions,
> >> reason prevailed and we got rid of that wart.
> >>
> >> It *is* possible to influence the comitee as it seems.
> >> This is good news.
> >
> > I wouldn't say it's good news. Firstly, it will break a lot of old
> > code if it's dropped.
>
> No, it won't break any old code that was not already broken.
>
> > Secondly, gets() is completely safe *as long as
> > _you_ control the data passed to it*.
>
> And you can't guarantee that you do.

You can if your code isn't strictly conforming ANSI C, you've forked a
process, and you're using pipes for communication between the parent
and the child.

Of course, if the only possible safe uses of gets() rely on extensions
to standard C, it wouldn't be bad to make gets() itself an extension
as well, so I'm not saying deprecating it was a bad idea.

Keith Thompson

unread,
Apr 26, 2007, 4:19:05 PM4/26/07
to
"Malcolm McLean" <regn...@btinternet.com> writes:
> "Chris Dollin" <chris....@hp.com> wrote in message
> news:f0q7lv$1d0$1...@murdoch.hpl.hp.com...
>> Malcolm McLean wrote:
>>
>>> And fgets() is in practise too difficult for any but the best
>>> programmers to
>>> use safely.
>>
>> I think that's absurd. Do you have a reason for this interesting
>> point of view?
>>
> You've provided your own evidence.
> You can't articulate why fgets() is dangerous, or why it could be
> considered dangerous if you persist in disagreeing with me. A threat
> you can't recognise is much more deadly than one that you can.

You haven't provided a reason for your claim, you've merely reiterated
it and implicitly insulted anyone who doesn't already agree with you.

I persist in disagreeing with you. Don't waste my time telling me
again that you're right and I'm wrong. Explain yourself.

Flash Gordon

unread,
Apr 26, 2007, 4:17:01 PM4/26/07
to
Malcolm McLean wrote, On 26/04/07 20:58:

>
> "Chris Dollin" <chris....@hp.com> wrote in message
> news:f0q7lv$1d0$1...@murdoch.hpl.hp.com...
>> Malcolm McLean wrote:
>>
>>> And fgets() is in practise too difficult for any but the best
>>> programmers to
>>> use safely.
>>
>> I think that's absurd. Do you have a reason for this interesting point
>> of view?
>>
> You've provided your own evidence.
> You can't articulate why fgets() is dangerous, or why it could be
> considered dangerous if you persist in disagreeing with me. A threat you
> can't recognise is much more deadly than one that you can.

So tell us all why fgets is so dangerous that only the best programmers
can use it safely, especially as you came up with this in response to
discussion of gets being deprecated and the justification being
applicable to the unqualified %s in a scanf call.
--
Flash Gordon

Flash Gordon

unread,
Apr 26, 2007, 4:19:26 PM4/26/07
to
Dave Vandervies wrote, On 26/04/07 20:08:

> In article <f0qt88$1kp$1...@rumours.uwaterloo.ca>,
> Dave Vandervies <dj3v...@caffeine.csclub.uwaterloo.ca> wrote:
>
>> I don't think that getting required non-fatal warnings for obsolescent
>> or deprecated features would be worth creating that distinction in the
>> language implementation, especially since most reasonable implementations
> ^^^^^^^^^^^^^^
>> already *do* issue non-fatal warnings for them.
>
> I meant "in the language specification", of course.
>
> But even in this correction it took me three tries to convince my fingers
> of that for some reason.

I don't think it would be a big thing, just adding one sentence (or
paragraph at the most). It is not as if it would be that big a thing for
most implementations to implement, after all most can warn against the
things which have been deprecated anyway.
--
Flash Gordon

Malcolm McLean

unread,
Apr 26, 2007, 5:07:13 PM4/26/07
to

"Keith Thompson" <ks...@mib.org> wrote in message
news:lnzm4uk...@nuthaus.mib.org...

> "Malcolm McLean" <regn...@btinternet.com> writes:
>> "Chris Dollin" <chris....@hp.com> wrote in message
>> news:f0q7lv$1d0$1...@murdoch.hpl.hp.com...
>>> Malcolm McLean wrote:
>>>
>>>> And fgets() is in practise too difficult for any but the best
>>>> programmers to
>>>> use safely.
>>>
>>> I think that's absurd. Do you have a reason for this interesting
>>> point of view?
>>>
>> You've provided your own evidence.
>> You can't articulate why fgets() is dangerous, or why it could be
>> considered dangerous if you persist in disagreeing with me. A threat
>> you can't recognise is much more deadly than one that you can.
>
> You haven't provided a reason for your claim, you've merely reiterated
> it and implicitly insulted anyone who doesn't already agree with you.
>
> I persist in disagreeing with you. Don't waste my time telling me
> again that you're right and I'm wrong. Explain yourself.
>
OK.
No one else can articulate why fgets() is dangerous. Therefore there are two
possibilities. The first is that it isn't dangerous at all, the second is
that it is especially dangerous and even experienced programmers often can't
see the problem.

Why do I go for the second? Because there are two actions you need to take
when using fgets() safely.
Firstly you need to check for the trailing newline to be sure that the whole
line has been read. Secondly you need to take action in the event of a
failure to ensure that the partially read input doesn't cause any problems.
In practise these steps are seldom followed. The degree of danger obviously
depends on the application, whether it is possible for the input to be
sabotaged by some malicious person with access to the source. But it is
certainly there.

Ian Collins

unread,
Apr 26, 2007, 5:14:21 PM4/26/07
to
Malcolm McLean wrote:

>
> "Keith Thompson" <ks...@mib.org> wrote:
>>
>> You haven't provided a reason for your claim, you've merely reiterated
>> it and implicitly insulted anyone who doesn't already agree with you.
>>
>> I persist in disagreeing with you. Don't waste my time telling me
>> again that you're right and I'm wrong. Explain yourself.
>>
> OK.
> No one else can articulate why fgets() is dangerous. Therefore there are
> two possibilities. The first is that it isn't dangerous at all, the
> second is that it is especially dangerous and even experienced
> programmers often can't see the problem.
>
> Why do I go for the second? Because there are two actions you need to
> take when using fgets() safely.
> Firstly you need to check for the trailing newline to be sure that the
> whole line has been read. Secondly you need to take action in the event
> of a failure to ensure that the partially read input doesn't cause any
> problems.

Yes, but with fgets() you *can* check. With gets() or %s in scanf(),
you can't defend against malicious attack. The former is sloppy
practice, the latter a defect in the language.

--
Ian Collins.

Flash Gordon

unread,
Apr 26, 2007, 5:47:20 PM4/26/07
to
Malcolm McLean wrote, On 26/04/07 22:07:

Anyone who either thinks about it or reads the specification for fgets
will know they need to check to see if a complete line has been read.

> Secondly you need to take action in the event
> of a failure to ensure that the partially read input doesn't cause any
> problems.

Anyone with any decent training in SW development will know they need to
define what action should be taken in the event of incorrect input and
write the SW to do this.

> In practise these steps are seldom followed.

A lot of SW is written by people who are not very good.

> The degree of danger
> obviously depends on the application, whether it is possible for the
> input to be sabotaged by some malicious person with access to the
> source. But it is certainly there.

That can be said about the input functions of any language.

If you have to specify the size of the line buffer then you have to deal
with the potential for a longer line being entered and handle it
correctly. If the language provides a function that will grow the buffer
until it is large enough then you have to allow for the possibility that
a line is too long for your available memory (I can easily construct a
file with a line too long for a machine with 32 bit addressing to load
in to its address space).

I'm interfacing to SW written in Java that crashes if given bad input.
With an earlier version of the SW we found that if we had 4 processes
sending data to this multi-user server code written in Java that we
would actually bring down the entire system, and this was without even
being malicious! The code doing the sending was also written in Java, BTW.
--
Flash Gordon

Keith Thompson

unread,
Apr 26, 2007, 5:50:50 PM4/26/07
to

There is a third possibility, that you're wrong and the rest of us are
right.

As I already acknowledged, fgets() can be problematic, but it's not
nearly as bad as gets() or scanf("%s", ...).

> Why do I go for the second? Because there are two actions you need to
> take when using fgets() safely.
> Firstly you need to check for the trailing newline to be sure that the
> whole line has been read. Secondly you need to take action in the
> event of a failure to ensure that the partially read input doesn't
> cause any problems.

And the likely result of failing to do this is that a long line is
treated as if it were two or more shorter lines. It won't cause
undefined behavior.

> In practise these steps are seldom followed. The degree of danger
> obviously depends on the application, whether it is possible for the
> input to be sabotaged by some malicious person with access to the
> source. But it is certainly there.

fgets() *can* be used safely, and most of us here know how to do so.
Even if its limitations are ignored, the consequences are relatively
mild.

Christopher Benson-Manica

unread,
Apr 26, 2007, 5:53:28 PM4/26/07
to
Malcolm McLean <regn...@btinternet.com> wrote:

> No one else can articulate why fgets() is dangerous. Therefore there are two
> possibilities. The first is that it isn't dangerous at all, the second is
> that it is especially dangerous and even experienced programmers often can't
> see the problem.

What do you advocate instead? fgetc()? (If you're arguing that
scanf() is less dangerous than fgets(), be prepared to lose that
argument.) Assuming a bug-free conforming implementation, the choices
are A) use fgets() per its documentation and take precautions on par
with those required for the safe use of virtually all other
non-trivial library functions, or B) implement your own replacement
for fgets(), which will invariably include caveats for safe use on the
order those necessary to use fgets() and any number of other library
functions. Option B certainly seems to call for a more advanced
programmer than A.

> In practise these steps are seldom followed. The degree of danger obviously
> depends on the application, whether it is possible for the input to be
> sabotaged by some malicious person with access to the source. But it is
> certainly there.

A simple strcpy() call can easily be "dangerous" in a completely
non-obvious way; I'm presuming you aren't going to claim that
strcpy() is impossibly dangerous for all but the best programmers.

--
C. Benson Manica | I *should* know what I'm talking about - if I
cbmanica(at)gmail.com | don't, I need to know. Flames welcome.

Michael Brennan

unread,
Apr 26, 2007, 9:19:49 PM4/26/07
to
On 2007-04-26, Malcolm McLean <regn...@btinternet.com> wrote:
>
> And fgets() is in practise too difficult for any but the best programmers to
> use safely.

That certainly means I am unable to use fgets() safely,
and since I just wrote this function which reads from stdin
using fgets() I thought I would to like to hear any opinions
on my code from the people here.
Although it may not be the best way to handle memory, I'm
mostly interested to know if this code is correct, and safe.
Thanks!

/Michael Brennan


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

#define BUFSZ 128
char *readstr(void)
{
char buffer[BUFSZ];
char *input;
size_t size;
char *tmp;

input = NULL;
size = 0;
do {
tmp = realloc(input, size + BUFSZ);
if (tmp == NULL) {
free(input);
return NULL;
}
input = tmp;

if (fgets(buffer, sizeof buffer, stdin) == NULL) {
free(input);
return NULL;
}

if (size == 0)
strcpy(input, buffer);
else
strcat(input, buffer);

size = strlen(input);
} while (strrchr(buffer, '\n') == NULL);

input[strcspn(input, "\n")] = '\0';

return input;
}

CBFalconer

unread,
Apr 26, 2007, 8:43:19 PM4/26/07
to
Malcolm McLean wrote:
>
... snip ...

>
> No one else can articulate why fgets() is dangerous. Therefore
> there are two possibilities. The first is that it isn't dangerous
> at all, the second is that it is especially dangerous and even
> experienced programmers often can't see the problem.
>
> Why do I go for the second? Because there are two actions you need
> to take when using fgets() safely. Firstly you need to check for
> the trailing newline to be sure that the whole line has been read.
> Secondly you need to take action in the event of a failure to
> ensure that the partially read input doesn't cause any problems.
> In practise these steps are seldom followed. The degree of danger
> obviously depends on the application, whether it is possible for
> the input to be sabotaged by some malicious person with access to
> the source. But it is certainly there.

So don't use it. You can use ggets (or fggets), available at:

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

written in purely standard C, so portable anywhere.

--
<http://www.cs.auckland.ac.nz/~pgut001/pubs/vista_cost.txt>
<http://www.securityfocus.com/columnists/423>
<http://www.aaxnet.com/editor/edit043.html>
<http://kadaitcha.cx/vista/dogsbreakfast/index.html>
cbfalconer at maineline.net

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

CBFalconer

unread,
Apr 26, 2007, 8:54:56 PM4/26/07
to
"Gregor H." wrote:
>
... snip ...

>
> It's extremely idiotic to have such a function in the first place,
> even if only interested in "private/development/toy code" ...
>
> Why do you think that
>
> fgets(buffer, MAXBUF, stdin);
>
> is less useful than
>
> gets(buffer);

Just use ggets:

if (ggets(&buffptr)) somethingfailed();
else {
/* all is well. buffptr points to input line. */
}

Written in standard C, fully portable, no usage restrictions. See:

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

cbfalconer at maineline dot net

Richard Heathfield

unread,
Apr 27, 2007, 1:22:47 AM4/27/07
to
Michael Brennan said:

<snip>

> Although it may not be the best way to handle memory, I'm
> mostly interested to know if this code is correct, and safe.

I can't see anything "incorrect" about it, in terms of C rules. It does,
however, expose your program to the possibility of a memory exhaustion
attack, since you place no upper limit on the size of the block to be
allocated.

Also, there are a couple of places where you could speed it up.
Specifically, you could use an exponential allocation strategy rather
than linear, and you could avoid repeated calls to strlen and strcat by
keeping track of length information.

Anyway, why are you using fgets at all? Wouldn't the code be a lot
simpler and perhaps a touch quicker if you just used getc?

Richard Heathfield

unread,
Apr 27, 2007, 1:29:04 AM4/27/07
to
Harald van D?k said:

> Richard Heathfield wrote:
>> Francin...@googlemail.com said:
>>

<snip>


>>
>> > Secondly, gets() is completely safe *as long as
>> > _you_ control the data passed to it*.
>>
>> And you can't guarantee that you do.
>
> You can if your code isn't strictly conforming ANSI C, you've forked a
> process, and you're using pipes for communication between the parent
> and the child.

You seem to believe that the program is only run in ways of which you
approve. Programs, despite being written by programmers, have a nasty
habit of ending up in the hands of users, and users don't as a rule
worry about such things as the flakiness of the programs they are
using. (Were this not the case, it would be impossible to explain the
popularity of Internet Explorer.)

> Of course, if the only possible safe uses of gets() rely on extensions
> to standard C, it wouldn't be bad to make gets() itself an extension
> as well, so I'm not saying deprecating it was a bad idea.

I think any implementation offering gets() as an extension should itself
be deprecated - for low QoI.

Richard Bos

unread,
Apr 27, 2007, 2:17:21 AM4/27/07
to
Flash Gordon <sp...@flash-gordon.me.uk> wrote:

After all, we already do have _required_-fatal diagnostics, in the case
of #error. Adding the opposite should not be a problem.

Richard

Richard Bos

unread,
Apr 27, 2007, 2:18:29 AM4/27/07
to
Gregor H. <nomail@invalid> wrote:

> On 26 Apr 2007 09:53:18 -0700, Francin...@googlemail.com wrote:
>
> > Secondly, gets() is completely safe *as long as _you_ control the
> > data passed to it*.
> >

> Hear, hear. Well, sure, a gun is also completely safe as long you do
> not aim at people with it.

In which context it is significant that people _do_ get killed with
their own guns, both by others and by themselves.

Richard

jacob navia

unread,
Apr 27, 2007, 2:25:22 AM4/27/07
to
Richard Heathfield wrote:
> Michael Brennan said:
>
> <snip>
>
>>Although it may not be the best way to handle memory, I'm
>>mostly interested to know if this code is correct, and safe.
>
>
> I can't see anything "incorrect" about it, in terms of C rules. It does,
> however, expose your program to the possibility of a memory exhaustion
> attack, since you place no upper limit on the size of the block to be
> allocated.
>

If the hacker types 10 chars/second, it will take him/her
27.77 hours to get to 1MB, 11 days of continuous
typing to just allocate 10MB, and more than half a year
to type 100MB...

Today allocating 100MB is no problem at all, most machines
dispose of 2GB Virual memory. This means that you have
years to catch the hacker trying to exhaust your
memory by typing.

If stdin is redirected, that's another problem.


> Also, there are a couple of places where you could speed it up.
> Specifically, you could use an exponential allocation strategy rather
> than linear, and you could avoid repeated calls to strlen and strcat by
> keeping track of length information.
>

Typing speed is the limit quantity here

柑\/b

unread,
Apr 27, 2007, 3:56:49 AM4/27/07
to
On Thu, 26 Apr 2007 18:46:12 +0100, Flash Gordon wrote:
>Francine wrote, On 26/04/07 17:53:

>> On Apr 25, 12:02 am, jacob navia <j...@jacob.remcomp.fr> wrote:
>>> This is a very positive development. After all those discussions,
>>> reason prevailed and we got rid of that wart.

>>> It *is* possible to influence the comitee as it seems.
>>> This is good news.
>>
>> I wouldn't say it's good news.
>

>I and many others here disagree.


>
> > Firstly, it will break a lot of old
>> code if it's dropped.
>

>Most people here (even those who have argued for keeping gets) think
>that it is only useful for quick throw-away programs (which are not a
>problem as they are going to be thrown away anyway) and very specialised
>situations (which being very specialised do not occur often and so do
>not make up a lot of code). Any other code needs to be fixed anyway, so
>the sooner it will not build the better since it will force it to be
>fixed or discarded.


>
> > Secondly, gets() is completely safe *as long as
>> _you_ control the data passed to it*.
>

>In such a situation you know the size of the buffer you have allocated
>so is it really such a big problem to do:
> fgets(buffer,sizeof buffer,stdin);
>or
> fgets(buffer,BUFFER_SIZE,stdin);

fgets should to return the number of char successfull written in
buffer; so the use is easier and should not be use strlen one more
time again

something like:

unsigned h;
char buf[2048];
if((h=fgets(buf, sizeof buf, stdin))==0 || buf[h-1]!='\n')
error();
"" error
"\n" ok
"fifjfj\n" ok
"jfofif^D" error
"jfofif^Z" error
2070 string error
etc

or something like:
char buf[2048], *h;
if((h=fgets(buf, sizeof buf, stdin))==0 || *h!='\n')
error();

Richard Heathfield

unread,
Apr 27, 2007, 3:59:41 AM4/27/07
to
jacob navia said:

> Richard Heathfield wrote:
>>
>> I can't see anything "incorrect" about it, in terms of C rules. It
>> does, however, expose your program to the possibility of a memory
>> exhaustion attack, since you place no upper limit on the size of the
>> block to be allocated.
>
> If the hacker types 10 chars/second, it will take him/her
> 27.77 hours to get to 1MB,

Ever heard of redirection?

<snip>



> If stdin is redirected, that's another problem.

Oh look, you have. Well done.

柑\/b

unread,
Apr 27, 2007, 3:59:04 AM4/27/07
to
On Fri, 27 Apr 2007 09:56:49 +0200, "Źa\\/b" <al@f.g> wrote:

>something like:
>
>unsigned h;
>char buf[2048];
>if((h=fgets(buf, sizeof buf, stdin))==0 || buf[h-1]!='\n')
> error();
>"" error
>"\n" ok
>"fifjfj\n" ok
>"jfofif^D" error
>"jfofif^Z" error
>2070 string error
>etc
>
>or something like:
>char buf[2048], *h;
>if((h=fgets(buf, sizeof buf, stdin))==0 || *h!='\n')
> error();

i already have above functions

Flash Gordon

unread,
Apr 27, 2007, 3:49:29 AM4/27/07
to
jacob navia wrote, On 27/04/07 07:25:

> Richard Heathfield wrote:
>> Michael Brennan said:
>>
>> <snip>
>>
>>> Although it may not be the best way to handle memory, I'm
>>> mostly interested to know if this code is correct, and safe.
>>
>>
>> I can't see anything "incorrect" about it, in terms of C rules. It
>> does, however, expose your program to the possibility of a memory
>> exhaustion attack, since you place no upper limit on the size of the
>> block to be allocated.
>
> If the hacker types 10 chars/second, it will take him/her
> 27.77 hours to get to 1MB, 11 days of continuous
> typing to just allocate 10MB, and more than half a year
> to type 100MB...
>
> Today allocating 100MB is no problem at all, most machines
> dispose of 2GB Virual memory. This means that you have
> years to catch the hacker trying to exhaust your
> memory by typing.
>
> If stdin is redirected, that's another problem.

The program does not ensure that stdin is not redirected. It also fails
to ensure that I have not reprogrammed the keyboard controller to
generate such input.

If a hacker has access to the keyboard s/he can probably redirect stdin,
if not it is a remote attack and there is no reason to assume it is a
person typing.

>> Also, there are a couple of places where you could speed it up.
>> Specifically, you could use an exponential allocation strategy rather
>> than linear, and you could avoid repeated calls to strlen and strcat
>> by keeping track of length information.
>
> Typing speed is the limit quantity here

Only assuming input is someone typing, which frequently is not the case.

>> Anyway, why are you using fgets at all? Wouldn't the code be a lot
>> simpler and perhaps a touch quicker if you just used getc?

I'm not convinced using getc would be faster. C makes no such guarantee ;-)
--
Flash Gordon

Richard Heathfield

unread,
Apr 27, 2007, 4:06:52 AM4/27/07
to
Flash Gordon said:
<snip>

>> Richard Heathfield wrote:
>
>>> Anyway, why are you using fgets at all? Wouldn't the code be a lot
>>> simpler and perhaps a touch quicker if you just used getc?
>
> I'm not convinced using getc would be faster. C makes no such
> guarantee ;-)

Indeed it doesn't, which is why I said "perhaps". Nevertheless, the
possibility is a real one. fgets must copy the data into the supplied
buffer (as if by repeated calls to getc, IIRC), and then the OP copies
it out again into another buffer. Using getc directly, whilst not
guaranteed to produce any saving at all (let alone a significant
saving), is nevertheless highly likely so to do.

Chris Dollin

unread,
Apr 27, 2007, 4:15:37 AM4/27/07
to
Malcolm McLean wrote:

> "Chris Dollin" <chris....@hp.com> wrote in message
> news:f0q7lv$1d0$1...@murdoch.hpl.hp.com...
>> Malcolm McLean wrote:
>>
>>> And fgets() is in practise too difficult for any but the best programmers
>>> to
>>> use safely.
>>
>> I think that's absurd. Do you have a reason for this interesting point of
>> view?
>>
> You've provided your own evidence.

Where?

> You can't articulate why fgets() is dangerous,

You have no evidence for this claim.

> or why it could be considered dangerous if you persist in disagreeing with me.

What? I think my parser is broken, or something.

> A threat you can't recognise is much more deadly than one that you can.

/Some/ threats you can't recognise are more deadly than ones that
you can. This is not news.

Do you have an actual /reason/ for the claim you made in the nested
quote above?

--
"Reaching out for mirrors hidden in the web." - Renaissance, /Running Hard/

Hewlett-Packard Limited Cain Road, Bracknell, registered no:
registered office: Berks RG12 1HN 690597 England

Chris Dollin

unread,
Apr 27, 2007, 4:20:31 AM4/27/07
to
Malcolm McLean wrote:

> No one else can articulate why fgets() is dangerous.

False.

> Therefore there are two
> possibilities.

False dichotomy.

> The first is that it isn't dangerous at all, the second is
> that it is especially dangerous and even experienced programmers often can't
> see the problem.

The third is that you have to be awake when you use it, just like you
have to be awake when you use `+` or `if` or `*`.

`fgets` is "dangerous" in the same way that most code is.

--
QUIZ (undo letter-change-then-clue). "Royalty insists on doing their own hair."

Michael Brennan

unread,
Apr 27, 2007, 8:36:59 AM4/27/07
to
On 2007-04-27, Richard Heathfield <r...@see.sig.invalid> wrote:
> Michael Brennan said:
>
><snip>
>
>> Although it may not be the best way to handle memory, I'm
>> mostly interested to know if this code is correct, and safe.
>
> I can't see anything "incorrect" about it, in terms of C rules. It does,
> however, expose your program to the possibility of a memory exhaustion
> attack, since you place no upper limit on the size of the block to be
> allocated.
>
> Also, there are a couple of places where you could speed it up.
> Specifically, you could use an exponential allocation strategy rather
> than linear, and you could avoid repeated calls to strlen and strcat by
> keeping track of length information.

Points taken. Thank you!

> Anyway, why are you using fgets at all? Wouldn't the code be a lot
> simpler and perhaps a touch quicker if you just used getc?
>

Good point. I did not realize that when I wrote it, since my goal
was just to handle the case where the line exceeded the size I
passed to fgets(). But as it looks now I might just as well
use getc().

But that makes me wonder, how should I use fgets() if I want to
make sure that a too long input line won't break my program by
sending the trailing data to functions that expect something else?

I mean, if I just write this convenient line

fgets(buffer, sizeof buffer, stdin);

I'd have trailing data waiting if the user inputs a too long line.

I suppose I could just have a loop with getc() at the end that
discards the rest of the input. Is that a good way to do it
if you use fgets()?

/Michael Brennan

Richard Heathfield

unread,
Apr 27, 2007, 9:20:33 AM4/27/07
to
Michael Brennan said:

> On 2007-04-27, Richard Heathfield <r...@see.sig.invalid> wrote:

<snip>

>> Anyway, why are you using fgets at all? Wouldn't the code be a lot
>> simpler and perhaps a touch quicker if you just used getc?
>>
>
> Good point. I did not realize that when I wrote it, since my goal
> was just to handle the case where the line exceeded the size I
> passed to fgets(). But as it looks now I might just as well
> use getc().
>
> But that makes me wonder, how should I use fgets() if I want to
> make sure that a too long input line won't break my program by
> sending the trailing data to functions that expect something else?

Um... don't? :-) Just use your super-duper new function instead.

> I mean, if I just write this convenient line
>
> fgets(buffer, sizeof buffer, stdin);
>
> I'd have trailing data waiting if the user inputs a too long line.
>
> I suppose I could just have a loop with getc() at the end that
> discards the rest of the input. Is that a good way to do it
> if you use fgets()?

As ever, it depends. If the data matters, read it and process it. If
not, then throwing it away is reasonable. If you do decide to use fgets
*and* discover that you have not captured an entire line (because there
is no \n in your buffer) *and* you don't want the rest of the line,
then you can do something like:

int clreol(FILE *fp)
{
int ch;
while((ch = getc(fp)) != EOF && ch != '\n')
{
continue;
}
return ch == '\n';

CBFalconer

unread,
Apr 27, 2007, 9:30:12 AM4/27/07
to
Flash Gordon wrote:
> jacob navia wrote, On 27/04/07 07:25:
>> Richard Heathfield wrote:
>>
... snip ...

>>
>> Typing speed is the limit quantity here
>
> Only assuming input is someone typing, which frequently is not
> the case.
>
>>> Anyway, why are you using fgets at all? Wouldn't the code be a
>>> lot simpler and perhaps a touch quicker if you just used getc?
>
> I'm not convinced using getc would be faster. C makes no such
> guarantee ;-)

No guarantee, but often true when getc is implemented as a macro.

CBFalconer

unread,
Apr 27, 2007, 9:36:11 AM4/27/07
to
Michael Brennan wrote:
>
... snip ...

>
> I mean, if I just write this convenient line
>
> fgets(buffer, sizeof buffer, stdin);
>
> I'd have trailing data waiting if the user inputs a too long line.
>
> I suppose I could just have a loop with getc() at the end that
> discards the rest of the input. Is that a good way to do it
> if you use fgets()?

Which is all one more reason to use ggets. The call is simpler
(ggets(&buf);) and the results always have the terminal \n
removed. You still have complete error reporting. ggets (and
fggets) are completely portable. See:

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

Harald van Dijk

unread,
Apr 27, 2007, 12:36:03 PM4/27/07
to
Richard Heathfield wrote:
> Harald van D?k said:
>
> > Richard Heathfield wrote:
> >> Francin...@googlemail.com said:
> >>
> <snip>
> >>
> >> > Secondly, gets() is completely safe *as long as
> >> > _you_ control the data passed to it*.
> >>
> >> And you can't guarantee that you do.
> >
> > You can if your code isn't strictly conforming ANSI C, you've forked a
> > process, and you're using pipes for communication between the parent
> > and the child.
>
> You seem to believe that the program is only run in ways of which you
> approve.

I don't. Are you perhaps assuming that the separate processes are
separate programs? If so, yes, running the intended child separately
would be unsafe, but there is no need to make separate programs
available. The same program can act both as parent and as child.

Dave Vandervies

unread,
Apr 27, 2007, 12:54:09 PM4/27/07
to
In article <u7GdnZu8ut-...@bt.com>,

Malcolm McLean <regn...@btinternet.com> wrote:
>
>"Chris Dollin" <chris....@hp.com> wrote in message
>news:f0q7lv$1d0$1...@murdoch.hpl.hp.com...
>> Malcolm McLean wrote:
>>
>>> And fgets() is in practise too difficult for any but the best programmers
>>> to
>>> use safely.
>>
>> I think that's absurd. Do you have a reason for this interesting point of
>> view?
>>
>You've provided your own evidence.
>You can't articulate why fgets() is dangerous, or why it could be considered
>dangerous if you persist in disagreeing with me. A threat you can't
>recognise is much more deadly than one that you can.

Can you articulate why breathing air is dangerous?

No? Then it must be EXTREMELY dangerous. I think you should stop.


dave

--
Dave Vandervies dj3v...@csclub.uwaterloo.ca

Feh. I only care about invective if it comes from people I take seriously.
--Richard Bos in comp.lang.c

Default User

unread,
Apr 27, 2007, 1:34:30 PM4/27/07
to
Charlton Wilbur wrote:

> >>>>> "DU" == Default User <defaul...@yahoo.com> writes:
>
> DU> As he humbly discards the possibility that he's one of the
> DU> best programmers.
>
> In my case, I have to. I know how inexpert I am, and the notion that
> I might be one of the best is truly horrifying.

I'd be happy around here to be considered competent. On the other hand,
for my "skills assessment" at work, I blithely checked "expert" level
for C. I know my competition.

Brian

Default User

unread,
Apr 27, 2007, 2:01:14 PM4/27/07
to
Malcolm McLean wrote:


> No one else can articulate why fgets() is dangerous. Therefore there
> are two possibilities. The first is that it isn't dangerous at all,


> the second is that it is especially dangerous and even experienced
> programmers often can't see the problem.


It's a fairly typical C function, especially of the string-handling
type. If you give the wrong size as the second argument, or pass in a
null or unintialized pointer, UB awaits with Nasty, Big, Pointy Teeth.

The only thing the user can do is give you something longer than can be
read a single gulp. So what? That's pretty minor on the list of things
C programmers have to watch out for.

Brian

Richard Heathfield

unread,
Apr 27, 2007, 2:17:00 PM4/27/07
to
CBFalconer said:

> Michael Brennan wrote:
>>
> ... snip ...
>>
>> I mean, if I just write this convenient line
>>
>> fgets(buffer, sizeof buffer, stdin);
>>
>> I'd have trailing data waiting if the user inputs a too long line.
>>
>> I suppose I could just have a loop with getc() at the end that
>> discards the rest of the input. Is that a good way to do it
>> if you use fgets()?
>
> Which is all one more reason to use ggets.

Chuck, this subthread started with Mr Brennan's own attempt at a dynamic
string capture routine, which - whilst not perfect - was a fair stab at
the problem, and one which he was clearly prepared to improve. So why
would he want to use ggets?

> The call is simpler
> (ggets(&buf);) and the results always have the terminal \n
> removed. You still have complete error reporting. ggets (and
> fggets) are completely portable.

And still subject to memory exhaustion attacks.

Al Balmer

unread,
Apr 27, 2007, 2:17:36 PM4/27/07
to
On 27 Apr 2007 17:34:30 GMT, "Default User" <defaul...@yahoo.com>
wrote:

Well put :-) Same here.

--
Al Balmer
Sun City, AZ

Richard Heathfield

unread,
Apr 27, 2007, 2:20:09 PM4/27/07
to
Harald van D?k said:

If I understand you correctly, you're suggesting that a program could
feed its own output to itself by stuffing it down a pipe and picking it
up with gets(). This seems ludicrously pointless.

柑\/b

unread,
Apr 27, 2007, 2:45:13 PM4/27/07
to
On Fri, 27 Apr 2007 09:56:49 +0200, "Źa\\/b" <al@f.g> wrote:
>something like:
>
>unsigned h;
>char buf[2048];
>if((h=fgets(buf, sizeof buf, stdin))==0 || buf[h-1]!='\n')
> error();

unsigned h;
char buf[2048];

if((h=fgets(buf, sizeof buf, stdin))<=1 || buf[h-2]!='\n')
error();


>"" error
>"\n" ok
>"fifjfj\n" ok
>"jfofif^D" error
>"jfofif^Z" error
>2070 string error
>etc
>
>or something like:
>char buf[2048], *h;
>if((h=fgets(buf, sizeof buf, stdin))==0 || *h!='\n')
> error();

char buf[2048], *h;

if( (h=fgets(buf, sizeof buf, stdin))==buf || h[-1]!='\n')
error();
fgets return buf on input error
in the ok case return the h in buffer that *h=0

i can not remember all (nor use them much in the direct way) but i
think they are like as the last i wrote

Walter Roberson

unread,
Apr 27, 2007, 2:47:43 PM4/27/07
to
In article <t9KdnWNuypj3o6_b...@bt.com>,

Richard Heathfield <r...@see.sig.invalid> wrote:
>Harald van D?k said:

>> I don't. Are you perhaps assuming that the separate processes are
>> separate programs? If so, yes, running the intended child separately
>> would be unsafe, but there is no need to make separate programs
>> available. The same program can act both as parent and as child.

>If I understand you correctly, you're suggesting that a program could
>feed its own output to itself by stuffing it down a pipe and picking it
>up with gets(). This seems ludicrously pointless.

I believe he is talking about fork(), in which case you -do- have
control over the input and output because both sides are the same
program (though not the same process.)

Forking and communicating between the processes with a pipe is
common for cases where a portion of the work must be done with
different access permissions.
--
"It is important to remember that when it comes to law, computers
never make copies, only human beings make copies. Computers are given
commands, not permission. Only people can be given permission."
-- Brad Templeton

Harald van Dijk

unread,
Apr 27, 2007, 3:20:33 PM4/27/07
to
Richard Heathfield wrote:
> Harald van D?k said:
>
> > Richard Heathfield wrote:
> >> Harald van D?k said:
> >>
> >> > Richard Heathfield wrote:
> >> >> Francin...@googlemail.com said:
> >> >>
> >> <snip>
> >> >>
> >> >> > Secondly, gets() is completely safe *as long as
> >> >> > _you_ control the data passed to it*.
> >> >>
> >> >> And you can't guarantee that you do.
> >> >
> >> > You can if your code isn't strictly conforming ANSI C, you've
> >> > forked a process, and you're using pipes for communication between
> >> > the parent and the child.
> >>
> >> You seem to believe that the program is only run in ways of which you
> >> approve.
> >
> > I don't. Are you perhaps assuming that the separate processes are
> > separate programs? If so, yes, running the intended child separately
> > would be unsafe, but there is no need to make separate programs
> > available. The same program can act both as parent and as child.
>
> If I understand you correctly, you're suggesting that a program could
> feed its own output to itself by stuffing it down a pipe and picking it
> up with gets().

Correct.

> This seems ludicrously pointless.

It's not. If you have a complex text processing routine, often the
easiest way of writing it is to intermix reads and writes. If you have
two such text processing routines, you cannot directly combine them,
if you want the second to act on the output of the first, because it's
not easy to rewrite the first as a function returning the next
character it would output. A pipe is a logical solution for this.

Malcolm McLean

unread,
Apr 27, 2007, 3:31:54 PM4/27/07
to

"Chris Dollin" <chris....@hp.com> wrote in message
news:f0sbpl$26f$1...@murdoch.hpl.hp.com...

> Malcolm McLean wrote:
>
>> No one else can articulate why fgets() is dangerous.
>
> False.
>
>> Therefore there are two
>> possibilities.
>
> False dichotomy.
>
>> The first is that it isn't dangerous at all, the second is
>> that it is especially dangerous and even experienced programmers often
>> can't
>> see the problem.
>
> The third is that you have to be awake when you use it, just like you
> have to be awake when you use `+` or `if` or `*`.
>
> `fgets` is "dangerous" in the same way that most code is.
>
You are very nearly right.
All functions or nearly all are dangerous if passed bad data. fgets() is
distinguished because, if used improperly, it can be a source of corrupted
data fed to other functions. For instance a patient record with the last
digit of the weight field cut off, fed to a function that calculates his
drug dose, all because someone didn't check for that trailing newline.

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


Flash Gordon

unread,
Apr 27, 2007, 3:15:21 PM4/27/07
to
Źa\/b wrote, On 27/04/07 08:56:

> On Thu, 26 Apr 2007 18:46:12 +0100, Flash Gordon wrote:
>> Francine wrote, On 26/04/07 17:53:

<snip>

>>> Secondly, gets() is completely safe *as long as
>>> _you_ control the data passed to it*.
>> In such a situation you know the size of the buffer you have allocated
>> so is it really such a big problem to do:
>> fgets(buffer,sizeof buffer,stdin);
>> or
>> fgets(buffer,BUFFER_SIZE,stdin);
>
> fgets should to return the number of char successfull written in
> buffer;

<snip more stuff based on this completely false statement>

Wrong. fgets is defined by the C standard as returning a null pointer on
failure or a pointer to the start of the buffer on success. I suggest
you go back to school.
--
Flash Gordon

Flash Gordon

unread,
Apr 27, 2007, 3:20:28 PM4/27/07
to
Źa\/b wrote, On 27/04/07 19:45:

> On Fri, 27 Apr 2007 09:56:49 +0200, "Źa\\/b" <al@f.g> wrote:
>> something like:
>>
>> unsigned h;
>> char buf[2048];
>> if((h=fgets(buf, sizeof buf, stdin))==0 || buf[h-1]!='\n')
>> error();
>
> unsigned h;
> char buf[2048];
> if((h=fgets(buf, sizeof buf, stdin))<=1 || buf[h-2]!='\n')
> error();

Still based on a completely incorrect belief of how fgets is defined.

<snip>

>> or something like:
>> char buf[2048], *h;
>> if((h=fgets(buf, sizeof buf, stdin))==0 || *h!='\n')
>> error();

I failed to spot this before. How can you possibly believe that fgets
returns an integer AND that it returns a pointer?

Anyway, it is rubbish since it will error on enything other than an
empty line.

> char buf[2048], *h;
> if( (h=fgets(buf, sizeof buf, stdin))==buf || h[-1]!='\n')
> error();
> fgets return buf on input error
> in the ok case return the h in buffer that *h=0

This is even worse.

> i can not remember all (nor use them much in the direct way) but i
> think they are like as the last i wrote

You seem to to have remembered anything since I've not managed to find
anything correct in your post.
--
Flash Gordon

Malcolm McLean

unread,
Apr 27, 2007, 4:32:31 PM4/27/07
to

"Michael Brennan" <brennan...@gmail.com> wrote in message
news:VccYh.39468$E02....@newsb.telia.net...

> On 2007-04-26, Malcolm McLean <regn...@btinternet.com> wrote:
>>
>> And fgets() is in practise too difficult for any but the best programmers
>> to
>> use safely.
>
> That certainly means I am unable to use fgets() safely,
> and since I just wrote this function which reads from stdin
> using fgets() I thought I would to like to hear any opinions
> on my code from the people here.

> Although it may not be the best way to handle memory, I'm
> mostly interested to know if this code is correct, and safe.
> Thanks!
>
> /Michael Brennan
>
>
> #include <stdio.h>
> #include <stdlib.h>
> #include <string.h>
>
> #define BUFSZ 128
> char *readstr(void)
> {
> char buffer[BUFSZ];
> char *input;
> size_t size;
> char *tmp;
>
> input = NULL;
> size = 0;
> do {
> tmp = realloc(input, size + BUFSZ);
> if (tmp == NULL) {
> free(input);
> return NULL;
> }
> input = tmp;
>
> if (fgets(buffer, sizeof buffer, stdin) == NULL) {
> free(input);
> return NULL;
> }
>
> if (size == 0)
> strcpy(input, buffer);
> else
> strcat(input, buffer);
>
> size = strlen(input);
> } while (strrchr(buffer, '\n') == NULL);
>
> input[strcspn(input, "\n")] = '\0';
>
> return input;
> }
>

What happens if we pass a line greater than max size_t bytes to your code?

Ian Collins

unread,
Apr 27, 2007, 4:42:09 PM4/27/07
to
Malcolm McLean wrote:

>
> "Chris Dollin" <chris....@hp.com> wrote:
>>
>> The third is that you have to be awake when you use it, just like you
>> have to be awake when you use `+` or `if` or `*`.
>>
>> `fgets` is "dangerous" in the same way that most code is.
>>
> You are very nearly right.
> All functions or nearly all are dangerous if passed bad data. fgets() is
> distinguished because, if used improperly, it can be a source of
> corrupted data fed to other functions. For instance a patient record
> with the last digit of the weight field cut off, fed to a function that
> calculates his drug dose, all because someone didn't check for that
> trailing newline.
>
Just as well you have unit tests to verify the valid range and or number
of characters in your input data.

--
Ian Collins.

Ian Collins

unread,
Apr 27, 2007, 4:44:03 PM4/27/07
to
What's the old saying about the one eyed man in the land of the blind?

:)

--
Ian Collins.

Flash Gordon

unread,
Apr 27, 2007, 4:58:27 PM4/27/07
to
Ian Collins wrote, On 27/04/07 21:42:

I would expect it to be caught in the design review myself, when the
reviewer would ask what it is to do if the line is too long. Then, of
course, the requirement specification would have to be updated to
include the missing information on error handling and the people who
reviewed the requirements get kicked for not having spotted the problem.

Well, for the sort of SW Malcolm is talking about I would. For several
degrees of less critical SW I would still expect it to be caught in
either design or code review.
--
Flash Gordon

Dave Vandervies

unread,
Apr 27, 2007, 4:58:46 PM4/27/07
to
In article <PKGdnXIZeOtZwK_b...@bt.com>,
Malcolm McLean <regn...@btinternet.com> wrote:

>What happens if we pass a line greater than max size_t bytes to your code?

Your computer vanishes in a puff of logic.


dave

--
Dave Vandervies dj3v...@csclub.uwaterloo.ca

Surprise your compiler. Write better code than it asks you to.
--Keith Thompson in comp.lang.c

Malcolm McLean

unread,
Apr 27, 2007, 5:18:54 PM4/27/07
to

"Dave Vandervies" <dj3v...@caffeine.csclub.uwaterloo.ca> wrote in message
news:f0to66$uv0$1...@rumours.uwaterloo.ca...

> In article <PKGdnXIZeOtZwK_b...@bt.com>,
> Malcolm McLean <regn...@btinternet.com> wrote:
>
>>What happens if we pass a line greater than max size_t bytes to your code?
>
> Your computer vanishes in a puff of logic.
>
>
You can generate a text file longer than 4GB and containing no newlines. A
standard PC disk will hold it these days. Then direct it to stdin and feed
it to the program. I suspect many OSes would choke, but I don't think that
is guaranteed.

Christopher Benson-Manica

unread,
Apr 27, 2007, 9:12:02 AM4/27/07
to
Richard Bos <r...@hoekstra-uitgeverij.nl> wrote:

> After all, we already do have _required_-fatal diagnostics, in the case
> of #error. Adding the opposite should not be a problem.

#ifndef __STDC__
#diagnostic Danger, Will Robinson!
#endif

--
C. Benson Manica | I *should* know what I'm talking about - if I
cbmanica(at)gmail.com | don't, I need to know. Flames welcome.

Drew Lawson

unread,
Apr 27, 2007, 7:35:58 PM4/27/07
to
In article <01v9g4x...@news.flash-gordon.me.uk>

Flash Gordon <sp...@flash-gordon.me.uk> writes:
>Źa\/b wrote, On 27/04/07 19:45:
>> On Fri, 27 Apr 2007 09:56:49 +0200, "Źa\\/b" <al@f.g> wrote:
>>> something like:
>>>
>>> unsigned h;
>>> char buf[2048];
>>> if((h=fgets(buf, sizeof buf, stdin))==0 || buf[h-1]!='\n')
>>> error();
>>
>> unsigned h;
>> char buf[2048];
>> if((h=fgets(buf, sizeof buf, stdin))<=1 || buf[h-2]!='\n')
>> error();
>
>Still based on a completely incorrect belief of how fgets is defined.

I believe that the poster is trying to talk about the interface he
feels that fgets() *should* have.

It would be useful to have it return the size read, like read()
does. But as discussed elsewhere in this thread, one can easily
impliment a different "get line and return line size" routine based
on fgetc().


--
Drew Lawson I had planned to be dead by now, but
dr...@furrfu.com the schedule slipped, they do that.
-- Casady

It is loading more messages.
0 new messages