I am a newbie in C programming.
I have to make an implementation of gets() function from stdio.h, but
I am not sure where to start.
Please advice, any help is welcome.
Thank you,
Brian.
> Please advice, any help is welcome.
My first advice is: This is a bad assignment, because the gets()
function is inherently broken.
Your instructor may not know this, but strictly speaking, you're not
allowed to make a function named gets() -- that name is reserved. You
can try it, and it might even happen to work, but it's not really
the right thing to do.
Here's a thing to start with.
Describe what gets() does. What parameters does it take? What does
it return? What does it *DO*?
For instance, I might start out with something like:
The mygets() function takes as a parameter the address of a
buffer assumed to be large enough to hold any input data.
The function then gets characters from standard input until
it sees either EOF or a newline, at which point it null
terminates the string and returns. If no characters are
received before EOF, the function indicates an error.
That's not a very good spec -- see if you can find some of the flaws
in it and correct them.
Once you have the spec, it shouldn't be too hard to write the routine.
-s
--
Copyright 2010, all wrongs reversed. Peter Seebach / usenet...@seebs.net
http://www.seebs.net/log/ <-- lawsuits, religion, and funny pictures
http://en.wikipedia.org/wiki/Fair_Game_(Scientology) <-- get educated!
As others have pointed out, gets() will (probably) crash if you pass
it a buffer shorter than the line you read. Given the specifications,
there's no way to prevent this behaviour, so think of it as an
undesireable feature rather than a bug.
Thank you for your thorough advice.
For example a standard description of gets() function says:
The gets() function shall read bytes from the standard input stream,
stdin, into the array pointed to by s, until a <newline> is read or an
end-of-file condition is encountered. Any <newline> shall be discarded
and a null byte shall be placed immediately after the last byte read
into the array.
I would like to do the same. Some guy recommended me to use getc() and
a loop,
But I think I should to try to implement it without using standard
stdio.h function, just pure C programming, if you know what I mean....
What could you advice on that?
Virtually all of this programming can be done in C, or C with a few
extensions and assembly calls. However it's imossible to do it without
an intimate knowledge of the system. Whilst not excessively
complicated or difficult, it tends to be hard to find the information
and it's not very accessibly-presented, because very few people have a
need to write keyborad drivers.
Don't. There's no such thing as "pure C programming" -- unless you mean
"using the standard library only, not any implementation-specific stuff".
In any given environment, there may well be a way to do whatever would
be done under the hood by something like getchar(). For instance, on
Unix-like systems, you could probably do this with read(2). ("(2)" is
an indicator of the section of the manual to look in, not an argument
to pass to read().) But this is a BAD thing to do when you're at a novice
level.
The *purest* C is when you use the standard library and no platform-specific
stuff. Any time you migrate away from that, you're migrating away from
pure C.
-s
--
Or think of it as a bug in the requirement, rather than a bug in your
code.
--
Keith Thompson (The_Other_Keith) ks...@mib.org <http://www.ghoti.net/~kst>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
>On 10 Apr, 16:41, brian <bec...@gmail.com> wrote:
>>
>> But I think I should to try to implement it without using standard
>> stdio.h function, just pure C programming, if you know what I mean....
>> What could you advice on that?
>>
>The problem is implementing getchar(). Once ypu've done that, it's
>trivial to build gets() on top.
>I don't know exactly how the system works myself these days, but
>essentially it goes something like this. The keyboard sends an
>interrupt to the processor when a key is depressed, and another one
>when it is released. In the interrupt routine, the processor can query
That may be how it works on your system but my keyboard sends no
signals to the processor until enter is pressed. I wonder how it
works on the OP's system or if he even knows.
>the state of the keyboard, finding out which keys are depressed. That
>raw information is passed to a higher-level process, which translates
>the pattern of physical key presses into a "keyborad buffer"
>contianing a queue of characters. Applications level-programs then
>extract characters from the queue. There's some system for sending the
>right characters to the program which has keyboard focus at the time.
>
>Virtually all of this programming can be done in C, or C with a few
>extensions and assembly calls. However it's imossible to do it without
>an intimate knowledge of the system. Whilst not excessively
>complicated or difficult, it tends to be hard to find the information
>and it's not very accessibly-presented, because very few people have a
>need to write keyborad drivers.
--
Remove del for email
>Thank you for your thorough advice.
>
>For example a standard description of gets() function says:
>The gets() function shall read bytes from the standard input stream,
>stdin, into the array pointed to by s, until a <newline> is read or an
>end-of-file condition is encountered. Any <newline> shall be discarded
>and a null byte shall be placed immediately after the last byte read
>into the array.
>
>I would like to do the same. Some guy recommended me to use getc() and
>a loop,
>But I think I should to try to implement it without using standard
>stdio.h function, just pure C programming, if you know what I mean....
>What could you advice on that?
It is extremely counter productive for a newcomer to try to
simultaneously learn both C and the internal workings of both the
hardware and operating system. Too many brand new concepts lead to
confusion, not understanding.
"Pure C programming" uses only the features described in the standard.
If you want to try to build a "complex" function (such as gets) using
only the more "basic" functions available (such as getchar), it is not
a completely unreasonable exercise. But to discard all standard
functions and try to use system specific tools eliminates one of the
major reasons for studying C in the first place, its ability to create
portable functions.
That must suck for tetris. Or vi, or notepad. Or even a shell.
Or text entry in a browser window. Or keyboard shortcuts in
any gui program. Or basically almost anything. I would find such
a keyboard basically useless.
Are you _sure_?
Phil
--
I find the easiest thing to do is to k/f myself and just troll away
-- David Melville on r.a.s.f1
> That must suck for tetris. Or vi, or notepad. Or even a shell.
> Or text entry in a browser window. Or keyboard shortcuts in
> any gui program. Or basically almost anything. I would find such
> a keyboard basically useless.
> Are you _sure_?
Could be a smart terminal -- such certainly exist. The keyboard I'm
typing this on is not electrically connected to the machine that's
running the editor I'm writing in -- and while right now it's sending signals
to that machine pretty much whenever I hit a key, it can also arrange
to send no signals until I hit enter on this machine over here.
But the canonical example was the old mainframe terminals which sent a
form, and then the terminal let you edit the form, and then send back
the entire form as a block.
-s
--
It's called an IBM mainframe and I am sure. As for being useless,
there seems to be a significant body of evidence to the contrary. But
then, it wasn't designed for games. And I consider the ISPF editor I
use on it infinitely superior to both vi and Notepad but that is just
a personal opinion which will probably cause this thread to degenerate
into another "my favorite editor" religious war. (I understand your
points about the other applications but I don't see why it would
affect a shell. The ones I occasionally use on a Sun workstation
running some flavor of Solaris don't seem to do anything until I press
enter anyway.)
They can do fairly elaborate command-line editing and things like "when
I hit tab, expand the word I've just typed into the longest unique filename
matching it" or "when I hit /, start searching for previous commands
matching a pattern".
So they really are live/interactive at that point.
-s
--
/*
** getc is the bottom level in C io programming.
** This is what the output for getcx.c looks like on my machine:
*/
/* BEGIN getcx.c output */
getc(X) looks like this: (--(X)->_cnt >= 0 ? 0xff & *(X)->_ptr++ :
_filbuf(X))
/* END getcx.c output */
/*
** This is what getcx.c looks like:
*/
/* BEGIN getcx.c */
#include <stdio.h>
#define str(s) # s
#define xstr(s) str(s)
int main(void)
{
puts("/* BEGIN getcx.c output */\n");
#ifndef getc
puts("getc is not a macro.");
#else
puts("getc(X) looks like this: " xstr(getc(X)));
#endif
puts("\n/* END getcx.c output */");
return 0;
}
/* END getcx.c */
--
pete
It sounds quite difficult to use.
How do you know you haven't made mistake before you hit Enter?
Typing a password with a conventional machine is also difficult but at least
you can see how many characters you've typed.
Does the mouse work the same way, nothing happens until you click the
button?
--
Bartc
>
>"Barry Schwarz" <schw...@dqel.com> wrote in message
>news:cig1s5pmnjp3p7bs7...@4ax.com...
>> On Sat, 10 Apr 2010 09:45:10 -0700 (PDT), Malcolm McLean
>> <malcolm...@btinternet.com> wrote:
>>
>>>On 10 Apr, 16:41, brian <bec...@gmail.com> wrote:
>>>>
>>>> But I think I should to try to implement it without using standard
>>>> stdio.h function, just pure C programming, if you know what I mean....
>>>> What could you advice on that?
>>>>
>>>The problem is implementing getchar(). Once ypu've done that, it's
>>>trivial to build gets() on top.
>>>I don't know exactly how the system works myself these days, but
>>>essentially it goes something like this. The keyboard sends an
>>>interrupt to the processor when a key is depressed, and another one
>>>when it is released. In the interrupt routine, the processor can query
>>
>> That may be how it works on your system but my keyboard sends no
>> signals to the processor until enter is pressed. I wonder how it
>> works on the OP's system or if he even knows.
>
>It sounds quite difficult to use.
>
>How do you know you haven't made mistake before you hit Enter?
The fact that no data has been sent to the processor doesn't mean you
can't read it on the screen. One might consider the screen as the
buffer where the data is held until Enter is pressed.
>
>Typing a password with a conventional machine is also difficult but at least
>you can see how many characters you've typed.
I assume by conventional you mean PC.
Believe it or not, there are real security people who say that
displaying those cute little asterisks is a bad idea. It allows any
over-the-shoulder lurker to see how many characters are in your
password, thus making attempts to hack the password easier.
>
>Does the mouse work the same way, nothing happens until you click the
>button?
My system doesn't actually use a mouse but - Since the cursor moves
when I type without any help from the processor, I wouldn't need the
processor to move the cursor using some pointing device either.
>>> That may be how it works on your system but my keyboard sends no
>>> signals to the processor until enter is pressed. I wonder how it
>>> works on the OP's system or if he even knows.
>>
>>It sounds quite difficult to use.
>>
>>How do you know you haven't made mistake before you hit Enter?
>
> The fact that no data has been sent to the processor doesn't mean you
> can't read it on the screen. One might consider the screen as the
> buffer where the data is held until Enter is pressed.
OK, so maybe there's a local processor which reads or scans the keyboard and
updates the display (unless your terminal is so old that it uses random
logic).
In that case, perhaps that can be considered the 'processor'. As far as the
main processor is concerned, it doesn't have a proper interactive device
attached, only something that might sporadically give a line of text.
>>Typing a password with a conventional machine is also difficult but at
>>least
>>you can see how many characters you've typed.
>
> I assume by conventional you mean PC.
>
> Believe it or not, there are real security people who say that
> displaying those cute little asterisks is a bad idea. It allows any
> over-the-shoulder lurker to see how many characters are in your
> password, thus making attempts to hack the password easier.
(Does it? What word am I thinking of at this minute? I'll give you a clue:
it's got 7 letters and not 6 or 8 or 9.
But maybe password input should allow extra, discarded, white space to fix
that.)
--
Bartc
Any outside knowledge about my password is too much.
> But maybe password input should allow extra, discarded, white space to fix
> that.)
No thanks. What if a password actually contains whitespace?
Incidentally, I once used a system that would echo a dot for each
character of a password, but would echo a space for any spaces that
were actually part of the password.
Right -- but your C code is running on the big processor.
-s
--
>
>"Barry Schwarz" <schw...@dqel.com> wrote in message
>news:g904s5t7j11m616vh...@4ax.com...
>> On Sun, 11 Apr 2010 17:56:54 -0000, "bartc" <ba...@freeuk.com> wrote:
>>>"Barry Schwarz" <schw...@dqel.com> wrote in message
>>>news:cig1s5pmnjp3p7bs7...@4ax.com...
>
>>>> That may be how it works on your system but my keyboard sends no
>>>> signals to the processor until enter is pressed. I wonder how it
>>>> works on the OP's system or if he even knows.
>>>
>>>It sounds quite difficult to use.
>>>
>>>How do you know you haven't made mistake before you hit Enter?
>>
>> The fact that no data has been sent to the processor doesn't mean you
>> can't read it on the screen. One might consider the screen as the
>> buffer where the data is held until Enter is pressed.
>
>OK, so maybe there's a local processor which reads or scans the keyboard and
>updates the display (unless your terminal is so old that it uses random
>logic).
>
>In that case, perhaps that can be considered the 'processor'. As far as the
>main processor is concerned, it doesn't have a proper interactive device
>attached, only something that might sporadically give a line of text.
Since you get to define what you mean by proper, your assessment is
obviously correct.
However, in the context of this discussion, my counter-example serves
to show conclusively that the original description of how often the
processor executing the C code is interrupted by the user typing was
hardly universal.
>
>>>Typing a password with a conventional machine is also difficult but at
>>>least
>>>you can see how many characters you've typed.
>>
>> I assume by conventional you mean PC.
>>
>> Believe it or not, there are real security people who say that
>> displaying those cute little asterisks is a bad idea. It allows any
>> over-the-shoulder lurker to see how many characters are in your
>> password, thus making attempts to hack the password easier.
>
>(Does it? What word am I thinking of at this minute? I'll give you a clue:
>it's got 7 letters and not 6 or 8 or 9.
So now my exhaustive attack no longer has to deal with any password
length other than 7. Considering only letters and numbers, a
6-character password can contain any of pow(6,36) possible values.
Similar values for the longer ones. By restricting my effort, you
have reduced my task by 99.988%, from 2.28556E34 to 2.65173E30.
(Calculation performed using Excel 2003 with default options.) A
ten-thousand fold reduction in effort meets my definition of easier.
> > > I am a newbie in C programming.
> > > I have to make an implementation of gets() function from stdio.h, but
> > > I am not sure where to start.
> > > Please advice, any help is welcome.
>
> > My first advice is: Â This is a bad assignment, because the gets()
> > function is inherently broken.
google for it. Basically gets() has no way to know how large the
buffer you called it with is. Hence a user can type charcaters until
the buffer overflows and then Bad Things Happen. I believe the latest
draft standard is removing gets() from the standard C library. And
about time too.
> > Your instructor may not know this, but strictly speaking, you're not
> > allowed to make a function named gets() -- that name is reserved. Â You
> > can try it, and it might even happen to work, but it's not really
> > the right thing to do.
>
> > Here's a thing to start with.
>
> > Describe what gets() does. Â What parameters does it take? Â What does
> > it return? Â What does it *DO*?
>
> > For instance, I might start out with something like:
> > Â Â Â Â The mygets() function takes as a parameter the address of a
> > Â Â Â Â buffer assumed to be large enough to hold any input data.
> > Â Â Â Â The function then gets characters from standard input until
> > Â Â Â Â it sees either EOF or a newline, at which point it null
> > Â Â Â Â terminates the string and returns. Â If no characters are
> > Â Â Â Â received before EOF, the function indicates an error.
>
> > That's not a very good spec -- see if you can find some of the flaws
> > in it and correct them.
>
> > Once you have the spec, it shouldn't be too hard to write the routine.
>
> > -s
> > --
> > Copyright 2010, all wrongs reversed. Â Peter Seebach / usenet-nos...@seebs.nethttp://www.seebs.net/log/<-- lawsuits, religion, and funny pictureshttp://en.wikipedia.org/wiki/Fair_Game_(Scientology) <-- get educated!
don't quote sigs- text that appears after "-- "
> Thank you for your thorough advice.
>
> For example a standard description of gets() function says:
> The gets() function shall read bytes from the standard input stream,
> stdin, into the array pointed to by s, until a <newline> is read or an
> end-of-file condition is encountered. Any <newline> shall be discarded
> and a null byte shall be placed immediately after the last byte read
> into the array.
>
> I would like to do the same. Some guy recommended me to use getc() and
> a loop,
> But I think I should to try to implement it without using standard
> stdio.h function, just pure C programming, if you know what I mean....
> What could you advice on that?
ask whoever set the assignment if this is what he intended. But I
doubt he intended the assignment to be as hard as that. You can't
write getc() completly in standard C. At some point you're going to
have to access the hardware and you can't do this in standard C. Plus
modern operating systems make direct access to the hardware quite
difficult (for very good reasons)
if yer lucky
gts() has been implicated in various security breaches
> Given the specifications,
> there's no way to prevent this behaviour, so think of it as an
> undesireable feature rather than a bug.
I consider behaviour as bad as this to be a bug
Malcolm, that isn't how password crackers work. You don't sit at the
keyboard and guess. You sit at the keyboard and run your
password-cracking program, which tries millions of passwords a second,
and it starts off by whizzing through the dictionary and minor
variations thereof.
> If you can try a billion passwords a
> second, it's 10^21 versus 10^25 seconds. You'll be just as dead before
> the shorter time is up than before the longer one is.
Anyone stupid enough to type in his password where an adversary can
count the asterisks may well be stupid enough to use a seven-letter
English word as his seven-letter password, in which case the castle wall
could well be breached in just a few seconds.
--
Richard Heathfield <http://www.cpax.org.uk>
Email: -http://www. +rjh@
"Usenet is a strange place" - dmr 29 July 1999
Sig line vacant - apply within
Start off by finding out why gets() is an open invitation to adversaries
to stomp all over your system.
Once you know that, implementing gets() is easy - Just Say No.
And if I have any *other* information, it's quite possible that
knowing your password is 7 characters makes an otherwise infeasible
attack feasible.
Consider a system that requires all passwords to be exactly 7
characters, no more, no less. Is such a system more or less secure
than a system that allows longer passwords?
If we have the same security expert in mind, he changed his mind
over such things radically a while back. A perfect example of why
Appeal to Authority really can be a logical fallacy.
>>> It allows any
>>> over-the-shoulder lurker to see how many characters are in your
>>> password, thus making attempts to hack the password easier.
>>
>>(Does it? What word am I thinking of at this minute? I'll give you a clue:
>>it's got 7 letters and not 6 or 8 or 9.
>
> So now my exhaustive attack no longer has to deal with any password
> length other than 7. Considering only letters and numbers, a
> 6-character password can contain any of pow(6,36) possible values.
> Similar values for the longer ones. By restricting my effort, you
> have reduced my task by 99.988%, from 2.28556E34 to 2.65173E30.
> (Calculation performed using Excel 2003 with default options.) A
> ten-thousand fold reduction in effort meets my definition of easier.
If you'd be saving 99.988%, then you'd have been doing it wrong.
You've not indicated in what order you would perform your exhaustive
attack. Most sensible techniques will start with the lowest entropy
ones first. Therefore you'd not even start any 8- or 9- character ones
until you'd completed the 7-character ones. Therefore you can't count
the fact that you don't search >7-character passwords as a saving.
You can avoid searching shorter passwords, but that's a saving of 2.9%
(or 1.6% if you assume mixed case).
So a divide and conquer strategy where different resources are used in
parallel to test passwords of different lengths wouldn't be sensible.
Neither would one where the resource are split depending on some
initial sequence of characters. I thought I read an article some
years ago how a collaborative effort (along the lines of SETI) was
able to factor a very large composite number into its two large prime
constituents in a quite reasonable time frame. It seems that hacking
a password could achieve the same benefit. But, since I don't attempt
to hack passwords, I must allow for the possibility you're right.
So what I was advised, is to use a loop and a getc() function from
stdio.h, some also advised to use pointers.
How would that work exactly?
By length, nope, chopping off only a couple of % of the work isn't
divide and conquer. If you were going to not use a dictionary-
based attack you would split the work based on initial sequences of
characters, as each of the work packets would be expected to take
the same length of time, and you can get "embarassing parallelism".
Using a dictionary, you'd probably split on the word you're doping
the attempt with, and again it would be mostly embarassingly parallel.
(The transforms you'd apply to the word would mean that you'd
probably be testing duplicates, and so you'd have more overhead trying
to reduce that.)
> I thought I read an article some
> years ago how a collaborative effort (along the lines of SETI) was
> able to factor a very large composite number into its two large prime
> constituents in a quite reasonable time frame.
As someone closely involved in distributed factoring, I find the
reference to SETI annoying. People were doing distributed factoring
long before nonsense like SETI ever existed. (But the protocols,
being email based and requiring humans to step through the state
machine manually, have been honed a lot since those days.)
> It seems that hacking
> a password could achieve the same benefit. But, since I don't attempt
> to hack passwords, I must allow for the possibility you're right.
These are all "embarassingly parallel" problems. It doesn't take
any experience of cracking passwords to model an attack on such a
problem. It's probably in the 101 class for distributed computing.
I remember someone mentioning a few facts about his cashcard pin
(things like no repeated numbers, no 3's or 4's and so on). After a
few of those I told him I could guess his pin in about 40 tries. He
looked terrified.
> > > > > I am a newbie in C programming.
> > > > > I have to make an implementation of gets() function from stdio.h, but
> > > > > I am not sure where to start.
> > > > > Please advice, any help is welcome.
<snip>
[it's good usenet practice to snip stuff you aren't responding to]
> > > > Describe what gets() does. Â What parameters does it take? Â What does
> > > > it return? Â What does it *DO*?
<snip>
> > > For example a standard description of gets() function says:
> > > The gets() function shall read bytes from the standard input stream,
> > > stdin, into the array pointed to by s, until a <newline> is read or an
> > > end-of-file condition is encountered. Any <newline> shall be discarded
> > > and a null byte shall be placed immediately after the last byte read
> > > into the array.
<snip>
> So what I was advised, is to use a loop and a getc() function from
> stdio.h, some also advised to use pointers.
> How would that work exactly?
it's getting very hard to answer this without actually writing the
program for you! Look up getc() (google will find you a page that
describes getc()). ignore the end-of-file stuff for the moment. How
are you going to test for a <newline>?
So in pseudo code:-
LOOP UNTIL newline
read character
stuff it in array
terminate string with nul character
Then convert each line into C. What C constructs repeatedly loops
while some condition is true?
You might find it use easier to arrays rather than pointers (some
pedant will point out that in this case they are the same thing- well
yes but they don't *look* the same)
good luck, happy programming!
--
"NaN is a floating point number"
(Edward Nilges)
which may not get him a passing mark in his course
> I remember someone mentioning a few facts about his cashcard pin
> (things like no repeated numbers, no 3's or 4's and so on). After a
> few of those I told him I could guess his pin in about 40 tries. He
> looked terrified.
For a four-digit PIN, there are 10,000 combinations. Simply eliminating
repeated numbers (i.e. no digit appears in the PIN more than once)
reduces the number to 5,040. Adding the constraint "no threes" reduces
the number to 3024. Keeping those two constraints in place, and adding
the constraint "no fours", we are down to 1680 combinations.
You said "after a few of those", so let's add some more constraints.
The PIN is a prime that is greater than its reverse (ABCD > DCBA). It
contains precisely two odd digits, and the sum of its digits is 8 (mod 11).
If he's okay with those constraints...
If that's the case, the course isn't worth passing.
I wasn't being too serious.
>> But maybe password input should allow extra, discarded, white space to
>> fix
>> that.)
>
> No thanks. What if a password actually contains whitespace?
>
> Incidentally, I once used a system that would echo a dot for each
> character of a password, but would echo a space for any spaces that
> were actually part of the password.
That is actually a tremendous help. It gives the 'shape' of a phrase and is
a method I used all the time to help solve crossword clues, where there are
multiple words. (Example: the clue hints at a book or film title, the answer
is (1,7,2,5) and the letters so far are - ------- -- i----. Simple! (If not,
see below...))
--
Bartc
--
--
--
--
a passage to india
> Barry Schwarz <schw...@dqel.com> writes:
> > That may be how it works on your system but my keyboard sends no
> > signals to the processor until enter is pressed.
>
> That must suck for tetris. Or vi, or notepad. Or even a shell.
> Or text entry in a browser window. Or keyboard shortcuts in
> any gui program. Or basically almost anything.
Almost. It is, however, extremely useful for paying your salary. Never
underestimate the importance of mainframes; behind the scenes, they are
the machines the world runs on.
Richard
> Nick Keighley wrote:
>> which may not get him a passing mark in his course
Richard Heathfield <r...@see.sig.invalid> writes:
> If that's the case, the course isn't worth passing.
Not necessary. The idea behind the exercises could be to let students
implement gets() and then when that is done show how to exploit the bug
in it's specification. thus illustrating why this function is unsafe.
--
Best regards, _ _
.o. | Liege of Serenly Enlightened Majesty of o' \,=./ `o
..o | Computer Science, Michal "mina86" Nazarewicz (o o)
ooo +--<mina86-tlen.pl>--<jid:mina86-jabber.org>--ooO--(_)--Ooo--
Not unless it has internal linkage though?
> Not unless it has internal linkage though?
External, I assume you mean?
It gets fussy. In practice, the right answer is "treat it as
completely reserved regardless and you'll make fewer mistakes". :)
-s
--
> >>> I am a newbie in C programming.
> >>> I have to make an implementation of gets() function from stdio.h, but
> >>> I am not sure where to start.
>
> >> Start off by finding out why gets() is an open invitation to adversaries
> >> to stomp all over your system.
>
> >> Once you know that, implementing gets() is easy - Just Say No.
>
> > which may not get him a passing mark in his course
>
> If that's the case, the course isn't worth passing.
this is simply nonsense.
It's a mistake, yes, but not a big enough mistake to invalidate the
entire course.
K&R for instance don't comment on gets()'s problem when they (very
briefly) mention it
--
Teleology is a lady without whom no biologist can live. Yet he
is ashamed to show himself with her in public.
Ernst Wilhelm von Bruecke, [1819-1892]
Yes, it is. Using gets() demonstrates a complete inability to reason
about buffers or their boundaries, and writing such a beast is even
worse.
I would fail this assignment because there is no way within the
bounds of the C language to do it correctly. For the same reason,
no legitimate course would ever have such an assignment.
> K&R for instance don't comment on gets()'s problem when they (very
> briefly) mention it
>
To their fault.
--
Andrew Poelstra
http://www.wpsoftware.net/andrew
Really? What if you're writing a conforming implementation of the
standard C library? In that case, you *have* to implement gets()
(unless you're only interested in conforming to the C201X standard --
you know, the one that doesn't exist yet).
> I would fail this assignment because there is no way within the
> bounds of the C language to do it correctly. For the same reason,
> no legitimate course would ever have such an assignment.
Have you considered the possibility that the point of the assignment
is to demonstrate the danger of using gets()? Admittedly we've seen
no direct evidence of that but it's possible.
[...]
We had a discussion a while back about whether this is a conforming
implementation:
char *gets(char *buffer) {
fputs("Hey jerk!!", stderr);
exit(0);
return NULL;
}
Since in the general case, there is no way to guarantee buffer will
not be run, causing undefined behavior, and printing "Hey jerk" and
dying is well within the bounds of undefined behavior.
I don't remember where the group ended up on it, but that looks
perfectly okay to me.
>> I would fail this assignment because there is no way within the
>> bounds of the C language to do it correctly. For the same reason,
>> no legitimate course would ever have such an assignment.
>
> Have you considered the possibility that the point of the assignment
> is to demonstrate the danger of using gets()? Admittedly we've seen
> no direct evidence of that but it's possible.
>
I have considered it, yes, but it doesn't seem like the OP
is at an appropriate skill level to be learning such things.
It isn't.
The behavior of gets() is well defined as long as you don't feed it a
line too long to be stored in the buffer. A conforming implementation
may not take advantage of the permissions granted by undefined
behavior unless the undefined behavior actually occurs.
> >> I would fail this assignment because there is no way within the
> >> bounds of the C language to do it correctly. For the same reason,
> >> no legitimate course would ever have such an assignment.
> >
> > Have you considered the possibility that the point of the assignment
> > is to demonstrate the danger of using gets()? Admittedly we've seen
> > no direct evidence of that but it's possible.
> >
>
> I have considered it, yes, but it doesn't seem like the OP
> is at an appropriate skill level to be learning such things.
What is the "appropriate skill level" for learning that gets() is
dangerous? Or did I misunderstand you?
The argument against that was that there is always the possibility
of I/O errors - if not a malicious user, then a corrupted file, bad
pipe or network connection, stray emfs flipping bits, etc, and the
buffer could be overrun despite one's best intentions.
>> >> I would fail this assignment because there is no way within the
>> >> bounds of the C language to do it correctly. For the same reason,
>> >> no legitimate course would ever have such an assignment.
>> >
>> > Have you considered the possibility that the point of the assignment
>> > is to demonstrate the danger of using gets()? Admittedly we've seen
>> > no direct evidence of that but it's possible.
>> >
>>
>> I have considered it, yes, but it doesn't seem like the OP
>> is at an appropriate skill level to be learning such things.
>
> What is the "appropriate skill level" for learning that gets() is
> dangerous? Or did I misunderstand you?
>
Partially. When first learning C, it's fine to say "gets is
dangerous" or "gets is evil" and leave it at that. And given
how easy it is to replace it with fgets() and a fixed buffer
(thus turning "undefined behaviour" into "defined but probably
wrong behavior"), there's no reason not to.
Using fgets() also helps them to understand how arrays and
C strings work, what buffers are, why they have boundaries
and that said boundaries are not checked.
At that point, you can explain /why/ gets() is bad. But requiring
students to implement the function, when they are at a point where
they aren't able to slodge together
c = getc();
while(c != '\n' && c != EOF) {
*buff++ = c;
c = getc();
}
, will quite likely result in the dangers going completely over
the students' heads.
> On 2010-04-15, Michal Nazarewicz <min...@tlen.pl> wrote:
>> Not unless it has internal linkage though?
Seebs <usenet...@seebs.net> writes:
> External, I assume you mean?
Yes, of course.
<shrug> we'll just have to agree to disagree. It must be nice in your
perfect world
> On 15 Apr, 16:02, Andrew Poelstra <apoels...@localhost.localdomain>
> > On 2010-04-15, Nick Keighley <nick_keighley_nos...@hotmail.com> wrote:
> > > On 12 Apr, 09:33, Richard Heathfield <r...@see.sig.invalid> wrote:
> > >> If that's the case, the course isn't worth passing.
> >
> > > this is simply nonsense. It's a mistake, yes, but not a big enough
> > > mistake to invalidate the entire course.
> >
> > Yes, it is.
>
> <shrug> we'll just have to agree to disagree. It must be nice in your
> perfect world
It's not a matter of perfection, it's a matter of getting even the
basics wrong. A teacher who thinks that implementing gets() is a good
exercise simply isn't qualified to teach programming. It's like a
driving instructor asking his pupils to devise a safe way of running a
red light. At that point, nothing else he teaches can be trusted.
Richard
> On 2010-04-15, Keith Thompson <ks...@mib.org> wrote:
> > Andrew Poelstra <apoe...@localhost.localdomain> writes:
> >> Since in the general case, there is no way to guarantee buffer will
> >> not be run, causing undefined behavior, and printing "Hey jerk" and
> >> dying is well within the bounds of undefined behavior.
> > It isn't.
> >
> > The behavior of gets() is well defined as long as you don't feed it a
> > line too long to be stored in the buffer. A conforming implementation
> > may not take advantage of the permissions granted by undefined
> > behavior unless the undefined behavior actually occurs.
>
> The argument against that was that there is always the possibility
> of I/O errors - if not a malicious user, then a corrupted file, bad
> pipe or network connection, stray emfs flipping bits, etc, and the
> buffer could be overrun despite one's best intentions.
That's not an argument. If you start letting EMF get into the way of
defined behaviour, every single function in the Standard has UB. That's
not specific to gets() at all. In fact, if you allow EMF to have an
influence, calling _no_ function has UB, too. For example,
int main(void)
{
return 0;
}
could have a padding bit in the 0 flipped by EMF and crash on trying to
return a trap value. And not a single gets() call in sight.
> >> I have considered it, yes, but it doesn't seem like the OP
> >> is at an appropriate skill level to be learning such things.
> >
> > What is the "appropriate skill level" for learning that gets() is
> > dangerous? Or did I misunderstand you?
>
> Partially. When first learning C, it's fine to say "gets is
> dangerous" or "gets is evil" and leave it at that. And given
> how easy it is to replace it with fgets() and a fixed buffer
> (thus turning "undefined behaviour" into "defined but probably
> wrong behavior"), there's no reason not to.
> At that point, you can explain /why/ gets() is bad. But requiring
> students to implement the function, when they are at a point where
> they aren't able to slodge together
I would go further and say that once they _are_ able to understand the
danger, there is no longer any use in implementing gets(). So either
implementing gets() is a bad exercise because it is dangerous for
low-level students, or it is a bad exercise because it is useless for
higher(FSVO)-level students, or it is a bad exercise for both reasons
for mid-level students; it is _never_ a good exercise.
Richard
What total and utter nonsense.
Designing and implementing a version of gets() would show a LOT about
someones C knowledge. Especially when the student produces the
documented shortcomings.
--
"Avoid hyperbole at all costs, its the most destructive argument on
the planet" - Mark McIntyre in comp.lang.c
Your analogy fails badly.
There are people who need to know a safe way of running a red light:
policemen, firefighters, ambulance drivers.
And then the world of bits is completely unlike the world of molecules.
In a virtual environment you have the possibility to repeat missions
until you succeed, you can undo moves back to the point of safety, and
you can experiment with the insane. Flight simulators are routinely used
to train pilots on how to crash land.
In an ideal world teachers would not just let their students implement
a broken design like gets(). They would also teach them how to write
an exploit to attack their own program.
--
I stand by my claim.
> The idea behind the exercises could be to let students
> implement gets() and then when that is done show how to exploit the bug
> in it's specification. thus illustrating why this function is unsafe.
In which case, he *would* get a passing mark in his course - Just Say No
should get him a merit, and explaining why would get him a distinction.
Nonsense. It's hyperbole. (And I stand by it. It's *good* hyperbole.)
> Michal Nazarewicz wrote:
>>>> On 11 Apr, 21:49, Richard Heathfield <r...@see.sig.invalid> wrote:
>>>>> Start off by finding out why gets() is an open invitation to adversaries
>>>>> to stomp all over your system.
>>>>>
>>>>> Once you know that, implementing gets() is easy - Just Say No.
>>
>>> Nick Keighley wrote:
>>>> which may not get him a passing mark in his course
>>
>> Richard Heathfield <r...@see.sig.invalid> writes:
>>> If that's the case, the course isn't worth passing.
>>
>> Not necessary.
>
> I stand by my claim.
>
>> The idea behind the exercises could be to let students
>> implement gets() and then when that is done show how to exploit the bug
>> in it's specification. thus illustrating why this function is unsafe.
>
> In which case, he *would* get a passing mark in his course - Just Say No
> should get him a merit, and explaining why would get him a
> distinction.
Saying "no" should get him kicked off the course and instantly failed
for being a cocksure idiot.
Doing the task well and documenting the weaknesses in the API approach
would see him through.
You need to take a step back and think about things before launching your
high and mighty pronouncements.
Very well put.
Engineers need to know who to secure unsafe buildings for example. And
building a new one is not on the agenda most of the time ...
In fact the more I think about it, the more full of shit I think Bos is
and this question is actually PERFECT. It shows how someone can code AND
think about the issues and design it to be as safe as possible WITHIN
the enforced constraints.
why do you have to insult people?
> <shrug> we'll just have to agree to disagree. It must be nice in your
> perfect world
>
>
>> Using gets() demonstrates a complete inability to reason
>> about buffers or their boundaries, and writing such a beast is even
>> worse.
>>
>> I would fail this assignment because there is no way within the
>> bounds of the C language to do it correctly. For the same reason,
>> no legitimate course would ever have such an assignment.
>>
>> > K&R for instance don't comment on gets()'s problem when they (very
>> > briefly) mention it
It's not like they didn't provide fgets to help with the situation. I
have always wondered why they forgot that second parameter though.
--
Burton Samograd
> Richard Bos wrote:
> > [...]
> > It's not a matter of perfection, it's a matter of getting even the
> > basics wrong. A teacher who thinks that implementing gets() is a good
> > exercise simply isn't qualified to teach programming. It's like a
> > driving instructor asking his pupils to devise a safe way of running a
> > red light. At that point, nothing else he teaches can be trusted.
>
> Your analogy fails badly.
>
> There are people who need to know a safe way of running a red light:
> policemen, firefighters, ambulance drivers.
My analogy doesn't fail at all, since there are also people who need to
write an implementation of gets(): authors of a C implementation. But
just as a beginning driver should not learn to pretend he is behind the
wheel of an ambulance (lest he find himself in the back of one), a
beginning programmer should not pretend to write an implementation (lest
the UB format his drive and he has to install anew).
Richard