Bufferoverflow, snprintf instead char resizes? [duplicate] - c

This question already has answers here:
Undefined, unspecified and implementation-defined behavior
(9 answers)
No out of bounds error
(7 answers)
Closed 3 years ago.
I have a hard time to understand why the below code is not resulting in a bufferoverflow and instead some how seems to resize the char example from 1 to 16.
I checked the snprintf documentation but nothing to be found about this.
//set char example size 1
char example[1];
//set example to args->arg2 which is a 15 character + 1 null byte.
//trying to put something to big into something too small, in my mind causing not a resize but a bof.
snprintf(example, 16, "%s", args->arg2);
fprintf(stdout,"[%s],example);
The fprintf in the end does not display 1 character nor does char example overflows but instead it seems to be resized and displays the full string of 16.
What am i misunderstanding here ?

Your array is not resized. Instead what happens is that there is some memory following it (in fact it's your call stack, which is why overruns like this are dangerous), and snprintf 'trusts' you and writes into that memory. fprintf after that happily reads whatever snprintf wrote there.
It works for you now, but it is undefined behavior, which means that, sooner or later, it will break.

Related

Why is this snippet giving 6 as output? [duplicate]

This question already has an answer here:
How does the strlen function work internally?
(1 answer)
Closed 5 years ago.
int main(){
char s[1000];
s[0]='Q';
printf("%d",strlen(s));
return 0;
}
The above code is giving 6 as output.
The output should be 1 in this case.
int main(){
char s[1000];
printf("%d",strlen(s));
return 0;
}
This code was even giving 6 as output.
where it should be 1000 or 0 or some garbage value.
I have tried it in " hackerrank ", but it was giving 6 as the length.
When the same code was tried in TURBOC it was giving the correct answer.
I was unable to find the reason for this output. Can someone please sort it out and give the exact solution to this problem.
Local non-static variables, like your array, will not be initialized. Its value or contents will be indeterminate.
That means the likelihood of your array containing a string terminator where you want it to be is close to zero.
Passing your array without initialization to a string-function leads to undefined behavior.
You need to explicitly initialize your array, like e.g.
char s[1000] = "";
The line:
char s[1000];
declares an array of 1000 chars but it doesn't put anything in it. Because it is a local variable, it is allocated on the stack and, apart from reserving the necessary space to hold 1000 chars, the compiler doesn't generate any code to set their content (to zero or something else).
All 1000 values are garbage. It just happens that the 7th of them is zero. strlen() stops counting when it reaches it and returns 6 but this value is also garbage. It could be 230790345 or something else as well. It could also produce an infinite loop, a segmentation fault or make you spit fire like a dragon. Anything is possible and permitted by the language in this situation. It is called Undefined Behaviour.

No SEG_FAULT when copying large string to small buffer after integer overflow [duplicate]

This question already has answers here:
What's the point of using malloc when you can use pointer? [duplicate]
(3 answers)
Closed 6 years ago.
I'm trying to demonstrate an integer overflow bug and its consequences by writing a small code as follows:
int main(int argc, char** argv)
{
size_t len = 0;
sscanf (argv[1], "%lu", &len);
char* buffer = malloc(len + 5);
strcpy (buffer, argv[2]);
printf("str = \'%s\'\n", buffer)
return 0;
}
A safe input to this program is like this:
./program 16 "This is a string"
Where an unsafe input to demo the integer overflow is like this:
./program 18446744073709551613 "`perl -e 'print "This is a very very large string "x20'`"
Yet to my surprise, even though the integer overflow is happening and a very small buffer is being allocated, the program does NOT produce any SEGMENTATION FAULT and the program executes fine without any problems to the end!
Can someone explain why this is ?
I'm compiling this with GCC-5.2.1 and running on 64-bit Ubuntu system.
A more complete version of the code can be viewed here.
What you're seeing here is simply undefined behavior. It may work sometimrs but really randomly and often will fail in more complex scenarios - like allocating another buffer and later freeing them both etc.
Specifically here C library allocates bigger chunk of memory and splits it according to demand. In other words the memory behind the buffer still exists and from OS point of view it's valid. But writing there corrupt sooner or later another buffer or its linking and will cause either fault or just unexpected content.

Error Copying 1 string to another in C [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
Improve this question
I was trying to copy the contents of 1 string to another (a into b) .
I deliberately took the second string(b) to be smaller than the 1st
one(a) .
I copied the contents of the first one into second
. I added WATCH on both of them . In the Debug tab , I found out that while
copying the original string gets destroyed and the new one also
DISPLAYED LARGER than its size.
#include<stdio.h>
int main()
{
char a[10]="What?";
char b[2];
int i;
for(i=0;i<6;i++)
{
b[i]=a[i];
}
printf("This is %s",a);
printf("\n this is b now: ",b);
return 0;
}
I have attached the screenshot for the same. I took a = a string of
size 10 . a="WHat?" then I took a string b[2]
After copying , I printed both a and b . I expected the output to be
, a = "WHat?" , b="WH" But the output is coming something else.(See
the screenshot)
Why did the original string get destroyed ? Has the pointer changed ? But I have made it a constant pointer .It can't be changed.
Here is the Screen shot to the problem I am facing :
https://www.dropbox.com/s/8xwxwb27qis8xww/sjpt.jpg
Please Help Somebody !!
You are copying 6 bytes into an array of two bytes, essentially invoking undefined behavior.
You are passing array b to printf with %s specifier that expects a null-terminated string, while b is most likely not null-terminated at that point, which is another undefined behavior.
Also, a null-terminated string that can fit into 2 bytes array can essentially have only one printable character, so you should not expect b to be "WH". At best, if you fix the copying, it can only be "W" as the second character will be a termination byte (\0). If you want to have two characters, either increase the array size to 3 to allow for null terminator, or simply do not use C strings and print out two bytes using "%c%c" format string.
As pointed out in other answers, you are writing outside the bounds of the array. The original string a changes because it happens to be exactly after b in memory as you can see in the debug window.
Before the loop, memory looks like this:
b a
|00|WHat?00000|
After the loop, memory looks like this:
b a
|WH|at?0?00000|
This explains why
a is changed
the original questionmark in a is still there (you only write 6 characters - two into the location reserved for b, 4 (including null terminator) into the location of a)
Of course this is undefined behavior as already mentioned by Vlad Lazarenko, but it explains the behavior for your compiler/settings/version/etc.
A constant pointer only exists for the compiler. It ensures that you cannot explicitly manipulate its data, but if you have memory leaks, nothing can be guaranteed.
What you're doing currently is very unsafe! It might work on Windows for some godforsaken reason, but don't do this!
The C standard library has special functions for working with strings and memory, strcpy for example is for copying character arrays. I suggest you learn more about how strings work and how you can manipulate them.

memcpy overlapping not understandable [duplicate]

This question already has an answer here:
Please look into this inexplicable behavior and output of memcpy() for overlapping memory blocks
(1 answer)
Closed 8 years ago.
I'm playing with memcpy in order to acquire better perception of its work and i've run into things i can't understand.
I start from very simple piece of code:
char str [] = "0123456789abcdef";
memcpy(str + 5, str, 5);
puts(str);// prints 0123401234abcdef
that's absolutely understandable for me. Then i move on:
char str [] = "0123456789abcdef";
memcpy(str + 5, str, 6);
puts(str); // 01234012340bcdef
at first i expected the output to be 01234012345bcdef assuming that the function will take first six characters but it started from 0 again. Ok, thought i, probably it somehow takes characters from already built new string. And putting 7 like this memcpy(str + 5, str, 7); confirmed this my assumption because it had produced 012340123401cdef as output.
But then things started to get more unclear. If i do this memcpy(str + 5, str, 8); it outputs 0123401234567def!!!. Just like i expected from the beginning.
I'm totally confused. Why it behaves this way? Ok, i can even understand printing 01 as 11th and 12th characters of the string (but this is not what i expected and i would be grateful for an explanation). But why when i determine the length as 8 it changes its behaviour???
I hope you understand what i mean. Please provide a detailed explanation. Thanks a lot in advance
The memcpy() function shall copy n bytes from the object pointed to by s2 into the object pointed to by s1. If copying takes place between objects that overlap, the behavior is undefined.
memcpy assumes that the source and destination don't overlap. If they do, anything can happen, and exactly what happens may depend on what compiler you use, what machine you compile or run on, how big the region you're copying is, what time of day it is, etc. If you want to copy a block of memory to a destination overlapping the original position, use memmove.
For memcpy():
[...] If the objects overlap, the behavior is undefined.
You should use memmove() instead for overlapping cases.
[...] The objects may overlap: copying takes place as if the characters were copied to a temporary character array and then the characters were copied from the array to dest.

sprintf in C resets the value of counting variable [duplicate]

This question already has answers here:
sprintf buffer sizes
(3 answers)
Closed 9 years ago.
I'm having an issue with sprintf in C resetting the value of a counter variable when I run it. Here in a nutshell is what is happening:
int count = 0;
count++;
printf("%d\n", count); // count will equal 1
char title[7];
sprintf(title, "%.3d.jpg", count);
printf("%d\n", count); // count now equals 0 again
Is this normal behavior for sprintf?
title is too small, sprintf is writing beyond the bounds of title, and writing into count, corrupting its value.
Note that title needs to be long at least 8 bytes: 3 for %.3d, 4 for .jpg and 1 for the terminator \0.
As Grijesh Chauhan points out, you can make sure that you never write beyond the allocated size of the string by using snprintf, i.e.:
char title[8];
snprintf(title, sizeof(title), "%.3d.jpg", count);
You simply need more space in the string title: 3 digits+".jpg" = 7 chars, and u need one extra for '\0'(end of the string). Sprintf can change argument in a case such as this(Using sprintf will change the specified variable)
Solution: change
char title[7];
to
char title[8];
You problem is called buffer overflow. sprintf has no idea of the size of title, and write has much as needed, even if it exceeds the boundaries of your array. To fully understand, you also have to know that strings are terminated by a zero. This allows to find the end of a string, without prior knowledge of its true size. This extra zero takes the place of an extra character that you have to consider when dimensioning your buffers.
Consider also the use of snprintf that ensures you are not going over the boundaries of your buffer.

Resources