I need to know if this StrBuff struct is supposed to operate like an array. I've looked and looked, and honestly can't tell just due to the pointer syntax - it seems like as an array it could work, and as an array it could not work.
I see that in the second method, malloc() is used, so I'm guessing that the buf-str uChar is supposed to be an array.
Teh codez:
typedef struct {
unsigned char *str;
unsigned int len;
} StrBuf;
static StrBuf *
strbuf_new ()
{
StrBuf *buf;
buf = (StrBuf *) calloc (sizeof (StrBuf), 1);
buf->str = (unsigned char *) strdup ("");
return buf;
}
static void
strbuf_append (StrBuf *buf, unsigned char *data, int len)
{
int offset;
if (len <= -1)
len = strlen ((char *) data);
offset = buf->len;
buf->len += len;
buf->str = (unsigned char *) realloc (buf->str, buf->len + 1);
memcpy (buf->str + offset, data, len);
buf->str[buf->len] = '\0';
}
So, judging from these methods I'm guessing for any C/C++ veterans out there this should be a piece of cake.
Edit:
My goal has been to convert an app (which uses this code here) into a Java port, but I've been quite confused as to how I should do it. I've gotten fairly far doing (for the most part) the same thing in Java, only this time using a byte[] array, seeing as how unsigned chars are supposed to be equivalent to bytes in Java.
It's not an array. It's a structure to hold values (probably strings) using dymamic memory allocation. If you use an array to allocate some datas, then array size is determined at compile time.
For example:
char buf[10];
With a structure like StrBuf you can allocate the required memory when the string buf of the given length is supplied :
buf->str = (unsigned char *) realloc (buf->str, buf->len + 1);
Related
I'm working on a C project, the goal is to reach a web server, read the data inside a file (example.com/shellcode.bin for example) and store it inside an array.
Currently, I managed to make the necessary GET requests, i can find my shellcode, insert it into an array (mycode) but when I return it, it sends me the wrong size.
For example, if sizeof(mycode) return 270, sizeof(PE) return 8.
Is it possible to find the total size of the PE variable ?
size_t size = sizeof(mycode);
char* PE = (char*)malloc(size);
for (int i = 0; i < sizeof(mycode); i++) {
PE[i] = mycode[i];
}
printf("Shellcode size before return : %ld\n", sizeof(PE));
return PE;
I tried different format string outputs (%s with strlen, %d, %ld, %zu ....) all of them returned 8.
One solution is to return a struct containing both a pointer to the buffer and the length.
// outside the function
typedef struct {
char* data;
size_t size;
} Buffer;
// in the function
Buffer buffer;
buffer.data = PE;
buffer.size = size;
return buffer;
And also change the return type to Buffer.
A pointer points to a single object of the pointed-to type; given a pointer value, there's no way to know whether you're looking at the first object of a sequence or not. There's no metadata in the pointer saying "there are N more elements following the thing I point to."
sizeof PE gives you the size of the pointer variable, not the number of things in the buffer; sizeof PE == sizeof (char *). sizeof *PE gives you the size of a single char object, which is 1 by definition; sizeof *PE == sizeof (char).
You have to manually keep track of how much memory you allocated - you somehow have to persist that size variable anywhere you intend to use PE.
As others have pointed out, you can bundle that into a struct type:
struct buffer {
size_t size;
char *PE;
};
struct buffer newBuf( const char *mycode, size_t size )
{
struct buffer b;
b.PE = calloc( size, sizeof *b.PE );
if ( b.PE )
{
memcpy( b.PE, mycode, size );
b.size = size;
}
return b;
}
int main( void )
{
char shellcode[] = { /* some char data here */ };
struct buffer b = newBuf( shellcode, sizeof shellcode );
...
}
I have developed a function for copying elements from one unsigned char buffer to another. I designed the function to return a pointer to the next available (empty) element in the destination buffer. The point of doing that is so that I know where start writing to the destination buffer if I choose to call the function again and write more data to the destination buffer (from some other source buffer). Here is the function:
unsigned char *copyBuffer(unsigned char *sourceBuf,
unsigned char *destBuf,
int size)
{
int i = 0;
for (i; i < size; ++i) {
*(destBuf + i) = *(sourceBuf + i);
};
// return a pointer to the next unpopulated element in the dest buffer
return (destBuf + i + 1);
}
The dilemma I have is that though this compiles fine, I think I may run into runtime issues because I may be referencing an out-of-bounds pointer once the destination buffer has been completely filled.
For example:
unsigned char destBuf[10];
unsigned char sourceBuf1[6];
unsigned char sourceBuf2[4];
unsigned char *pBuffer = NULL;
pBuffer = copyBuffer(sourceBuf1, destBuf, 6);
copyBuffer(sourceBuf2, pBuffer, 4);
After the second copy operation, won't the pointer returned be out of bounds because the last line of my function is
return (destBuf + i + 1);
How can I achieve the functionality that I'm seeking without having this issue? Or is there another way entirely to achieve this which is better?
Thanks in advance.
Add additional parameter showing the size of the buffer. Return value NULL indicates that the buffer is full.
destBuf + i + 1 does not point to the next "free" character, only one after
use the correct type for size.
unsigned char* copyBuffer(const unsigned char *sourceBuf, unsigned char *destBuf, const size_t size, const size_t destbuffsize)
{
char *result = NULL;
memcpy(destBuf, sourceBuf, size <= destbuffsize ? size : destbuffsize);
if(size < destbuffsize) result = destBuf + size;
return result;
}
There is a problem in your approach: while it is OK to return a pointer one past the address of the last element of an array, you actually return a pointer 1 byte beyond the end. Is this the intent? i is incremented after the last copy so buf + i points to the next available element.
Note also these remarks:
sourceBuf should be declared as const unsigned char * as you do not modify the source buffer.
the ; after the body of the for loop is redundant, remove it.
the lonely i in the first clause of the for is useless and confusing.
I would suggest using size_t for the type of size and i
the order of arguments is confusing as it is the opposite of that of memcpy.
Here is a modified version:
unsigned char *copyBuffer(unsigned char *destBuf,
const unsigned char *sourceBuf,
size_t size)
{
size_t i;
for (i = 0; i < size; ++i) {
destBuf[i] = sourceBuf[i];
}
// return a pointer to the next unpopulated element in the dest buffer
return destBuf + i;
}
Incrementing the pointers allows for a simpler version:
unsigned char *copyBuffer(unsigned char *destBuf,
const unsigned char *sourceBuf,
size_t size)
{
while (size --> 0) {
*destBuf++ = *sourceBuf++;
}
// return a pointer to the next unpopulated element in the dest buffer
return destBuf;
}
This above function has the same behavior as mempcpy() available in the GNU libC and some other ones:
void *mempcpy(void *dest, const void *src, size_t n);
You should consider using this one as it is optimized on systems that support it and can be easily added on systems lacking it.
I want to copy the content of a char **pointer to another pointer. My attempt was:
void test(char **arr, int len) {
printf("1: ");
printArr(arr, len);
char ***res = malloc(sizeof(char **));
res[0] = malloc(sizeof(char *) * len);
memcpy(&res[0], arr, len);
printArr(res[0], len);
Here I just wanted to copy the contents of arr, which holds several strings, to r[0] whereby len denotes the number of elements in arr. However, when inspecting res[0] I realised that it only stores two times null. As one can tell I'm a very beginner and have been learning C since a few days, so onc can expect simple mistakes.
char ***res = malloc(sizeof(char **));
res[0] = malloc(sizeof(char *) * len);
memcpy(&res[0], arr, len);
The first line allocates space for a single char ** and makes res point at it
The second line allocates space for an array of len pointers to char and makes res[0] point at it.
The third line copies len byes from arr over the top of the memory pointed at by res, overwriting the result of the second malloc call and then scribbling over memory after the block allocated by the first malloc call.
You probably actually want something like
mempy(res[0], arr, len * sizeof(char*));
which will copy an array of len pointers (pointed at by arr) into the memory allocated by the second malloc call.
If this is an array of C strings that you need deep copied:
char** array_deep_copy(char **arr, int len) {
// calloc() makes "allocation of N" calculations more clear
// that this is N allocations of char* becoming char**
char **res = calloc(len, sizeof(char*));
for (int i = 0; i < len; ++i) {
// Use strdup() if available
res[i] = strdup(arr[i]);
}
return res;
}
Note that this needs a proper release function that will go through and recursively free() those cloned strings or this leaks memory.
If you only need a shallow copy:
char** array_shallow_copy(char **arr, int len) {
char **res = calloc(len, sizeof(char*));
// memcpy(dest, src, size) is usually more efficient than a loop
memcpy(res, arr, sizeof(char*) * len);
return res;
}
This one doesn't need a recursive free(), you can just free() the top-level pointer and you're done. This one shares data with the original, so if any of those pointers are released before this structure is then you'll have invalid pointers in it. Be careful!
I am trying my luck with pthreads for a problem -
I have two questions about that and will add some excerpts from the code:
I have a struct, which contains an input array and one as output (or result) array. Where do I have to allocate the memory for this result, within the main-function or within the thread-function?
These results shall be merged into one big result array using realloc and memcpy. I think I am using memcpy and realloc not correctly in this case, or do I?
thread-Function:
struct thread_input {
unsigned char *buf;
unsigned char *result;
int start;
int end;
int tid;
};
void* thread_function(void* arg){
struct thread_input *param = (struct thread_input*)arg;
param->result = (unsigned char*)malloc((1+(param->end-param->start))*sizeof(unsigned char));
for(int i = param->start; i <= param->end; i++){
param->result[i] = some_function(param->buf[i]);
printf("%d %d\n", param->tid, param->result[i]);
}
return NULL;
}
So the some_function is working with every unsigned char and returns it to the param->result array.
This shall be merged here (where n_elemts is the number calculated in every thread):
unsigned char* arr1 = (unsigned char*)malloc(n_elements*sizeof(unsigned char));
for (int t = 0; t < n_threads; t++){
pthread_join(threads[t], NULL);
memcpy(arr1, thread_args[t].result, n_elements);
if(t<n_threads-1){
arr1 = (unsigned char*)realloc(arr1, (t+1)*n_elements*sizeof(unsigned char));
}
}
print_function(arr1, fileSize);
The problem given by the compiler is located at the realloc and called "invalid read of size 1", I suppose it is due to a wrong file_size, or array length, after the realloc. Plus the allocation of the param->result that I could not figure out completely.
Thanks for lookin at these excerpts and for any comment! Hope this question was asked in concise enough way, if not bombard me with critic.
typedef struct testMsg_ {
unsigned char opCode;
unsigned int Count;
char *macsStrList[MAC_ADDR_STR_LEN];
} testMsg_t;
Number of elements in macsStrList is m_Count.
I know following is not correct:
testMsg_t *pInput = (testMsg_t *) malloc(sizeof(testMsg_t) );
This is correct, given the structure you have done
testMsg_t *pInput = (testMsg_t *) malloc(sizeof(testMsg_t) );
However you are probably confused to the meaning of *arr[dimension] -- which is an array length dimension of pointers to chars -- reading between the lines,
MAC_ADDR_STR_LEN
Is probably ment to the legth of the string representation of a mac address (say <20 bytes?)
However your struct gives you 20 char pointers, and the character pointers still have to be initializaed to point to valid memory.
testMsg_t *pInput = (testMsg_t *) malloc(sizeof(testMsg_t) );
pInput->macsStrList[0] = (char *) malloc( MAC_ADDR_STR_LEN+1 );
pInput->macsStrList[1] = (char *) malloc( MAC_ADDR_STR_LEN+1 );
pInput->macsStrList[2] = (char *) malloc( MAC_ADDR_STR_LEN+1 );
...
or redefine your struct to
typedef struct testMsg_ {
unsigned char opCode;
unsigned int Count;
char macsStrList[NUMBER_OF_MAC_ADDRESSES][MAC_ADDR_STR_LEN];
} testMsg_t;
To avoid having to deal with multiple number of allocations.
ADDITION;
As per comments, given that the number of mac addresses are dynamically determined, you could also define the struct as;
typedef struct testMsg_ {
unsigned char opCode;
unsigned int Count;
char macsStrList[1][MAC_ADDR_STR_LEN];
} testMsg_t;
and then allocate it using
testMsg_t *pInput = (testMsg_t *) malloc(sizeof(testMsg_t) + (countOfMacsAddresses * MAC_ADDR_STR_LEN) );
That would have the added over a solution with pointers of that you could use realloc to resize the array dynamically if you needed to do that as well.....
I think what you're looking for is maybe (ok, Soren got in first, but I'll show a way to allocate a single contiguous chunk):
/* assuming we only need macStrList[0] ... [Count-1] */
struct testMsg
{
unsigned char opCode;
unsigned int Count;
char *macsStrList[];
};
struct testMsg *allocate_testMsg(int count)
{
char *string_storage;
struct testMsg *msg;
size_t size = sizeof(struct testMsg) /* base object */
+ (count * sizeof(char *)) /* char* array */
+ (count * (MAC_ADDR_STR_LEN+1)) /* char storage */
;
msg = malloc(size);
msg->Count = count;
string_storage = (char *)&(msg->macStrList[count]);
/* note msg->macStrList points to UNINITIALIZED but allocated storage.
it might be sensible to zero-fill string_storage, depending on how you'll
initialize it
*/
for (count=0; count < msg->Count;
++count, string_storage += (MAC_ADDR_STR_LEN+1))
{
msg->macStrList[count] = string_storage;
}
return msg;
}
Of course it is. You allocate a pointer to a testMsg_t which is an alias for struct testMsg_. However you need to initialize this object yourself.
(And you don't need to cast the allocated pointer in C).