我试图从地址窃取两个LSB位,我写了 以下内联函数。我想确认一下是否有效 64位和32位机器。
我使用stealing bits from a pointer帖作为参考。
我得到一个奇怪的错误,其中getAddress()返回0x100
0x1
没问题,因为setFlag1(NULL)
会返回此地址
0x2
没问题,因为setFlag2(NULL)
会返回此地址
0x11
也可以setFlag1(NULL)
,setFlag2(NULL)
将返回此地址
但我不确定哪种组合会返回0x100
#define UINTPTR_MAX_XOR_WITH_1 (uintptr_t) (UINTPTR_MAX ^ 0x1)
#define UINTPTR_MAX_XOR_WITH_2 (uintptr_t) (UINTPTR_MAX ^ 0x2)
#define UINTPTR_MAX_XOR_WITH_3 (uintptr_t) (UINTPTR_MAX ^ 0x3)
struct node
{
unsigned long key;
struct node* lChild; //format <address,flag2,flag1>
struct node* rChild; //format <address,flag2,flag1>
};
static inline struct node* getAddress(struct node* p)
{
return (struct node*)((uintptr_t) p & UINTPTR_MAX_XOR_WITH_3);
}
static inline bool isFlag2(struct node* p)
{
return (uintptr_t) p & 0x2;
}
static inline bool isFlag1(struct node* p)
{
return (uintptr_t) p & 0x1;
}
static inline struct node* setFlag1(struct node* p)
{
return((struct node*) (((uintptr_t) p & UINTPTR_MAX_XOR_WITH_1) | 0x1));
}
static inline struct node* unsetFlag1(struct node* p)
{
return((struct node*) (((uintptr_t) p & UINTPTR_MAX_XOR_WITH_1)));
}
static inline struct node* setFlag2(struct node* p)
{
return((struct node*) (((uintptr_t) p & UINTPTR_MAX_XOR_WITH_2) | 0x2));
}
答案 0 :(得分:3)
该bug可能与此标记方案无关。
getAddress
可以返回地址0x100
:您只需将其输入0x100
到0x103
。
你的getAddress
函数所做的就是删除两个最低有效位以恢复对齐的指针。由于0x100
在两个最低有效位中是明确的,getAddress
正在完成其工作。
GIGO:垃圾进,垃圾出来!
添加一些跟踪以打印进入getAddress
的值。
当取消引用空指针以获取结构成员的地址时,有时会产生类似0x100的地址:null_pointer->something_at_offset_256
。当然,一般来说,它们可以以多种方式出现。
答案 1 :(得分:2)
各种函数依赖于UINTPTR_MAX
设置了2个LSBits。重新编码以消除这种依赖性。
一些简化。
执行bool
返回的比较。
确保这些函数在被调用时被正确声明或原型化。否则,返回值假定为int
并且可以解释0x100
返回。
问题可能仍在其他地方。你是否期望像setFlag1(p)
这样的调用设置p
的位(哪些代码不能执行)或者返回一个设置了位的指针(代码是什么)?
static inline struct node* getAddress(struct node* p) {
return (struct node*)((uintptr_t) p & ~((uintptr_t) 3));
}
static inline bool isFlag1(struct node* p) {
return ((uintptr_t) p & 1) != 0;
}
static inline bool isFlag2(struct node* p) {
return ((uintptr_t) p & 2) != 0;
}
static inline struct node* setFlag1(struct node* p) {
return (struct node*) ((uintptr_t) p | 1);
}
static inline struct node* unsetFlag1(struct node* p) {
return (struct node*) ((uintptr_t) p & ~((uintptr_t) 1));
}
static inline struct node* setFlag2(struct node* p)
return (struct node*) ((uintptr_t) p | 2);
}
static inline struct node* unsetFlag2(struct node* p) {
return (struct node*) ((uintptr_t) p & ~((uintptr_t) 2));
}
[编辑]
在审核中,可以确定UINTPTR_MAX
2 LSBits必须为1.请参阅上面的@Kaz评论。