If the x and y parameter receive data from untrusted user would this piece of code pose some security threat?
char *p = malloc(x * y);
while (x > 0)
while (y > 0)
*p++ = 0;
Update:
Most people seems to comment on that it is an infinite loop and that this code piece will crash the program eventually when it write over its allocated memory.
However except for that problem. Isn't there possibly some issue with how malloc is used? E.g. heap overflow since no upper bound check for x and y?
You will write memory infinitely until the program craps out if x and y are positive, which I would expect. Not a good idea.
Receiving that code from a TRUSTED user would be a problem.
x and y never change. Assuming one of them is positive, the while loops will always evaluate to the same thing, and result in an infinite loop. If both are positive, you will keep writing memory until your program crashes.
Not a good piece of code.
If y and x are greater than 0, this will cause undefined behavior since you enter an infinite loop and assigning 0 to a pointer that points to memory you don't own.
Yes, that will write into memory that's not allocated, and the program will segfault.
Use memset if you want to empty a block of memory, the prototype looks like this:
void * memset(void *dest, int c, size_t count);
so the code would look something like this:
char *p = malloc(x * y);
memset(p, 0, x * y);
I don't see a security threat. Either you get values larger than 0, which will put you in an infinite loop and overwrite your process' memory until a segmentation fault occurs and your process dies. If one of the parameters is zero, you have a call to malloc(0), which might result in a memory leak.
The code is completely mad anyway, so I asume your question was academic.
Yes,there is an infinite loop and there can be a stack overflow, in your while loops.
Also Not sure how it is going to pose security threat, but it is a potential threat to the system, as it can cause memory issues.
There is no check of boundaries for "x" and "y", so user can send in a huge amount of data and you might get segmentation fault error.
There is missing cast of address returned by the malloc.
Also the coding style(*p++) confuses people so, it is difficult to maintain such a code.
This code will surely fail the application in real world.
As others have pointed out the code you've posted contains an infinite loop. You probably meant to do the following:
char *p = malloc( sizeof(x) * x * y );
if( p != NULL ) {
memset( p, 0, sizeof(x) * x * y );
} else {
// error allocating memory, handle it somehow
}
Related
I'm creating the below array:
int p[100];
int
main ()
{
int i = 0;
while (1)
{
p[i] = 148;
i++;
}
return (0);
}
The program aborts with a segmentation fault after writing 1000 positions of the array, instead of the 100. I know that C doesn't check if the program writes out of bounds, this is left to the OS. I'm running it on ubuntu, the size of the stack is 8MB (limit -s). Why is it aborting after 1000? How can I check how much memory my OS allocates for an array?
Sorry if it's been asked before, I've been googling this but can't seem to find a specific explanation for this.
Accessing an invalid memory location leads to Undefined Behavior which means that anything can happen. It is not necessary for a segmentation-fault to occur.
...the size of the stack is 8MB (limit -s)...
variable int p[100]; is not at the stack but in data area because it is defined as global. It is not initialized so it is placed into BSS area and filled with zeros. You can check that printing array values just at the beginning of main() function.
As other said, using p[i] = 148; you produced undefined behaviour. Filling 1000 position you most probably reached end of BSS area and got segmentation fault.
It appear that you clearly get over the 100 elements defined (int p[100];) since you make a loop without any limitation (while (1)).
I would suggest to you to use a for loop instead:
for (i = 0; i < 100; i++) {
// do your stuff...
}
Regarding you more specific question about the memory, consider that any outside range request (in your situation over the 100 elements of the array) can produce an error. The fact that you notice it was 1000 in your situation can change depending on memory usage by other program.
It will fail once the CPU says
HEY! that's not Your memory, leave it!
The fact that the memory is not inside of the array does not mean that it's not for the application to manipulate.
The program aborts with a segmentation fault after writing 1000 positions of the array, instead of the 100.
You do not reason out Undefined Behavior. Its like asking If 1000 people are under a coconut tree, will 700 hundred of them always fall unconscious if a Coconut smacks each of their heads?
I have a basic problem using memcpy and don't understand where the problem is. I show below the relevant parts of the code. The code seg. faults in the last right iteration of the loop. Why can't I index in to an memory area that is reserved?
Thank you in advance.
mystr->data = malloc(2048);
unsigned char buf[8500];
for (i=0;i<32;i++){
offset = i*256;
memcpy(&mystr->data[64*i],&buf[8+offset],64);
}
From the comments it'cs clear that my suspicion was right:
if sizeof( *mystr->data ) > 1 (because e.g. it's unsigned long long *data;) then you run beyond the end of the buffer because the offsets calculated by expressions like &mystr->data[64*i] are relative to the type, here it is mystr->data + 64*i*sizeof(*mystr->data) bytes which was up to 64*31*8 in your code.
You could either change the type, as you have done, or change the offsets (to &mystr->data[8*i] in your case) depending on what what seems 'right' semantically in your context
ive got a C program that gets caught in a for loop that it shouldn't, running it with
valgrind --tool=memcheck --leak-check=yes a.out
doesnt return anything even up until the program gets caught. is there a way to change the settings of valgrind to help me find the leak? as many have pointed out, it wouldnt be considered a leak, apologies
thanks in advance
here is the loop in question
int clockstate=0;
int clocklength=0;
int datalength=0;
int datastate=0;
int dataloc = 9;
((((some other code that i don't think is important to this part))))
int dataerr[13] = {0};
int clockerr[13] = {0}; // assumes that spill does not change within an event.
int spill=0;
int k = 0;
spill = Getspill(d+4*255+1); // get spill bit from around the middle
//printf("got spill: %d \n", spill); // third breakpoint
for( k = 0; k < 512; k++)
{
// Discardheader(d); // doesnt actually do anything, since it's a header.f
int databit = Getexpecteddata(d+4*k+1);
printf("%d ",k);
int transmitted = Datasample(&datastate, &datalength, d+4*k+2,dataerr,dataloc, databit);
printf("%d ",k);
Clocksample(&clockstate, &clocklength, d+4*k+3,clockerr, transmitted);
printf("%d \n",k);
// assuming only one error per event (implying the possibility of multi-error "errors"
// we construct the final error at the very end of the (outside this loop)
}
and the loop repeats after printing
254 254 254
255 255 255
256 256 1 <- this is the problem
2 2 2
3 3 3
edit** so i've tracked down where it is happening, and at one point in
void Clocksample (int* state, int* length, char *d, int *type, int transbit);
i have code that says *length = 1; so it seems that this command is somehow writing onto int k. my question now is, how did this happen, why isnt it changing length back to one like i want, and how do i fix it. if you want, i can post the whole code to Clocksample
Similar to last time, something in one of those functions, Clocksample() this time, is writing to memory that doesn't belong to the data/arrays that the function should be using. Most likely an out of bounds array write. Note: this is not a memory leak, which is allocating then losing track of memory blocks that should be freed.
Set a breakpoint at the call to Clocksample() for when k is 256. Then step into Clocksample(), keeping a watch on k (or the memory used by k). You can probably also just set a hardware memory write breakpoint on the memory allocated to k. How you do any of this depends on the debugger you're using.
Now single-step (or just run to the return of Clocksample() if you have a hardware breakpoint set) and when k changes, you'll have the culprit.
Please note that Valgrind is exceedingly weak when it comes to detecting stack buffer overflows (which is what appears to be happening here).
Google address-sanitizer is much better at detecting stack overflows, and I suggest you try it instead.
So your debugging output indicates that k is being changed during the call to your function Clocksample. I see that you are passing the addresses of at least two variables, &clockstate and &clocklength into that call. It seems quite likely to me that you have an array overrun or some other wild pointer in Clocksample that ends up overwriting the memory location where k is stored.
It might be possible to narrow down the bug if you post the code where k is declared (and whatever other variables are declared nearby in the same scope). For example if clocklength is declared right before k then you probably have a bug in using the pointer value &clocklength that leads to writing past the end of clocklength and corrupting k. But it's hard to know for sure without having the actual layout of variables you're using.
valgrind doesn't catch this because if, say, clocklength and k are right next to each other on the stack, valgrind can't tell if you have a perfectly valid access to k or a buggy access past the end of clocklength, since all it checks is what memory you actually access.
As the title says (and suggests), I'm new to C and I'm trying to return an arbitrary sized array of structs from a function. I chose to use malloc, as someone on the internet, whose cleverer than me, pointed out that unless I allocate to the heap, the array will be destroyed when points_on_circle finishes executing, and a useless pointer will be returned.
The code I'm presenting used to work, but now I'm calling the function more and more in my code, I'm getting a runtime error ./main: free(): invalid next size (normal): 0x0a00e380. I'm guessing this is down to my hacked-together implementation of arrays/pointers.
I'm not calling free as of yet, as many of the arrays I'm building will need to persist throughout the life of the program (I will be adding free() calls to the remainder!).
xy* points_on_circle(int amount, float radius)
{
xy* array = malloc(sizeof(xy) * amount);
float space = (PI * 2) / amount;
while (amount-- >= 0) {
float theta = space * amount;
array[amount].x = sin(theta) * radius;
array[amount].y = cos(theta) * radius;
}
return array;
}
My ground-breaking xy struct is defined as follows:
typedef struct { float x; float y; } xy;
And an example of how I'm calling the function is as follows:
xy * outer_points = points_on_circle(360, 5.0);
for(;i<360;i++) {
//outer_points[i].x
//outer_points[i].y
}
A pointer in the right direction would be appreciated.
Allocating memory in one function and freeing it in another is fraught with peril.
I would allocate the memory and pass it (the memory buffer) to the function with a parameter indicating how many structures are allowed to be written to the buffer.
I've seen APIs where there are two functions, one to get the memory required and then another to actually get the data after the memory has been allocated.
[Edit] Found an example:
http://msdn.microsoft.com/en-us/library/ms647005%28VS.85%29.aspx
I would say that this program design is fundamentally flawed. First of all, logically a function which is doing calculations has nothing to do with memory allocation, those are two different things. Second, unless the function that allocates memory and the one that frees it belong to the same program module, the design is bad and you will likely get memory leaks. Instead, leave allocation to the caller.
The code also contains various dangerous practice. Avoid using -- and ++ operators as part of complex expressions, it is a very common cause for bugs. Your code looks as if it has a fatal bug and is writing out of bounds on the array, just because you are mixing -- with other operators. There is never any reason to do so in the C language, so don't do it.
Another dangerous practice is the reliance on C's implicit type conversions from ints to float (balancing, aka "the usual arithmetic conversions"). What is "PI" in this code? Is it an int, float or double? The outcome of the code will vary depending on this.
Here is what I propose instead (not tested):
void get_points_on_circle (xy* buffer, size_t items, float radius)
{
float space = (PI * 2.0f) / items;
float theta;
signed int i;
for(i=items-1; i>=0; i--)
{
theta = space * i;
buffer[i].x = sin(theta) * radius;
buffer[i].y = cos(theta) * radius;
}
}
EDIT: You are returning the array correctly, but ...
Consider you're making an array with 1 element
xy *outer_points = points_on_circle(1, 5.0);
What happens inside the function?
Let's check ...
xy* array = malloc(sizeof(xy) * amount);
allocate space for 1 element. OK!
while (amount-- >= 0) {
1 is greater or equal to 0 so the loop executes (and amount gets decreased)
after setting array[0] you return to the top of the loop
while (amount-- >= 0) {
0 is greater or equal to 0 so the loop executes (and amount gets decreased)
You're now trying to set array[-1], which is invalid because the index refers to an area outside of the array.
I think this:
while (amount-- >= 0 ) {
should be:
while ( --amount >= 0 ) {
Consider the case where amount is zero initially.
You're doing the right thing as far as I'm concerned, provided of course your callers are free'ing the results.
Some people prefer to have the memory allocation and freeing responsibility in the same place (for symmetry), i.e. outside your function. In this case you would pass a pre-allocated xy* as a parameter and return the size of the buffer if the pointer was null:
int requiredSpace = points_on_circle(10, 10, NULL);
xy* myArray = (xy*)malloc(requiredSpace);
points_on_circle(10, 10, myArray);
free(myArray);
You are iterating over one element to much.
You should use the goes down to zero operator instead:
while ( amount --> 0) {
...
}
Allocating memory in one function and freeing it in the other is like giving a gun to a four year old. You shoudn't do that.
While your decision to count down amount and use while instead of using a temp value saved a few memory cycles, it is more conceptually confusing. Especially in a case where the maths are taking all the time here, you only save fractions.
But that is not the reason why you should waste minor amounts of time. This question is the reason: you've wasted hours! This applies to even the most experienced and smartest programmers. The mistakes are just more complicated and beyond the scope of a stackoverflow answer! In other words, the Peter Principle applies to coding too.
Don't make the mistake as you gain experience that you can get away with taking these kinds of risks to save a cycle or two. That is why McConnell in Code Complete lists Humility as a positive programmer attribute.
Here's the solution you probably thought of to start with:
xy* points_on_circle(int amount, float radius)
{
xy* array = malloc(sizeof(xy) * amount);
float space = (PI * 2) / amount;
int index;
for (index=0;index<amount;index++) {
float theta = space * index;
array[index].x = sin(theta) * radius;
array[index].y = cos(theta) * radius;
}
return array;
}
If you need speed, a tiny thing you can do is put theta outside the loop set to 0 and add 'space' each time since + is bound to be cheaper than * in floating point.
speed it up 10x or more?
If you need serious speed, this tip from answers.com will give you an improvement of 10x if you do it right:
By Pythagoream's theorem, x2 + y2 is
radius2. It is then simple to solve
for x or y, given the other along with
radius. You also do not need to
compute for the whole circle - you can
compute for one quadrant, and generate
the other three quadrants by symmetry.
You generation loop would, for
example, simply iterate from origin to
radius as x by delta x, generating y,
and reflecting that in the other three
quadrants. You can also compute for
one half of a quadrant, and use both
symmetry and reflection to generate
the other seven half quadrants.
When I was 12 I thought I was hot stuff drawing a circle using sin and cos in graphics 8 on my atari 800. My cousin Marty (when as of late worked form Microsoft robotics) erased my program and implemented the above solution, using only addition in the loop if I remember right, and draw the same circle in 4 seconds instead of a minute! Had I not been baptized I would have bowed down in worship. Too bad I don't have the code handy but I'd bet a little googling would bring it up. Anybody?
I'll copy the relevant lines:
(Declarations)
typedef struct { /* per una entrada de la taula de posicion */
int f;
int c;
} pos;
pos *p_opo[9];
(in main)
for (i = 0; i < num; i++) {
p_opo[i] = (pos *) calloc(n_fil * n_col / 2, sizeof (pos));
}
Now, after only having introduced this lines, the code breaks in an arbitrary point (in a call to a given library function). I suspect I'm corrupting something with this, although I don't know what.
All I want is to have an array of variable size arrays!
PD: num is an argument of the program. I've been running it with num=1 anyway.
num should be less or equal to 9. (0..8 allocated pointers in p_opo equals 9 !)
Note that in C that you get errors in a different place in case of memory leaks, etc. The reason for this is that by changing some code, other code or data can be rearranged and this may end up in segmentation faults.
So the problem may very well be in another part of your program. Make sure you have all you warnings turned on (like the -Wall option in gcc), it may give you some clues.
If your call to calloc asks for memory of size 0 it may return NULL, and if you are making use of that memory it could be causing the segmentation fault. So if:
0 == (n_fil * n_col / 2)
or somehow
0 == sizeof (pos) /* I don't think that this is possible */
the size of the memory that you are asking for is 0, and so calloc can return NULL.
If this is not the case then I don't think that you have enough code up there for anyone to know why it is segfaulting. You should keep in mind that errors like this can go unnoticed until you add or change some code that seems to be totally unrelated to the code that has the actual error.
Seeing you casting the return of calloc makes me suspicious. Don't do that, this leads to a typical error if you forget the include for the system function.
This happes if you are on a machine with 64 bit pointers and 32 bit int.