davidkomer
davidkomer

Reputation: 3078

Pass data to dll via pointer value

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

Answers (1)

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

Related Questions