• Understanding Undefined Behavior


    • 什么是未定义的行为
    • 编译器和未定义的行为之间的关系
    • 未定义行为导致的安全问题
    • 检查未定义行为的工具介绍
    • Swift相比OC更安全一些

    什么是程序的未定义行为?

    • 在 ISO C++14 Standard未定义成为标准的行为,有些错误的行为没有多加检测和控制
    • 即语法检查不到的错误,语法正确,运行起来却会有错误
    • 比如除数未0,数组越界,数值类型溢出,空指针访问异常,更改字符串的字面量这些都是我们在项目中经常会碰到的.
    • 详细见下图
    • 编译器如何处理未定义行为

      • 编译器可以帮助整段并给出错误或者警告信息
      • 安装文档中的规则执行
      • 产生不可预料的后果
    • 未定义行为是一个利弊权衡的取舍过程

      • 性能和安全性之间需要做一个取舍
    • 一些未定义行为的例子

    //值未初始化
    int uninitialized_variable(int arg) { int value;
        if (arg <= 0)
            value = 42;
        return arg + value;
    }
    //使用未初始化的值
    int uninitialized_variable(int arg) { int value;
        if (arg <= 0)
            value = 42;
        return arg + value;
    }
    //指针没有按照要求对齐,char和int混用
    char *serialize_misaligned(char *buffer, int a, int b) { *(int *)buffer = a;
    buffer += sizeof(a);
    *(int *)buffer = b;
        buffer += sizeof(b);
        return buffer;
    } 
    ![-w415](media/16025922849569/16025945666340.jpg)
    //访问已经释放的对象或变量,value指针得到的是局部变量`default_value`的地址,但是这个变量是一个局部变量,离开if语句就释放了
    int lifetime_issue(int *value) {
        if (value == NULL) {
             int default_value = 42;
             value = &default_value;
         }
    }
    

    编译器和未定义行为之间的关系

    • 关系见下图:

      • Singed int不能溢出,通过 x<x+1判定
      • 指针自然对齐,自动根据type类型偏移查找,使用向量指令检查
      • 空指针不能取值,空指针没有地址
    • 编译器是如何优化这些未定义行为的?

      • 图解
        • 读取源代码
        • 生成中间代码
        • 分析
        • 优化
        • 输出目标文件
      • 优化无用代码 Objective-C int foo(int *P) {
        int var = *P; //无用的 *P直接去掉
        return 42;
        }
      • 去除冗余的校验
      • 在优化时可能会有不同的优化行为

        • 消除NULL -> 去除无用代码

        • 消除无用代码 -> ..

      • 编译器优化分为多个等级

        • 未定义的行为危害
          • 不可预知的
          • 后果可能会影响整个程序的执行结果
          • bug会更加隐蔽

    未定义行为的安全性问题

    • 安全性问题和用户隐私息息相关,举些例子
    • 未定义行为是很多安全漏洞的核心
      • 缓冲区溢出
      • 使用未定义的变量
      • 使用释放的变量
      • 重复释放
      • 多线程冲突

    处理未定义行为

    • 工具检测
      • 编译检测
      • Static Analyzer: 静态分析
      • Address Sanitizer: 地址安全性
      • Thread Sanitizer: 多线程问题检测
      • Undefined Behavior Sanitizer: 未定义行为检测
    • 充分利用编译器规则并相信它
      • 注意编译器警告
      • 使用release版本的Xcode
      • 为工程定义化更多的验证设置信息(Editor → Validate Settings)
    • 运行静态检测工具(Run the Static Analyzer)

      • 扫描编写的代码
      • 分析每次构建
      • 持续集成分析
      • 分析Runtime检测信息分析

        • 值运算溢出

        • 开启检查

        • 使用更安全的语言功能

          • 自动引用计数
          • C++智能指针(std::shared_ptr, std::unique_ptr)
          • 数组边界检查
      • 推荐使用Swift

        • 强大的类型推导
        • 可选链有效的避免空指针访问异常
        • 自动引用计数

    Swift是目前iOS开发中最安全的语言

    • 对比C语言
      • Optionals: 通过可选链?对空指针取消引用的应答,避免Crash,注意不要强制解包 - (nullable NSView *)ancestorSharedWithView:(nonnull NSView *)aView; // Objective-C func ancestorShared(with view: NSView) -> NSView? // Swift

    Swift中的UnsafeTypes

    • 指针类型的操作在Swift是不安全的类型,提供了面向对象的指针访问。 Swift UnsafePointer<Pointee> 不可变指针
      UnsafeMutablePointer<Pointee> 可变指针
      UnsafeRawBufferPointer<Pointee> 不可变数组指针
      UnsafeMutableRawBufferPointer<Pointee> 变的数组指针

    参考文档

    https://developer.apple.com/wwdc17/407

  • 相关阅读:
    Spring Security配置logout地址
    flex布局
    视口的学习笔记
    box-sizing属性
    css清除浮动
    line-height的理解
    position和float小结
    css居中方法小结
    margin重叠
    浅谈负margin
  • 原文地址:https://www.cnblogs.com/wwoo/p/understanding-undefined-behavior.html
Copyright © 2020-2023  润新知