我们使用Coverity来检测代码中的漏洞。基本上,这是代码片段:
static int vendor_request(
const struct OFPHDR *oh,
size_t length,
const struct OFPUTIL_MT **typep
)
{
const struct OFPSM *osr;
ovs_be32 vendor;
osr = (const struct OFPSM *) oh;
memcpy(&vendor, ((char*)osr + sizeof(struct OFPSM)), sizeof( vendor ));
if (vendor == htonl(VENDOR_A))
return (functionA(oh, typep));
if (vendor == htonl(VENDOR_B))
return (functionB(oh, length, typep));
else
return 0;
}这里,
sizeof(struct OFPSM) = 12 bytes.
sizeof(struct OFPHDR) = 8 bytes.Coverity说:
CID xxxxx (#1 of 2): Out-of-bounds access (OVERRUN)
1. overrun-buffer-val: Overrunning struct type OFPHDR of 8 bytes by passing it to a function which accesses it at byte offset 12. Pointer osr indexed by constant 12U through dereference in call to memcpy.基本上,struct OFPHDR是TCP层之上的一个PDU,它的大小是8字节,但它可以根据它是什么类型的OFP消息而变化。Coverity说我在字节偏移量索引12处取消引用*oh,它是出站访问索引。
但我不理解这个问题,因为我将OFPHDR类型转换为12字节的适当结构,然后取消对它的引用。那么,如何避免这个错误呢?
发布于 2014-05-06 01:33:40
演员阵容:
osr = (const struct OFPSM *) oh;违反了严格的别名规则,因为它强制转换为不兼容的类型。很明显,它们是不兼容的,因为你会说:
sizeof(SM结构)=12字节。
sizeof(HDR结构)=8字节。
发布于 2014-05-06 02:03:05
但我不理解这个问题,因为我将OFPHDR类型转换为正确的结构,即12字节,然后取消引用它。
Coverity试图将您从一条路径中拯救出来,在该路径中,您可能只分配/读取了sizeof OFPHDR字节,而您却试图访问超出该分配的内容。您可以看到两种合理的可能性:您的vendor == htonl(VENDOR_A)逻辑可能没有正确实现,或者您从网络读取的值是恶意创建的/错误的。
您的强制转换假设了有关调用者实现的信息,而coverity认为您在vendor_request中不能确定这些信息。
那么,如何避免这个错误呢?
您可以通过更改vendor_request来避免它,如下所示:
typedef union {
struct OFPHDR oh;
struct OFPSM osm;
} son_of_OFPHDR;
static int vendor_request(
const son_of_OFPHDR *oh,
size_t length,
const struct OFPUTIL_MT **typep
)这显式地告诉编译器、静态检查器和人类,oh输入可以是OFPHDR,也可以是OFPSM。
每个同意接受son_of_OFPHDR *的人都有一个来自调用者的隐含保证,即整个结构的内存已经分配。无论在哪里出现自动存储持续时间的son_of_OFPHDR,都会分配足够的内存。
发布于 2014-05-06 13:29:50
各位,谢谢你的回答。
@PeterSW:结构是不兼容的,但正如我提到的,OFPHDR是TCP层之上的PDU,它的大小是可变的。我们需要从该指针中提取(供应商)的信息位于它的第12字节偏移量上。
这是通过将其类型转换为正确的结构来解决的,该结构的大小足以容纳超过12个字节,并包括该元素(供应商):
struct OFPVSM {
struct OFPSM osm;
ovs_be32 vendor; /* Vendor ID:
/* Followed by vendor-defined arbitrary additional data. */
};这里,
sizeof(struct OFPVSM) = 16 bytes.git diff格式解决方案:
- const struct OFPSM *osr;
+ const struct OFPVSM *osr;
- osr = (const struct OFPSM *) oh;
+ osr = (const struct OFPVSM*) oh;很抱歉没有提到一个重要的信息:
struct OFPSM实际上由struct OFPHDR组成
struct OFPSM{
struct OFPHDR header;
ovs_be16 type;
ovs_be16 flags;
};“供应商”位于struct OFPSM的末尾。
https://stackoverflow.com/questions/23478008
复制相似问题