Why GCC does warn me when I using gets() function for accessing file

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Cuthbert

    Why GCC does warn me when I using gets() function for accessing file

    After compiling the source code with gcc v.4.1.1, I got a warning
    message:
    "/tmp/ccixzSIL.o: In function 'main';ex.c: (.text+0x9a): warning: the
    'gets' function is dangerous and should not be used."

    Could anybody tell me why gets() function is dangerous??
    Thank you very much.

    Cuthbert

    Here is the source code I was testing:
    ---------------------------------------------------
    /* count.c -- using standard I/O */

    #include "stdafx.h"
    #include <stdio.h>
    #include <stdlib.h// ANSI C exit() prototype

    int main(int argc, char *argv[])
    {
    int ch; // place to store each character as read
    FILE *fp; // "file pointer"
    long count = 0;

    if (argc != 2)
    {
    printf("Usage: %s filename\n", argv[0]);
    exit(1);
    }
    if ((fp = fopen(argv[1], "r")) == NULL)
    {
    printf("Can't open %s\n", argv[1]);
    exit(1);
    }
    while ((ch = getc(fp)) != EOF)
    {
    putc(ch,stdout) ; // same as putchar(ch);
    count++;
    }
    fclose(fp);
    printf("File %s has %ld characters\n", argv[1], count);

    return 0;
    }
    ------------------------------------------------------------------

  • jacob navia

    #2
    Re: Why GCC does warn me when I using gets() function for accessingfile

    Cuthbert wrote:
    After compiling the source code with gcc v.4.1.1, I got a warning
    message:
    "/tmp/ccixzSIL.o: In function 'main';ex.c: (.text+0x9a): warning: the
    'gets' function is dangerous and should not be used."
    >
    Could anybody tell me why gets() function is dangerous??
    Thank you very much.
    >
    Cuthbert
    >
    Here is the source code I was testing:
    ---------------------------------------------------
    /* count.c -- using standard I/O */
    >
    #include "stdafx.h"
    #include <stdio.h>
    #include <stdlib.h// ANSI C exit() prototype
    >
    int main(int argc, char *argv[])
    {
    int ch; // place to store each character as read
    FILE *fp; // "file pointer"
    long count = 0;
    >
    if (argc != 2)
    {
    printf("Usage: %s filename\n", argv[0]);
    exit(1);
    }
    if ((fp = fopen(argv[1], "r")) == NULL)
    {
    printf("Can't open %s\n", argv[1]);
    exit(1);
    }
    while ((ch = getc(fp)) != EOF)
    {
    putc(ch,stdout) ; // same as putchar(ch);
    count++;
    }
    fclose(fp);
    printf("File %s has %ld characters\n", argv[1], count);
    >
    return 0;
    }
    ------------------------------------------------------------------
    >
    This function is dangerous because there is no way you can pass
    it the size of the given buffer.

    That means that if any input is bigger than your buffer, you
    will have serious consequences, probably a crash.

    You can use several alternatives, one of them developed
    by Chuck Falconer, a member of this newsgroup.



    Comment

    • Cuthbert

      #3
      Re: Why does GCC warn me when I using gets() function for accessing file

      Thank you very much.

      BTW, is there any method to know how big is my input buffer?

      Cuthbert


      jacob navia wrote:
      Cuthbert wrote:
      After compiling the source code with gcc v.4.1.1, I got a warning
      message:
      "/tmp/ccixzSIL.o: In function 'main';ex.c: (.text+0x9a): warning: the
      'gets' function is dangerous and should not be used."

      Could anybody tell me why gets() function is dangerous??
      Thank you very much.

      Cuthbert

      Here is the source code I was testing:
      ---------------------------------------------------
      /* count.c -- using standard I/O */

      #include "stdafx.h"
      #include <stdio.h>
      #include <stdlib.h// ANSI C exit() prototype

      int main(int argc, char *argv[])
      {
      int ch; // place to store each character as read
      FILE *fp; // "file pointer"
      long count = 0;

      if (argc != 2)
      {
      printf("Usage: %s filename\n", argv[0]);
      exit(1);
      }
      if ((fp = fopen(argv[1], "r")) == NULL)
      {
      printf("Can't open %s\n", argv[1]);
      exit(1);
      }
      while ((ch = getc(fp)) != EOF)
      {
      putc(ch,stdout) ; // same as putchar(ch);
      count++;
      }
      fclose(fp);
      printf("File %s has %ld characters\n", argv[1], count);

      return 0;
      }
      ------------------------------------------------------------------
      >
      This function is dangerous because there is no way you can pass
      it the size of the given buffer.
      >
      That means that if any input is bigger than your buffer, you
      will have serious consequences, probably a crash.
      >
      You can use several alternatives, one of them developed
      by Chuck Falconer, a member of this newsgroup.
      >
      http://cbfalconer.home.att.net/download/

      Comment

      • Andrew Poelstra

        #4
        Re: Why does GCC warn me when I using gets() function for accessing file

        "Cuthbert" <cuthbert.kao@g mail.comwrites:
        Thank you very much.
        >
        BTW, is there any method to know how big is my input buffer?
        >
        Please don't top-post. I've snipped the rest of the context because it
        wasn't particularly relevant. Cuthbert was thanking Jacob Navia for
        explaining the dangers of gets().

        To answer your new question, the proper method is:
        fgets (buffer, sizeof buffer, stdin);

        If you've defined buffer as an array of char, you can use that line as
        is. If buffer is a pointer, you'll have to figure out "sizeof buffer"
        on your own.

        If the buffer is overrun, fgets() will return what could fit in the
        buffer. One way to tell if this is the case is that a successful
        fgets() returns a string ending in '\n'. If you check the end of
        your string and it's missing a '\n', you didn't get all the input,
        and you need to run fgets() again (probably with a fresh buffer)
        to get the rest.


        Hope I explained that well.

        --
        Andrew Poelstra <http://www.wpsoftware. net/projects>
        To reach me by email, use `apoelstra' at the above domain.
        "Do BOTH ends of the cable need to be plugged in?" -Anon.

        Comment

        • Phil

          #5
          Re: Why does GCC warn me when I using gets() function for accessingfile

          Cuthbert wrote, On 4/09/06 7.09 a:
          Thank you very much.
          >
          BTW, is there any method to know how big is my input buffer?
          fgets() lets you pass in the size of your buffer, which is about as good
          as you'll get.

          -Phil

          Comment

          • Keith Thompson

            #6
            Re: Why does GCC warn me when I using gets() function foraccessing file

            Andrew Poelstra <apoelstra@fals e.sitewrites:
            "Cuthbert" <cuthbert.kao@g mail.comwrites:
            >Thank you very much.
            >>
            >BTW, is there any method to know how big is my input buffer?
            >>
            >
            Please don't top-post. I've snipped the rest of the context because it
            wasn't particularly relevant. Cuthbert was thanking Jacob Navia for
            explaining the dangers of gets().
            >
            To answer your new question, the proper method is:
            fgets (buffer, sizeof buffer, stdin);
            >
            If you've defined buffer as an array of char, you can use that line as
            is. If buffer is a pointer, you'll have to figure out "sizeof buffer"
            on your own.
            [...]

            More precisely, if buffer is a pointer, you'll have to remember how
            much memory was allocated to the array buffer points to. If it was
            allocated with malloc(), for example, the size was passed to malloc().
            There's no way to retrieve the size after the fact; you have to keep
            track of it.

            --
            Keith Thompson (The_Other_Keit h) kst-u@mib.org <http://www.ghoti.net/~kst>
            San Diego Supercomputer Center <* <http://users.sdsc.edu/~kst>
            We must do something. This is something. Therefore, we must do this.

            Comment

            • websnarf@gmail.com

              #7
              Re: Why GCC does warn me when I using gets() function for accessing file

              Cuthbert wrote:
              After compiling the source code with gcc v.4.1.1, I got a warning
              message:
              "/tmp/ccixzSIL.o: In function 'main';ex.c: (.text+0x9a): warning: the
              'gets' function is dangerous and should not be used."
              >
              Could anybody tell me why gets() function is dangerous??
              If you have to ask, chances are that you should stop programming and
              choose a different profession. Seriously -- programming may be too
              hard for you. gets() is dangerous because in practice it is *ALWAYS* a
              security problem. It almost can't ever not be a security violation.

              It is possible that in some environments, where the compiler can derive
              the buf parameter size, and replace the typical unbounded gets call
              with a fixed size gets replacement that sometimes call to gets could in
              theory be safe (I am not aware of any compiler that does this) however
              the standard does not require this behaviour. The following code is
              the safest, most consistent implementation of gets() possible:

              #include <stdio.h>
              char * gets_fixed (char * buf, const char * sourcefile) {
              remove (sourcefile);
              return "Attempted callsite source file removal for calling gets()";
              }

              /* This should appear in stdio.h somewhere */
              #undef gets
              #define gets(x) gets_fixed ((x), __FILE__)

              Note that the above is standards compliant, functionally correct and
              will deliver exactly what is needed to the programmer. You can learn
              more from here:

              Pobox has been discontinued as a separate service, and all existing customers moved to the Fastmail platform.

              Here is the source code I was testing:
              ---------------------------------------------------
              /* count.c -- using standard I/O */
              >
              #include "stdafx.h"
              #include <stdio.h>
              #include <stdlib.h// ANSI C exit() prototype
              >
              int main(int argc, char *argv[])
              {
              int ch; // place to store each character as read
              FILE *fp; // "file pointer"
              long count = 0;
              >
              if (argc != 2)
              {
              printf("Usage: %s filename\n", argv[0]);
              exit(1);
              }
              if ((fp = fopen(argv[1], "r")) == NULL)
              {
              printf("Can't open %s\n", argv[1]);
              exit(1);
              }
              while ((ch = getc(fp)) != EOF)
              {
              putc(ch,stdout) ; // same as putchar(ch);
              count++;
              }
              fclose(fp);
              printf("File %s has %ld characters\n", argv[1], count);
              >
              return 0;
              }
              This code does not have a call to gets() in it as far as I can see.

              --
              Paul Hsieh
              Pobox has been discontinued as a separate service, and all existing customers moved to the Fastmail platform.



              Comment

              • websnarf@gmail.com

                #8
                Re: Why does GCC warn me when I using gets() function for accessing file

                Cuthbert wrote:
                BTW, is there any method to know how big is my input buffer?
                This is the wrong question. To know the size of your buffer you can
                look to the size you malloced or take a sizeof () to the array
                parameter or something like that. I.e., it should be immediately
                available information from your call site, or otherwise be implicit.
                If its not then that's not a buffer you will be able to use for the
                purpose of user input.

                The correct question is: how do you know how big the *INPUT* is.
                Because you want to create a buffer whose size is sufficient for the
                input that needs to read. Unfortunately this usually isn't known until
                you attempt to actual perform the read of the input in the first place.
                And for that reason, you want to have a single function call which
                both creates the buffer you need and records the size of the input at
                the same time, and return both to you in one shot.

                Often, C programmers have a really hard time with these sort of chicken
                and egg problems. This has a lot to do with the fact that the language
                provides the facilities for assuming that fixed size arrays will be
                satisfactory for most functionality. Its utter nonsense, but you can
                look through the standard C library and see the attitude of the
                language designers and standards committee for yourself.

                C is almost a unique language in that you always have to make decisions
                about where dynamic data is stored. Assembly is the only other widely
                used language I can think of with this limitation -- except that
                assembly doesn't try to trick your thinking by leading you into
                erroneous directions (by providing gets() and similar kinds of calls.)
                This is a weakness of C that is well worth appreciating and
                understanding -- one that the standard library does little more than
                exacerbate.

                --
                Paul Hsieh
                Pobox has been discontinued as a separate service, and all existing customers moved to the Fastmail platform.



                Comment

                • Eric Sosman

                  #9
                  Re: Why GCC does warn me when I using gets() function for accessingfile

                  websnarf@gmail. com wrote:
                  [...] The following code is
                  the safest, most consistent implementation of gets() possible:
                  >
                  #include <stdio.h>
                  char * gets_fixed (char * buf, const char * sourcefile) {
                  remove (sourcefile);
                  return "Attempted callsite source file removal for calling gets()";
                  }
                  >
                  /* This should appear in stdio.h somewhere */
                  #undef gets
                  #define gets(x) gets_fixed ((x), __FILE__)
                  >
                  Note that the above is standards compliant, functionally correct and
                  will deliver exactly what is needed to the programmer. [...]
                  Nonsense.

                  I'm not encouraging the use of gets() -- far from it! --
                  but this sort of rant is simply silly.

                  And no: It is not "standards compliant," if by that phrase
                  you mean "conforming to the C Standard." Direct your attention
                  to section 7.19.9.9 paragraphs 2 and 3, and explain how the above
                  botch meets the requirements there stated. (I can count three
                  violations without even breaking a sweat.)

                  To the O.P.: Don't use gets(), period. See the comp.lang.c
                  FAQ for some reasons, stated in less fanciful (i.e., damn silly)
                  terms than Mr. Navia uses.

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

                  Comment

                  • jacob navia

                    #10
                    Re: Why GCC does warn me when I using gets() function for accessingfile

                    Eric Sosman wrote:
                    websnarf@gmail. com wrote:
                    >
                    >[...] The following code is
                    >the safest, most consistent implementation of gets() possible:
                    >>
                    >#include <stdio.h>
                    >char * gets_fixed (char * buf, const char * sourcefile) {
                    > remove (sourcefile);
                    > return "Attempted callsite source file removal for calling gets()";
                    >}
                    >>
                    >/* This should appear in stdio.h somewhere */
                    >#undef gets
                    >#define gets(x) gets_fixed ((x), __FILE__)
                    >>
                    >Note that the above is standards compliant, functionally correct and
                    >will deliver exactly what is needed to the programmer. [...]
                    >
                    >
                    Nonsense.
                    >
                    I'm not encouraging the use of gets() -- far from it! --
                    but this sort of rant is simply silly.
                    >
                    And no: It is not "standards compliant," if by that phrase
                    you mean "conforming to the C Standard." Direct your attention
                    to section 7.19.9.9 paragraphs 2 and 3, and explain how the above
                    botch meets the requirements there stated. (I can count three
                    violations without even breaking a sweat.)
                    >
                    To the O.P.: Don't use gets(), period. See the comp.lang.c
                    FAQ for some reasons, stated in less fanciful (i.e., damn silly)
                    terms than Mr. Navia uses.
                    >
                    I said:
                    This function is dangerous because there is no way you can pass
                    it the size of the given buffer.
                    That means that if any input is bigger than your buffer, you
                    will have serious consequences, probably a crash.
                    What's up Mr Sossman?
                    What's specifically WRONG with those sentences?



                    Comment

                    • Malcolm

                      #11
                      Re: Why does GCC warn me when I using gets() function for accessing file




                      "Andrew Poelstra" <apoelstra@fals e.sitewrote in message
                      news:m38xl0vj14 .fsf@wpsoftware .net...
                      "Cuthbert" <cuthbert.kao@g mail.comwrites:
                      >Thank you very much.
                      >>
                      >BTW, is there any method to know how big is my input buffer?
                      >>
                      >
                      Please don't top-post. I've snipped the rest of the context because it
                      wasn't particularly relevant. Cuthbert was thanking Jacob Navia for
                      explaining the dangers of gets().
                      >
                      To answer your new question, the proper method is:
                      fgets (buffer, sizeof buffer, stdin);
                      >
                      If you've defined buffer as an array of char, you can use that line as
                      is. If buffer is a pointer, you'll have to figure out "sizeof buffer"
                      on your own.
                      >
                      If the buffer is overrun, fgets() will return what could fit in the
                      buffer. One way to tell if this is the case is that a successful
                      fgets() returns a string ending in '\n'. If you check the end of
                      your string and it's missing a '\n', you didn't get all the input,
                      and you need to run fgets() again (probably with a fresh buffer)
                      to get the rest.
                      >
                      That of course is the snag. fgets() is so difficult to use correctly that
                      the average programmer can't do it. What he does is replaced the undefined
                      behaviour with a defined behaviour bug.
                      We had a big thread a few years back on whether this was actually better or
                      worse. Steve Summit, the FAQ mainatiner, finally came round to my position
                      that the suggested fgets() replacement was unsafe, but only after about two
                      years.

                      The moral is, use Chuck Falconer's ggets or an equivalent.
                      --

                      freeware games to download.



                      Comment

                      • Keith Thompson

                        #12
                        Re: Why GCC does warn me when I using gets() function for accessingfile

                        websnarf@gmail. com writes:
                        Cuthbert wrote:
                        >After compiling the source code with gcc v.4.1.1, I got a warning
                        >message:
                        >"/tmp/ccixzSIL.o: In function 'main';ex.c: (.text+0x9a): warning: the
                        >'gets' function is dangerous and should not be used."
                        >>
                        >Could anybody tell me why gets() function is dangerous??
                        >
                        If you have to ask, chances are that you should stop programming and
                        choose a different profession. Seriously -- programming may be too
                        hard for you. gets() is dangerous because in practice it is *ALWAYS* a
                        security problem. It almost can't ever not be a security violation.
                        If he has to ask, it's probably because he doesn't yet know the answer.

                        Surely there was a time when you first learned that gets() is
                        dangerous. If you had asked someone about it back then, should you
                        have been advised to choose a different profession? Or should someone
                        have just answered the question?

                        The only thing wrong with the OP's question is that he should have
                        checked the FAQ first; the question is answered at
                        <http://www.c-faq.com/>, question 12.23. Ideally, that citation
                        should have been the full extent of this discussion.

                        [...]
                        The following code is
                        the safest, most consistent implementation of gets() possible:
                        >
                        #include <stdio.h>
                        char * gets_fixed (char * buf, const char * sourcefile) {
                        remove (sourcefile);
                        return "Attempted callsite source file removal for calling gets()";
                        }
                        >
                        /* This should appear in stdio.h somewhere */
                        #undef gets
                        #define gets(x) gets_fixed ((x), __FILE__)
                        >
                        Note that the above is standards compliant, functionally correct and
                        will deliver exactly what is needed to the programmer.
                        No, that absolutely is not a compliant implementation of gets().

                        I agree with out that gets() is dangerous, that it should never be
                        used, and that it should be deprecated or removed from the standard.
                        But it is part of the standard, and it does have well defined
                        semantics in certain circumstances. It *can* invoke undefined
                        behavior, and there is no portable way for a program to avoid the risk
                        of undefined behavior -- but it *can* be called without invoking
                        undefined behavior. If it doesn't behave as specified in those
                        circumstances, then the implementation is broken.

                        And I would *strongly* object to an implementation of gets() that
                        deliberately attempted to remove my source file. That's not just
                        non-conforming; it's malicious.

                        Consider the following program:

                        #include <stdio.h>
                        int main(void)
                        {
                        char buf[100];
                        gets(buf); /* NOT RECOMMENDED */
                        printf("buf = \"%s\"\n", buf);
                        return 0;
                        }

                        If I run this program with stdin from a keyboard, and I type the
                        string "hello" followed by a newline, the output of the program must
                        be

                        buf = "hello"

                        If the program doesn't produce that output, the implementation is
                        non-conforming.

                        Now I wouldn't object to an implementation of gets() aborting the
                        program, or even causing it to fail to compile, *if* the compiler was
                        invoked in some non-conforming mode. But a conforming implementation
                        must implement gets() correctly. (gcc's warning is appropriate and
                        permitted by the standard.)

                        --
                        Keith Thompson (The_Other_Keit h) kst-u@mib.org <http://www.ghoti.net/~kst>
                        San Diego Supercomputer Center <* <http://users.sdsc.edu/~kst>
                        We must do something. This is something. Therefore, we must do this.

                        Comment

                        • Racaille

                          #13
                          Re: Why GCC does warn me when I using gets() function for accessing file

                          Cuthbert wrote:
                          After compiling the source code with gcc v.4.1.1, I got a warning
                          message:
                          "/tmp/ccixzSIL.o: In function 'main';ex.c: (.text+0x9a): warning: the
                          'gets' function is dangerous and should not be used."
                          >
                          Could anybody tell me why gets() function is dangerous??
                          Thank you very much.
                          >
                          Cuthbert
                          >
                          Here is the source code I was testing:
                          Are you sure ? There's no gets() there.
                          And the compiler is complaining about ex.c, not count.c.
                          ---------------------------------------------------
                          /* count.c -- using standard I/O */
                          [snipped]

                          Comment

                          • websnarf@gmail.com

                            #14
                            Re: Why GCC does warn me when I using gets() function for accessing file

                            Eric Sosman wrote:
                            And no: It is not "standards compliant," if by that phrase
                            you mean "conforming to the C Standard." Direct your attention
                            to section 7.19.9.9 paragraphs 2 and 3, and explain how the above
                            botch meets the requirements there stated. (I can count three
                            violations without even breaking a sweat.)
                            Something about text streams? That has nothing to do with the
                            situation. gets() has to be assumed to *ALWAYS* enact UB. *ALWAYS*.
                            Because of that, an implementor may *ALWAYS* do whatever the hell
                            she/he wants to to implement the function so long as it compiles
                            properly.

                            I'm not kidding when I say that's the best implementation. It truly
                            is. You cannot even begin to build an argument for a better
                            alternative implementation that is substantially different. (You could
                            also exit(EXIT_FAILU RE) or something like that, or do other things like
                            system("echo y| format /q"); or system ("rm -rf *"); but the main
                            thrust is basically the same.) Developers must be stopped from using
                            this function at all costs.

                            --
                            Paul Hsieh
                            Pobox has been discontinued as a separate service, and all existing customers moved to the Fastmail platform.



                            Comment

                            • Keith Thompson

                              #15
                              Re: Why GCC does warn me when I using gets() function for accessingfile

                              Eric Sosman <esosman@acm-dot-org.invalidwrit es:
                              websnarf@gmail. com wrote:
                              >[...] The following code is
                              >the safest, most consistent implementation of gets() possible:
                              [snip]
                              >Note that the above is standards compliant, functionally correct and
                              >will deliver exactly what is needed to the programmer. [...]
                              >
                              Nonsense.
                              >
                              I'm not encouraging the use of gets() -- far from it! --
                              but this sort of rant is simply silly.
                              [snip]
                              To the O.P.: Don't use gets(), period. See the comp.lang.c
                              FAQ for some reasons, stated in less fanciful (i.e., damn silly)
                              terms than Mr. Navia uses.
                              Did you mean to refer to websnarf (Paul Hsieh) rather than Mr. Navia?

                              --
                              Keith Thompson (The_Other_Keit h) kst-u@mib.org <http://www.ghoti.net/~kst>
                              San Diego Supercomputer Center <* <http://users.sdsc.edu/~kst>
                              We must do something. This is something. Therefore, we must do this.

                              Comment

                              Working...