How to use gets_s

This is a discussion on How to use gets_s within the C Programming forums, part of the General Programming Boards category; I don't know why I can't get this function to work, but I've spent all day and all night searching ...

  1. #1
    Registered User
    Join Date
    May 2008
    Posts
    22

    Question How to use gets_s

    I don't know why I can't get this function to work, but I've spent all day and all night searching and have found nothing but problems. gets_s(buffer, size) is supposed to be a more direct, more secure replacement for gets(). So, why is it that on VC++ compiler, I still get buffer overflows even though I specify the sizeof(buffer) as the second argument? And on OS X (Darwin), it won't even compile, I get this error:
    Undefined symbols:
    "_gets_s", referenced from:
    _main in ccHlsIH2.o
    ld: symbol(s) not found
    collect2: ld returned 1 exit status

  2. #2
    C++まいる!Cをこわせ! Elysia's Avatar
    Join Date
    Oct 2007
    Posts
    22,455
    Gets_s only works on VS.
    But you had better use fgets instead of gets. I don't know if there's a safer version of gets, though.

    And as for the size, you had better post some code you get problems with, so as for someone to have a look for you.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  3. #3
    Registered User
    Join Date
    May 2008
    Posts
    22
    Gets_s only works on VS.
    gets_s is defined in ISO/IEC 99 maybe that is why it is not in other compilers?

    but for VC++ my code looks like this:
    Code:
    #include <stdio.h>
    
    int main ( int argc, char *argv[] )
    {
    	char stringArray[10] ;
    	
    	printf( "please enter some text" ) ;
    	gets_s( stringArray, sizeof( stringArray ) ) ;
    	
    }
    I've also tried using gets_s( stringArray, 10 ). The function works fine if the input is <= the amount attempted to store in stringArray, but if you type more than 9 characters, the program crashes and windows reports an error.

  4. #4
    C++まいる!Cをこわせ! Elysia's Avatar
    Join Date
    Oct 2007
    Posts
    22,455
    Is its really? Well, maybe it is, I don't really have a good check but...
    Many compilers do not implement these safe functions.
    Running your code, I get an assert followed by a crash. As it should be.
    You don't?
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  5. #5
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    21,456
    gets_s is defined in ISO/IEC 99 maybe that is why it is not in other compilers?
    As far as I can tell, ISO/IEC 9899:1999 does not define gets_s.
    C + C++ Compiler: MinGW port of GCC
    Version Control System: Bazaar

    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  6. #6
    Registered User
    Join Date
    May 2008
    Posts
    22
    As for ISO definition of gets_s, I got my information from this site: buildsecurityin.us-cert.gov

    As far as I can tell from the explanation of the gets_s function, explained in the link above, it is supposed to return a NULL pointer if the input was larger than the size spec in the second argument. Not halt the program.

  7. #7
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    21,456
    As for ISO definition of gets_s, I got my information from this site: buildsecurityin.us-cert.gov
    Read your source carefully: "gets_s() function is defined by ISO/IEC WDTR 24731". The function is not part of standard C (yet).
    C + C++ Compiler: MinGW port of GCC
    Version Control System: Bazaar

    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  8. #8
    Registered User
    Join Date
    May 2008
    Posts
    22
    I see now, it had ISO/IEC 99 as a reference as well simply because it was talking about current standard functions as well as ISO/IEC WDTR 24731 (Secure C Library).

    So the VC++ implementation of it still should not crash if there is more input than expected right? Isn't that why fgets and gets_s was designed to prevent overloading the buffer and causing a crash possibly opening the computer to security risks?

  9. #9
    C++まいる!Cをこわせ! Elysia's Avatar
    Join Date
    Oct 2007
    Posts
    22,455
    Quote Originally Posted by gwarf420 View Post
    So the VC++ implementation of it still should not crash if there is more input than expected right? Isn't that why fgets and gets_s was designed to prevent overloading the buffer and causing a crash possibly opening the computer to security risks?
    No, it will throw an assert and then crash, without doing a buffer overrun.
    Yes, they were designed to prevent buffer overruns, but they aren't perfect. If you pass a buffer that's not large enough, it's (usually), your fault, a programmer mistake.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  10. #10
    Registered User
    Join Date
    May 2008
    Posts
    22
    so, because every modern OS has memory protection, using gets() throws a fault and doesn't continue just like gets_s. Why should I go through the trouble of using these supposedly more robust/secure functions for standard input if they all behave the same way? A function like gets_s should (like I understood it to) simply see if the line in stdin is <= the amount of storage available, if not return a NULL pointer so I can handle that and say If NULL, printf("Your response is too long") ;

    Is there no way to determine the amount of input coming from stdin like peak in VBasic and be able to handle the error like Try...Catch ---- or use malloc to dynamically allocate enough memory to store the input line?

  11. #11
    C++まいる!Cをこわせ! Elysia's Avatar
    Join Date
    Oct 2007
    Posts
    22,455
    Quote Originally Posted by gwarf420 View Post
    so, because every modern OS has memory protection, using gets() throws a fault and doesn't continue just like gets_s.
    No. Buffer overruns are a security issue and can cause data corruption.
    http://cpwiki.sf.net/Buffer_overrun
    Do take a look.

    Why should I go through the trouble of using these supposedly more robust/secure functions for standard input if they all behave the same way? A function like gets_s should (like I understood it to) simply see if the line in stdin is <= the amount of storage available, if not return a NULL pointer so I can handle that and say If NULL, printf("Your response is too long") ;
    They are more meant to safeguard that you don't do buffer overruns, not as a solution to the problem.

    Is there no way to determine the amount of input coming from stdin like peak in VBasic and be able to handle the error like Try...Catch ---- or use malloc to dynamically allocate enough memory to store the input line?
    Use fgets to chip away at the current data stored until you get a newline as the last character in the buffer or EOF.
    There are no other solutions, other than maybe unportable functions or platform specific functions. Sorry, C is pretty limited in this regard.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  12. #12
    Registered User
    Join Date
    May 2008
    Posts
    22
    In the secure coding article at buildinsecurity.us-cert.gov what is the purpose of the following code if it is only going to bomb out before the exception can be handled?

    Code:
    if (gets_s(buff, BUFFSIZE) == NULL)
    {
         printf("diagnosed undefined behavior.\n");
         abort();
    }

  13. #13
    C++まいる!Cをこわせ! Elysia's Avatar
    Join Date
    Oct 2007
    Posts
    22,455
    Why? Because otherwise you would use a potential buffer that is uninitialized. Garbage data or other worrysome things that can cause security issues.
    It may not cause problems in this specific instance (since the previous fread succeeded), but can cause problems elsewhere. It's just an example. Not real code.
    Sure, you can handle the error if you want. It was just a simple example and they didn't handle the error simply because of simplicity I guess.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  14. #14
    Registered User
    Join Date
    May 2008
    Posts
    22
    so, the line "if (gets_s( buff, BUFFSIZE ) == NULL )" is not testing the return value of gets_s() but in fact testing to see if the buffer I specified was NULL? I'm sorry but that doesn't make sense to me. It doesn't look like the error can be handled. As soon as it enters the if and does gets_s, if the input is too large it will halt and end the program. Unless someone can show me otherwise. Does fgets() act this same way?

  15. #15
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Quote Originally Posted by gwarf420 View Post
    so, the line "if (gets_s( buff, BUFFSIZE ) == NULL )" is not testing the return value of gets_s() but in fact testing to see if the buffer I specified was NULL? I'm sorry but that doesn't make sense to me. It doesn't look like the error can be handled. As soon as it enters the if and does gets_s, if the input is too large it will halt and end the program. Unless someone can show me otherwise. Does fgets() act this same way?
    No, NULL is return if there was an error (such as end-of-file when the first attempt to read was made). Of course if you pass in NULL, it will also return NULL (assuming it succesfully completes), since it returns the address of the buffer. But since NULL should normally cause a trap/exception/fault of some sort if you try to read/write to such an address, it's unlikely that you ever see a NULL returned for that reason - it will at the very least try to write a 0 at the end of the string. So, conclusion: If you pass in a NULL buffer, it will cause the program to crash, and you will not see a return value [unless you use exception handling and catch the system fault and then continue, but you should then come back to somewhere other than the return of the gets_s() function, so I don't think this can happen]

    The only exception would be if your input is already at end-of-file, in which case the function will not modify the input, but it will return a constant NULL, rather than your passed in buffer NULL - do you really care about this rather obscure case?

    What we really want to prevent is that someone maliciously can allow input data to be executed - if you allow that, you potentially allow others to interfere with your machine. This gets even better if the interface is available to external users (e.g. through the internet).

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

Page 1 of 2 12 LastLast
Popular pages Recent additions subscribe to a feed

Tags for this Thread


1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21