變數指南

簡介

如「總覽」頁面所述,主機程式碼會向沙箱程式庫發出 RPC 呼叫。沙箱機制會讓程序之間產生記憶體分離,因此主機程式碼無法直接存取沙箱程式庫中的記憶體。

為了確保主機程式碼可以在遠端程序中存取變數和記憶體區塊,以及簡化主要邏輯程式碼的實作,SAPI 提供一組完整的 C++ 類別。不過在許多情況下,您也可以使用原生 C 類型。

將指標傳遞至簡單類型和記憶體區塊 (結構、陣列) 時,就會需要特殊類型 (SAPI 類型)。

舉例來說,呼叫函式接收指標時,必須將指標轉換為沙箱程式庫記憶體內的對應指標。以下程式碼片段以視覺化方式呈現這個情境。系統不會建立 ::sapi::v::Array<int> 物件,而非三個整數的陣列,而是建立物件後,即可在沙箱程式庫的 API 呼叫中傳遞:

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 指標的說明文件。

API 結構體

範本 ::sapi::v::Struct 記錄於 var_struct.h。該範本提供可用於包裝現有結構的建構函式。SAPI Struct 提供 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));
…

如果現有的 struct 包含指標,這些指標會指向 Sandboxee 中的位址。因此,您必須先轉移 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 物件。