Thread: preparing for the null

  1. #1
    Madly in anger with you
    Join Date
    Nov 2005
    Posts
    211

    preparing for the null

    okay, this is a problem that has been bugging me for a while now, and as almost everytime I use a function from string.h I encounter it, it's time for me to get this clear.

    I don't know where I've picked it up, most likely from reading open source, but it's become a habit. my intentions by doing it is for safety, to ensure that the string passed will always include a terminating null. but after reading a little about buffer overflows, I'm not exactly sure if this is a good habit. this is the kind of stuff that I'm talking about:

    Code:
    strncpy(dest, source, sizeof dest - 1);
    now, after reading the description for strncpy, I see that this is okay:

    No null-character is implicitly appended to the end of destination, so destination will only be null-terminated if the length of the C string in source is less than num.
    the "sizeof dest - 1" will ensure that the number of characters copied from source will always be shorter than dest, and that there will always be room for 1 terminating null character in the case of any truncation of source (assuming that dest is initialized with null).

    now, lets take a look at another function from string.h, where this is not so clear:

    Code:
    strncat(dest, source, sizeof dest - 1);
    same parameters, different function.

    Appends the first num characters of source to destination, plus a terminating null-character. If the length of the C string in source is less than num, only the content up to the terminating null-character is copied.
    that would mean that the "sizeof dest - 1" is still correct, right?

    I just want to make sure that I'm getting this right, as a lot of the descriptions at MSDN for Win32 API functions are rather vague when it comes to preparing for null terminators. I just want to make sure that the programs I'm writing aren't riddled with buffer overflow vulnerabilities as a result of this "- 1" habit.

    could anyone please tell me if everything I've shown as an example here is correct, and when I should not be using - 1?

    this is a rather newbie question, but it's got me paranoid, everytime I write - 1 I'm worrying if I am just setting myself up for buffer overflows. if anyone could clear this up for me, it would be greatly appreciated.


    thank you in advance.

    Intel Core 2 Quad Q6600 @ 2.40 GHz
    3072 MB PC2-5300 DDR2
    2 x 320 GB SATA (640 GB)
    NVIDIA GeForce 8400GS 256 MB PCI-E

  2. #2
    Officially An Architect brewbuck's Avatar
    Join Date
    Mar 2007
    Location
    Portland, OR
    Posts
    7,396
    Quote Originally Posted by sl34k View Post
    could anyone please tell me if everything I've shown as an example here is correct, and when I should not be using - 1?
    You need to use "- 1" for functions which don't guarantee null termination. You know this by reading the manual

    Equally important, for functions which don't guarantee null termination, you must not only subtract 1, you must ALSO append a null terminator if none was supplied.

    The best thing is to forget about strncat() and strncpy() and start using sprintf(). I don't think I've coded a call to either of those functions in at least a decade -- sprintf() is always the superior choice.

  3. #3
    Algorithm Dissector iMalc's Avatar
    Join Date
    Dec 2005
    Location
    New Zealand
    Posts
    6,318
    I presume you're setting the buffer to all zeros beforehand as well, or at least the last character? Otherwise subtracting one wont help you anyway.
    My homepage
    Advice: Take only as directed - If symptoms persist, please see your debugger

    Linus Torvalds: "But it clearly is the only right way. The fact that everybody else does it some other way only means that they are wrong"

  4. #4
    Officially An Architect brewbuck's Avatar
    Join Date
    Mar 2007
    Location
    Portland, OR
    Posts
    7,396
    Quote Originally Posted by iMalc View Post
    I presume you're setting the buffer to all zeros beforehand as well, or at least the last character? Otherwise subtracting one wont help you anyway.
    It's fine, unless it fills the buffer.

  5. #5
    Technical Lead QuantumPete's Avatar
    Join Date
    Aug 2007
    Location
    London, UK
    Posts
    894
    Code:
    strncpy(dest, source, sizeof dest - 1);
    This is just me being pedantic, but you ought to put brackets around dest in the call to sizeof
    Code:
    strncpy(dest, source, sizeof (dest) - 1);
    Brackets and Braces are your friends!

  6. #6
    Madly in anger with you
    Join Date
    Nov 2005
    Posts
    211
    okay, thanks all.

    I presume you're setting the buffer to all zeros beforehand as well, or at least the last character? Otherwise subtracting one wont help you anyway.
    all of the buffers I'm doing this with are either globally declared (Windows automatically initializes global variables to zero, as I believe they are placed in the BSS segment), or locally declared and manually null initialized.

    Code:
    strncpy(dest, source, sizeof dest - 1);
    This is just me being pedantic, but you ought to put brackets around dest in the call to sizeof

    Code:
    strncpy(dest, source, sizeof (dest) - 1);
    Brackets and Braces are your friends!
    hehe, that's just my minimal style.

    since dest is a variable, the parenthesis are not necessary. the parenthesis in sizeof are only necessary when you are using it to find the size of a type. sizeof is one of the C/C++ keywords (evaluated at compile time), not a function, which explains why the parenthesis are not necessary with variables. I'd assume they're necessary with types as the compiler would probably just see the statements as botched declarations if they weren't there.

    Intel Core 2 Quad Q6600 @ 2.40 GHz
    3072 MB PC2-5300 DDR2
    2 x 320 GB SATA (640 GB)
    NVIDIA GeForce 8400GS 256 MB PCI-E

  7. #7
    Technical Lead QuantumPete's Avatar
    Join Date
    Aug 2007
    Location
    London, UK
    Posts
    894
    Quote Originally Posted by sl34k View Post
    hehe, that's just my minimal style.
    That's perfectly fine ;-) Don't want to impose my coding style on people!

    QuantumPete

  8. #8
    and the hat of sweating
    Join Date
    Aug 2007
    Location
    Toronto, ON
    Posts
    3,545
    Extra parenthesis are always better than not enough.
    Even if you have all the order of operations memorized, other people reading your code might not, and when they see something like:

    sizeof dest - 1

    They might wonder whether it's a bug and wonder if the compiler sees it as:

    sizeof (dest) - 1
    or
    sizeof (dest - 1)

    i.e. It makes the intention of your code more explicit.

  9. #9
    Algorithm Dissector iMalc's Avatar
    Join Date
    Dec 2005
    Location
    New Zealand
    Posts
    6,318
    Quote Originally Posted by brewbuck View Post
    It's fine, unless it fills the buffer.
    Yes of course, and filling the buffer is exactly what we are concerned with here.
    My homepage
    Advice: Take only as directed - If symptoms persist, please see your debugger

    Linus Torvalds: "But it clearly is the only right way. The fact that everybody else does it some other way only means that they are wrong"

  10. #10
    Officially An Architect brewbuck's Avatar
    Join Date
    Mar 2007
    Location
    Portland, OR
    Posts
    7,396
    Quote Originally Posted by cpjust View Post
    They might wonder whether it's a bug and wonder if the compiler sees it as:

    sizeof (dest) - 1
    or
    sizeof (dest - 1)
    Being that the second isn't even syntactically valid, I hardly see how people could get confused.

    EDIT: Nevermind. It's valid, but completely pointless.

  11. #11
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,660
    It's valid enough, just not what you want.
    Code:
    #include <stdio.h>
    #include <stdlib.h>
    
    int main ( ) {
        int a[100];
        printf("&#37;d %d\n", sizeof(a)-1, sizeof(a-1) );
        return 0;
    }
    
    $ gcc foo.c
    $ ./a.exe
    399 4
    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.

  12. #12
    Registered User ssharish2005's Avatar
    Join Date
    Sep 2005
    Location
    Cambridge, UK
    Posts
    1,732
    Salem , how did you get this

    Code:
    ./a.exe
    Shouldn't that be ./a.out. Just curious to know that it.

    ssharish2005

  13. #13
    Officially An Architect brewbuck's Avatar
    Join Date
    Mar 2007
    Location
    Portland, OR
    Posts
    7,396
    Quote Originally Posted by ssharish2005 View Post
    Salem , how did you get this

    Code:
    ./a.exe
    Shouldn't that be ./a.out. Just curious to know that it.

    ssharish2005
    cygwin does that.

  14. #14
    Registered User ssharish2005's Avatar
    Join Date
    Sep 2005
    Location
    Cambridge, UK
    Posts
    1,732
    Quote Originally Posted by brewbuck View Post
    cygwin does that.

    Oh cool, So he is using cygwin on windows platform

    ssharish2005
    Last edited by ssharish2005; 08-30-2007 at 05:34 PM.

  15. #15
    Registered User
    Join Date
    Sep 2006
    Posts
    835
    Quote Originally Posted by ssharish2005 View Post
    Salem , how did you get this

    Code:
    ./a.exe
    Shouldn't that be ./a.out. Just curious to know that it.

    ssharish2005
    I'm guessing that in the filesystem used in Windows, there's no execute flag, so whether a file is executable is determined by its suffix, so a.out had to be renamed.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Global Variables
    By Taka in forum C Programming
    Replies: 34
    Last Post: 11-02-2007, 03:25 AM
  2. Syntax Error??
    By Kennedy in forum C Programming
    Replies: 8
    Last Post: 09-06-2006, 11:04 AM
  3. Tweakable Radar...
    By DoraTehExploda in forum Game Programming
    Replies: 8
    Last Post: 06-07-2005, 10:49 AM
  4. Help with yacc/compiler design/seg fault
    By trippeer in forum C Programming
    Replies: 1
    Last Post: 04-08-2005, 03:43 AM
  5. Really Need Help With My Opengl Camera!!!!
    By psychopath in forum Game Programming
    Replies: 13
    Last Post: 05-28-2004, 03:05 PM