変数ガイド

はじめに

[概要] ページで説明したように、ホストコードはサンドボックス化されたライブラリに対して RPC 呼び出しを行います。サンドボックス化によってプロセス間でメモリが分離されるため、ホストコードはサンドボックス化ライブラリのメモリに直接アクセスできなくなります。

ホストコードがリモート プロセスの変数やメモリブロックにアクセスできるようにし、メイン ロジック コードの実装を簡素化するために、SAPI には包括的な C++ クラスセットが用意されています。ただし多くの場合、ネイティブの C タイプを使用することもできます。

単純な型やメモリブロック(構造体、配列)にポインタを渡す場合、特殊な型(SAPI 型)が必要になります。

たとえば、ポインタを受け取る関数を呼び出す場合、ポインタはサンドボックス ライブラリのメモリ内で対応するポインタに変換する必要があります。次のコード スニペットは、このシナリオを視覚化したものです。3 つの整数の配列の代わりに、サンドボックス化されたライブラリの 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 タイプ

このセクションでは、ホストコードでよく見られる 3 つの SAPI タイプを紹介します。

SAPI ポインタ

サンドボックス化する関数がポインタを渡す必要がある場合、このポインタは以下の PtrXXX() メソッドのいずれかから取得する必要があります。これらのメソッドは、SAPI 変数クラスによって実装されます。

ポインタの種類
::PtrNone() サンドボックス化された API 関数に渡されたときに、ホストコード プロセスとサンドボックス化されたライブラリ プロセスの間で基盤となるメモリは同期されません。
::PtrBefore() サンドボックス化された API 関数呼び出しが行われる前に、ポイントしているオブジェクトのメモリを同期します。 つまり、ポイントされた変数のローカルメモリは、呼び出しの開始前にサンドボックス化されたライブラリ プロセスに転送されます。
::PtrAfter() サンドボックス化された API 関数呼び出しが行われた後に、それがポイントしているオブジェクトのメモリを同期します。 つまり、ポイントされた変数のリモートメモリは、呼び出し完了にホストコード プロセスメモリに転送されます。
::PtrBoth() ::PtrBefore()::PtrAfter() の機能を組み合わせたものです。

SAPI ポインタのドキュメントについては、こちらをご覧ください。

SAPI 構造体

テンプレート ::sapi::v::Struct は、var_struct.h に記載されています。これは、既存の構造をラップするために使用できるコンストラクタを提供します。SAPI 構造体には、サンドボックス化されたライブラリ呼び出しに使用できる ::sapi::v::Ptr オブジェクトを取得するための、SAPI ポインタで説明されているすべてのメソッドが用意されています。

以下のコード スニペットは、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 内のアドレスを指します。そのため、ホストコードからアクセスできるようになる前に、Sandboxee のデータを転送する必要があります。

SAPI 配列

テンプレート ::sapi::v::Arrayvar_array.h に記述されています。これには 2 つのコンストラクタがあります。1 つは既存の要素配列をラップするために使用できるもので、もう 1 つは配列を動的に作成するためのものです。

次のコード スニペット(sum の例から取得)は、このオブジェクトに所有されていない配列をラップするコンストラクタを使用しています。

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::v::Ptr オブジェクトを取得するための、SAPI ポインタで説明されているすべてのメソッドを備えています。