Segmentation fault (strcat_sse2_unaligned) while calling a function

R

Rudra Banerjee

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?
 
J

James Kuyper

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.
 
H

Heinrich Wolf

Noob said:
Rudra said:
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
 
N

Noob

Heinrich said:
Noob said:
#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?
 
H

Heinrich Wolf

Noob said:
Heinrich said:
Noob said:
#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.
 
N

Noob

Eric said:
Noob said:
#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.
 
H

Heinrich Wolf

A

Angel

Noob said:
Heinrich said:
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. [...]
 
H

Heinrich Wolf

Angel said:
Noob said:
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. [...]
 
K

Keith Thompson

James Kuyper said:
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 */
 
J

James Kuyper

James Kuyper said:
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.
 
T

Tim Rentsch

James Kuyper said:
[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'.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,054
Latest member
TrimKetoBoost

Latest Threads

Top