-
消除 C 和 C++ 中的边界安全漏洞
探究 Xcode 中的边界安全技术如何消除现有 C 和 C++ 代码库中的一整类越界漏洞。了解如何将 C 边界安全扩展与 __counted_by 等注释搭配使用,在不破坏 ABI 兼容性的情况下强制执行边界检查。此外,探索如何启用 C++ 安全缓冲区和强化版 C++ 标准库,以最小的性能开销保护生产版 App。
这个讲座最初作为“与 Apple 会面交流”活动“加固你的 App:关键策略助你增强安全性”的一部分讲授。请观看完整视频,以了解更多见解和相关讲座。资源
-
搜索此视频…
大家好。我是所有者安全工具团队的成员 Yeoul, 今天将由我的同事 Louis 与我一同进行讲解。 今天的讲座主题是边界安全, 这是一项能够从你的 C 和 C++ 代码 中彻底消除整类内存安全漏洞的技术。
本次讲座的议程如下: 首先,以一个真实的漏洞为例, 说明边界安全为何重要。
接着,介绍其工作原理。 为何应采用边界安全技术,
以及如何在实践中加以应用。
我还将探讨构建更广泛的边界 安全生态系统的相关工作。
最后,是针对 C++ 的具体方案。
下面是一个真实案例。 最近,一个零点击漏洞 影响了一个广泛使用的音频库。 所谓零点击,是指攻击者无需用户任何操作, 即可悄无声息地执行任意代码。 在大多数平台上, 这会让攻击者悄无声息地接管设备。 但在Apple平台上,该漏洞利用却直接失败。 这是因为边界安全技术使得 这一整类漏洞无法被利用。 如今,你已拥有相关工具,可将同样的防护机制 融入你的 App 中。
内存安全仍是系统编程 中首要的安全挑战。 你可能已经在努力利用静态分析、 内存 sanitizer 和代码 审查来查找并修复漏洞。 但问题在于: 攻击者不断发现新的漏洞。
漏洞检测工具固然有价值, 但仅靠它们还不足以真正改变攻击者的攻击模式。 必须彻底消除整类漏洞,这样即使存在漏洞, 攻击者也无法加以利用。
实现内存安全的完整解决方案 是使用 Swift 这样的内存安全语言。 对于新代码而言,这绝对是正确的选择。
但现有代码库的情况则截然不同。 有时甚至包含数亿行 C 和 C++ 代码。 彻底重写可能需要数十年时间。
但人们现在就需要保护。
一条切实可行的前进之路。 现有代码至关重要。
我们需要的是能够消除整类漏洞的技术, 而不仅仅是发现单个漏洞。
这些技术必须比彻底重写更容易采用。
而且至关重要的是,它们必须能够逐步适应。 这样,你无需等待大规模迁移项目, 今天就能开始保护你的代码。
今天早些时候, Mark 对五类不同的内存 安全漏洞进行了精彩的概述。 这些都是重要问题, 但每类都需要不同的解决方案。
本次演讲将专注探讨边界安全问题, 这是与生命周期安全并列的两大主要问题之一。
还记得之前提到的音频编解码器漏洞吗? 那是一个安全问题。 它约占所有内存安全问题的半数。
这意味着要解决边界安全问题。 解决边界安全问题将消除一半的内存安全问题。 接下来,我将向大家展示 如何利用 Apple 为 C 语言开发的边界安全 技术来保护你的 App。 假设你正在为 App 开发一个图像滤镜。
它需要一个缓冲区、一个大小参数,并遍历像素。
但请注意这里的循环条件。 它使用了小于或等于 size的条件。 这在最后一次迭代中引入了一个典型的 偏移量为 1错误, 导致写入的元素超出了缓冲区末尾一个位置。
虽然这是一个简化的示例, 但它恰恰代表了那种越界错误—— 当这种错误与攻击者控制的输入相结合时, 便会成为无数现实世界中安全漏洞的根本原因。
以下是 C 语言的边界安全 扩展如何通过边界安全机制解决此问题。 索引操作需要边界信息。 如果不知道指针的边界, 编译器不会允许你通过该指针进行索引。
请看这里的错误信息。 编译器正在告诉你, `image` 没有边界信息, 因此你不能使用非零索引对其进行索引。
这个错误会引导你添加必要的边界注释。 即告诉编译器 `image` 指向多少个元素。
这就是counted by 派上用场的地方。 即counted by size。 这告诉编译器,该指针指向 size 个元素。
现在编译器知道了边界范围。
它会在每次内存访问前自动插入边界检查。
如果发生越界写入,边界安全机制会 在程序触发异常之前拦截。
虽然代码中仍存在该漏洞,但已无法被利用。
C 程序使用指针的方式各不相同, 因此边界安全扩展提供了一组边界注释。 让我向大家展示一些常见的指针模式, 以及每种情况下应使用哪种注释。
我将从指向单个元素的指针开始讲起。
在检查 C 和 C++ 中的边界安全漏洞时, 存在一个明显的模式。 大多数问题都源于数组索引和指针运算。
在此图中,这是一个包含四个整数的数组。 绿色方框表示有效的元素索引, 范围从 0 到 3。 红色方框表示越界区域。 内存。 获取指向数组的指针 p0, 它指向第一个元素。这是安全的。
但在进行数组索引或指针运算时, 很容易超出数组边界并访问红色区域。
有趣的是, C 语言中大多数指针 实际上并不需要进行指针运算。 它们只是指向单个对象,比如这个类型 T。 像数组那样对其进行递增或索引操作会导致越界, 既不安全也毫无必要。
你真正需要的是解引用——使用箭头访问成员, 或使用星号运算符直接解引用。
而这正是single注解所体现的。
它表示该指针指向的恰好是一个元素, 或者为空(null); 通过 `single` 注解, 编译器会阻止指针运算和数组索引操作。 你无法意外地将指针移动到该单一对象之外,
因为这些错误会在编译时被捕获, 因此默认情况下它是安全的。
好的,所以 `single` 对于大多数指针来说效果很好。 即仅指向单个对象的指针; 但对于指向多个元素的指针— —你确实需要进行索引和指针运算时— —你需要弹跳信息。 你需要知道可以安全访问多少个元素。 有效范围是什么?
这种弹跳信息必须来自某个地方。
幸运的是,大多数代码已经具备了这一信息。
以处理图像为例。 指针与其大小是同时传递的。
或者考虑类型T 的信息。 数据指针就紧挨着数据大小。
这种模式在 C 函数中随处可见。 路径大小与指针结构体将它们并排存储。
这些信息已经存在。 它只需要一种方式来明确表达。
这就是 Counted by 的用 武之地。它让你能够说明这些指针的边界 由另一个变量决定。你正在将其显式化。 在代码中原本就存在的 counted by是最常见的注解。 但还有其他注解可以捕获不同的边界模式。
我将通过一个稍作修改的示例向你展示另一个。 假设该函数现在接受一个 void 指针来处理不透明的序列化数据。 类型未知,但知道有多少字节可用。
结构体中也是如此。 假设现在要处理一个序列化数据, 该数据是一个 void 指针。 结构体未知,但 `datasize` 会跟踪其中包含多少字节。
这就是你应该使用 `size by` 注解的地方。
它不像 `counted by` 那样计数元素,而是计数字节。
现在来看另一个例子。 `allocate pixels` 函数 将图像分配为一个像素数组。 它要么返回指向 n 个像素元素的指针, 要么返回 null。 如果分配失败,
除非 n 为零,否则将返回 类型设置为counted by n 个元素是错误的, 因为当它返回 null 时, 该指针并不指向 n 个元素, 而是指向空。
这就是你需要使用counted by 或null注解的地方。 它表明:要么该指针指向 n 个元素, 要么不指向任何元素。 当指针可能为 null 而计数 不为零时,请使用此注解。
我已经介绍了最常见的几种, 但还有其他注解适用于其他父类, 例如 size Y、 null、 Devi 等。
你可以在关于边界安全 扩展的文档中找到完整列表。
现在你已经了解了边界安全扩展的工作原理, 以下是你应该采用它的理由。
主要有两个原因:它提供了强安全保证, 而且采用起来非常实用。
首先,强安全保证意味着编译器 会始终插入必要的平衡检查。
多年来,开发者一直依赖于 Unison 和 Fortify Source 这样的机会性平衡检查工具。
这些工具固然很有价值, 但它们只能在尽最大努力的基础上发现错误。 这就像是在玩一场永无止境的打地鼠游戏。
攻击者总能找到我们遗漏的漏洞。
Bond安全彻底改变了这一局面。 它为你提供了有保障的检查机制。 编译器充当你的安全网, 确保平衡信息始终存在且始终正确。 这从结构上消除了这一类漏洞。
首先,编译器确保平衡信息始终可用,
因此尝试在没有平衡 信息的情况下对指针进行索引,
会在第一个函数中引发编译器错误。 由于没有边界检查 或对 `image` 的标记,
编译器会拒绝该数组访问。
第二个由 `counted by` 提供的函数则提供了边界检查。 因此代码能够编译通过, 且编译器会插入边界检查。
这意味着,如果代码能编译通过, 边界检查就已到位。
没错。这是我最喜欢的功能之一。 你有多少次更新了缓冲区却忘记更新大小? 借助这一扩展,编译器实际上能够理解 指针与大小变量之间的关系, 并在编译时和运行时强制执行, 这意味着你无法意外地越界。 正确性。
看看上面的这个例子。 数据指针与下方的数据大小相关联。 该函数为数据分配了内存,却忘记更新数据大小。 这种经典错误通常会导致大小值过时, 从而引发越界错误。
但现在,编译器会立即捕获该错误并拒绝编译。
要修复它,你只需在更新 指针的同时更新大小值即可。
不仅限于编译时检查。 由于 size 字段被硬编码为 100,
编译器还会插入运行时检查。 在此情况下,编译器会自动 确保 100 确实能容纳 在原始分配的内存中。
凭借这些安全保障, 边界安全扩展的采用具有很强的实用性。
首先,大多数指针并不需要注解。 智能默认值会自动处理常见情况,
而且你可以在保持 ABI 兼容 性的同时逐步进行适配。 你可以一次转换一个文件,而不会 破坏与代码库其余部分的兼容性。
我将从智能默认值开始讲起。 让我们回到消息处理的示例。 该函数接受一个指向单个消息 T 对象的指针, 并添加了 `single` 来表达这一点。
由于这种模式非常常见, 边界安全扩展将 `single` 设为 ABI 边界处指针的默认值。 函数参数、结构体字段、 全局变量以及嵌套指针均适用。
因此,你无需为该参数添加注解。 它默认已经是 `single` 了。
只有当你需要不同行为时(例如按 特定方式计数),才需要添加注解。
现在你可能会想:嘿, 我真的必须为数百万行代码中的每一个局部 指针都添加注解吗? 答案绝对是否定的, 因为局部变量不会暴露在 ABI 边界上。 编译器做了一件非常巧妙的事情。 它会在后台自动将它们提升为宽指针。 你可以获得完整的指针运算功能, 还能得到自动的运行时检查, 并且无需在局部代码中添加任何注解, 就能获得所有这些安全保障。 它就是这么自然地工作。
下面是一个示例。 processimage 函数
使用局部变量来跟踪当前位置并标记数组的末尾。 这两个变量都是自动转换为宽指针的。 无需任何注解。
当你递增 PTR 时,编译器会自动维护边界。
当你解引用 TR 时, 系统会自动进行边界检查, 确保安全,而无需添加任何注解。
以下是采用该方案的最实际理由。
它专为在实际环境中逐步采用而设计。 暂停开发并在一夜之间重写 庞大的 SQL 代码库根本不可行,
因为这些注解不会改变 ABI 边界处的指针表示形式。 完全重写并非必要。 你可以选取一个高度安全的关键文件, 立即启用反向跳转安全机制, 并将其直接链接回现有的未注释项目中。
在某些实际场景中,系统头文件等未 注释的 API 是必需的。 默认情况下,来自这些头文件的指针 会被视为不安全。 没有反向跳转信息。 不,没有跳转检查。 编译器无法验证它们,
但这允许跳转安全的代码仍然 能够编译并与旧版库互操作。
以下是一个示例。 open 函数调用 open 来获取文件指针。
由于 file 来自一个带注释的系统头文件, 编译器将其视为不安全的指针, 并将其赋值给安全变量。 要将安全变量 F 进行显式转换,
要实现这一点,请使用 `unsafe_for_single` 宏。 它接受基础指针类型和不安全指针作为参数。 这意味着:我知道这些指针指向同一个文件对象, 并且我对此负责。
目标是随着上游添加适当的注解, 逐步审核并移除这些不安全的构造。
好的。理论部分就讲到这里,对吧? 现在进入有趣的部分。 下面将详细介绍如何在你的项目 中应用边界安全机制。
具体流程如下:首先为头文件添加注解。 然后逐个处理你的文件。 为已适配的文件启用边界安全, 并进行测试和调试。 处理完所有文件后, 在 Xcode 中全局启用边界安全。
我将逐一讲解每个步骤。
首先,在定义 API 契约的头文件中 添加双重bounce注解。
以这个头文件为例。
首先,包含 `to check that H`, 这会提供bounce安全注解和宏, 然后使用
`to check Abi` 或 `some single`。 当你修改头文件时。 这个宏可确保调用方自动将你的 Abi 指 针视为 `single` 类型, 而非 `unsafe` 类型。 最后,根据需要添加 `counted by` 或其他bounce注解。
就这样。该头文件现在已具备跳转安全性。 如果另一个具备跳转安全性的代码调用此函数, 编译器会在调用处插入跳转检查。
接下来,选择一个源文件。 启用该扩展功能。
为此,需添加编译器标志。 在构建阶段添加 -bounce-safety 标志, 为所选源文件启用该功能。
然后进行编译并关注编译器诊断信息。 编译器会立即标记缺失或不匹配的注解。
一旦为该流程启用了bounce安全功能。 如图所示,将出现两条诊断信息。
第一条指出函数定义必须与头文件 声明中的注解相匹配。
第二条指出参数 `image` 没有bounce注解, 因此不允许对其进行索引操作。
通过按大小计数来修正该参数, 即可解决这两条诊断信息。
现在运行测试,并调试任何运行时检查。
如果遇到异常,可能是编译器调用了错误的注解, 或者存在像这样的真实错误。 偏移量为一错误。
Xcode 会立即停止执行, 并准确告知我们发生了什么。
引用超出了上界。
在此处修复逻辑后,代码即可正常运行。
一旦测试通过,该文件即受保护。
你可以逐步将剩余文件纳入保护范围。
当整个项目准备就绪后, 请在 Xcode 构建设置中启用 Bounce Safety扩展。
操作方法如下:进入项目的构建设置, 找到安全部分,启用 C 语言的扩展功能。 我将 C 语言的Bounce Safety 扩展设置为是。 从那时起,目标中的所有 C 代码都将受到保护, 新代码必须遵循Bounce Safety 规则。
现在我要明确一点:这不仅仅是一个研究项目。 它已在实际应用中得到大规模验证。
Apple 公司已经利用 它来保护数百万行生产代码。 它存在于驱动Apple平台的内核网络堆栈中。 它存在于内置的音频和图像编解码器中。 安全启动库中。 N1 网络芯片的固件中,以及更多地方。
目前,该技术正应用于高度注重 安全性的系统中,并已交付给客户。
Apple 每天都依赖这项 技术来保护数十亿用户。
现在轮到你了。采用这项技术, 保障你的用户安全。
当然,如果你使用 C 语言编程, 你肯定会在意性能。 你可能在想,这其中有什么陷阱。 因此,我们在内核网络堆栈中 进行了性能测试——在那里, 每一微秒都至关重要。 需要明确的是,在此次测试中, 所有控制路径均完全启用了下行安全机制。
在启用边界安全 机制的情况下,93%的测试显示其开销完全 在测量噪声的容差范围内。
而在少数几个实际可测得差异的地方, 该差异始终低于 2%。 归根结底,你将获得 跳转安全这一圣杯, 同时兼具极高的实际性能。
Bounce Safety 对于 你的代码库而言是一大胜利, 但当它无处不在时, 它将成为彻底改变游戏规则的存在。 以下是我们如何构建更广泛的 Bounce Safety 生态系统。
目标很简单:你应该能够保护任何平台上的用户, 而不仅仅是 Apple 用户。 为了实现这一目标, Bounce Safety 目前已 在 Clang 的 Swift 分支中开源。
我们也在积极将其回流到 LLVM 主线, 以便所有人都能使用,
但这还远不止于此。
Apple 正与 C 标准委员会直接合作, 将 Bounce 安全直接标准 化到 C 语言本身中。
最终,这将使每一位 C 开发者都 能受益于 Bounce 安全, 无论他们正在为哪个平台开发。
好的,现在我将把话筒交给 Louis, 请他来谈谈 C++ 方面的做法。
谢谢。 大家好。我叫路易斯, 在Apple公司负责 C++ 标准库的开发工作。 很高兴能来到这里。 现在让我们深入探讨 C++ 方面的内容。
C++ 与C 的不同 之处在于,它已经提供了许多 包含足够信息以确保安全性的抽象。 例如,标准 `span` 包含一个指针和一个大小, 因此它在被访问时知道哪些边界是有效的。
标准库中的许多其他组件也是如此, 例如标准向量(vector)、 标准字符串(string)、 标准数组(array)等。
然而, C++ 标准并未要求在这些 API 中强制执行安全性检查,事实上, C++ 标准库在历史上也从未这样做过。
例如,右侧的代码是 将 UL 之前展示的 C 语言 process_image 函数直接转换为 C++的版本。 它使用标准 `span` 代替了原始指针。 然而,尽管使用了标准 `span`, 该代码默认情况下并不 强制执行跳出安全检查。 现在,Xcode 使改变这一情况成为可能。
这是通过一种名为C++ 安全缓冲 区的双管齐下方法实现的。 首先, Xcode 提供了工具,帮助确保你的 C++ 代码 在访问缓冲区时使用标准库提供的惯用抽象。
其次,它现在 还附带了一个强化版的 C++ 标准库, 启用后可检测其众多 API 中的误用情况。
现在,为了帮助你在代码中采用更安全的抽象, Xcode 提供了诊断功能, 可以标记代码中以非惯用方式访问缓冲区的位置。 例如,这段代码是使用原始指针 编写的处理图像函数的一个版本。 在此情况下,新的 Xcode 诊断功能会标记这段代码, 因为它使用原始指针进行索引,这并不安全。
因此,这使你 能够发现代码中未使用 惯用结构访问缓冲区的位置, 并加以修正。
在这种情况下,一种方法 是改用 standard_span 重写代码,错误就会消失。
现在,为了让使用惯用 抽象方式的代码真正更安全, Xcode 还提供了一个强化 版 C++ 标准库。
在 Xcode 设置中启用 该功能后,标准库会利用 其已包含的边界信息来检查 你对某些API的使用情况。
在此示例中,如果在启用强化 功能的情况下对标准 span 进行索引,系统将利用其已 有的边界信息来确保访问有效。
现在,如果索引 无效,强化标准库将确保程序终止运行。 这意味着程序不会继续运行,从而避免潜在的数据 损坏或App安全风险。
另外值得注意的是,这些 API的使用方式和契约均未发生改变。
强化标准库仍然是一个符合 ISO C++ 标准的库。
启用强化标准库时,ABI 也不会发生变化。 所有这些都意味着,无需修改 代码即可享受额外的安全保障。 这使得采用强化功能变得非常容易。 现在。
要同时启用新的 Xcode 诊断功能和标准库强化功能。 请转到构建设置中的安全选项卡, 并启用在 C++ 中强制执行 边界安全缓冲区使用选项。
在某些情况下,你可能已有 使用不安全构造的现有代码, 但尚无法将其更新为使用现代编程惯用法,
此时仍可立即利用强化后的标准库, 而不会在代码中引入新的错误。
你可以仅启用强化后的标准库: 在 Apple Clang - Language - C++ 下的构建设置中, 选择启用 C++ 标准库强化。
另外需要注意的是, 这不仅仅是一个调试功能,对吧? 调试功能对于提高开发效率非常有帮助, 但仅靠它们还不足以。 让你的代码在运行时真正更安全。 在生产环境中的设备上运行。 事实上,使用强化标准 库的代码旨在部署到生产环境, 而标准库中的强化 设计正是经过精心考量,以确保其可行性。
这确保了你的代码在生产环境中运行时—— 当它在用户设备上处理真实数据时— —能够更加安全, 而这正是安全性真正重要的时刻。
在使用强化版标准库时, 许多 API 提供了额外的安全保障。
目前,普遍的认知是:那些具有直接 大小要求的容器访问 API 和容器修改 API 都经过了强化处理。 事实上,这些 API 本身已具备检查 边界所需的必要信息, 而检测这些 API 中的误用 能直接带来安全价值。
例如,容器的索引运算符。 它们的 back、 pub 和 front 方法。 这些方法均经过强化处理。
访问可选值时也经过了强化处理。
一般而言,在 ISO C++ 26 强化实现中, 你可以确信任何经过检查的先决条件都会被验证。
此外,还有一些情况下, 标准库默认已提供检查机制。 例如,当标准函数为空时 调用该函数,系统会自动抛出异常。 强化措施不会影响这些 API。
其他虽然容易进行强化 但安全价值有限的 API, 同样未被强化。 为了最大限度地减少强化 措施对App性能的影响, 优先处理那些真正能提供安全价值的检查。
例如,使用空指针构造字符串 在技术上是不正确的。 但在实际中,这已经会导致段错误并终止程序。 因此,针对这种情况添加 显式检查所带来的安全价值有限。
最后,迭代器是强化措施的一个值得注意的例外。 迭代器通常不存储足够的信息来执行 边界检查。 添加这些信息需要更改 ABI, 这会大大增加采用的难度。 因此,迭代器访问未被强化。
现在你已经很好地了解了哪些 API 被强化, 我将讨论开发强化的 App 程序时你可能会遇到的情况。
因此,当加固检查失败时, 程序将在 Xcode 内终止运行。 系统会将你引导至加固断言失败的位置 (位于标准库中), 随后你可以使用左侧的栈帧选择器 导航至你自己的代码。
调试控制台将显示一条错误消息, 提供有关失败的额外上下文信息, 然后你可以使用 Xcode 中的常规调试工作 流来理解并解决问题。
在正式发布的 App 中,情况略有不同, 因为 无法附加调试器, 程序将通过陷阱机制终止,这与C和 C++ 中绑定安全扩展的行为类似。 这种机制是终止程序最快捷、 最安全的方式,因为它在断言失败后, 几乎不给潜在的恶意攻击者 任何机会来篡改程序的控制流。
具体来说,这意味着控制台不会记录任何消息。 这既能防止程序信息泄露, 又能通过不在可执行文件中存储诊断字符串, 确保二进制文件保持 尽可能小的体积。
但这还不是全部。 Xcode 甚至提供了其他检查模式, 这些模式在性能上各有取舍。
我之前一直提到的强化模式, 实际上被称为快速模式。 除了快速模式之外, Xcode 还提供了一种 扩展模式,该模式会添加 一些开销较小但未必对安全性至关重要的检查。
这种模式非常适合在确保严格编程规范的同时, 避免付出过高的性能代价。
此外,在扩展模式之上, Xcode 还提供了一种调试模式。 调试模式会进行更全面的检查, 但会带来更大的性能影响。
例如,在调试模式下, C++ 库可以检查提供给标准 排序函数的比较器是否具备排序所需的属性。 这对于发现App中难以 察觉的语义错误非常有帮助。
目前,快速和全面模式可用于生产环境, 而调试模式仅应在开发过程中使用。
此外,还可以在不同的文件 中混合使用不同的模式。 这可用于在代码库中逐步采用强化措施, 或进行精确的性能调整。 例如,你可以在整个 代码库中启用全面或快速检查, 但在一个对性 能非常敏感的源文件中禁用强化措施。
而且由于强化措施不会影响 ABI, 所有这些操作都能无缝进行。
对于这些功能如今能在 Xcode 中正式推出,我真的非常兴奋。 事实上,Apple公司开发这 项技术已有相当长的时间, 并且已在内部广泛采用,才使 其发展到今天的水平。
特别是,这项技术已被应用于整个 WebKit 以及操作系统的多个部分, 包括内核的部分组件。
未观察到显著的性能影响,同时发现了多个漏洞, 其中包括一些非常难以察觉的漏洞。
除了Apple自身的经验外, 业内还有许多关于该技术应用的案例。
例如,谷歌记录了他们在整个服务器 集群中的部署情况。 这涉及数百万行对性能敏感的代码。
他们观察到的性能影响最低仅为 0.3%。 经过一些调整后,他们报告称 发现了超过 1000 个漏洞, 其中包括关键安全漏洞。
行业采用的另一个例子是 C++ 26, 它基于快速模式采用了强化标准库的概念。
因此,总体而言,相关经验极为积极, 我非常期待该功能现在 能在 Xcode 中正式推出。
好的。我们已经介绍了 Xcode 目前提供的工具, 这些工具可帮助你消除 C 和 C++ 中的重要漏洞类别。 这意味着,你现在可以按文件逐个 启用 C 代码中的边界安全扩展。 你应从代码中安全敏感度最高的部分开始, 待准备就绪后再逐步扩展到其余代码。 对于 C++ 代码, 请在整个项目中启用该功能。 立即启用快速模式, 无需修改代码即可提升App的安全性。
在测试和开发过程中,你还应启用调试模式。 这将帮助你发现那些否则容易被忽略的细微错误, 并查出代码中未使用标准 库惯用抽象方式直接访问缓冲区的情况。 启用新的 Xcode 诊断功能,并…… 如果你想进一步了解…… 以及我今天介绍的内容, 网上有详尽的文档可供查阅。
请记住,人们依赖你的代码来保障安全, 而且每一步都至关重要。 所以,从今天开始,试用这些功能吧。 至此,我将话筒交还给Kurt。
-