Buffer overflow with random size buffer? (gets) - c

I'm trying to learn more about ways to exploit/prevent buffer overflow in my programs. I know that the following code is vulnerable if the size is constant, but what if the size is random every time? Is there still a way to grab it from the stack and somehow alter the amount of overflow characters dynamically?
void vulnFunc(int size){
char buffer[size];
gets(buffer);
// Arbitrary code
}

Consider
fgets(buf, sizeof(buf)-1, stdin);
with stdin and a size that matches your buffer. It will be safe. There are other possibilities, such as a loop with getc(stdin): when the data becomes larger than
your buffer you can realloc().

It depends on the variable that is used to represent the array, if its of type char[] or char *. let me explain why:
for char[], the variable name represents an array and the sizeof operator returns the size of the array in the memory (number of cell * sizeof(type)), so basicly you can get the number of cells using the following call:
sizeof(array)/sizeof(array[0])
for char*, the variable is a pointer which holds the value of the first cell of the array, sizeof(array) in this case will return the size of pointer in memory that is 8Byte for 64bit architecture, it has nothing with the array so you cant get the information from this kind of variable. Maybe you could store the size of the allocated buffer in memory but I don't know if it suits your needs.

Related

What is the point of buffer in getline?

http://man7.org/linux/man-pages/man3/getline.3.html
I don't understand the point of the second parameter size_t *n.
Why would you need a buffer between the input (stdin for example) and the output (some character array).
Also, in the example they provide, size_t len = 0;. What is the significance of setting a buffer of size 0?
The point of getline() is that it can reallocate the buffer it receives.
Given a caller doing
size_t n = some_value();
char *buffer = malloc(n);
getline(&buffer, &n, stdin);
The caller supplies an initial buffer of length n. If getline() reallocates, it changes buffer so it points at the memory, and changes n to record the new length.
Obviously, this assumes that it is valid to do a realloc() on buffer i.e. that buffer is either NULL or is the value returned by malloc(), calloc(), or realloc().
The significance of setting n to zero AND buffer to NULL is telling getline() that it has been given no buffer. getline() will therefore reallocate if it reads anything.
All of this is actually described in the link you referred to.
getline() needs to know if the array is big enough to hold the line that the user has entered. It gets the current size of the array from the n parameter. If the array isn't big enough, it reallocates it to the required size. It then updates *lineptr and *n to the new array and size. Updating *n allows the caller to know how big the array is for its future use (such as calling getline() in a loop, as in the example).
Remember, C pointers don't include the size of the array they point to. If a function needs to know this, it has to be passed as a parameter.

Why am I getting 8 always?

char *c = (char *)malloc(30*sizeof(char));
printf("%lu \n",sizeof(c));
In the above code I am trying to print the size of 'c'. No matter what number I give instead of '30' in the code, I get the sizeof(c) as 8.
What is the problem? How can I determine the size of an array?
Is length and size the same for an array?
At the moment you are asking for the size of a pointer which on a 64 bits machine is 8 bytes. Since this is a malloc and not a real array, you can't retrieve the size of the buffer allocated through c.
If c was declared as
char c[30];
You could determine size with
size_t size = sizeof(c)/sizeof(c[0])
But to be honest if I had to do that, I would just #define the array size even though the size calculation would be stripped out at compilation. It makes the code clearer in my opinion.
You are printing the size of a char * which in your system is 8.
If you want to know the amount of memory that was "malloc"ed you must store it somewhere. In your case your should store the 30 for future use if you are going to need it.
sizeof(c) means give me the size of the variable c. Since c is a pointer it's giving you back the number of bytes that the pointer takes up in memory. The fact you're seeing 8 suggests you're compiling for 64bit. On a 32bit built it would be 4.
It's your job to remember the size of the thing you've allocated. After all, you asked for an amount of memory, so you do know how much you allocated! In your case, size_t size = 30*sizeof(char) will give you the amount you've allocated.
sizeof is an operator, not a function, thus the compiler creates the code equivalent to something like sizeof(char *) and pointer of a char (depending on the architecture of course) is of 8 bytes.
Actually sizeof(*c) will return 1. The size of a mallocced buffer cannot be determined compile time (which is what sizeof does).
You're getting the size of the variable c, not the size of the memory region it points to. There's no way to get the size of an array inside a function because it always decays to pointer. You must store the size yourself. If you've passed the size to malloc then why can't you store that size to a variable?

allocating memory to pointer with exact character length

I am new to c and learning pointers at the moment what I know is that pointer points to the memory address of whatever it points to.
my question is this how you allocates memory exactly the length of the character or it will take 50 bytes?
Lets say they entered a title: hunger games
BOOL AddNewDVD(Database* data){
}
I am new to c and learning pointers
Pointers are tough for beginners. Make sure you get a solid foundation.
at the moment what I know is that pointer points to the memory address of whatever it points to.
Though that is in practice correct, that's not how I like to think of it. What you are describing is how pointers are typically implemented, not what they are conceptually. By confusing the implementation with the concept you set yourself up for writing bad code later that makes unwarranted assumptions. There is no requirement that a pointer be a number which is an address in a virtual memory system.
A better way to think of a pointer is not as an address, but rather:
A pointer to t is a value.
Applying the * operator to a pointer to t gives you a variable of type t.
Applying the & operator to a variable of type t gives you a pointer to t.
A variable of type t can fetch or store a value of type t.
An array is a set of variables each identified by an index.
If a pointer references the variable associated with index i in an array then p + x gives you a pointer that references the variable associated with index i + x.
Applying the [i] operator to a pointer is a shorthand for *(p+i).
That is, rather than thinking of a pointer as a number that refers to a location in memory, just think of it as something that you can force to give you a variable.
is this how you allocates memory exactly the length of the scanned string or it will take 50 bytes?
char *title = malloc(50 * sizeof(char));
scanf(" %[^\n]s", title);
malloc(50*sizeof(char)) gives you an array of 50 chars.
title is a pointer to char.
When dereferenced, title will give you the variable associated with the first item in the array. (Item zero; remember, the index is the distance from the first item, and the first item has zero distance from the first item.)
scanf fills in the characters typed by the user into your array of 50 chars.
If they type in more than 49 chars (remembering that there will be a zero char placed at the end by convention) then arbitrarily bad things can happen.
As you correctly note, either you are wasting a lot of space or you are possibly overflowing the buffer. The solution is: don't use scanf for any production code. It is far too dangerous. Instead use fgets. See this question for more details:
How to use sscanf correctly and safely
You need to have a buffer to know how long the entered name is. This is your title, which can be filled maximum with 49 chars. Then you compute len and see it is only 6 byte long. You allocate string to have exactely this size + 1.
Of course you can then write the content of title to string, even if title is a 50 byte long buffer, and string only 7 byte long - copying of the content ends with the \0 termination char, and this is guaranteed to be inside capacity of string.
You cannot use scanf to determine the length of a string and then allocate memory for it. You need to either:
Ask the user the length of the string. Obviously, this is a poor choice.
Create a static buffer that is more than large enough and then create a dynamic string that is the exact length you need. The problem is, determining what the maximum length the string may be. fgets might be what you need. Consider the following code fragment:
#define MAX_STR_LEN (50)
char buf[MAX_STR_LEN] = {0};
char *str, *cPtr;
/* Get User Input */
printf("Enter a string, no longer than %d characters: ", MAX_STR_LEN);
fgets(buf, MAX_STR_LEN, stdin);
/* Remove Newline Character If Present */
cPtr = strstr(buf, "\n");
if(cPtr)
*cPtr = '\0';
/* Allocate Memory For Exact Length Of String */
str = malloc(strlen(buf) + 1);
strncpy(str, buf, strlen(buf));
/* Display Result */
printf("Your string is \"%s\"\n", str);

Getting array size in C. Cannot understand output

I am curious why I am getting the following behaviour in my code.
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
int M=24;
int arr[M];
int N=24;
int* ptr=(int*) malloc(sizeof(int)*N); /*Allocate memory of size N */
printf("Size of your malloced array is %lu\n",sizeof(ptr)/sizeof(ptr[0])); /* Get the size of memory alloctaed. Should be the same as N?*/
printf ("Size of your normal arrays is %lu\n",sizeof(arr)/sizeof(arr[0])); /* Ditto */
free(ptr);
return 0;
}
The output is
Size of your malloced array is 2
Size of your normal arrays is 24
I would have thought the output would be 24 in both places. How then does one get the size of the malloced array If somehow I have "forgotten" it?
Surely the pointer ptr will contain some information about the size of the malloced array since when we call free(ptr) it will release the array just malloced
When you use sizeof() on a pointer, you get the size of the pointer. Not the size of the allocated array. In your case, a pointer is probably 8 bytes and an int is 4 bytes, hence why you get 2.
In short, you can't get the size of an allocated array. You need to keep track of it yourself.
EDIT : Note that some compilers do actually support this functionality as an extension:
For example, MSVC supports _msize(): http://msdn.microsoft.com/en-us/library/z2s077bc.aspx
While sizeof() works as you'd expect with fixed-length and variable-length arrays, it doesn't know anything about the sizes of malloc()'ed arrays.
When applied to a pointer, sizeof() simply returns the size of the pointer.
More generally, given a pointer to a malloc()'ed block, there's no standard way to discover the size of that block.
See C FAQ questions 7.27 and 7.28.
In summary, if you need to know the size of a heap-allocated array in a portable manner, you have to keep track of that size yourself.
You cannot obtain, at runtime, the size of an array if you only have a pointer to (the first element of) the array. There are no constructs at all in C that allow you to do this. You have to keep track of the length yourself.
If you happen to have an array rather than a pointer then you can find its length, but not for a pointer to an element of the array.
In your code, ptr is a pointer and so you cannot find out the length of the array to which it points. On the other hand, arr is an array and so you can find out its length with sizeof(arr)/sizeof(arr[0]).
As this other question points out, there is no portable way getting the size of a dynamic array, since malloc may allocate more memory than requested. Furthermore managing malloc requests is up to the operating system. For instance *nix would calls sbrkand store the requests somewhere. So, when you call sizeof(ptr) it returns the size of the pointer and not the size of the array. On the other hand, if your array is fixed, the size of it is determined at compile time, so the compiler is able to replace sizeof(arr) with the size of the fixed array, thus providing you the "correct" size.
The size of a pointer is 4 bytes on 32-bit machines and 8 bytes on 64-bit machines. I guess you work on a 64-bit machine since the size of an int is 4, and you got that sizeof(ptr)/sizeof(ptr[0]) is 2.
The thing to remember about sizeof is that it is a compile-time operator1; it returns the number of bytes based on the type of the operand.
The type of arr is int [24], so sizeof arr will evaluate to the number of bytes required to store 24 int values. The type of ptr is int *, so sizeof ptr will evaluate to the number of bytes required to store a single int * value. Since this happens at compile time, there's no way for sizeof to know what block of memory ptr is pointing to or how large it is.
In general, you cannot determine how large a chunk of memory a pointer points to based on the pointer value itself; that information must be tracked separately.
Stylistic nit: a preferred way to write the malloc call is
int *ptr = malloc(sizeof *ptr * N);
In C, you do not need to cast the result of malloc to the target pointer type2, and doing so can potentially mask a useful diagnostic if you forget to include stdlib.h or otherwise don't have a prototype for malloc in scope.
Secondly, notice that I pass the expression *ptr as the operand to sizeof rather than (int). This minimizes bugs in the event you change the type of ptr but forget to change the type in the corresponding malloc call. This works because sizeof doesn't attempt to evaluate the operand (meaning it doesn't attempt to dereference ptr); it only computes its type.
1 The exception to this rule occurs when sizeof is applied to a variable-length array; since the size of the array isn't determined until runtime, a sizeof operator applied to a VLA will be evaluated at runtime.
2 Note that this is not the case in C++; a cast is required, but if you're writing C++ you should be using new and delete instead of malloc and free anyway. Also, this is only true since C89; older versions of C had malloc return char * instead of void *, so for those versions the cast was required. Unless you are working on a very old implementation (such as an old VAX mini running an ancient version of VMS), this shouldn't be an issue.

Is this possible? [pointer to char array C]

Is this possible?
size_t calculate(char *s)
{
// I would like to return 64
}
int main()
{
char s[64];
printf("%d", calculate(s));
return 0;
}
I want to write a function which calculates the size of the char array declared in main().
Your function calculate(), given just the pointer argument s, cannot calculate how big the array is. The size of the array is not encoded in the pointer, or accessible from the pointer. If it is designed to take a null-terminated string as an argument, it can determine how long that string is; that's what strlen() does, of course. But if it wants to know how much information it can safely copy into the array, it has to be told how big the array is, or make an assumption that there is enough space.
As others have pointed out, the sizeof() operator can be used in the function where the array definition is visible to get the size of the array. But in a function that cannot see the definition of the array you cannot usefully apply the sizeof() operator. If the array was a global variable whose definition (not declaration) was in scope (visible) where calculate() was written - and not, therefore, the parameter to the function - then calculate() could indicate the size.
This is why many, many C functions take a pointer and a length. The absence of the information is why C is somewhat prone to people misusing it and producing 'buffer overflow' bugs, where the code tries to fit a gallon of information into a pint pot.
On statically declared char[] you can use operator sizeof, which will return 64 in this case.
printf("%d", sizeof(s));
On dynamically declared char*, it is not possible to get the size of the allocated memory.
Dynamic arrays are obtained through malloc and friends. All the others are statically declared, and you can use sizeof on them, as long as you use it in the same scope as the array was declared (same function, in your case, for example).
Yes, it's possible if s has a specific character in the end of it's array. For example you could have s[63] = 125 and by knowing that every other character from 0 to 62 won't be 125, you can do a for loop until you find 125 and return the size of the array.
Otherwise, it's not possible, as s in the function parameter is just a pointer to your array, so sizeof(s) inside calculate will only return your machines pointer size and not 64 as someone could expected.
Unfortunately, you cannot determine from a pointer value alone how many elements are in the corresponding array. You either need some sort of sentinel value in the array (like the 0 terminator used for strings), or you need to keep track of it separately.
What you can do is get the number of bytes or elements in an array using the sizeof operator:
char arr[64];
size_t size = sizeof arr; // # of bytes in arr
size_t count = sizeof arr / sizeof *arr; // # of elements in arr
However, this only works if arr is an array type; if you tried to do this in your function
size_t calculate(char *s)
{
return sizeof s;
}
it would return the size in bytes of the pointer value, not of the corresponding array object.
No. char *x or char x[] just creates a pointer to a memory location. A pointer doesn't hold any information about the size of the memory region.
However, char *x = "Hello" occupies 6 bytes (including the terminating null), and strlen(x) would return 5. This relies on the null char at the end of the string, strlen still knows nothing about the underlying buffer. So strlen("Hello\000There") would still be 5.
This is usually done with a macro in C, like:
#define ARRAY_SIZE(x) (sizeof(x)/sizeof(*x))
Whether it's a good idea is a totally different question.

Resources