首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Coverity静态分析代码缺陷

Coverity静态分析代码缺陷
EN

Stack Overflow用户
提问于 2014-05-06 01:21:15
回答 3查看 8.3K关注 0票数 2

我们使用Coverity来检测代码中的漏洞。基本上,这是代码片段:

代码语言:javascript
复制
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;
   }

这里,

代码语言:javascript
复制
sizeof(struct OFPSM) = 12 bytes.

sizeof(struct OFPHDR) = 8 bytes.

Coverity说:

代码语言:javascript
复制
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字节的适当结构,然后取消对它的引用。那么,如何避免这个错误呢?

EN

回答 3

Stack Overflow用户

发布于 2014-05-06 01:33:40

演员阵容:

代码语言:javascript
复制
osr = (const struct OFPSM *) oh;

违反了严格的别名规则,因为它强制转换为不兼容的类型。很明显,它们是不兼容的,因为你会说:

sizeof(SM结构)=12字节。

sizeof(HDR结构)=8字节。

票数 3
EN

Stack Overflow用户

发布于 2014-05-06 02:03:05

但我不理解这个问题,因为我将OFPHDR类型转换为正确的结构,即12字节,然后取消引用它。

Coverity试图将您从一条路径中拯救出来,在该路径中,您可能只分配/读取了sizeof OFPHDR字节,而您却试图访问超出该分配的内容。您可以看到两种合理的可能性:您的vendor == htonl(VENDOR_A)逻辑可能没有正确实现,或者您从网络读取的值是恶意创建的/错误的。

您的强制转换假设了有关调用者实现的信息,而coverity认为您在vendor_request中不能确定这些信息。

那么,如何避免这个错误呢?

您可以通过更改vendor_request来避免它,如下所示:

代码语言:javascript
复制
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,都会分配足够的内存。

票数 3
EN

Stack Overflow用户

发布于 2014-05-06 13:29:50

各位,谢谢你的回答。

@PeterSW:结构是不兼容的,但正如我提到的,OFPHDR是TCP层之上的PDU,它的大小是可变的。我们需要从该指针中提取(供应商)的信息位于它的第12字节偏移量上。

这是通过将其类型转换为正确的结构来解决的,该结构的大小足以容纳超过12个字节,并包括该元素(供应商):

代码语言:javascript
复制
struct OFPVSM {
    struct OFPSM osm;
    ovs_be32 vendor;            /* Vendor ID:
    /* Followed by vendor-defined arbitrary additional data. */
};

这里,

代码语言:javascript
复制
sizeof(struct OFPVSM) = 16 bytes.

git diff格式解决方案:

代码语言:javascript
复制
-   const struct OFPSM *osr;
+   const struct OFPVSM *osr;

-   osr = (const struct OFPSM *) oh;
+   osr = (const struct OFPVSM*) oh;

很抱歉没有提到一个重要的信息:

struct OFPSM实际上由struct OFPHDR组成

代码语言:javascript
复制
struct OFPSM{
    struct OFPHDR header;
    ovs_be16 type;
    ovs_be16 flags;
};

“供应商”位于struct OFPSM的末尾。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/23478008

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档