Question related to string functions

Discussion in 'C Programming' started by somenath, Sep 10, 2007.

  1. somenath

    somenath Guest

    Hi All,

    I was going through one piece of code which is written by an
    experience programmer and it is working fine.
    But I think the use of "strstr" is not proper because it may show
    undefined behavior.



    char *returnValueFromIniFile(char *iniFilePath,char *keyIntheFile)
    {
    FILE *FD_IniFileP =NULL;
    char key[SIZE_OF_ARRAY]={'0'};
    static char value[SIZE_OF_ARRAY]={'\0'};
    FD_IniFileP = fopen(iniFilePath,"r");
    if( FD_IniFileP != NULL )
    {
    /* File Open Success*/
    while (fscanf(FD_IniFileP,"%s",key)!= EOF)
    {
    if(strstr(key,keyIntheFile)!=NULL)
    {


    /*Make sure key contains "="*/
    if(strstr(key,"=")!=NULL)
    {
    /*Sepereate the key and the value */
    char *positionOfequal = strstr(key,"="); /* as "="
    is not terminated by '\0' it can show undefined behavior ? */

    /*increment the positionOfequal to reach the
    beganing of the value */
    positionOfequal +=1;
    assert(strlen(positionOfequal)<SIZE_OF_ARRAY);
    strcpy(value,positionOfequal);
    break;
    }

    }/* End of if(strstr(key,keyIntheFile)!=NULL)*/
    memset(key,'\0',SIZE_OF_ARRAY);

    }/* End of while (fscanf(FD_IniFileP,"%s",key)!= EOF)*/

    }/* End of if( FD_IniFileP != NULL )*/
    if (FD_IniFileP)
    {
    fclose(FD_IniFileP);
    }

    return value;

    }

    I think the statement "char *positionOfequal = strstr(key,"=");" can
    show undefined behavior .
    1) Is my understanding correct ?
    I have another question
    2) Can we pass directly sequence of characters to the function which
    expects string ?
    For example strcpy(dest,"some");
    Strcat(dest,"abc"); ?
    Regards,
    Somenath
     
    somenath, Sep 10, 2007
    #1
    1. Advertising

  2. somenath said:

    > Hi All,
    >
    > I was going through one piece of code which is written by an
    > experience programmer and it is working fine.


    It fails to protect its key buffer against overruns, so I can't agree
    that it's working fine.

    > But I think the use of "strstr" is not proper because it may show
    > undefined behavior.


    <snip>

    > if(strstr(key,keyIntheFile)!=NULL)
    > {
    >
    >
    > /*Make sure key contains "="*/
    > if(strstr(key,"=")!=NULL)
    > {
    > /*Sepereate the key and the value */
    > char *positionOfequal = strstr(key,"=");


    Calling strstr twice here seems to be a little unnecessary. Still, it's
    not actually wrong. Incidentally, strchr would have been adequate.

    /* as "="
    > is not terminated by '\0' it can show undefined behavior ? */


    "=" is a string literal, which *IS* terminated by a null character.

    <snip>

    > 2) Can we pass directly sequence of characters to the function which
    > expects string ?
    > For example strcpy(dest,"some");
    > Strcat(dest,"abc"); ?


    Yes, you can pass string literals to standard library functions when you
    are matching parameters that take const char * (as in your strcpy
    example). I can't answer for your Strcat example, since I've never
    heard of a Strcat function. If you meant strcat, then yes, that, too,
    can legitimately take a string literal as the second argument.

    --
    Richard Heathfield <http://www.cpax.org.uk>
    Email: -www. +rjh@
    Google users: <http://www.cpax.org.uk/prg/writings/googly.php>
    "Usenet is a strange place" - dmr 29 July 1999
     
    Richard Heathfield, Sep 10, 2007
    #2
    1. Advertising

  3. somenath

    somenath Guest

    On Sep 10, 8:33 am, Richard Heathfield <> wrote:
    > somenath said:
    >
    > > Hi All,

    >
    > > I was going through one piece of code which is written by an
    > > experience programmer and it is working fine.

    >
    > It fails to protect its key buffer against overruns, so I can't agree
    > that it's working fine.


    Many thanks for the response.

    If i have propely understood you are indicating that " while
    (fscanf(FD_IniFileP,"%s",key)!= EOF) "
    can cause problem . is it so ?
    if it is then if I change the code as following will it solve the
    problem ?
    #define str(x) # x
    #define xstr(x) str(x)


    char *returnValueFromIniFile(char *iniFilePath,char *keyIntheFile)
    {
    FILE *FD_IniFileP =NULL;
    char key[SIZE_OF_ARRAY+1]={'0'};
    static char value[1]={'\0'};
    FD_IniFileP = fopen(iniFilePath,"r");
    if( FD_IniFileP != NULL )
    {
    /* File Open Success*/
    //cout<<"\n Opening of INI file Succeeded \n "<<endl;
    while (fscanf(FD_IniFileP,"%" xstr(SIZE_OF_ARRAY) "[^
    \n]" ,key)!= EOF)
    {



    >
    > > But I think the use of "strstr" is not proper because it may show
    > > undefined behavior.

    >
    > <snip>
    >
    > > if(strstr(key,keyIntheFile)!=NULL)
    > > {

    >
    > > /*Make sure key contains "="*/
    > > if(strstr(key,"=")!=NULL)
    > > {
    > > /*Sepereate the key and the value */
    > > char *positionOfequal = strstr(key,"=");

    >
    > Calling strstr twice here seems to be a little unnecessary. Still, it's
    > not actually wrong. Incidentally, strchr would have been adequate.
    >
    > /* as "="
    >
    > > is not terminated by '\0' it can show undefined behavior ? */

    >
    > "=" is a string literal, which *IS* terminated by a null character.
    >
    > <snip>
    >
    > > 2) Can we pass directly sequence of characters to the function which
    > > expects string ?
    > > For example strcpy(dest,"some");
    > > Strcat(dest,"abc"); ?

    >
    > Yes, you can pass string literals to standard library functions when you
    > are matching parameters that take const char * (as in your strcpy
    > example). I can't answer for your Strcat example, since I've never
    > heard of a Strcat function. If you meant strcat,


    Sorry it is my typing mistake. It would be strcat.

    > then yes, that, too,
    > can legitimately take a string literal as the second argument.
     
    somenath, Sep 10, 2007
    #3
  4. somenath

    somenath Guest

    On Sep 10, 8:33 am, Richard Heathfield <> wrote:
    > somenath said:
    >
    > > Hi All,

    >
    > > I was going through one piece of code which is written by an
    > > experience programmer and it is working fine.

    >
    > It fails to protect its key buffer against overruns, so I can't agree
    > that it's working fine.
    >
    > > But I think the use of "strstr" is not proper because it may show
    > > undefined behavior.

    >
    > <snip>
    >
    > > if(strstr(key,keyIntheFile)!=NULL)
    > > {

    >
    > > /*Make sure key contains "="*/
    > > if(strstr(key,"=")!=NULL)
    > > {
    > > /*Sepereate the key and the value */
    > > char *positionOfequal = strstr(key,"=");

    >
    > Calling strstr twice here seems to be a little unnecessary. Still, it's
    > not actually wrong. Incidentally, strchr would have been adequate.
    >
    > /* as "="
    >
    > > is not terminated by '\0' it can show undefined behavior ? */

    >
    > "=" is a string literal, which *IS* terminated by a null character.
    >
    > <snip>
    >
    > > 2) Can we pass directly sequence of characters to the function which
    > > expects string ?
    > > For example strcpy(dest,"some");
    > > Strcat(dest,"abc"); ?

    >
    > Yes, you can pass string literals to standard library functions when you
    > are matching parameters that take const char * (as in your strcpy
    > example). I can't answer for your Strcat example, since I've never
    > heard of a Strcat function. If you meant strcat, then yes, that, too,
    > can legitimately take a string literal as the second argument.
    >

    I have one doubt here.
    Suppose
    #define TEMP_STR "xyz"
    can i use string related function such as strcpy(dest,TEMP_STR); ?
     
    somenath, Sep 10, 2007
    #4
  5. somenath said:

    > On Sep 10, 8:33 am, Richard Heathfield <> wrote:


    <snip>

    >> Yes, you can pass string literals to standard library functions when
    >> you are matching parameters that take const char * (as in your strcpy
    >> example). [...]
    >>

    > I have one doubt here.
    > Suppose
    > #define TEMP_STR "xyz"
    > can i use string related function such as strcpy(dest,TEMP_STR); ?


    Yes, because it's just a different way of writing strcpy(dest,"xyz");

    But TEMP_STR is a bad name for a string literal. String literals exist
    for the entire lifetime of the program, so they are hardly temporary!

    --
    Richard Heathfield <http://www.cpax.org.uk>
    Email: -www. +rjh@
    Google users: <http://www.cpax.org.uk/prg/writings/googly.php>
    "Usenet is a strange place" - dmr 29 July 1999
     
    Richard Heathfield, Sep 10, 2007
    #5
  6. somenath <> writes:
    > I was going through one piece of code which is written by an
    > experience programmer and it is working fine.
    > But I think the use of "strstr" is not proper because it may show
    > undefined behavior.

    [...]
    > /*Sepereate the key and the value */
    > char *positionOfequal = strstr(key,"="); /* as "="
    > is not terminated by '\0' it can show undefined behavior ? */

    [...]
    > I think the statement "char *positionOfequal = strstr(key,"=");" can
    > show undefined behavior .
    > 1) Is my understanding correct ?
    > I have another question
    > 2) Can we pass directly sequence of characters to the function which
    > expects string ?
    > For example strcpy(dest,"some");
    > Strcat(dest,"abc"); ?


    A string literal is (almost) always implicitly terminated by a '\0'
    character. The literal "=" specifies the two-character sequence
    '=', '\0'.

    (The only exception is when a string literal is used to initialize an
    array whose size is specified as exactly the length of the array, such
    as
    char s[3] = "abc";
    but this is a very unusual case, and should be avoided; instead, you
    can use
    char s[] = "abc";
    to get a properly zero-terminated string.)

    --
    Keith Thompson (The_Other_Keith) <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."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"
     
    Keith Thompson, Sep 10, 2007
    #6
  7. Keith Thompson said:

    > somenath <> writes:
    >> I was going through one piece of code which is written by an
    >> experience programmer and it is working fine.
    >> But I think the use of "strstr" is not proper because it may show
    >> undefined behavior.

    > [...]
    >> /*Sepereate the key and the value */
    >> char *positionOfequal = strstr(key,"="); /* as
    >> "="
    >> is not terminated by '\0' it can show undefined behavior ? */

    > [...]
    >> I think the statement "char *positionOfequal = strstr(key,"=");" can
    >> show undefined behavior .
    >> 1) Is my understanding correct ?
    >> I have another question
    >> 2) Can we pass directly sequence of characters to the function which
    >> expects string ?
    >> For example strcpy(dest,"some");
    >> Strcat(dest,"abc"); ?

    >
    > A string literal is (almost) always implicitly terminated by a '\0'
    > character. The literal "=" specifies the two-character sequence
    > '=', '\0'.
    >
    > (The only exception is when a string literal is used to initialize an
    > array whose size is specified as exactly the length of the array, such
    > as
    > char s[3] = "abc";


    What makes you think this is an exception?

    The Standard says:

    "A character string literal has static storage duration and type "array
    of char," and is initialized with the given characters. A wide string
    literal has static storage duration and type "array of wchar_t," and is
    initialized with the wide characters corresponding to the given
    multibyte characters. Character string literals that are adjacent
    tokens are concatenated into a single character string literal. A null
    character is then appended."

    No exceptions.

    I know what you're thinking of, but that's a special case of
    initialisation, not a special case of string literals.


    > but this is a very unusual case, and should be avoided;


    ....by newbies, at any rate. There are (rare) times when it's Exactly
    What's Needed.

    <snip>

    --
    Richard Heathfield <http://www.cpax.org.uk>
    Email: -www. +rjh@
    Google users: <http://www.cpax.org.uk/prg/writings/googly.php>
    "Usenet is a strange place" - dmr 29 July 1999
     
    Richard Heathfield, Sep 10, 2007
    #7
  8. Richard Heathfield <> writes:
    > Keith Thompson said:

    [...]
    >> A string literal is (almost) always implicitly terminated by a '\0'
    >> character. The literal "=" specifies the two-character sequence
    >> '=', '\0'.
    >>
    >> (The only exception is when a string literal is used to initialize an
    >> array whose size is specified as exactly the length of the array, such
    >> as
    >> char s[3] = "abc";

    >
    > What makes you think this is an exception?
    >
    > The Standard says:
    >
    > "A character string literal has static storage duration and type "array
    > of char," and is initialized with the given characters. A wide string
    > literal has static storage duration and type "array of wchar_t," and is
    > initialized with the wide characters corresponding to the given
    > multibyte characters. Character string literals that are adjacent
    > tokens are concatenated into a single character string literal. A null
    > character is then appended."
    >
    > No exceptions.
    >
    > I know what you're thinking of, but that's a special case of
    > initialisation, not a special case of string literals.


    What are you, some kind of pedant?

    :cool:}

    Yeah, you're right. C99 6.7.8p14 says:

    An array of character type may be initialized by a character
    string literal, optionally enclosed in braces. Successive
    characters of the character string literal (including the
    terminating null character if there is room or if the array is of
    unknown size) initialize the elements of the array.

    >> but this is a very unusual case, and should be avoided;

    >
    > ...by newbies, at any rate. There are (rare) times when it's Exactly
    > What's Needed.


    Hmm. I meant to qualify that somehow, and I thought I had.

    --
    Keith Thompson (The_Other_Keith) <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."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"
     
    Keith Thompson, Sep 10, 2007
    #8
  9. somenath wrote:

    > On Sep 10, 8:33 am, Richard Heathfield <> wrote:
    >> somenath said:
    >>
    >> > Hi All,

    >>
    >> > I was going through one piece of code which is written by an
    >> > experience programmer and it is working fine.

    >>
    >> It fails to protect its key buffer against overruns, so I can't agree
    >> that it's working fine.

    >
    > Many thanks for the response.
    >
    > If i have propely understood you are indicating that " while
    > (fscanf(FD_IniFileP,"%s",key)!= EOF) "
    > can cause problem . is it so ?
    > if it is then if I change the code as following will it solve the
    > problem ?
    > #define str(x) # x
    > #define xstr(x) str(x)
    >
    >
    > char *returnValueFromIniFile(char *iniFilePath,char *keyIntheFile)
    > {
    > FILE *FD_IniFileP =NULL;
    > char key[SIZE_OF_ARRAY+1]={'0'};
    > static char value[1]={'\0'};
    > FD_IniFileP = fopen(iniFilePath,"r");
    > if( FD_IniFileP != NULL )
    > {
    > /* File Open Success*/
    > //cout<<"\n Opening of INI file Succeeded \n "<<endl;
    > while (fscanf(FD_IniFileP,"%" xstr(SIZE_OF_ARRAY) "[^
    > \n]" ,key)!= EOF)
    > {
    >


    Yes, that will properly protect you from a buffer overrun of the key
    array.
    But your change also changes the semantics of the program.
    The original line:
     while (fscanf(FD_IniFileP,"%s",key)!= EOF)
    would stop reading on the first whitespace character, but your rewrite
    only stops at the end of a line.
    To preserve the original semantics, you should use
    while (fscanf(FD_IniFileP,"%" xstr(SIZE_OF_ARRAY) "s" ,key)!= EOF)

    Bart v Ingen Schenau
    --
    a.c.l.l.c-c++ FAQ: http://www.comeaucomputing.com/learn/faq
    c.l.c FAQ: http://www.eskimo.com/~scs/C-faq/top.html
    c.l.c++ FAQ: http://www.parashift.com/c -faq-lite/
     
    Bart van Ingen Schenau, Sep 10, 2007
    #9
  10. "Keith Thompson" <> wrote in message
    news:...
    > Richard Heathfield <> writes:
    >> I know what you're thinking of, but that's a special case of
    >> initialisation, [ unterminated char arrays] not a special case of
    >> string literals.

    >
    > What are you, some kind of pedant?
    >

    If we can't be literal about literals, where is it appropriate?

    --
    Free games and programming goodies.
    http://www.personal.leeds.ac.uk/~bgy1mm
     
    Malcolm McLean, Sep 10, 2007
    #10
    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. james
    Replies:
    2
    Views:
    410
    Nick Hounsome
    Feb 20, 2004
  2. Xiangliang Meng
    Replies:
    1
    Views:
    1,607
    Victor Bazarov
    Jun 21, 2004
  3. Jeremy Chapman

    WebForm_PostBackOptions and related functions

    Jeremy Chapman, Jun 26, 2006, in forum: ASP .Net
    Replies:
    0
    Views:
    955
    Jeremy Chapman
    Jun 26, 2006
  4. Maxwell Hammer
    Replies:
    7
    Views:
    644
    Peter Hansen
    Jun 18, 2005
  5. Replies:
    4
    Views:
    253
    Nikita the Spider
    Apr 15, 2007
Loading...

Share This Page