将指针的值(即变量所在的地址)作为整数传递给由同一主应用程序加载的另一个库,然后创建指向该地址的指针并获取该值是否安全?
例如:
#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是通过环境设置或其他东西传递的
具体来说 - 我的问题是&#34;地址是一个地址是一个地址&#34;,或者当内存在穿过该dll屏障时如何映射内容会发生变化,这样123!= 123(&#34;虚拟记忆&#34;&#34;分页&#34;我认为是相关术语,但我不太了解它们)
(实际用例通过qt-&gt; vlc-qt或qmlvlc(c ++)传递给libvlc(gnu99 c),并通过自定义过滤器设置发送指针值)
作为后续内容 - 让我们进一步假设我们想要以安全的方式在某个时刻擦除内存,并防止它通过优化进行可能的破坏。可以将这样的指针声明为volatile(我仍然没有100%清楚它是如何工作的 - 但是样本代码搜索安全擦除会导致这种情况吗?)
答案 0 :(得分:2)
您无法将指针作为int
传递,因为您不知道int
是否足以容纳指针。您也不应该使用明确大小的整数,例如int64_t
,因为它们会模糊您的意图。要将指针作为整数传递,您应该使用intptr_t
或uintptr_t
。这些类型是专门提供的,以明确表达您的意图,并确保(void*)
适合他们。
要安全擦除内存,您必须使用适当的API。在Windows上,这将是SecureZeroMemory
,在最近的Unices上是memset_s
。它不关心它获得什么样的指针,只要它是指向数据的指针。