通过指针值将数据传递给 dll
Pass data to dll via pointer value
将指针的值(即变量所在的地址)作为整数传递给由同一主应用程序加载的另一个库,然后创建指向该地址的指针并获取该值是否安全?
例如:
#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;
}
请注意,它是统一的,可以运行,但假设 SomewhereElse() 实际上在一个完全独立的 dll 中,并且 addressAsString 是通过环境设置或其他方式传递的
具体来说——我的问题是 "an address is an address is an address",或者内存在跨越 dll 屏障时的映射方式是否发生了变化,例如 123 != 123("virtual memory" 和 "paging" 是我认为的相关术语,虽然我不太理解它们)
(实际用例是通过qt->vlc-qt或qmlvlc(c++)传递给libvlc(gnu99 c),并通过自定义过滤器设置发送指针值)
作为后续行动 - 让我们进一步假设我们希望在某个时候以安全的方式擦除内存并防止它通过优化可能发生的损坏。可以将这样的指针声明为 volatile(我仍然不是 100% 清楚它是如何工作的——但搜索安全擦除的示例代码导致了这种情况)?
您不能将指针作为 int
传递,因为您不知道 int
是否足够大以容纳指针。您也不应该使用 int64_t
之类的明确大小的整数,因为它们会混淆您的意图。要将指针作为整数传递,您应该使用 intptr_t
或 uintptr_t
。这些类型是专门提供的,目的是清楚地表达您的意图并确保(void*)
适合它们。
要安全地擦除内存,您必须使用适当的API。在 Windows 上,那将是 SecureZeroMemory
, on recent Unices it is memset_s
。它不关心它得到什么样的指针,只要它是指向数据的指针即可。
将指针的值(即变量所在的地址)作为整数传递给由同一主应用程序加载的另一个库,然后创建指向该地址的指针并获取该值是否安全?
例如:
#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;
}
请注意,它是统一的,可以运行,但假设 SomewhereElse() 实际上在一个完全独立的 dll 中,并且 addressAsString 是通过环境设置或其他方式传递的
具体来说——我的问题是 "an address is an address is an address",或者内存在跨越 dll 屏障时的映射方式是否发生了变化,例如 123 != 123("virtual memory" 和 "paging" 是我认为的相关术语,虽然我不太理解它们)
(实际用例是通过qt->vlc-qt或qmlvlc(c++)传递给libvlc(gnu99 c),并通过自定义过滤器设置发送指针值)
作为后续行动 - 让我们进一步假设我们希望在某个时候以安全的方式擦除内存并防止它通过优化可能发生的损坏。可以将这样的指针声明为 volatile(我仍然不是 100% 清楚它是如何工作的——但搜索安全擦除的示例代码导致了这种情况)?
您不能将指针作为 int
传递,因为您不知道 int
是否足够大以容纳指针。您也不应该使用 int64_t
之类的明确大小的整数,因为它们会混淆您的意图。要将指针作为整数传递,您应该使用 intptr_t
或 uintptr_t
。这些类型是专门提供的,目的是清楚地表达您的意图并确保(void*)
适合它们。
要安全地擦除内存,您必须使用适当的API。在 Windows 上,那将是 SecureZeroMemory
, on recent Unices it is memset_s
。它不关心它得到什么样的指针,只要它是指向数据的指针即可。