返回介绍

安全

发布于 2024-10-12 21:58:10 字数 1649 浏览 0 评论 0 收藏 0

安全编程也称作 防御性编程 (defensive programming),核心理念是不对函数调用和库使用做任何假设。

断言

用断言对输入输出数据进行检查,尽可能在调试或测试阶段找出自己或调用方潜在问题。以 NDEBUG 宏控制,不会影响发行版(release)性能。

#ifdef NDEBUG
	#define assert(condition) ((void)0)
#else
	#define assert(condition) /*implementation defined*/
#endif
$ gcc -DNDEBUG -g -o test main.c

还可用 static_assert 进行编译期检查,比如某些结构体字段位置(offset)不能改变等。不会生成指令。

建议

编码常见安全问题清单。

  • 使用常量代替字面量。( MIN = 10, MAX = MIN + 90
  • 尝试用 typedef 提高可读性。(函数类型)
  • 用括号保证优先级。
  • 不要依赖跨单元的初始化顺序。
  • 不要在子作用域中复用变量名。(尤其是全局变量名命名)
  • 不要在一个声明中超过一个变量。( int *p, x
  • 不要引用未初始化内存。
  • 不被导出的对象声明为 static。
  • 不被修改的参数声明为 const。
  • 不要忽略函数返回值。
  • 打开高警告级别,尝试通过代码修改消除警告。
  • 断言的副作用。(不要在 assert 表达式执行 ++ 等操作,断言可被忽略)
  • 指针长度和指针目标长度的差别。( sizeof(ptr) , sizeof(*ptr)
  • 不要在另一个线程中解锁。
  • 结构长度和结构成员长度总和的差别。(对齐)
  • 不要通过字节对比来判断结构是否相同,因为填充字节内容未定。
  • 获取数组长度时,需要知道当前是数组名还是指针。
  • 避免数组越界。
  • 函数签名区别指针和数组。( int *d vs int d[]
  • 字符串结束方式,是有长度计数,还是结束标记。
  • 字符串是否可被修改,子串如何返回?是否共享内存?
  • 如果引用字符串常量,建议使用 const 表示不能修改(编译器检查)。
  • 在相同单元里处理内存申请和分配。(malloc, free)
  • 调用 free 后,将指针赋值为 NULL。
  • 内存敏感信息处理。
    (释放前覆盖 memset,避免被交换 mlock,避免 realloc 异地分配留下副本)
  • 警惕编译器优化掉安全措施。
    (比如认为 memset 覆盖清除无意义,被忽略,可在后面继续引用)
  • 禁止被 core dump。(setrlimit CORE, 0)
  • 小心使用伪随机数。(安全攻击)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文