Segmentation fault (strcat_sse2_unaligned) while calling a function

Discussion in 'C Programming' started by Rudra Banerjee, Jun 12, 2013.

  1. Hello friends,
    Please refer to the question http://www.gtkforums.com/viewtopic.php?f=3&t=178532&p=196942#p196942.

    As commented by errol, the seg fault is caused by
    "Your error is in the use of strcat() in gs_open() and how you declared buffer.

    If you declared buffer as
    Code:
    char *buffer = "";
    Your use of strcat() would case a buffer overflow. The initial buffer is only 1 byte in size and that contains the '\0' terminator. Also if buffer has been used before the contents or even the pointer could also be mangled giving you more problems."

    can I get some insight?
     
    Rudra Banerjee, Jun 12, 2013
    #1
    1. Advertising

  2. Rudra Banerjee

    Noob Guest

    Rudra Banerjee wrote:

    > can I get some insight? [using strcat]


    http://man7.org/linux/man-pages/man3/strcat.3.html

    Here's a small example.

    #include <string.h>
    #include <stdio.h>

    int main(void)
    {
    const char s1[] = "hello";
    const char s2[] = "world";

    char s3[80];
    sprintf(s3, "%s, %s!", s1, s2);
    printf("%s\n", s3);

    memset(s3, 0, sizeof s3);
    strcpy(s3, s1);
    strcat(s3, s2);
    printf("%s\n", s3);

    return 0;
    }
     
    Noob, Jun 12, 2013
    #2
    1. Advertising

  3. Rudra Banerjee

    James Kuyper Guest

    On 06/12/2013 03:58 AM, Rudra Banerjee wrote:
    > Hello friends,
    > Please refer to the question http://www.gtkforums.com/viewtopic.php?f=3&t=178532&p=196942#p196942.
    >
    > As commented by errol, the seg fault is caused by
    > "Your error is in the use of strcat() in gs_open() and how you declared buffer.
    >
    > If you declared buffer as
    > Code:
    > char *buffer = "";
    > Your use of strcat() would case a buffer overflow. The initial buffer is only 1 byte in size and that contains the '\0' terminator. Also if buffer has been used before the contents or even the pointer could also be mangled giving you more problems."
    >
    > can I get some insight?
    >


    "" is an empty string literal. Since C strings are null terminated, it
    implicitly contains one null character. The use of a string literal
    causes the creation of an unnamed array long enough to contain the
    string. The string literal itself is converted into a pointer to the
    first element of the unnamed array, and the value of that pointer is
    stored in buffer. In other words, the above code is functionally
    equivalent to:

    char unnamed[1] = {'\0'};
    char *buffer = &unnamed[0];

    When you call strcat(buffer, gs_text), it tries to catenate the string
    pointed at by gs_text onto the end of the string contained in the array
    pointed at by buffer. If gs_text is also an empty string, this is fine;
    the catenation of two empty strings is an empty string, which needs only
    a terminating null character. However, if gs_text isn't empty, which is
    presumably the normal case, then it will contain at least two
    characters: the first character of that string and the terminating null
    character. The array pointed at by buffer isn't big enough to hold that
    many characters, and bad things can happen (and apparently did happen)
    when strcat() attempts to put more characters into that array than there
    is room for. The behavior is undefined in that case, so in principle
    just about anything could happen. In your case, strcat() tried to write
    into the locations in memory that come after the unnamed array. At least
    part of that memory didn't belong to your program, so your attempt to
    write to that location triggered a segment violation which aborted your
    program. Your operating system works on a policy that says that a
    program which attempts to write to memory that it doesn't have a right
    to is too dangerous to be allowed to continue running.
    If the memory after the end of the array does belong to your program ,
    then other kinds of bad behavior are possible. The write will, in
    general, cause whatever variables your program is storing in that
    location to change their value, causing unpredictable errors in the way
    your program behaves. DONT DO THIS.

    Always make sure that the first pointer that you pass to strcat() points
    to an array that is long enough to store the entire length of the
    catenated strings, including the terminating null character.
    --
    James Kuyper
     
    James Kuyper, Jun 12, 2013
    #3
  4. "Noob" <root@127.0.0.1> schrieb im Newsbeitrag
    news:kp9atj$7bq$...
    > Rudra Banerjee wrote:
    >
    >> can I get some insight? [using strcat]

    >
    > http://man7.org/linux/man-pages/man3/strcat.3.html
    >
    > Here's a small example.
    >
    > #include <string.h>
    > #include <stdio.h>
    >
    > int main(void)
    > {
    > const char s1[] = "hello";
    > const char s2[] = "world";
    >
    > char s3[80];
    > sprintf(s3, "%s, %s!", s1, s2);
    > printf("%s\n", s3);


    This printf will likely lead to a segmentation fault. s3 is not initialized
    and I doubt that one of it's 80 chars is 0. So printf will read beyond the
    end of s3.

    > memset(s3, 0, sizeof s3);


    This memset should have been placed before printf. Here it is completely
    useless. The strcpy in the next line of code initializes s3 as well as
    memset, even if it does not pad it to the end with 0's.

    > strcpy(s3, s1);
    > strcat(s3, s2);
    > printf("%s\n", s3);
    >
    > return 0;
    > }
    >


    Heiner
     
    Heinrich Wolf, Jun 12, 2013
    #4
  5. Rudra Banerjee

    Noob Guest

    Heinrich Wolf wrote:

    > Noob wrote:
    >
    >> #include <string.h>
    >> #include <stdio.h>
    >>
    >> int main(void)
    >> {
    >> const char s1[] = "hello";
    >> const char s2[] = "world";
    >>
    >> char s3[80];
    >> sprintf(s3, "%s, %s!", s1, s2);
    >> printf("%s\n", s3);

    >
    > This printf will likely lead to a segmentation fault. s3 is not initialized
    > and I doubt that one of its 80 chars is 0.


    Would you like to bet on it?
     
    Noob, Jun 12, 2013
    #5
  6. Rudra Banerjee

    Eric Sosman Guest

    On 6/12/2013 4:23 AM, Noob wrote:
    > Rudra Banerjee wrote:
    >
    >> can I get some insight? [using strcat]

    >
    > http://man7.org/linux/man-pages/man3/strcat.3.html
    >
    > Here's a small example.
    >
    > #include <string.h>
    > #include <stdio.h>
    >
    > int main(void)
    > {
    > const char s1[] = "hello";
    > const char s2[] = "world";
    >
    > char s3[80];
    > sprintf(s3, "%s, %s!", s1, s2);
    > printf("%s\n", s3);
    >
    > memset(s3, 0, sizeof s3);


    Why?

    > strcpy(s3, s1);
    > strcat(s3, s2);
    > printf("%s\n", s3);
    >
    > return 0;
    > }


    --
    Eric Sosman
    d
     
    Eric Sosman, Jun 12, 2013
    #6
  7. "Noob" <root@127.0.0.1> schrieb im Newsbeitrag
    news:kp9pop$f4k$...
    > Heinrich Wolf wrote:
    >
    >> Noob wrote:
    >>
    >>> #include <string.h>
    >>> #include <stdio.h>
    >>>
    >>> int main(void)
    >>> {
    >>> const char s1[] = "hello";
    >>> const char s2[] = "world";
    >>>
    >>> char s3[80];
    >>> sprintf(s3, "%s, %s!", s1, s2);
    >>> printf("%s\n", s3);

    >>
    >> This printf will likely lead to a segmentation fault. s3 is not
    >> initialized
    >> and I doubt that one of its 80 chars is 0.

    >
    > Would you like to bet on it?


    Statistics tells me a chance of 73% for segmentation fault. But I did not
    consider that the memory after s3 might also be readable.
     
    Heinrich Wolf, Jun 12, 2013
    #7
  8. Rudra Banerjee

    Noob Guest

    Eric Sosman wrote:

    > Noob wrote:
    >
    >> #include <string.h>
    >> #include <stdio.h>
    >>
    >> int main(void)
    >> {
    >> const char s1[] = "hello";
    >> const char s2[] = "world";
    >>
    >> char s3[80];
    >> sprintf(s3, "%s, %s!", s1, s2);
    >> printf("%s\n", s3);
    >>
    >> memset(s3, 0, sizeof s3);

    >
    > Why?


    [What's up with the bike sheds?!]

    I thought the OP might get confused by the remnants
    of the previous operation if they examined s3 in a
    step-by-step debugger.

    Regards.
     
    Noob, Jun 12, 2013
    #8
  9. "Heinrich Wolf" <> schrieb im Newsbeitrag
    news:kp9oqh$tjr$-online.net...
    >
    > "Noob" <root@127.0.0.1> schrieb im Newsbeitrag
    > news:kp9atj$7bq$...
    >> Rudra Banerjee wrote:
    >>
    >>> can I get some insight? [using strcat]

    >>
    >> http://man7.org/linux/man-pages/man3/strcat.3.html
    >>
    >> Here's a small example.
    >>
    >> #include <string.h>
    >> #include <stdio.h>
    >>
    >> int main(void)
    >> {
    >> const char s1[] = "hello";
    >> const char s2[] = "world";
    >>
    >> char s3[80];
    >> sprintf(s3, "%s, %s!", s1, s2);


    I'm sorry!
    I did not read carefully enough.
    I thought of printf("%s, %s!", in place of sprintf(s3, "%s, %s!",

    >> printf("%s\n", s3);

    >
    > This printf will likely lead to a segmentation fault. s3 is not
    > initialized and I doubt that one of it's 80 chars is 0. So printf will
    > read beyond the end of s3.
    >
    >> memset(s3, 0, sizeof s3);

    >
    > This memset should have been placed before printf. Here it is completely
    > useless. The strcpy in the next line of code initializes s3 as well as
    > memset, even if it does not pad it to the end with 0's.
    >
    >> strcpy(s3, s1);
    >> strcat(s3, s2);
    >> printf("%s\n", s3);
    >>
    >> return 0;
    >> }
    >>

    >
    > Heiner
     
    Heinrich Wolf, Jun 12, 2013
    #9
  10. Rudra Banerjee

    Angel Guest

    Re: Segmentation fault (strcat_sse2_unaligned) while calling afunction

    On 2013-06-12, Heinrich Wolf <> wrote:
    >
    > "Noob" <root@127.0.0.1> schrieb im Newsbeitrag
    > news:kp9pop$f4k$...
    >> Heinrich Wolf wrote:
    >>
    >>> Noob wrote:
    >>>
    >>>> #include <string.h>
    >>>> #include <stdio.h>
    >>>>
    >>>> int main(void)
    >>>> {
    >>>> const char s1[] = "hello";
    >>>> const char s2[] = "world";
    >>>>
    >>>> char s3[80];
    >>>> sprintf(s3, "%s, %s!", s1, s2);
    >>>> printf("%s\n", s3);
    >>>
    >>> This printf will likely lead to a segmentation fault. s3 is not
    >>> initialized
    >>> and I doubt that one of its 80 chars is 0.

    >>
    >> Would you like to bet on it?

    >
    > Statistics tells me a chance of 73% for segmentation fault. But I did not
    > consider that the memory after s3 might also be readable.


    I can't find offhand if it's standard or not, but the glibc implementation
    of sprintf() writes a terminating null to the output buffer, so if it is
    compiled against glibc this program will not segfault.

    http://www.gnu.org/software/libc/manual/html_node/Formatted-Output-Functions.html

    Function: int sprintf (char *s, const char *template, ...)

    This is like printf, except that the output is stored in the
    character array s instead of written to a stream. A null character
    is written to mark the end of the string. [...]


    --
    I survived the end of the world and I didn't even get a lousy T-shirt!
     
    Angel, Jun 12, 2013
    #10
  11. "Angel" <> schrieb im Newsbeitrag
    news:...
    > On 2013-06-12, Heinrich Wolf <> wrote:
    >>
    >> "Noob" <root@127.0.0.1> schrieb im Newsbeitrag
    >> news:kp9pop$f4k$...
    >>> Heinrich Wolf wrote:
    >>>
    >>>> Noob wrote:
    >>>>
    >>>>> #include <string.h>
    >>>>> #include <stdio.h>
    >>>>>
    >>>>> int main(void)
    >>>>> {
    >>>>> const char s1[] = "hello";
    >>>>> const char s2[] = "world";
    >>>>>
    >>>>> char s3[80];
    >>>>> sprintf(s3, "%s, %s!", s1, s2);
    >>>>> printf("%s\n", s3);
    >>>>
    >>>> This printf will likely lead to a segmentation fault. s3 is not
    >>>> initialized
    >>>> and I doubt that one of its 80 chars is 0.
    >>>
    >>> Would you like to bet on it?

    >>
    >> Statistics tells me a chance of 73% for segmentation fault. But I did not
    >> consider that the memory after s3 might also be readable.

    >
    > I can't find offhand if it's standard or not, but the glibc implementation
    > of sprintf() writes a terminating null to the output buffer, so if it is
    > compiled against glibc this program will not segfault.


    You are right as I wrote in the meantime. I did not read Noob's code well
    enough.

    > http://www.gnu.org/software/libc/manual/html_node/Formatted-Output-Functions.html
    >
    > Function: int sprintf (char *s, const char *template, ...)
    >
    > This is like printf, except that the output is stored in the
    > character array s instead of written to a stream. A null character
    > is written to mark the end of the string. [...]
    >
    >
    > --
    > I survived the end of the world and I didn't even get a lousy T-shirt!
     
    Heinrich Wolf, Jun 12, 2013
    #11
  12. James Kuyper <> writes:
    > On 06/12/2013 03:58 AM, Rudra Banerjee wrote:
    >> Hello friends,
    >> Please refer to the question http://www.gtkforums.com/viewtopic.php?f=3&t=178532&p=196942#p196942.
    >>
    >> As commented by errol, the seg fault is caused by
    >> "Your error is in the use of strcat() in gs_open() and how you declared buffer.
    >>
    >> If you declared buffer as
    >> Code:
    >> char *buffer = "";
    >> Your use of strcat() would case a buffer overflow. The initial buffer
    >> is only 1 byte in size and that contains the '\0' terminator. Also if
    >> buffer has been used before the contents or even the pointer could
    >> also be mangled giving you more problems."
    >>
    >> can I get some insight?
    >>

    >
    > "" is an empty string literal. Since C strings are null terminated, it
    > implicitly contains one null character. The use of a string literal
    > causes the creation of an unnamed array long enough to contain the
    > string. The string literal itself is converted into a pointer to the
    > first element of the unnamed array, and the value of that pointer is
    > stored in buffer. In other words, the above code is functionally
    > equivalent to:
    >
    > char unnamed[1] = {'\0'};
    > char *buffer = &unnamed[0];
    >
    > When you call strcat(buffer, gs_text), it tries to catenate the string
    > pointed at by gs_text onto the end of the string contained in the array
    > pointed at by buffer. If gs_text is also an empty string, this is fine;
    > the catenation of two empty strings is an empty string, which needs only
    > a terminating null character.

    [...]

    You missed something. The unnamed array is read-only; it's not
    const-qualified, but any attempt to modify it has undefined behavior.
    Even this:

    char *buffer = "";
    strcat(buffer, "");

    has undefined behavior; see N1570 7.1.4p1:

    If an argument to a function has an invalid value (such
    as [...], or a pointer to non-modifiable storage when the
    corresponding parameter is not const-qualified) [...], the
    behavior is undefined.

    The strcat() call is likely to behave as a no-op, since it doesn't
    actually have to copy anything; that is, of course, a possible symptom
    of undefined behavior.

    This can be alleviated by declaring pointers to string literals a
    "const":

    const char *buffer = "";
    strcat(buffer, ""); /* the compiler will complain about this */

    --
    Keith Thompson (The_Other_Keith) <http://www.ghoti.net/~kst>
    Working, but not speaking, for JetHead Development, Inc.
    "We must do something. This is something. Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"
     
    Keith Thompson, Jun 12, 2013
    #12
  13. Rudra Banerjee

    James Kuyper Guest

    On 06/12/2013 11:40 AM, Keith Thompson wrote:
    > James Kuyper <> writes:
    >> On 06/12/2013 03:58 AM, Rudra Banerjee wrote:
    >>> Hello friends,
    >>> Please refer to the question http://www.gtkforums.com/viewtopic.php?f=3&t=178532&p=196942#p196942.
    >>>
    >>> As commented by errol, the seg fault is caused by
    >>> "Your error is in the use of strcat() in gs_open() and how you declared buffer.
    >>>
    >>> If you declared buffer as
    >>> Code:
    >>> char *buffer = "";
    >>> Your use of strcat() would case a buffer overflow. The initial buffer
    >>> is only 1 byte in size and that contains the '\0' terminator. Also if
    >>> buffer has been used before the contents or even the pointer could
    >>> also be mangled giving you more problems."
    >>>
    >>> can I get some insight?
    >>>

    >>
    >> "" is an empty string literal. Since C strings are null terminated, it
    >> implicitly contains one null character. The use of a string literal
    >> causes the creation of an unnamed array long enough to contain the
    >> string. The string literal itself is converted into a pointer to the
    >> first element of the unnamed array, and the value of that pointer is
    >> stored in buffer. In other words, the above code is functionally
    >> equivalent to:
    >>
    >> char unnamed[1] = {'\0'};
    >> char *buffer = &unnamed[0];
    >>
    >> When you call strcat(buffer, gs_text), it tries to catenate the string
    >> pointed at by gs_text onto the end of the string contained in the array
    >> pointed at by buffer. If gs_text is also an empty string, this is fine;
    >> the catenation of two empty strings is an empty string, which needs only
    >> a terminating null character.

    > [...]
    >
    > You missed something. The unnamed array is read-only; it's not
    > const-qualified, but any attempt to modify it has undefined behavior.



    You're right. I missed that point. The code was bad enough because of
    the problem I did explain, but this makes it even worse.
     
    James Kuyper, Jun 12, 2013
    #13
  14. Rudra Banerjee

    Tim Rentsch Guest

    James Kuyper <> writes:

    > [snip]
    >
    > When you call strcat(buffer, gs_text), it tries to catenate the
    > string pointed at by gs_text onto the end of the string
    > contained in the array pointed at by buffer. [snip]


    The usual word is "concatenate", not "catenate". The word
    "catenate" means something different from "concatenate".
    The 'strcat()' function will concatenate two strings, not
    catenate them. See, eg,

    http://en.wikipedia.org/wiki/Concatenation
    http://en.wikipedia.org/wiki/Catenation

    Note also that the ISO standard refers to strcat and related
    functions as 'Concatenation functions'.
     
    Tim Rentsch, Jun 15, 2013
    #14
    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. Atulvid
    Replies:
    2
    Views:
    1,087
    Martin Ambuhl
    Aug 11, 2003
  2. mufasa
    Replies:
    1
    Views:
    637
    Maxim Yegorushkin
    Jul 21, 2005
  3. Replies:
    1
    Views:
    425
  4. H.S.
    Replies:
    9
    Views:
    751
    Richard Herring
    Aug 13, 2008
  5. sanket
    Replies:
    11
    Views:
    1,931
    sanket
    Apr 15, 2009
Loading...

Share This Page