Discussion:
removing gets() from the standard [POLL}
(too old to reply)
Bill Cunningham
2016-05-22 19:01:23 UTC
Permalink
Raw Message
I just wondered how many people like me think removing gets() from the
standard is a mistake. I think so because C has some much heritage left over
from so many different standards; such as c89 C99 C11. It is well know about
gets() problems just don't use it. C++ style comments were added the /* */
comment delimiters weren't removed. sterror ad errno was added. perror
wasn't removed.

Versatility and using various mixes and styles is part of C's appeal. I
like C89 and C99 myself. C11 I don't even bother with.

Bill
Casper H.S. Dik
2016-05-23 07:59:35 UTC
Permalink
Raw Message
Post by Bill Cunningham
I just wondered how many people like me think removing gets() from the
standard is a mistake. I think so because C has some much heritage left over
from so many different standards; such as c89 C99 C11. It is well know about
gets() problems just don't use it. C++ style comments were added the /* */
comment delimiters weren't removed. sterror ad errno was added. perror
wasn't removed.
The reason is likely because there is no problem with keep these old
contrustctions (/* */ & perror) but there is no safe way to use gets().

So gets() can't be used by any program that want to make sure it
works properly regarding of the inputs given to it, it is proper to
remove it from the standard.

Casper
Richard Kettlewell
2016-05-23 08:04:14 UTC
Permalink
Raw Message
Post by Casper H.S. Dik
So gets() can't be used by any program that want to make sure it
works properly regarding of the inputs given to it, it is proper to
remove it from the standard.
I’m not sorry to see it gone. But in C99 and earlier:

The Committee decided that gets was useful and convenient in those
special circumstances when the programmer does have adequate control
over the input, and as longstanding existing practice, it needed a
standard specification.

...so I wonder what changed for C2011.
--
http://www.greenend.org.uk/rjk/
Casper H.S. Dik
2016-05-23 09:04:53 UTC
Permalink
Raw Message
Post by Richard Kettlewell
Post by Casper H.S. Dik
So gets() can't be used by any program that want to make sure it
works properly regarding of the inputs given to it, it is proper to
remove it from the standard.
The Committee decided that gets was useful and convenient in those
special circumstances when the programmer does have adequate control
over the input, and as longstanding existing practice, it needed a
standard specification.
...so I wonder what changed for C2011.
The risk of programmers using the interface without knowing its
problems or because since 1988 programmers had sufficient wawrning
to no longer use it?

Casper
Francis Glassborow
2016-05-23 09:05:25 UTC
Permalink
Raw Message
Post by Richard Kettlewell
Post by Casper H.S. Dik
So gets() can't be used by any program that want to make sure it
works properly regarding of the inputs given to it, it is proper to
remove it from the standard.
The Committee decided that gets was useful and convenient in those
special circumstances when the programmer does have adequate control
over the input, and as longstanding existing practice, it needed a
standard specification.
...so I wonder what changed for C2011.
They finally understood how bad it was and any programmer who had enough
knowledge to use it 'safely' knew how to write it for themselves.

Francis
Richard Kettlewell
2016-05-23 10:46:05 UTC
Permalink
Raw Message
Post by Francis Glassborow
Post by Richard Kettlewell
The Committee decided that gets was useful and convenient in those
special circumstances when the programmer does have adequate control
over the input, and as longstanding existing practice, it needed a
standard specification.
...so I wonder what changed for C2011.
They finally understood how bad it was and any programmer who had
enough knowledge to use it 'safely' knew how to write it for
themselves.
Perhaps there’s hope for a more pragmatic approach to the other
landmines in C then...
--
http://www.greenend.org.uk/rjk/
Keith Thompson
2016-05-23 19:38:24 UTC
Permalink
Raw Message
Post by Richard Kettlewell
Post by Francis Glassborow
Post by Richard Kettlewell
The Committee decided that gets was useful and convenient in those
special circumstances when the programmer does have adequate control
over the input, and as longstanding existing practice, it needed a
standard specification.
...so I wonder what changed for C2011.
They finally understood how bad it was and any programmer who had
enough knowledge to use it 'safely' knew how to write it for
themselves.
Perhaps there’s hope for a more pragmatic approach to the other
landmines in C then...
Perhaps -- but none of them are as bad as gets(). Every other
standard library function *can* be used safely with some care.
gets() cannot be used safely unless you have control over what will
appear on standard input.
--
Keith Thompson (The_Other_Keith) kst-***@mib.org <http://www.ghoti.net/~kst>
Working, but not speaking, for JetHead Development, Inc.
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Richard Kettlewell
2016-05-23 22:20:09 UTC
Permalink
Raw Message
Post by Keith Thompson
Post by Richard Kettlewell
Post by Francis Glassborow
Post by Richard Kettlewell
The Committee decided that gets was useful and convenient in those
special circumstances when the programmer does have adequate control
over the input, and as longstanding existing practice, it needed a
standard specification.
...so I wonder what changed for C2011.
They finally understood how bad it was and any programmer who had
enough knowledge to use it 'safely' knew how to write it for
themselves.
Perhaps there’s hope for a more pragmatic approach to the other
landmines in C then...
Perhaps -- but none of them are as bad as gets(). Every other
standard library function *can* be used safely with some care. gets()
cannot be used safely unless you have control over what will appear on
standard input.
It’s one of the least worrying landmines, since it’s trivial to search
for and can easily be replaced when found (indeed some toolchains do so
automatically). Identifying the other landmines in existing code is
much harder - there’s no keyword you can search for to identify signed
overflow, for instance.
--
http://www.greenend.org.uk/rjk/
Richard Kettlewell
2016-05-23 22:56:48 UTC
Permalink
Raw Message
Post by Richard Kettlewell
It’s one of the least worrying landmines, since it’s trivial to search
for and can easily be replaced when found (indeed some toolchains do so
automatically).
Of course I mean they do the searching (in the form of moaning if you
use it) - I don’t know of anything that automatically replaces gets()
with something safer.
Post by Richard Kettlewell
Identifying the other landmines in existing code is
much harder - there’s no keyword you can search for to identify signed
overflow, for instance.
--
http://www.greenend.org.uk/rjk/
Bill Cunningham
2016-05-25 23:18:15 UTC
Permalink
Raw Message
"Richard Kettlewell" <***@greenend.org.uk> wrote in message news:***@mantic.terraraq.uk...

[...]
Post by Richard Kettlewell
Of course I mean they do the searching (in the form of moaning if you
use it) - I don't know of anything that automatically replaces gets()
with something safer.
[...]

fgets. scanf. I really like stdin to fgets myself.

Bill
s***@casperkitty.com
2016-05-26 02:18:23 UTC
Permalink
Raw Message
Post by Bill Cunningham
fgets. scanf. I really like stdin to fgets myself.
Using fgets with stdin is annoyingly clunky in many cases. On some platforms
which have a guaranteed maximum input-line length, the following would be
clean and safe:

char input[256]; // If platform guarantees 255-character maximum
gets(input);
printf("You typed %s, didn't you?", input);

Using fgets doesn't work nearly as conveniently, since it's necessary to
use strlen to get the length of the input, then check for and strip out a
newline, and (if one wants robust behavior in the presence of long lines
at the input) figure out what to do if a line is longer than expected. A
function that was closer to gets(), but which defined a maximum buffer size
and rejected anything past (interactive applications on some systems could
beep if excessive characters were typed) would have been much more useful
in many cases.
Keith Thompson
2016-05-26 03:44:28 UTC
Permalink
Raw Message
Post by s***@casperkitty.com
Post by Bill Cunningham
fgets. scanf. I really like stdin to fgets myself.
Using fgets with stdin is annoyingly clunky in many cases. On some platforms
which have a guaranteed maximum input-line length, the following would be
char input[256]; // If platform guarantees 255-character maximum
gets(input);
printf("You typed %s, didn't you?", input);
If you can find a platform that actually imposes a limit on input line
lengths, and if you ignore the tremendous disadvantages of having such a
limit.

For example, it's perfectly reasonable to store data in CSV format,
which can easily result in text files with lines hundreds or thousands
of characters long. I've seen JSON data (also plain text) with *very*
long lines.
Post by s***@casperkitty.com
Using fgets doesn't work nearly as conveniently, since it's necessary to
use strlen to get the length of the input, then check for and strip out a
newline, and (if one wants robust behavior in the presence of long lines
at the input) figure out what to do if a line is longer than expected. A
function that was closer to gets(), but which defined a maximum buffer size
and rejected anything past (interactive applications on some systems could
beep if excessive characters were typed) would have been much more useful
in many cases.
stdin is not always connected to an interactive device.

The C standard library's support for interactive input is not
particularly strong -- but there's plenty of support for it outside
the standard.

We don't have a standard replacement for gets() that's quite as
convenient as gets() was. IMHO that's at most a minor problem.
--
Keith Thompson (The_Other_Keith) kst-***@mib.org <http://www.ghoti.net/~kst>
Working, but not speaking, for JetHead Development, Inc.
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Kaz Kylheku
2016-05-26 04:31:18 UTC
Permalink
Raw Message
Post by Keith Thompson
Post by s***@casperkitty.com
Post by Bill Cunningham
fgets. scanf. I really like stdin to fgets myself.
Using fgets with stdin is annoyingly clunky in many cases. On some platforms
which have a guaranteed maximum input-line length, the following would be
char input[256]; // If platform guarantees 255-character maximum
gets(input);
printf("You typed %s, didn't you?", input);
If you can find a platform that actually imposes a limit on input line
lengths, and if you ignore the tremendous disadvantages of having such a
limit.
How can a function that has been nuked from the C language suffer
any further disadvantages? :)

The platform doesn't have to impose line length limitations;
just the gets implementation!

There can be a GETS_MAX in <limits.h>, such that if you do this:

#include <limits.h>

// ...

char input[GETS_MAX];
gets(input); // will not fill more than GETS_MAX including NUL byte

everything is copacetic.

That was the obvious way to fix it.

Small systems can specify small-ish values for GETS_MAX; larger
systems larger values.
Keith Thompson
2016-05-26 16:46:01 UTC
Permalink
Raw Message
Post by Kaz Kylheku
Post by Keith Thompson
Post by s***@casperkitty.com
Post by Bill Cunningham
fgets. scanf. I really like stdin to fgets myself.
Using fgets with stdin is annoyingly clunky in many cases. On some
platforms which have a guaranteed maximum input-line length, the
char input[256]; // If platform guarantees 255-character maximum
gets(input);
printf("You typed %s, didn't you?", input);
If you can find a platform that actually imposes a limit on input line
lengths, and if you ignore the tremendous disadvantages of having such a
limit.
How can a function that has been nuked from the C language suffer
any further disadvantages? :)
I was referring to the disadvantages of imposing a limit on line
length in general, with or without gets(). I assumed that's what
supercat was referring to.
Post by Kaz Kylheku
The platform doesn't have to impose line length limitations;
just the gets implementation!
#include <limits.h>
// ...
char input[GETS_MAX];
gets(input); // will not fill more than GETS_MAX including NUL byte
everything is copacetic.
Except for the plethora of existing code that calls gets() with a buffer
shorter than GETS_MAX bytes. Code that calls gets() would have had to
be modified anyway, to set the buffer size to GETS_MAX. Removing gets()
caused such code to break in a way that forces it to be fixed (once it's
compiled with a C11 implementation).
Post by Kaz Kylheku
That was the obvious way to fix it.
It was *an* obvious way to fix it. (I think Doug Gwyn advocated
limiting it to BUFSIZ, which is 8192 on my system.)
Post by Kaz Kylheku
Small systems can specify small-ish values for GETS_MAX; larger
systems larger values.
--
Keith Thompson (The_Other_Keith) kst-***@mib.org <http://www.ghoti.net/~kst>
Working, but not speaking, for JetHead Development, Inc.
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Kaz Kylheku
2016-05-26 17:55:00 UTC
Permalink
Raw Message
Post by Keith Thompson
Post by Kaz Kylheku
Post by Keith Thompson
Post by s***@casperkitty.com
Post by Bill Cunningham
fgets. scanf. I really like stdin to fgets myself.
Using fgets with stdin is annoyingly clunky in many cases. On some
platforms which have a guaranteed maximum input-line length, the
char input[256]; // If platform guarantees 255-character maximum
gets(input);
printf("You typed %s, didn't you?", input);
If you can find a platform that actually imposes a limit on input line
lengths, and if you ignore the tremendous disadvantages of having such a
limit.
How can a function that has been nuked from the C language suffer
any further disadvantages? :)
I was referring to the disadvantages of imposing a limit on line
length in general, with or without gets(). I assumed that's what
supercat was referring to.
Post by Kaz Kylheku
The platform doesn't have to impose line length limitations;
just the gets implementation!
#include <limits.h>
// ...
char input[GETS_MAX];
gets(input); // will not fill more than GETS_MAX including NUL byte
everything is copacetic.
Except for the plethora of existing code that calls gets() with a buffer
shorter than GETS_MAX bytes.
That code doesn't go away no matter what you add to or remove from the
ISO document.

Almost no code which uses gets is correct (before a proposal such
as the above which introduces safe uses).

Therefore, a gets-related diagnostic is almost never a false positive
w.r.t. legacy code. (That is why it is feasible to have a link-time
warning not to use gets.)

So, under the above gets fix, implementations could diagnose all
situations when the argument to gets is not the result of an
array-to-pointer conversion/decay, or where that array is smaller than
GETS_MAX.

That still leaves programs which aren't recompiled.

Programs which are statically linked can't be fixed no matter
what you put into an ISO language document.

Programs which dynamically link to gets can be fixed by a decent
shared lib system that provides symbol versioning.

We can have it so that newly compiled programs calling gets
actually call __libc_gets_new, for which gets is an alias in the
current version node.

Existing binary clients request an older version node, in which gets
aliased to __libc_gets_old. This function can simpy be removed,
so that old binary clients which use gets will no longer load;
they will refuse to run with an unresolved symbol diagnostic.
s***@casperkitty.com
2016-05-26 05:14:38 UTC
Permalink
Raw Message
Post by Keith Thompson
stdin is not always connected to an interactive device.
Not every platform is Unix; being able to attach stdin to different kinds of
input is sometimes useful, but platforms that are more focused on interactive
I/O can often offer a better user experience than those which take the Unix
approach of buffering lines of input without regard for how an application
will process them, and then passing the input through to the application when
the user presses return.
Keith Thompson
2016-05-26 16:46:55 UTC
Permalink
Raw Message
Post by s***@casperkitty.com
Post by Keith Thompson
stdin is not always connected to an interactive device.
Not every platform is Unix; being able to attach stdin to different kinds of
input is sometimes useful, but platforms that are more focused on interactive
I/O can often offer a better user experience than those which take the Unix
approach of buffering lines of input without regard for how an application
will process them, and then passing the input through to the application when
the user presses return.
For example?
--
Keith Thompson (The_Other_Keith) kst-***@mib.org <http://www.ghoti.net/~kst>
Working, but not speaking, for JetHead Development, Inc.
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Kaz Kylheku
2016-05-26 17:56:47 UTC
Permalink
Raw Message
Post by Keith Thompson
Post by s***@casperkitty.com
Post by Keith Thompson
stdin is not always connected to an interactive device.
Not every platform is Unix; being able to attach stdin to different kinds of
input is sometimes useful, but platforms that are more focused on interactive
I/O can often offer a better user experience than those which take the Unix
approach of buffering lines of input without regard for how an application
will process them, and then passing the input through to the application when
the user presses return.
For example?
For example, the platform Unix, after:

tcsetattr(fileno(stdin), TCSADRAIN, &your_raw_mode_termios).

C standard I/O handles POSIX raw mode TTY input just swimmingly.
s***@casperkitty.com
2016-05-26 18:14:24 UTC
Permalink
Raw Message
Post by Kaz Kylheku
C standard I/O handles POSIX raw mode TTY input just swimmingly.
Well, sort of.

Many other languages include separate "get character" and "get line"
functions, with the former yielding a keystroke as soon as it is typed,
without echoing, and the latter echoing text as it is typed and allowing
the user to edit the input line before "enter" is hit. I don't know if
any C implementations carried that distinction into their getchar() and
gets() methods, but it would certainly be logical on a system where the
compiler-generated code would be talking directly to the keyboard and
display hardware.

While the Unix approach may be workable (I don't think it's 100% reliable
for ensuring that things echo when they should and not when they shouldn't)
it's not standard C, and I see no reason to expect that other implementations
wouldn't have decided that splitting getchar() and gets() [and hopefully
providing a non-broken version of gets() with a specifyable buffer length]
was a nicer approach.

Richard Bos
2016-05-26 10:53:18 UTC
Permalink
Raw Message
Post by Keith Thompson
Post by s***@casperkitty.com
Post by Bill Cunningham
fgets. scanf. I really like stdin to fgets myself.
Using fgets with stdin is annoyingly clunky in many cases. On some platforms
which have a guaranteed maximum input-line length, the following would be
char input[256]; // If platform guarantees 255-character maximum
gets(input);
printf("You typed %s, didn't you?", input);
If you can find a platform that actually imposes a limit on input line
lengths, and if you ignore the tremendous disadvantages of having such a
limit.
And the sysadmin, or a system update, doesn't increase the limit without
you noticing.
And you never accidentally port this code anywhere (but _anywhere_)
else.
And your cow-orkers never unknowingly re-use your code somewhere else.
And...

The only safe way to use gets() involves copious bondage gear and a
decent supply of thermite. Some people might pay good money for that;
I prefer to keep it away from my code.

Richard
s***@casperkitty.com
2016-05-26 13:41:03 UTC
Permalink
Raw Message
Post by Richard Bos
And the sysadmin, or a system update, doesn't increase the limit without
you noticing.
Not a danger on systems with static linkage, provided the header and library
file stay in sync.
Keith Thompson
2016-05-26 16:48:36 UTC
Permalink
Raw Message
Post by s***@casperkitty.com
Post by Richard Bos
And the sysadmin, or a system update, doesn't increase the limit without
you noticing.
Not a danger on systems with static linkage, provided the header and library
file stay in sync.
Your sample program had a literal 256 as the buffer size. Rebuild it
with a line length limit of 512 bytes, and it breaks.
--
Keith Thompson (The_Other_Keith) kst-***@mib.org <http://www.ghoti.net/~kst>
Working, but not speaking, for JetHead Development, Inc.
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
s***@casperkitty.com
2016-05-26 15:29:31 UTC
Permalink
Raw Message
Post by Richard Bos
And you never accidentally port this code anywhere (but _anywhere_)
else.
And your cow-orkers never unknowingly re-use your code somewhere else.
And...
I should clarify, btw, that I think the right approach would have been to
define a proper replacement for gets() which includes parameters for the
size of the buffer and an indication for how over-length lines should be
handled, and the Standard should have specified that compliant implementations
must allow user code to define gets() however it sees fit (an implementation
could either leave it undefined, or pre-define it using "weak-definition"
features of the implementation so as to allow for re-definition. That way,
code which is written for a platform where gets() is limited to a certain
length could define a version of gets() which chained to the new version
and used whatever maximum length the application code had been expecting.
Keith Thompson
2016-05-26 16:50:39 UTC
Permalink
Raw Message
Post by s***@casperkitty.com
Post by Richard Bos
And you never accidentally port this code anywhere (but _anywhere_)
else.
And your cow-orkers never unknowingly re-use your code somewhere else.
And...
I should clarify, btw, that I think the right approach would have been
to define a proper replacement for gets() which includes parameters
for the size of the buffer and an indication for how over-length lines
should be handled, and the Standard should have specified that
compliant implementations must allow user code to define gets()
however it sees fit (an implementation could either leave it
undefined, or pre-define it using "weak-definition" features of the
implementation so as to allow for re-definition. That way, code which
is written for a platform where gets() is limited to a certain length
could define a version of gets() which chained to the new version and
used whatever maximum length the application code had been expecting.
Code is already allowed to define gets() in any way it likes. Since it
was removed from the library, it's no longer a reserved identifier.
(I'd recommend *not* defining gets() to avoid confusion, but it's
legal.)
--
Keith Thompson (The_Other_Keith) kst-***@mib.org <http://www.ghoti.net/~kst>
Working, but not speaking, for JetHead Development, Inc.
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Francis Glassborow
2016-05-26 17:33:48 UTC
Permalink
Raw Message
Post by s***@casperkitty.com
Post by Richard Bos
And you never accidentally port this code anywhere (but _anywhere_)
else.
And your cow-orkers never unknowingly re-use your code somewhere else.
And...
I should clarify, btw, that I think the right approach would have been to
define a proper replacement for gets() which includes parameters for the
size of the buffer and an indication for how over-length lines should be
handled, and the Standard should have specified that compliant implementations
must allow user code to define gets() however it sees fit (an implementation
could either leave it undefined, or pre-define it using "weak-definition"
features of the implementation so as to allow for re-definition. That way,
code which is written for a platform where gets() is limited to a certain
length could define a version of gets() which chained to the new version
and used whatever maximum length the application code had been expecting.
Removing something from the standard library does not prevent an
implementation from providing it.

Francis
Bill Cunningham
2016-05-25 23:16:41 UTC
Permalink
Raw Message
Post by Keith Thompson
Post by Francis Glassborow
Post by Richard Kettlewell
The Committee decided that gets was useful and convenient in those
special circumstances when the programmer does have adequate control
over the input, and as longstanding existing practice, it needed a
standard specification.
...so I wonder what changed for C2011.
They finally understood how bad it was and any programmer who had
enough knowledge to use it 'safely' knew how to write it for
themselves.
Perhaps there's hope for a more pragmatic approach to the other
landmines in C then...
Perhaps -- but none of them are as bad as gets(). Every other
standard library function *can* be used safely with some care.
gets() cannot be used safely unless you have control over what will
appear on standard input.
In code your writing for yourself and you want to throw something in
quick and you understand not to overflow it, well just make sure to take it
out before you share it. That might be a use.
Richard Bos
2016-05-26 10:53:54 UTC
Permalink
Raw Message
Post by Bill Cunningham
In code your writing for yourself and you want to throw something in
quick and you understand not to overflow it, well just make sure to take it
out before you share it. That might be a use.
You evidently don't have a cat, or a toddler.

Richard
Bill Cunningham
2016-05-26 16:27:07 UTC
Permalink
Raw Message
Post by Richard Bos
You evidently don't have a cat, or a toddler.
A 16 yo and a 2 year cat.
Kaz Kylheku
2016-05-23 15:37:28 UTC
Permalink
Raw Message
Post by Richard Kettlewell
Post by Casper H.S. Dik
So gets() can't be used by any program that want to make sure it
works properly regarding of the inputs given to it, it is proper to
remove it from the standard.
The Committee decided that gets was useful and convenient in those
special circumstances when the programmer does have adequate control
over the input, and as longstanding existing practice, it needed a
standard specification.
...so I wonder what changed for C2011.
The passage of some 12 years, for one thing.
Francis Glassborow
2016-05-23 09:05:38 UTC
Permalink
Raw Message
Post by Bill Cunningham
I just wondered how many people like me think removing gets() from the
standard is a mistake. I think so because C has some much heritage left over
from so many different standards; such as c89 C99 C11. It is well know about
gets() problems just don't use it. C++ style comments were added the /* */
comment delimiters weren't removed. sterror ad errno was added. perror
wasn't removed.
Versatility and using various mixes and styles is part of C's appeal. I
like C89 and C99 myself. C11 I don't even bother with.
Bill
Please give an example where calling gets() would not be prone to error.
Books for novices and newcomers to C are littered with its use (actually
I cannot recall any introductory text for C that does not use it--
without any warnings as to its vulnerabilities). Authors continued to
argue that as it is in the Standard it must be fine. At least we can now
point out that it was withdrawn from the Standard because it has a
serious (and dangerous) flaw.

Francis
Kaz Kylheku
2016-05-23 15:46:41 UTC
Permalink
Raw Message
Post by Francis Glassborow
Post by Bill Cunningham
I just wondered how many people like me think removing gets() from the
standard is a mistake. I think so because C has some much heritage left over
from so many different standards; such as c89 C99 C11. It is well know about
gets() problems just don't use it. C++ style comments were added the /* */
comment delimiters weren't removed. sterror ad errno was added. perror
wasn't removed.
Versatility and using various mixes and styles is part of C's appeal. I
like C89 and C99 myself. C11 I don't even bother with.
Bill
Please give an example where calling gets() would not be prone to error.
Say I have a compiler which puts out textual assembly language, coded
in such a way that guarantees that no line of output is possibly longer
than 511 bytes. In the assembler, I do gets(input) on an array of 1024.

The two pieces are effectively a closed system, like two functions.
Functions in the same modulecan use unsafe interfaces between them. This
is just normal engineering. Instance, in an amplifier, the VAS (voltage
amplification stage) does not require an elaborate circuit to protect
against overvoltage from the input stage; it is not expected that the
stage will generate a 1500V spike. (And how could it, when the supply
rails are +/- 35V, and there is no inductor in there.) The device as a
whole may carry such protection, if it is a requirement to have it
built-in rather than using an external one.

I can't fathom, however, why this type of situation would make gets
"useful" and "convenient"; it saves hardly a minute's worth of work
compared to using fgets and, say, cleanly bailing the program on
excessive input length. "Convenient" and "useful" are things that
achieve some considerable improvements in productivity, readability,
maintainability.
s***@casperkitty.com
2016-05-23 16:36:22 UTC
Permalink
Raw Message
Post by Kaz Kylheku
I can't fathom, however, why this type of situation would make gets
"useful" and "convenient"; it saves hardly a minute's worth of work
compared to using fgets and, say, cleanly bailing the program on
excessive input length. "Convenient" and "useful" are things that
achieve some considerable improvements in productivity, readability,
maintainability.
There is one way in which gets() is superior to anything else in the C
library: it avoids the need to scan the string to strip out the newline.
I would suggest, however, that rather than keeping gets(), it would be
better to instead define a variant of fgets() that includes that advantage.
I'm not sure what best to call it, but I'd suggest that what would be
best would be to define a function that could be used as a basis for fgets,
gets, and other more useful variants which behaved just like fgets except
that:

1. It would accept a pointer to the byte following the end of the buffer
space it should use (facilitating the use of repeated calls to fill up
a buffer without having to recompute the remaining amount of space).

2. An option flag would permit it to trash the buffer following the newline
in cases where reading extra data, finding the newline, and rewinding the
file would be faster than character-by-character reads, and would indicate
whether lines longer than the buffer should have the balance flushed or
left pending.

3. The function would return a pointer to the byte following the last byte
that was "logically" read (and not put back) in case of success, or
NULL in case of error (reading a clean EOF would not be an error, but
would simply cause the function to return the passed-in pointer).

Such a function could then make it easy to write within user code a variety
of fgets() variants which are customized to particular application needs,
and would eliminate the one advantage gets() has over anything else the
library currently supports.
s***@casperkitty.com
2016-05-24 16:55:46 UTC
Permalink
Raw Message
Post by Francis Glassborow
Please give an example where calling gets() would not be prone to error.
On systems where stdin supports line-buffered input only and does not
allow redirection from files which could contain arbitrarily-long lines,
there may be a system-guaranteed maximum number of characters that could
be received without a newline. On such a system, it would be safe to use
gets() with a buffer whose size was sufficient to handle the longest
possible input line.

Of course, one isn't likely to find many such systems today outside museums,
but many such systems were produced in the 1970s and were still being used
in the 1980s. Perhaps the C Standard could have been improved in 1989 by
defining a macro which would indicate the buffer size required to make gets()
safe, and then specifying that gets() was limited to that size [which
must be at least 1, but which implementations could otherwise set as large
or as small as they saw fit]. If gets(x) was defined as a macro
__gets##GETS_MAX(x), compiler options could then be used to configure the
value to facilitate porting of code designed for systems which limited the
length of input lines.
Randy Howard
2016-05-24 17:01:00 UTC
Permalink
Raw Message
Post by s***@casperkitty.com
Post by Francis Glassborow
Please give an example where calling gets() would not be prone to error.
On systems where stdin supports line-buffered input only and does not
allow redirection from files which could contain arbitrarily-long lines,
there may be a system-guaranteed maximum number of characters that could
be received without a newline. On such a system, it would be safe to use
gets() with a buffer whose size was sufficient to handle the longest
possible input line.
There are other ways in which it could be used with a reasonable
expectation of safety. For example, as a utility to be used in a pipe
for a specific purpose. someprog | gets_filter | someotherprog

If a regular 'user' is not expected (or even to have writes) to
invoke it directly, it could be used with well defined input in a
way that isn't 'horrible'. Admittedly contrived today, but possibly
exactly what was expected in the beginning.
--
Randy Howard
(replace the obvious text in the obvious way if you wish to contact me
directly)
Kaz Kylheku
2016-05-24 17:54:59 UTC
Permalink
Raw Message
Post by Randy Howard
Post by s***@casperkitty.com
Post by Francis Glassborow
Please give an example where calling gets() would not be prone to error.
On systems where stdin supports line-buffered input only and does not
allow redirection from files which could contain arbitrarily-long lines,
there may be a system-guaranteed maximum number of characters that could
be received without a newline. On such a system, it would be safe to use
gets() with a buffer whose size was sufficient to handle the longest
possible input line.
There are other ways in which it could be used with a reasonable
expectation of safety. For example, as a utility to be used in a pipe
for a specific purpose. someprog | gets_filter | someotherprog
If a regular 'user' is not expected (or even to have writes) to
invoke it directly, it could be used with well defined input in a
way that isn't 'horrible'. Admittedly contrived today, but possibly
exactly what was expected in the beginning.
Such a filter situation can exist within a POSIX application that
creates pipes and forks sub-processes, without execing a different
image. Then it's entirely an internal matter. There is a monolithic
executable which cannot be used in any way such that the limit is
exceeded.
Post by Randy Howard
way that isn't 'horrible'. Admittedly contrived today, but possibly
exactly what was expected in the beginning.
Too bad they used in ftpd and other programs to read network input,
giving it a bad name! :)
Kaz Kylheku
2016-05-24 17:48:27 UTC
Permalink
Raw Message
Post by s***@casperkitty.com
Post by Francis Glassborow
Please give an example where calling gets() would not be prone to error.
On systems where stdin supports line-buffered input only and does not
allow redirection from files which could contain arbitrarily-long lines,
there may be a system-guaranteed maximum number of characters that could
be received without a newline. On such a system, it would be safe to use
gets() with a buffer whose size was sufficient to handle the longest
possible input line.
Line-buffering is a red herring there. If you know that the
system somehow doesn't allow lines longer than N, then gets(array)
with char array[N + 1] is safe, fully buffered or not.

(Full versus line buffering affects output, determining the situations
when an implicit flush takes place.)
Post by s***@casperkitty.com
Of course, one isn't likely to find many such systems today outside museums,
but many such systems were produced in the 1970s and were still being used
in the 1980s. Perhaps the C Standard could have been improved in 1989 by
defining a macro which would indicate the buffer size required to make gets()
safe , and then specifying that gets() was limited to that size [which
must be at least 1, but which implementations could otherwise set as large
or as small as they saw fit].
This could be done on any implementation whatsoever, regardless of
its characteristics: require <limits.h> to provide a macro which
indicates at most how many characters may be placed into the
array by gets, including null termination.
Bill Cunningham
2016-05-25 23:20:01 UTC
Permalink
Raw Message
"Francis Glassborow" <***@btinternet.com> wrote in message news:nhuguf$a56$***@dont-email.me...

[...]
Post by Francis Glassborow
Please give an example where calling gets() would not be prone to error.
Books for novices and newcomers to C are littered with its use (actually I
cannot recall any introductory text for C that does not use it--
without any warnings as to its vulnerabilities). Authors continued to
argue that as it is in the Standard it must be fine. At least we can now
point out that it was withdrawn from the Standard because it has a serious
(and dangerous) flaw.
Not prove to error. Writing test code and you know gets's flaws. Throw
it in quick, use it and remove it.

Bill
Keith Thompson
2016-05-25 23:56:21 UTC
Permalink
Raw Message
Post by Bill Cunningham
[...]
Post by Francis Glassborow
Please give an example where calling gets() would not be prone to error.
Books for novices and newcomers to C are littered with its use (actually I
cannot recall any introductory text for C that does not use it--
without any warnings as to its vulnerabilities). Authors continued to
argue that as it is in the Standard it must be fine. At least we can now
point out that it was withdrawn from the Standard because it has a serious
(and dangerous) flaw.
Not prove to error. Writing test code and you know gets's flaws. Throw
it in quick, use it and remove it.
That's not a good enough reason to have it in the standard.

Any C programmer with any skill can write a gets() equivalent, or can
write or use something safer.

gets() is gone. There is no such function in the C standard library.
Do you propose putting it back in the next edition of the standard?
--
Keith Thompson (The_Other_Keith) kst-***@mib.org <http://www.ghoti.net/~kst>
Working, but not speaking, for JetHead Development, Inc.
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Bill Cunningham
2016-05-26 01:00:40 UTC
Permalink
Raw Message
Post by Keith Thompson
Any C programmer with any skill can write a gets() equivalent, or can
write or use something safer.
gets() is gone. There is no such function in the C standard library.
Do you propose putting it back in the next edition of the standard?
Maybe in memorium to DMR. It must've at one time had a purpose anyway.

Bill
Keith Thompson
2016-05-26 01:37:24 UTC
Permalink
Raw Message
Post by Bill Cunningham
Post by Keith Thompson
Any C programmer with any skill can write a gets() equivalent, or can
write or use something safer.
gets() is gone. There is no such function in the C standard library.
Do you propose putting it back in the next edition of the standard?
Maybe in memorium to DMR. It must've at one time had a purpose anyway.
Of course it had a purpose. It just performed that purpose badly.

I don't know whether Dennis Ritchie was responsible for the gets()
function. If he was, restoring his mistake to the standard would
hardly be a fitting memorial.

It's gone. Nobody here other than you wants it back. Get over it.
--
Keith Thompson (The_Other_Keith) kst-***@mib.org <http://www.ghoti.net/~kst>
Working, but not speaking, for JetHead Development, Inc.
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Randy Howard
2016-05-24 15:59:26 UTC
Permalink
Raw Message
Post by Bill Cunningham
I just wondered how many people like me think removing gets() from the
standard is a mistake.
Many others have spoken already, but my two cents are that they should
have done it long ago. It's a simple enough function that anyone truly
wanting it could roll their own, and do a better job in the process. In
fact, I'd make a bar bet that just about every serious C programmer with
a lot of years of experience with C probably has already replaced it in
their own personal 'kitchen sink' library that they carry around with
them. Probably along with strtok() and pretty much everything that has
a ludicrous _s() suffix in the standard lib today.
Post by Bill Cunningham
I think so because C has some much heritage left over from so many
different standards; such as c89 C99 C11.
That's because they didn't *replace* C with another language every
time they put out another overpriced and underwonderful standard
document. That said, although there was much to like and little that
could not be accomplished with original K&R C, some things did get
tweaked. Occasionally those tweaks were even valuable.
Post by Bill Cunningham
It is well know about gets() problems just don't use it.
I'm not quite sure I am parsing the intent behind this sentence
correctly. If you meant to write that in order to avoid gets()
problems you should just not use it, then I can agree with the
logic of that. Unfortunately, in practice, that is not what happens.
CS professors all over the globe apparently love to use gets() even
today as a quick and dirty way to introduce young kids to C for
the first time, and usually without any warning(s). You see it
come up over and over again in places like comp.lang.c and various
IRC channels, usually around the start of a new term.
Post by Bill Cunningham
C++ style comments were added the /* */ comment delimiters
weren't removed.
And there is no reason to remove them. There aren't in any way
dangerous, and I'll make a little confession, I still use them
instead of the C++ flavor.
Post by Bill Cunningham
sterror ad errno was added. perror wasn't removed.
Again, perror isn't inherently broken, as gets clearly has been
all along.
Post by Bill Cunningham
Versatility and using various mixes and styles is part of C's appeal. I
like C89 and C99 myself. C11 I don't even bother with.
Well, you can certainly make a valid case that some, perhaps even many
of the things added in various versions of the standard aren't needed or
even useful for many programs. I'm not sure how that makes any kind of
argument in favor of keeping gets around though.

Putting it somewhat crudely, I was actually surprised to learn that the
committee had grown a pair and finally removed it. Then that feeling
was somewhat lessened when I saw gets_s. Then somewhat improved when
I realized that it was optional, so nobody will ever use it, which
perhaps was the real intent all along :-)
--
Randy Howard
(replace the obvious text in the obvious way if you wish to contact me
directly)
Loading...