Like Tree40Likes

strcpy get errors

This is a discussion on strcpy get errors within the C Programming forums, part of the General Programming Boards category; Well, it's fairly trivial to make a program given the ideas that were discussed in this thread. Here's one that ...

  1. #91
    Stoned Witch Barney McGrew's Avatar
    Join Date
    Oct 2012
    Location
    astaylea
    Posts
    420
    Well, it's fairly trivial to make a program given the ideas that were discussed in this thread. Here's one that prints the last few characters of a line providing the stream is seekable:

    Code:
    #include <stdio.h>
    #include <stdlib.h>
    
    enum { LIMIT = 4 };
    
    int main(void)
    {
        char buf[LIMIT + 1];
        int c, count = 0;
    
        while ((c = getchar()) != EOF) {
            int flush = c == '\n';
    
            count += !flush;
            if (!flush)
                continue;
            flush = count >= LIMIT;
            count = 0;
            if (!flush)
                continue;
            if (fseek(stdin, -LIMIT - 1, SEEK_CUR) || !gets(buf))
                return EXIT_FAILURE;
            puts(buf);
        }
    }
    So the assumption is the problem.
    Yes, and it doesn't need to be an assumption.

  2. #92
    and the hat of wrongness Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    32,499
    Gee, that's an awful lot of code (and assumptions) compared to passing 2 extra parameters to fgets()
    esbo must be spinning in apoplexy at this point.

    You may as well have done
    buf[count++] = c;
    and saved yourself 10 lines of code which won't work properly anyway.
    Congratulations, you've just implemented fgets() in 3 lines of code.

    Quote Originally Posted by c99 on fseek
    4 For a text stream, either offset shall be zero, or offset shall be a value returned by
    an earlier successful call to the ftell function on a stream associated with the same file
    and whence shall be SEEK_SET.
    Your fseek is neither of these things.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.
    I support http://www.ukip.org/ as the first necessary step to a free Europe.

  3. #93
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    21,650
    Quote Originally Posted by Barney McGrew
    Here's one that prints the last few characters of a line providing the stream is seekable:
    If the stream is not seekable, how do you recover to use gets?

    EDIT:
    Furthermore, you are using getchar()... that makes it seem as if the use of gets, not how it is used, is the problem. The proper recovery from fseek failure aside, this is still not convincing.
    Last edited by laserlight; 01-17-2013 at 02:56 AM.
    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

  4. #94
    Stoned Witch Barney McGrew's Avatar
    Join Date
    Oct 2012
    Location
    astaylea
    Posts
    420
    You may as well have done
    buf[count++] = c;

    I don't see how that's possible with this program since you don't know where the next newline is until you read it.

    Your fseek is neither of these things.
    Oh well. Call freopen with the binary mode setting if you want.

    The proper recovery from fseek failure aside, this is still not convincing.
    It doesn't even need to be, I just wrote that program out of curiosity. The point is you can predict what's being read from a stream, and in such a case gets can be used safely.

  5. #95
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    21,650
    Quote Originally Posted by Barney McGrew
    It doesn't even need to be, I just wrote that program out of curiosity. The point is you can predict what's being read from a stream, and in such a case gets can be used safely.
    As such, I'll stick to saying do not use gets because it cannot be used safely, except in special cases, which was what I stated earlier, except that now I can add "usage of some function to inspect stdin, when it works" to the list of special cases
    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. #96
    Stoned Witch Barney McGrew's Avatar
    Join Date
    Oct 2012
    Location
    astaylea
    Posts
    420
    I'll stick to saying do not use gets because it cannot be used safely, except in special cases
    I say it's harmful when used incorrectly (which 100% of the code on this forum, using gets, except for the code I've posted, probably does). I don't think the examples I've provided are 'special' in any way, they just rely on fseek or ungetc to make the call behave in a predictable manner. In any case, you have a stronger argument by stating that it's not part of the standard C library.

    Funny how such a simple comment caused this thread to span three or four extra pages.

  7. #97
    TEIAM - problem solved
    Join Date
    Apr 2012
    Location
    Melbourne Australia
    Posts
    1,344
    Barney, it was good for you to provide that example for academic purposes.

    However, the bottom line is: There is no reason why you should be using "gets".
    Fact - Beethoven wrote his first symphony in C

  8. #98
    Stoned Witch Barney McGrew's Avatar
    Join Date
    Oct 2012
    Location
    astaylea
    Posts
    420
    I've provided two examples in which gets is used. The program knows the exact number of characters that are on stdin preceding the new line in both cases, so there is absolutely zero harm in using it in both of those cases. A size parameter is unnecessary in both of the examples I've provided, just as it's unnecessary when you can verify that the destination buffer is large enough to store the source string in a call to strcpy. You shouldn't use gets when it introduces bugs in your programs, but that is not always the case, as I've already demonstrated.Although, there is one reason for why you should avoid the use of gets entirely, and that's because it's no longer part of the standard C library.edit: If you can come up with another reason (independent of the context in which it's used), then I'd like to hear it. Otherwise you'd just be repeating what I've said.
    Last edited by Barney McGrew; 01-17-2013 at 07:12 PM.

  9. #99
    Registered User
    Join Date
    Jun 2011
    Posts
    2,292
    I don't think anyone is questioning your proofs (from what I gather reading the thread - I can't really be bothered to check them over myself). It's just a matter of practicality.

    The question is: Would you really use that code in practice (be it professional, or even just hobby)? Or suggest that code (over, say, "fgets()") to a newbie who is using "gets()" dangerously in their program?

    I only ask because, while maybe technically valid, you're making a specious argument.

  10. #100
    TEIAM - problem solved
    Join Date
    Apr 2012
    Location
    Melbourne Australia
    Posts
    1,344
    Quote Originally Posted by Barney McGrew View Post
    I've provided two examples in which gets is used. The program knows the exact number of characters that are on stdin preceding the new line in both cases, so there is absolutely zero harm in using it in both of those cases. A size parameter is unnecessary in both of the examples I've provided, just as it's unnecessary when you can verify that the destination buffer is large enough to store the source string in a call to strcpy. You shouldn't use gets when it introduces bugs in your programs, but that is not always the case, as I've already demonstrated.Although, there is one reason for why you should avoid the use of gets entirely, and that's because it's no longer part of the standard C library.edit: If you can come up with another reason (independent of the context in which it's used), then I'd like to hear it. Otherwise you'd just be repeating what I've said.
    Fair enough.

    Your examples don't cover* unbuffered input streams (like one would find on a microcontroller), but I think that you've proven your point

    [edit]*I think that "don't cover" is incorrect - I meant to say "will never work with"[/edit]
    Last edited by Click_here; 01-17-2013 at 07:59 PM.
    Fact - Beethoven wrote his first symphony in C

  11. #101
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    21,650
    Quote Originally Posted by Matticus
    I don't think anyone is questioning your proofs (from what I gather reading the thread - I can't really be bothered to check them over myself).
    I did. The thing is, if I'm not convinced because the examples are flawed such that I dare not suggest them myself if someone were to ask me what is wrong with how they use gets, then sticking to just telling them that their use of gets itself is wrong makes sense to me. Basically, without a convincing proof of concept, I dispute Barney McGrew's insistence that gets can be used correctly, aside from toy examples or examples that make assumptions that do not necessarily hold in practice when suggested to a novice. Of course, with gets getting removed from the standard, there's won't be much to debate about the "how" versus the use itself in the future when C11 becomes more well used.
    Matticus likes this.
    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

  12. #102
    Stoned Witch Barney McGrew's Avatar
    Join Date
    Oct 2012
    Location
    astaylea
    Posts
    420
    The question is: Would you really use that code in practice (be it professional, or even just hobby)? Or suggest that code (over, say, "fgets()") to a newbie who is using "gets()" dangerously in their program?
    It depends on the situation. If they were trying to read an entire line from the user, I'd probably suggest fgets. If they were reading lines then delimiting words later on, I'd suggest simply using scanf with the 's' format specifier and a fixed field width. If they were reading lines then operating on individual chars, I'd suggest getchar.

    There are only a few good functions for doing specific things, and there are many bad ones. gets is both bad and unsafe when used in many situations, but it can clearly be used safely, so saying the function itself is 'unsafe' is misleading when it's entirely possible to use it safely in certain situations.

    If someone were trying to write a program like the last one I wrote, I wouldn't even suggest doing it the same way due to the limitations introduced by fseek. Rather, I'd suggest they use a circular list with getchar.

    if I'm not convinced because the examples are flawed such that I dare not suggest them myself if someone were to ask me what is wrong with how they use gets, then sticking to just telling them that their use of gets itself is wrong makes sense to me
    It's usually impractical to use gets in such cases anyway. I'm saying that it can be used reliably in certain situations, and that it's a mistake to say “gets as an individual unit is unsafe”.

  13. #103
    Registered User
    Join Date
    Jun 2005
    Posts
    6,261
    Quote Originally Posted by Barney McGrew View Post
    There are only a few good functions for doing specific things, and there are many bad ones. gets is both bad and unsafe when used in many situations, but it can clearly be used safely, so saying the function itself is 'unsafe' is misleading when it's entirely possible to use it safely in certain situations.
    Oh, come off it.

    The overall risk associated with anything is generally dominated by the worst case occurrence (and the likelihood of it occurring). That follows directly from standard definitions of risk - as in various international standards for risk management - being based on an aggregation of (impact of unwanted occurrence)*(probability of that unwanted occurrence occurring).

    You particular usage case - even if we accept your assertion that it cannot cause undefined behaviour, which I don't because you have based that assertion on shaky assumptions - is not exactly common in practice.

    The most common use case - by far - for gets() is using it to read a line of input from stdin. The unwanted occurrence is that the input read using gets() will overflow the supplied buffer. That particular use case, and unwanted occurrence, therefore dominates when computing the risk of using gets(). Since safety is a quantity that decreases as risk increases, this means that this usage case is also dominant in computing the loss of safety.

    In other words, a usage case that is rarely used does not make any significant improvement of safety, even if that particular use case is 100% safe when used. The dominant use case, and its safety (or otherwise) dominates.
    Salem likes this.
    Right 98% of the time, and don't care about the other 3%.

  14. #104
    Stoned Witch Barney McGrew's Avatar
    Join Date
    Oct 2012
    Location
    astaylea
    Posts
    420
    The overall risk associated with anything is generally dominated by the worst case occurrence (and the likelihood of it occurring).
    That idea simply doesn't apply here. The fact that strcpy(0, "abcdef") is unsafe doesn't affect the safety of char buf[1024]; strcpy(buf, "abcdef"); in the slightest. strcpy is used incorrectly in the first example, and correctly in the second. The latter example is 100% safe and the former is 100% unsafe. Now, is strcpy inherently safe or unsafe? Neither, because it's stupid to try to claim that it's either without considering *how* it's used. The same applies with gets.

  15. #105
    Registered User
    Join Date
    Jun 2005
    Posts
    6,261
    Quote Originally Posted by Barney McGrew View Post
    That idea simply doesn't apply here.
    Rubbish. You have just demonstrated you do not understand what safety is about. You are focusing on a minor aspect of safety.

    I'm just glad you will never be employed to write software for controlling a nuclear power plant, an aircraft, or a pacemaker. What you have demonstrated here would not cut the mustard.


    Quote Originally Posted by Barney McGrew View Post
    Neither, because it's stupid to try to claim that it's either without considering *how* it's used. The same applies with gets.
    Make up your mind. You have just contradicted your own insistence that a use case which is rarely (*cough* virtually never) used in practice, is significant in claiming that gets() is safe.

    How often is an aspect of how.
    Last edited by grumpy; 01-18-2013 at 01:12 AM.
    Right 98% of the time, and don't care about the other 3%.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Help using strcpy
    By laxkrzy in forum C Programming
    Replies: 1
    Last Post: 11-15-2010, 10:09 PM
  2. Replies: 1
    Last Post: 06-19-2010, 07:42 AM
  3. What's up with this strcpy?
    By fanoliv in forum C Programming
    Replies: 7
    Last Post: 06-19-2006, 05:24 PM
  4. strcpy
    By Tibo in forum C Programming
    Replies: 2
    Last Post: 03-27-2003, 06:02 AM
  5. strcpy
    By Unregistered in forum C++ Programming
    Replies: 6
    Last Post: 08-01-2002, 01:39 PM

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