注:本课程参考文献《C安全编码标准》
欢迎关注我👆,收藏下次不迷路┗|`O′|┛ 嗷~~
一.引言
根据C语言标准7.5小节第2段[ISO/IEC 9899:2011],在如下情况时程序行为未定义。
- errno的宏定义被抑制,以便访问实际对象,或者程序用名称errno定义标识符。*
errno
标识符可以被扩展成一个可以修改的左值,这个左值的类型是
int
,但它并不一定要是一个对象的直接标识符。换句话说,它可能代表的是通过某种函数调用(例如
*errno()
)获得的左值。对于
errno
,没有明确规定它必须是一个宏,还是必须是一个声明为具有外部链接的标识符。如果在代码中为了直接访问某个具体的对象而取消了对
errno
宏的定义,或者在程序中定义了名为
errno
的标识符,那么这些操作将导致未定义行为。
二.不安全代码
遗留代码可能包含不正确的声明,如:
extern int errno;
三.修改方案
声明errno的正确方法为包含头文件<errno.h>:
#include <errno.h>
遵循C语言标准的实现必须在<errno.h>中声明errno,但是因为历史遗留原因没有这么做。
注意:如果一个库函数的声明没有引用头文件中定义的任何类型,允许在不包含其头文件的情况下声明该函数,只要声明与标准声明兼容即可。
/* Not including stdlib.h */
void free(void *);
void func(void *ptr){
free(ptr);
}
四.练习与答案
如果程序显式地声明了标准库中的保留标识符,如
size_t
,并且声明与标准库中的声明不兼容,则程序行为未定义。
遗留代码可能包含不正确的声明,如:
typedef unsigned int size_t;
声明
size_t
的正确方法为包含头文件<stddef.h>:
#include <stddef.h>
遵循C语言标准的实现必须在<stddef.h>中声明
size_t
以及其他一些常用的类型定义和宏。用户代码应当避免重新定义这些标准类型,以防止与标准库中的声明冲突。
在这个案例中,不安全的代码显式地声明了
size_t
为
unsigned int
,这可能导致与标准库中的声明不兼容。标准库中的
size_t
可能是另一种无符号整数类型,如
unsigned long
,这取决于具体的实现。因此,必须包含<stddef.h>来确保
size_t
的正确声明,以避免未定义行为。
注意:如果一个库函数的声明没有引用头文件中定义的任何类型,允许在不包含其头文件的情况下声明该函数,只要声明与标准声明兼容即可。然而,对于类型定义,如
size_t
,必须包含相应的头文件。
/* Not including stddef.h */
#include <stdlib.h>
void func(void *ptr, unsigned int size){
/* Assuming size is of type size_t, which should be declared in stddef.h */
free(ptr);
/* Other operations using size... */
}
应当修改为:
#include <stddef.h>
#include <stdlib.h>
void func(void *ptr, size_t size){
free(ptr);
/* Other operations using size... */
}
非常感谢您花时间阅读我的博客,希望这些分享能为您带来启发和帮助。期待您的反馈与交流,让我们共同成长,再次感谢!
👇热门内容👇
python使用案例与应用_安城安的博客-CSDN博客
软硬件教学_安城安的博客-CSDN博客
Orbslam3&Vinsfusion_安城安的博客-CSDN博客
网络安全_安城安的博客-CSDN博客
教程_安城安的博客-CSDN博客
python办公自动化_安城安的博客-CSDN博客
👇个人网站👇
安城安的云世界
版权归原作者 安小呆 所有, 如有侵权,请联系我们删除。