美文网首页
【学习】安全编程之“字符串/数组”篇

【学习】安全编程之“字符串/数组”篇

作者: 老k的小茅屋 | 来源:发表于2025-09-15 11:27 被阅读0次

规则1:确保有足够的存储空间

部分字符串处理函数由于设计时安全考虑不足,或者存在一些隐含的目的缓冲区长度要求,容易被误用,导致缓冲区写溢出。典型函数如itoa,realpath。 以下的代码,试图将数字转为字符串,但是目标存储空间的长度不足。

1. int num = ...
2. char str[8] = {0};
3. itoa(num, str, 10); // 10进制整数的最大存储长度是12个字节

以下的代码,试图将路径标准化,但是目标存储空间的长度不足。

1. char resolvedPath[100] = {0};
2. realpath(path, resolvedPath); //realpath函数的存储缓冲区长度是由PATH_MAX常量定义,或是由_PC_PATH_MAX系统值配置的,通常都大于100字节

以下的代码,在对外部数据进行解析并将内容保存到name中,考虑了name的大小,是正确的做法。

1. char *msg = GetMsg();
2. ...
3. char name[MAX_NAME] = {0};
4. int i=0;
5. //必须考虑msg不包含预期的字符’\n’
6. while (*msg != '\0' && *msg != '\n' && i < sizeof(name) - 1) {
7.     name[i++] = *msg++;
8. }
9. name[i] = '\0'; //保证最后有’\0’

规则2:对字符串进行存储操作,确保字符串有’\0’结束符

对字符串进行存储操作,必须确保字符串有’\0’结束符,否则在后续的调用strlen等操作中,可能会导致内存越界访问漏洞。

规则3:外部数据作为数组索引时必须确保在数组大小范围内

外部数据作为数组索引对内存进行访问时,必须对数据的大小进行严格的校验,否则为导致严重的错误。 下面的代码,通过if语句判断offset的合法性:

1. int Foo(BYTE *buffer, int size)
2. {
3. ...
4. int offset = ReadIntFromMsg();
5. if (offset >= 0 && offset < size) {
6.     BYTE c = buffer[offset];
7. ...
8. }
9. ...
10. }

规则4:外部输入作为内存操作相关函数的复制长度时,需要校验其合法性

在调用内存操作相关的函数时(例如memcpy、memmove、memcpy_s、memmove_s等),如果复制长度外部可控,则必须校验其合法性,否则容易导致内存溢出。 下例中,循环长度来自设备外部报文,由于没有校验大小,可造成缓冲区溢出:

1. typedef struct BigIntType {
2.     unsigned int length;
3.     char val[MAX_INT_DIGITS];
4. }BigInt;
5.
6. BigInt *AsnOctsToBigInt(const AsnOcts *asnOcts)
7. {
8.      BigInt *bigNumber = NULL;
9.      ...
10.     for (i = 0; i < asnOcts->octetLen; i++) {
11.         bigNumber->val[i] = asnOcts->octs[i];
12.     }
13.     ...
14. }

规则5:调用格式化函数时,禁止format参数由外部可控

调用格式化函数时,如果format参数由外部可控,会造成字符串格式化漏洞。 这些格式化函数有:
格式化输出函数:xxxprintf ;
格式化输入函数:xxxscanf;
格式化错误消息函数:err(),verr(),errx(),verrx(),warn(),vwarn(),warnx(),vwarnx(),error(),error_at_line();
格式化日志函数:syslog(),vsyslog()。
错误示例:

1. char *msg = GetMsg();
2. ...
3. printf(msg);

推荐做法:

1. char *msg = GetMsg();
2. ...
3. printf("%s\n", msg);

规则6:调用格式化函数时,format中参数的类型与个数必须与实际参数类型一致

格式化函数中,format中的参数类型与个数与实际参数不一致,会导致读写的数据与期望不一致,造成输入输出数据错误,访问非法内存,写越界等问题。 例外: 在格式化输出函数中,signed char,signed short可以用有符号整型格式%d输出,unsigned char, unsigned short类型参数可以用无符号整型格式如%u输出。


参考:gitcode社区-开源文档-菊厂C&C++安全编程规范

相关文章

网友评论

      本文标题:【学习】安全编程之“字符串/数组”篇

      本文链接:https://www.haomeiwen.com/subject/ijaaajtx.html