socket编程sockaddr转换违反MISRA C++ 2008 5-2-7规则解决方案问询
Socket地址类型转换与MISRA合规问题解答
规则偏离要求说明
所有同时进行socket开发和MISRA合规校验的从业者,都需要为该类型转换操作提交正当的规则偏离说明,除非使用替代实现方案。
MISRA规范本身允许经过书面论证的规则偏离,该类型转换是POSIX标准规定的socket API标准用法,全行业默认其安全性:所有兼容POSIX的操作系统都会保证sockaddr和sockaddr_in的首字段(地址族标识)内存布局完全对齐,内核会根据首字段的地址族类型解析后续内存结构,不存在野指针访问、内存越界的风险。偏离说明仅需明确标注该操作属于POSIX socket标准约定用法,安全性由系统实现保证,即可通过合规审查。
替代类型转换的实现方案
存在无需指针类型转换的合规实现方案,目前工业界最常用的是共用体包装方案,无需申请规则偏离即可满足MISRA要求:
- 定义包含各类socket地址结构的共用体,利用共用体的内存共享特性避免跨类型指针转换:
union SocketAddr { struct sockaddr generic_addr; struct sockaddr_in ipv4_addr; // 如需支持IPv6可新增struct sockaddr_in6 ipv6_addr成员 };
- 使用示例:
union SocketAddr myaddr; int s; myaddr.ipv4_addr.sin_family = AF_INET; myaddr.ipv4_addr.sin_port = htons(3490); inet_aton("63.161.169.137", &myaddr.ipv4_addr.sin_addr.s_addr); s = socket(PF_INET, SOCK_STREAM, 0); // 无需指针强转,直接取共用体的generic_addr成员地址即可 bind(s, &myaddr.generic_addr, sizeof(myaddr.ipv4_addr));
如果项目不允许使用共用体,也可以通过内存拷贝的方式实现:先填充sockaddr_in结构,再按字节把内容拷贝到struct sockaddr类型的变量中,直接传入该变量的指针即可,该方案也符合MISRA要求,仅会产生极少量的内存拷贝开销,对性能影响可以忽略。
内容的提问来源于stack exchange,提问作者Javi
相关产品推荐
相关产品推荐

