Safe version of gets

Discussion in 'C Programming' started by Anthony Irwin, Aug 12, 2005.

  1. Hi,

    I am fairly new to C and all the C books I got talk about gets() but when
    I compile it says I should not use gets() because it is dangerous. I
    understand that it is dangerous because it doesn't check whether there is
    more characters entered by the user the what can be stored but I don't
    know what the safe equivalent of gets() is.

    Below is an example program I have written. (GCC is my compiler on
    GNU/Linux system.)

    Kind Regards,
    Anthony Irwin

    #include <stdio.h>

    char histogram[50];
    int i, space, begin, length;

    int main() {
    printf("\nEnter some words for the histogram: ");
    sgets(histogram);
    printf("\n\n");
    begin = 1;
    length = strlen(histogram);

    for (i = 0; i <= length; i++) {
    if (histogram != '\0') {
    if (space == 1 || begin == 1) {
    histogram = toupper(histogram);
    begin = 0;
    }
    printf("\n\t%c", histogram);
    printf("\t\t%d", i);

    if (histogram == ' ') {
    space = 1;
    printf("\t\tSpace");
    }
    else {
    space = 0;
    }
    }
    }

    return 0;
    }
    Anthony Irwin, Aug 12, 2005
    #1
    1. Advertising

  2. Anthony Irwin wrote:

    > I am fairly new to C and all the C books I got talk about gets() but when
    > I compile it says I should not use gets() because it is dangerous. I
    > understand that it is dangerous because it doesn't check whether there is
    > more characters entered by the user the what can be stored but I don't
    > know what the safe equivalent of gets() is.


    fgets()
    Peter Pichler, Aug 12, 2005
    #2
    1. Advertising

  3. On Fri, 12 Aug 2005 15:32:04 +1000, Anthony Irwin wrote:

    > Hi,
    >
    > I am fairly new to C and all the C books I got talk about gets() but when
    > I compile it says I should not use gets() because it is dangerous. I
    > understand that it is dangerous because it doesn't check whether there is
    > more characters entered by the user the what can be stored but I don't
    > know what the safe equivalent of gets() is.
    >
    > Below is an example program I have written. (GCC is my compiler on
    > GNU/Linux system.)
    >
    > Kind Regards,
    > Anthony Irwin
    >
    > #include <stdio.h>
    >
    > char histogram[50];
    > int i, space, begin, length;
    >
    > int main() {
    > printf("\nEnter some words for the histogram: ");
    > sgets(histogram);


    Above is actually gets(histogram); I was making changes before I posted
    and missed it sgets doesn't exist with gcc or ansi c.

    > printf("\n\n");
    > begin = 1;
    > length = strlen(histogram);
    >
    > for (i = 0; i <= length; i++) {
    > if (histogram != '\0') {
    > if (space == 1 || begin == 1) {
    > histogram = toupper(histogram);
    > begin = 0;
    > }
    > printf("\n\t%c", histogram);
    > printf("\t\t%d", i);
    >
    > if (histogram == ' ') {
    > space = 1;
    > printf("\t\tSpace");
    > }
    > else {
    > space = 0;
    > }
    > }
    > }
    >
    > return 0;
    > }
    Anthony Irwin, Aug 12, 2005
    #3
  4. Anthony Irwin

    Suman Guest

    Peter Pichler wrote:
    > Anthony Irwin wrote:
    >
    > > I am fairly new to C and all the C books I got talk about gets() but when
    > > I compile it says I should not use gets() because it is dangerous. I
    > > understand that it is dangerous because it doesn't check whether there is
    > > more characters entered by the user the what can be stored but I don't
    > > know what the safe equivalent of gets() is.

    >
    > fgets()


    gets() works (or not) on stdin. So, to be accurate:
    fgets( histogram, sizeof histogram, stdin );

    [1] variable histogram from code posted by OP

    Read up on this function, it's something like --
    "The fgets() function reads at most n-1 characters from stream into the
    buffer pointed to by s. No additional characters are read after fgets()
    has read and transferred a newline character to the buffer. A null
    character is written immediately after the last character that fgets()
    reads into the buffer."
    Suman, Aug 12, 2005
    #4
  5. On Fri, 12 Aug 2005 06:33:23 +0100, Peter Pichler wrote:

    > Anthony Irwin wrote:
    >
    >> I am fairly new to C and all the C books I got talk about gets() but when
    >> I compile it says I should not use gets() because it is dangerous. I
    >> understand that it is dangerous because it doesn't check whether there is
    >> more characters entered by the user the what can be stored but I don't
    >> know what the safe equivalent of gets() is.

    >
    > fgets()


    Hey thanks I can do the following:

    fgets(histogram,sizeof(histogram), stdin);

    Kind Regards,
    Anthony Irwin
    Anthony Irwin, Aug 12, 2005
    #5
  6. Anthony Irwin

    Villy Kruse Guest

    On Fri, 12 Aug 2005 15:50:06 +1000,
    Anthony Irwin <> wrote:


    > On Fri, 12 Aug 2005 06:33:23 +0100, Peter Pichler wrote:
    >
    >> Anthony Irwin wrote:
    >>
    >>> I am fairly new to C and all the C books I got talk about gets() but when
    >>> I compile it says I should not use gets() because it is dangerous. I
    >>> understand that it is dangerous because it doesn't check whether there is
    >>> more characters entered by the user the what can be stored but I don't
    >>> know what the safe equivalent of gets() is.

    >>
    >> fgets()

    >
    > Hey thanks I can do the following:
    >
    > fgets(histogram,sizeof(histogram), stdin);
    >


    Don't forget to handle the trailing newline character, and do realise
    that if there is no trailing new line, your record is truncated, in which
    case the following fgets will get you the rest of the line. Of cours,
    if the last line doesn't have a new line your last line read from the
    file may not have a new line, which you also need to deal with.

    Villy
    Villy Kruse, Aug 12, 2005
    #6
  7. Anthony Irwin wrote:
    > Hi,
    >
    > I am fairly new to C and all the C books I got talk about gets()


    Burn them. Where did you get "all the C books" that use gets()?

    > but when
    > I compile it says I should not use gets() because it is dangerous.


    That's right.

    > I
    > understand that it is dangerous because it doesn't check whether there is
    > more characters entered by the user the what can be stored but I don't
    > know what the safe equivalent of gets() is.


    fgets() is much safer. And you can always roll your own.
    Martin Ambuhl, Aug 12, 2005
    #7
  8. Anthony Irwin

    CBFalconer Guest

    Anthony Irwin wrote:
    >
    > I am fairly new to C and all the C books I got talk about gets()
    > but when I compile it says I should not use gets() because it is
    > dangerous. I understand that it is dangerous because it doesn't
    > check whether there is more characters entered by the user the
    > what can be stored but I don't know what the safe equivalent of
    > gets() is.


    Download and use the portable public domain ggets module at:

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

    --
    Chuck F () ()
    Available for consulting/temporary embedded and systems.
    <http://cbfalconer.home.att.net> USE worldnet address!
    CBFalconer, Aug 12, 2005
    #8
  9. Anthony Irwin

    Guest

    use fgets using stdout as input
    , Aug 12, 2005
    #9
  10. Anthony Irwin

    akarl Guest

    Anthony Irwin wrote:
    > Hi,
    >
    > I am fairly new to C and all the C books I got talk about gets() but when
    > I compile it says I should not use gets() because it is dangerous. I
    > understand that it is dangerous because it doesn't check whether there is
    > more characters entered by the user the what can be stored but I don't
    > know what the safe equivalent of gets() is.
    >
    > Below is an example program I have written. (GCC is my compiler on
    > GNU/Linux system.)


    Why don't you tell us (exactly) what the program does/is supposed to do?

    August
    akarl, Aug 12, 2005
    #10
  11. Anthony Irwin

    wolfman Guest

    I wrote a function, that I always use: (shure you have to include stdio.h)

    int mygets(FILE *stream, char *buffer, int lim)
    { int i = 0, c;

    while (i < lim - 1 && (c = getc(stream)) != EOF && c != '\n')
    { *buffer++ = (char) c;
    i++;
    }
    *buffer = 0; /* or better *buffer = '\0' in non ASCII / ANSI Systems */
    return i;
    }

    Parameters:
    stream: I/O-Stream or FILE-Pointer
    buffer: pointer to text buffer in memory
    lim: buffer size

    Return value:
    Function returns the number of read characters

    Remarks:
    - If you use 16-bit characters you have to change the datatype char to the
    appropriate datatype of your system,
    for example wchar.
    - You don't have to care about terminating zeros. The function always adds
    one.

    Best regards,
    wolfman


    "Anthony Irwin" <> schrieb im Newsbeitrag
    news:p...
    > Hi,
    >
    > I am fairly new to C and all the C books I got talk about gets() but when
    > I compile it says I should not use gets() because it is dangerous. I
    > understand that it is dangerous because it doesn't check whether there is
    > more characters entered by the user the what can be stored but I don't
    > know what the safe equivalent of gets() is.
    >
    > Below is an example program I have written. (GCC is my compiler on
    > GNU/Linux system.)
    >
    > Kind Regards,
    > Anthony Irwin
    >
    > #include <stdio.h>
    >
    > char histogram[50];
    > int i, space, begin, length;
    >
    > int main() {
    > printf("\nEnter some words for the histogram: ");
    > sgets(histogram);
    > printf("\n\n");
    > begin = 1;
    > length = strlen(histogram);
    >
    > for (i = 0; i <= length; i++) {
    > if (histogram != '\0') {
    > if (space == 1 || begin == 1) {
    > histogram = toupper(histogram);
    > begin = 0;
    > }
    > printf("\n\t%c", histogram);
    > printf("\t\t%d", i);
    >
    > if (histogram == ' ') {
    > space = 1;
    > printf("\t\tSpace");
    > }
    > else {
    > space = 0;
    > }
    > }
    > }
    >
    > return 0;
    > }
    wolfman, Aug 12, 2005
    #11
  12. Anthony Irwin

    Malcolm Guest

    "Martin Ambuhl" <> wrote
    >
    > fgets() is much safer. And you can always roll your own.
    >

    Actually it's more dangerous, unless the programmer really knows what he is
    doing.
    Undefined behaviour is usually correct behaviour, terminating the program
    with an appropriate message. Silently truncating input will usually produce
    incorrect behaviour.
    Malcolm, Aug 12, 2005
    #12
  13. wrote:

    > use fgets using stdout as input

    ^^^^^^
    ITYM stdin.
    Peter Pichler, Aug 12, 2005
    #13
  14. Anthony Irwin

    CBFalconer Guest

    wolfman wrote:
    >
    > I wrote a function, that I always use: (shure you have to include
    > stdio.h)
    >
    > int mygets(FILE *stream, char *buffer, int lim)
    > { int i = 0, c;
    >
    > while (i < lim - 1 && (c = getc(stream)) != EOF && c != '\n')
    > { *buffer++ = (char) c;
    > i++;
    > }
    > *buffer = '\0';
    > return i;
    > }


    Please don't toppost. Your answer belongs after (or intermixed
    with) the material to which you reply, after snipping anything not
    germane to your answer.

    Problem, because the caller has no idea whether a '\n' was received
    or not. The insidious advantage of gets is that it ALWAYS returns
    a complete line, regardless of what that tramples over. My ggets
    has the same advantage, without the trampling. Thus it is safe to
    remove the terminal \n in the function.

    Apart from the \n being returned, I see no essential difference
    between your function and fgets. In interactive work it is
    essential to know a line has been consumed.

    My ggets has the prototype:

    int ggets(char **ln);

    returning non-zero for error/EOF, and is called with:

    char *ln;

    result = ggets(&ln);
    or
    result = fggets(&ln, file);

    see <http://cbfalconer.home.att.net/download/ggets.zip>

    (The cost is that you have to free(ln) when done with it)

    --
    Chuck F () ()
    Available for consulting/temporary embedded and systems.
    <http://cbfalconer.home.att.net> USE worldnet address!
    CBFalconer, Aug 12, 2005
    #14
  15. Anthony Irwin

    Chris Torek Guest

    >"Martin Ambuhl" <> wrote
    >> fgets() is much safer. And you can always roll your own.


    In article <ddisep$1ab$-infra.bt.com>
    Malcolm <> wrote:
    >Actually it's more dangerous, unless the programmer really knows
    >what he is doing. Undefined behaviour is usually correct behaviour ...


    Except for the fact that it is not.

    >terminating the program with an appropriate message.


    Most often, undefined behavior leads to bugs in Microsoft products
    that result in viruses, worms, "zombie" PCs, and spam.

    Much of your spam is due to gets() calls (or equivalent). (Most
    of the rest is due to other bugs in IIS.)

    >Silently truncating input will usually produce
    >incorrect behaviour.


    But observable, repeatable, predictable incorrect behavior.
    Moreover, programs that use gets() in this same way also
    silently truncate input:

    gets(buf); /* XXX bad */
    error = FALSE;
    ...

    Since the "error" variable happens to alias &buf[sizeof buf], this
    truncates the input, silently. In other words, the function you
    claim to be "superior" has the same flaw as fgets(), plus additional
    flaws.
    --
    In-Real-Life: Chris Torek, Wind River Systems
    Salt Lake City, UT, USA (40°39.22'N, 111°50.29'W) +1 801 277 2603
    email: forget about it http://web.torek.net/torek/index.html
    Reading email is like searching for food in the garbage, thanks to spammers.
    Chris Torek, Aug 13, 2005
    #15
  16. CBFalconer wrote:

    > My ggets has the prototype:
    > int ggets(char **ln);


    Great. What if I use your ggets() in my program and someone will run it
    as ./myprogram </dev/zero? Sorry I didn't look into your code, but I
    suppose it will eat all available memory and then crash, right?
    --
    Anton Petrusevich
    Anton Petrusevich, Aug 13, 2005
    #16
  17. Anton Petrusevich wrote:
    > CBFalconer wrote:
    >
    >
    >>My ggets has the prototype:
    >> int ggets(char **ln);

    >
    >
    > Great. What if I use your ggets() in my program and someone will run it
    > as ./myprogram </dev/zero? Sorry I didn't look into your code, but I
    > suppose it will eat all available memory and then crash, right?


    But it won't crash... If you do 'rm -rf /' it is not the fault of the
    creator of rm...

    --
    one's freedom stops where other's begin

    Giannis Papadopoulos
    http://dop.users.uth.gr/
    University of Thessaly
    Computer & Communications Engineering dept.
    Giannis Papadopoulos, Aug 13, 2005
    #17
  18. Giannis Papadopoulos wrote:

    >>>My ggets has the prototype:
    >>> int ggets(char **ln);

    >> Great. What if I use your ggets() in my program and someone will run it
    >> as ./myprogram </dev/zero? Sorry I didn't look into your code, but I
    >> suppose it will eat all available memory and then crash, right?

    > But it won't crash... If you do 'rm -rf /' it is not the fault of the
    > creator of rm...


    rm -rf / must be executed with root privileges, but ./myprogram does not
    require that. "Analogies suck" (c). I just wanted to show that such a
    simple API have some drawbacks.
    --
    Anton Petrusevich
    Anton Petrusevich, Aug 13, 2005
    #18
  19. Anton Petrusevich wrote:
    > Giannis Papadopoulos wrote:
    >
    >
    >>>>My ggets has the prototype:
    >>>> int ggets(char **ln);
    >>>
    >>>Great. What if I use your ggets() in my program and someone will run it
    >>>as ./myprogram </dev/zero? Sorry I didn't look into your code, but I
    >>>suppose it will eat all available memory and then crash, right?

    >>
    >>But it won't crash... If you do 'rm -rf /' it is not the fault of the
    >>creator of rm...

    >
    >
    > rm -rf / must be executed with root privileges, but ./myprogram does not
    > require that. "Analogies suck" (c). I just wanted to show that such a
    > simple API have some drawbacks.


    Ok, then 'rm -rf ~'..
    You can't (and shouldn't always) protect a system from a complete idiot.

    There are numerous programs out there that if they had available memory,
    they would work with infinite input.

    And ggets() doesn't crash.. A well-written program in a well-written
    system would notify that memory allocation failed, return EXIT_FAILURE
    and the os would deallocate the memory. If you choose win98, then BSOD
    is the solution..

    Have you ever tried while(1) {fork();}? Should fork check how many times
    it is called? If not, why should CBFalconer bother to check how many
    chars are read, seriously hindering perfomance?

    --
    one's freedom stops where other's begin

    Giannis Papadopoulos
    http://dop.users.uth.gr/
    University of Thessaly
    Computer & Communications Engineering dept.
    Giannis Papadopoulos, Aug 13, 2005
    #19
  20. Anthony Irwin

    CBFalconer Guest

    Anton Petrusevich wrote:
    > CBFalconer wrote:
    >
    >> My ggets has the prototype:
    >> int ggets(char **ln);

    >
    > Great. What if I use your ggets() in my program and someone will run it
    > as ./myprogram </dev/zero? Sorry I didn't look into your code, but I
    > suppose it will eat all available memory and then crash, right?


    Yes, it will eat all memory. No, it won't crash. It will return
    an error indicator. If the caller then executes free(ln) the
    memory will be available again. This assumes /dev/zero returns an
    unending stream of zero bytes.

    --
    "If you want to post a followup via groups.google.com, don't use
    the broken "Reply" link at the bottom of the article. Click on
    "show options" at the top of the article, then click on the
    "Reply" at the bottom of the article headers." - Keith Thompson
    CBFalconer, Aug 13, 2005
    #20
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Stefan Mueller
    Replies:
    5
    Views:
    499
    Steven Saunderson
    Jul 10, 2006
  2. V Green
    Replies:
    0
    Views:
    808
    V Green
    Feb 5, 2008
  3. PA Bear [MS MVP]
    Replies:
    0
    Views:
    908
    PA Bear [MS MVP]
    Feb 5, 2008
  4. John Joyce

    gets gets

    John Joyce, Mar 26, 2007, in forum: Ruby
    Replies:
    2
    Views:
    325
    John Joyce
    Mar 26, 2007
  5. John Joyce

    Return of gets gets

    John Joyce, Apr 23, 2007, in forum: Ruby
    Replies:
    0
    Views:
    172
    John Joyce
    Apr 23, 2007
Loading...

Share This Page