Reputation: 3078
Is it safe to pass the value of a pointer (i.e. the address where a variable resides) as an integer to another library loaded by the same main app, which then creates a pointer to that address and grabs the value?
For example:
#define __STDC_FORMAT_MACROS
#include <stdio.h>
#include <inttypes.h>
#include <string.h>
#include <stdlib.h>
struct Book {
char title[50];
char subject[100];
int book_id;
};
void
DescribeBook(char *label, struct Book *someBook)
{
printf("\n%s\n", label);
printf("Book title : %s\n", someBook->title);
printf("Book subject : %s\n", someBook->subject);
printf("Book book_id : %d\n", someBook->book_id);
}
void mem_wipe(uint8_t *ptr, uint64_t len) {
while(len--) {
*(ptr++) = 0;
}
}
void
SomewhereElse(char *addressAsString)
{
struct Book *myBook;
//PRETEND THIS IS IN A DLL SOMEWHERE ELSE!!!
uint64_t idataptr;
sscanf(addressAsString, "%" PRIu64, &idataptr);
mem_wipe((uint8_t *)addressAsString, strlen(addressAsString));
free(addressAsString);
myBook = (struct Book *)idataptr;
DescribeBook("AFTER", myBook);
printf("Data Address (int): %"PRIu64"\n", idataptr);
printf("Data Address (string): %s\n", addressAsString);
strcpy(myBook->title, "Foo");
strcpy(myBook->subject, "Bar");
myBook->book_id = 7654321;
}
int
main(void)
{
struct Book myBook;
uint8_t *dataptr;
char *addressAsString;
strcpy(myBook.title, "Hello");
strcpy(myBook.subject, "World");
myBook.book_id = 1234567;
DescribeBook("BEFORE", &myBook);
printf("Data Address (int): %"PRIu64"\n", (uint64_t)&myBook);
dataptr = (uint8_t *) & myBook;
asprintf(&addressAsString, "%" PRIu64, (uint64_t) dataptr);
if (addressAsString == NULL) {
fprintf(stderr, "Error in asprintf\n");
return 1;
}
printf("Data Address (string): %s\n", addressAsString);
SomewhereElse(addressAsString);
DescribeBook("FINAL (modified)", &myBook);
printf("Data Address (string after wipe): %s\n", addressAsString);
return 0;
}
Note that it's unified there to be runable, but pretend SomewhereElse() is actually in a totally separate dll and that addressAsString is passed via environment settings or something
Specifically - my question is whether "an address is an address is an address", or if something changes in how memory is mapped when it goes across that dll barrier, such that 123 != 123("virtual memory" and "paging" are relevant terms I think, though I don't quite understand them)
(actual use case is passing to libvlc (gnu99 c) through qt->vlc-qt or qmlvlc (c++), and sending the pointer value via custom filter setting)
As a followup - let's further assume that we want to wipe the memory at some point in a secure manner and prevent it from possible mangling via optimizations. Can such a pointer be declared volatile (I'm still not 100% clear on how this works - but sample code searching for secure erase led to that)?
Upvotes: 1
Views: 628
Reputation: 98425
You can't pass a pointer as an int
, since you don't know whether int
is big enough to hold a pointer. You shouldn't be using explicitly sized integers like int64_t
either, since they obfuscate your intent. To pass pointers around as integers, you're supposed to use intptr_t
or uintptr_t
. These types are provided specifically to express your intent clearly and to ensure that a (void*)
fits into them.
To wipe the memory securely, you have to use appropriate API. On Windows, that would be SecureZeroMemory
, on recent Unices it is memset_s
. It doesn't care what kind of a pointer it gets, as long as it's a pointer to data.
Upvotes: 2