How can I free uint32_t pointer? - c

I'm newbie with pointer in c. I'm just testing code like this
void test(uint32_t *data)
{
unsigned char raw_data[] = "this is a test data";
unsigned char *raw = (unsigned char*)malloc(strlen((char*)raw_data));
memcpy(raw, raw_data, strlen((char*)raw_data)+1);
*data = (uint32_t)raw;
}
int _tmain(int argc, _TCHAR* argv[])
{
uint32_t data;
test(&data);
printf("%s\n", data);
if (data != NULL)
{
free(data);
}
return 0;
}
I use a uint32_t to store a unsigned char*, when I try to free data, I meet a error error C2664: “void free(void *)”: uint32_t can not convert to “void *".
How can I free data?
First, thanks to Phạm Anh Tuấn, Gerhardh, KBlr and son on. You are very kind.
Solution:
void test(uintptr_t *data)
{
unsigned char raw_data[] = "this is a test data";
unsigned char *raw = (unsigned char*)malloc(strlen((char*)raw_data) + 1);
memcpy(raw, raw_data, strlen((char*)raw_data));
raw[strlen((char *)raw_data)] = '\0';
*data = (uintptr_t)raw;
}
int _tmain(int argc, _TCHAR* argv[])
{
uintptr_t data;
test(&data);
printf("%s\n", data);
if (data != NULL)
{
free((void *)data);
}
getchar();
return 0;
}
Must add a '\0' to raw as terminating string, then free works. And for working on 64bit, change uint32_t to intptr_t.

Your program will not work on 64bit machine since size of pointer on 64bit machine is 8bytes.
You can use uintptr_t instead uint32_t to hold the address.
While freeing cast the uintptr_t to void* as below sample code shows.
#include<stdint.h>
#include<stdlib.h>
#include<stdio.h>
void test(uintptr_t *data)
{
unsigned char raw_data[] = "this is a test data";
unsigned char *raw = (unsigned char*)malloc(strlen((char*)raw_data));
memcpy(raw, raw_data, strlen((char*)raw_data)+1);
*data = (uintptr_t)raw;
}
int main(int argc, char* argv[])
{
uintptr_t data;
test(&data);
printf("%s\n", (char *)data);
if ((void *)data != NULL)
{
free((void *)data);
}
return 0;
}

Related

How to add function pointer in a tailq in C

I need to hold *char title and **int (callback)(void , unsigned int) variables pair in a tailq. Because there is another thread mechanism in my full code and it checks this global 'identifier' variable when triggered. I used memcpy but it did not work.
How can I do that?
The code snip is below.
struct callback_list_entry {
int (*callback)(void *, unsigned int);
char *title;
TAILQ_ENTRY(callback_list_entry) entries;
};
TAILQ_HEAD(callback_list, callback_list_entry);
struct sipc_identifier
{
unsigned int port;
int (*broadcast_callback)(void *, unsigned int);
struct callback_list callback_list;
};
typedef struct sipc_identifier _sipc_identifier;
static _sipc_identifier identifier;
int my_callback(void *prm, unsigned int len)
{
printf("here is %s: %s len: %d\n", __func__, (char *)prm, len);
return OK;
}
static int add_callback_to_callback_list(int (*callback)(void *, unsigned int), char *title, _sipc_identifier *identifier)
{
struct callback_list_entry *entry = NULL;
if (!callback || !identifier) {
errorf("args cannot be NULL\n");
return NOK;
}
entry = (struct callback_list_entry *)calloc(1, sizeof(struct callback_list_entry));
if (!entry) {
errorf("calloc failed\n");
return NOK;
}
debugf("%p and size %d title: %s %p\n", callback, (int)sizeof(callback), title, &callback);
entry->callback = (void *)calloc(1, sizeof(callback));
if (!entry->callback) {
errorf("calloc failed\n");
FREE(entry);
return NOK;
}
memcpy(entry->callback, callback, sizeof(callback));
debugf("entry->callback %p %p\n", entry->callback, *(entry->callback));
entry->title = (char *)calloc(1, strlen(title) + 1);
if (!entry->title) {
errorf("calloc failed\n");
FREE(entry->callback);
FREE(entry);
return NOK;
}
strcpy(entry->title, title);
TAILQ_INSERT_HEAD(&identifier->callback_list, entry, entries);
return OK;
}
static int register(char *title, int (*callback)(void *, unsigned int))
{
if (!title || !callback) {
errorf("args cannot be NULL\n");
return NOK;
}
return add_callback_to_callback_list(callback, title, &identifier);
}
int main(int argc, char **argv)
{
TAILQ_INIT(&identifier->callback_list);
register("App_A_Registered_title", &my_callback);
return OK;
}
Thanks for the help.

OpenSSL rsa routines:RSA_padding_check_PKCS1_type_2:pkcs decoding error

I'm trying to encrypt/decrypt an AES key/iv using RSA encryption algorithm using openssl in C.
The decryption is working before storing the encrypted data into the file . But the decryption threw an error while decrypting the same encrypted data stored on the file.
Here is my code:
#include <stdio.h>
#include <stdbool.h>
#include <openssl/pem.h>
#include <openssl/ssl.h>
#include <openssl/rsa.h>
#include <openssl/evp.h>
#include <openssl/bio.h>
#include <openssl/err.h>
#include <string.h>
int padding = RSA_PKCS1_PADDING;
#define RSA_KEY_Size 384;
#define AES_256_KEY_SIZE 32;
// testing encryption/decryption
int func(const char* pubkeyfile, unsigned char *key, unsigned char *iv)
{
unsigned char *encryptedkey = (unsigned char*)malloc(RSA_KEY_Size);
unsigned char *encryptediv = (unsigned char*)malloc(RSA_KEY_Size);
unsigned char *decryptedkey = (unsigned char*)malloc(AES_256_KEY_SIZE);
unsigned char *decryptediv = (unsigned char*)malloc(AES_256_KEY_SIZE);
int result1 = rsaEncrypt(key, pubkeyfile, encryptedkey);
int result2 = rsaEncrypt(iv, pubkeyfile, encryptediv);
serialize(encryptedkey, encryptediv);
///////tested here, this part working fine
int r1 = rsaDecrypt(encryptedkey, privkeyfile, decryptedkey);
int r2 = rsaDecrypt(encryptediv, privkeyfile, decryptediv);
///////////////////////////////
unsigned char *getkey = (unsigned char*)malloc(RSA_KEY_Size);;
unsigned char *getiv = (unsigned char*)malloc(RSA_KEY_Size);;
deserialize(getkey, getiv);
unsigned char *ikey = (unsigned char*)malloc(AES_256_KEY_SIZE);
unsigned char *iiv = (unsigned char*)malloc(AES_256_KEY_SIZE);
//////////tested here, failed to decrypt after taking encrypted data from a file/////////////////
int r22 = rsaDecrypt(getiv, privkeyfile, iiv);
int r21 = rsaDecrypt(getkey, privkeyfile, ikey);
//////////////////////////////////////////////////
return 0;
}
typedef struct item {
uint8_t keyivlen;
char keyiv[RSA_KEY_Size];
struct item *next;
} list;
int serialize(unsigned char* key, unsigned char* iv)
{
list *ptr;
char *buffer;
int listLength;
list first, second;
ptr = &first;
FILE *filePtr;
memcpy(first.keyiv, key, strlen(key));
first.keyivlen = strlen(first.keyiv);
first.next = &second;
memcpy(second.keyiv, iv, strlen(iv));
second.keyivlen = strlen(second.keyiv);
second.next = 0;
listLength = listSize(ptr);
buffer = (char *)malloc(listLength);
serializeList(ptr, buffer);
filePtr = fopen("example.data", "wb+");
fwrite(buffer, listLength, 1, filePtr);
fclose(filePtr);
free(buffer);
return 0;
}
int deserialize(unsigned char* key, unsigned char* iv)
{
FILE *filePtr;
int listLength = 0;
int done = 0;
uint8_t arrayLen;
unsigned char *buffer;
int i = 0;
listLength = fileSize("example.data");
filePtr = fopen("example.data", "rb");
while (done < listLength) {
fread(&arrayLen, 1, 1, filePtr);
buffer = (unsigned char *)malloc(arrayLen + 1);
fread(buffer, arrayLen, 1, filePtr);
buffer[arrayLen] = '\0';
if (i == 0)
{
memcpy(key, buffer, arrayLen + 1);
}
else
{
memcpy(iv, buffer, arrayLen + 1);
}
//addToList(arrayLen, buffer);
done += arrayLen + 1;
i++;
free(buffer);
}
//printList(start);
return 0;
}
Here is the error:
error:0407109F:rsa routines:RSA_padding_check_PKCS1_type_2:pkcs decoding error
error:04065072:rsa routines:rsa_ossl_private_decrypt:padding check failed
And it fails in:
int r22 = rsaDecrypt(getiv, privkeyfile, iiv);
int r21 = rsaDecrypt(getkey, privkeyfile, ikey);
What could be the reason for this error?
arrayLen is only uint8_t which fits at most 255 , so your deserialised data is too short. You need RSA_KEY_Size bytes.

passing char* args[] via voidpointer

Her is my simplified code:
void main(){
void* ptr;
char* args[3];
args[0]="Arg1";
args[1]="Arg2";
args[2]="Arg3";
ptr = &args;
myMethod(ptr);
}
static void myMethod(void* args){
}
how can I convert void* args to an char*[]? in myMethod(void*)?
You want a pointer to pointer to char:
#include <stdio.h>
static void myMethod(void *args)
{
char **ptr = args;
printf("%s\n", ptr[1]);
}
int main(void)
{
void *ptr;
char *args[3];
args[0]="Arg1";
args[1]="Arg2";
args[2]="Arg3";
ptr = args; /* You don't need the & */
myMethod(ptr);
return 0;
}
As pointed out by #Eregrith, pass the number of cells to the function in order to prevent an out of bounds access:
#include <stdio.h>
static void myMethod(void *args, size_t elems)
{
char **ptr = args;
for (size_t i = 0; i < elems; i++)
printf("%s\n", ptr[i]);
}
int main(void)
{
void *ptr;
char *args[3];
args[0]="Arg1";
args[1]="Arg2";
args[2]="Arg3";
ptr = args;
myMethod(ptr, sizeof(args) / sizeof(args[0]));
return 0;
}

How to see contents of char * since printf won't work?

Here is a snippet of my code:
#include <stdio.h>
#include "uhash.h"
#include <openssl/evp.h>
char * hash(item a)
{
const char * str= a.k;
int len= strlen(str);
int md_len;
unsigned char md_value[EVP_MAX_MD_SIZE]; /* Buff to store change result */
EVP_MD_CTX *mdctx; /* Digest data structure declaration */
const EVP_MD *md;
OpenSSL_add_all_digests();
md = EVP_get_digestbyname("SHA256");
mdctx = EVP_MD_CTX_create();
EVP_DigestInit_ex(mdctx, md, NULL);
EVP_DigestUpdate(mdctx, str, len);
EVP_DigestFinal_ex(mdctx, md_value, &md_len);
EVP_MD_CTX_destroy(mdctx);
char md5str[33];
for(int i=0;i<md_len;++i)
{
sprintf(&md5str[i*2],"%02x",(unsigned int)md_value[i]);
}
printf("%s\n", md5str);
return md5str;
}
int main(int argv, char **argc)
{
char *c;
if (argv>0)
{
int i=0;
int s=0;
for(i=1;i<argv;i++)
{
s+=strlen(argc[i]);
}
c=(char *)(malloc(sizeof(char)*s*(argv-2)+1));
s=0;
for(i=1;i<argv;i++)
{
char *t=c+s;
memcpy(t,argc[i],strlen(argc[i]));
if(i!=argv-1){
printf("%d\n", argv);
t[strlen(argc[i])]=' ';
s++;
}
s+=strlen(argc[i]);
}
*(c+s)='\0';
}
printf("%s\n", c);
item * kee= malloc(sizeof(item));
kee->k=c;
kee->v=10;
char *res= hash(*kee);
fflush(stdout);
if(res==NULL)
printf("result is null...");
else
printf("%s\n",res);
fflush(stdout);
}
So the main function takes the arguments fine(tested) and passes it fine(tested) but the hash() function although computing the hash, does not either return the right value or I can't print the result in main. I've been trying to check for errors since yesterday but I'm not very smart so any help would be greatly appreciated!
Root cause: You are returning something that has been created on the stack and once it returns it is wiped. res is pointing into your stack.
Fix: Put the declaration of md5str outside the routine hash or make it static within the routine hash.

Literal int to void *

Translating GPOINTER_TO_INT and GINT_TO_POINTER to plain C I get:
#include <stdio.h>
#include <stdlib.h>
void *fn(void *v)
{
int *i;
i = malloc(sizeof(int));
*i = (int)(long)v;
return i;
}
int main(void)
{
int *i = fn((void *)(long)10);
printf("%d\n", *i);
free(i);
return 0;
}
Is it portable?
Why the cast to long?
In GTK is used for callbacks e.g.:
#define FLAG 10
static void panel_set_handler(GtkWidget *widget, gpointer data)
{
panel_set(GPOINTER_TO_INT(data));
}
g_signal_connect(G_OBJECT(menu_item), "activate", G_CALLBACK(panel_set_handler), GINT_TO_POINTER(FLAG));
Solution 1: casts
The simplest, Just cast to and from intptr_t. It's the correct version of what the GLib macros do.
Solution 2: using the heap
If you have something bigger than an intptr_t, or when you're not confident in sizes, you can use a dynamically-allocated memory pointer, without casts this time:
void* ToHeap(void const *data, size_t dataSize)
{
void* ret = malloc(dataSize);
if(ret != NULL)
memcpy(ret, data, dataSize);
return ret;
}
int FromHeap(void* heapPtr, void *data, size_t dataSize)
{
int ret = 0;
if(heapPtr != NULL)
{
memcpy(data, heapPtr, dataSize);
free(heapPtr);
ret = 1;
}
return ret;
}
Here is a wrapper for use with ints:
void* IntToHeap(int i)
{
return ToHeap(&i, sizeof(int));
}
int IntFromHeap(void*heapPtr, int defaultValue)
{
int ret;
if(!FromHeap(heapPtr, &ret, sizeof(int))
ret = defaultValue;
return ret;
}
And you can use this that way:
#define FLAG 10
static void panel_set_handler(GtkWidget *widget, gpointer data)
{
panel_set(IntFromHeap(data, 0));
}
g_signal_connect(G_OBJECT(menu_item), "activate", G_CALLBACK(panel_set_handler), IntToHeap(FLAG));
That way is a bit like your post, minus all these casts.

Resources