变量指南

使用集合让一切井井有条 根据您的偏好保存内容并对其进行分类。

简介

概览页面中所述,主机代码会对沙盒化库进行 RPC 调用。沙盒会导致进程之间的内存分离,因此主机代码无法直接访问沙盒库中的内存。

为了确保主机代码可以访问远程进程中的变量和内存块,并简化主逻辑代码的实现,SAPI 提供了一套全面的 C++ 类。不过,在许多情况下,您也可以使用原生 C 类型。

将指针传递给简单类型和内存块(结构、数组)时,需要用到特殊类型(SAPI 类型)。

例如,在调用带有指针的函数时,必须将指针转换为沙盒化库的内存内的相应指针。以下代码段直观呈现了这种情况。创建由可在沙盒化库的 API 调用中传递的 ::sapi::v::Array<int> 对象(而非包含三个整数的数组):

int arr[3] = {1, 2, 3};
sapi::v::Array<int> sarr(arr, ABSL_ARRAYSIZE(arr));

如需全面了解所有可用的 SAPI 类型,请查看 SAPI 项目源代码中的 var_*.h 头文件。这些头文件提供代表各种数据类型的类和模板,例如:

  • ::sapi::v::UChar 表示已知的未签名字符。
  • ::sapi::v::Array<int> 表示整数数组

SAPI 类型

本部分介绍了主机代码中常见的三种 SAPI 类型。

SAPI 指针

如果要沙盒化的函数需要传递指针,则应从下面的 PtrXXX() 方法之一获取此指针。这些方法由 SAPI 变量类实现。

指针类型
::PtrNone() 在将代码传递到沙盒化 API 函数时,不会在主机代码进程和沙盒库进程之间同步底层内存。
::PtrBefore() 在进行沙盒化 API 函数调用之前,同步它所指向的对象的内存。 这意味着,在调用之前,所指向变量的本地内存将转移到沙盒库进程中。
::PtrAfter() 对在沙盒化 API 函数调用发生后所指向的对象的内存进行同步。 这意味着,指针变量的远程内存将在调用完成后转移到主机代码进程内存中。
::PtrBoth() 结合了 ::PtrBefore()::PtrAfter() 的功能。

点击此处可查看 SAPI 指针的相关文档。

SAPI 结构

::sapi::v::Struct 模板记录在 var_struct.h 中。它提供的构造函数可用于封装现有结构。SAPI 结构体提供了 SAPI 指针中列出的所有方法,以获取可用于沙盒库调用的 ::sapi::v::Ptr 对象。

以下代码段展示了系统会先启动一个结构,然后将其传递给 zlib 示例中沙盒化的函数调用:

sapi::v::Struct<sapi::zlib::z_stream> strm;
…
if (ret = api.deflateInit_(strm.PtrBoth(), Z_DEFAULT_COMPRESSION,
                             version.PtrBefore(), sizeof(sapi::zlib::z_stream));
…

如果现有结构体包含指针,则这些指针将指向沙盒中的地址。因此,您必须先转移 Sandboxee 数据,然后才能让主机代码访问这些数据。

SAPI 数组

模板 ::sapi::v::Array 记录在 var_array.h 中。它提供了两个构造函数,一个可用于封装现有元素数组,另一个用于动态创建数组。

以下代码段(摘自求和示例)展示了如何使用封装在不属于此对象的数组中的构造函数:

int arr[10];
sapi::v::Array<int> iarr(arr, ABSL_ARRAYSIZE(arr));

以下代码段展示了用于动态创建数组的构造函数示例:

sapi::v::Array<uint8_t> buffer(PNG_IMAGE_SIZE(*image.mutable_data()));

SAPI 数组提供了 SAPI 指针中列出的所有方法,以获取可用于沙盒化库调用的 ::sapi::v::Ptr 对象。