# Variables Guide

## Introduction

As explained on the [Overview](https://developers.google.com/code-sandboxing/sandboxed-api) page, the Host
Code makes RPC calls to the Sandboxed Library. Sandboxing results in a memory
separation between the processes, and thus the Host Code cannot directly access
memory in the Sandboxed Library.

In order to make sure that the Host Code can access variables and memory blocks
in a remote process and to make the implementation of the main logic code
simpler, SAPI provides a comprehensive set of C++ classes. However, in many
cases you will also be able to use native C-types.

The need for the special types (SAPI Types) arises when passing pointers to
simple types and memory blocks (structures, arrays).

For example, when calling a function taking a pointer, the pointer must be
converted into a corresponding pointer inside the Sandboxed Library's memory.
The below code snippet visualises this scenario. Instead of an array of three
integers, a `::sapi::v::Array<int>` object is created which can then be passed
in the Sandboxed Library's API call:

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

For a comprehensive overview of all available SAPI Types, review the `var_*.h`
header files in the [SAPI project source
code](https://github.com/google/sandboxed-api/tree/master/sandboxed_api). These
header files provide classes and templates representing various types of data,
e.g.:

- `::sapi::v::UChar` represents well-known unsigned chars
- `::sapi::v::Array<int>` represents an array of integers

## SAPI Types

This section introduces three SAPI Types that are commonly seen in Host Code.

### SAPI Pointers

If a function to be sandboxed requires passing a pointer, this pointer should be
obtained from one of the `PtrXXX()` methods below. These methods are implemented
by the SAPI variable classes.

| Pointer Types ||
|---|---|
| `::PtrNone()` | Doesn't synchronize the underlying memory between the Host Code process and the Sandboxed Library process when passed to a sandboxed API function. |
| `::PtrBefore()` | Synchronizes the memory of the object it points to **before** the sandboxed API function call takes place. This means the local memory of the pointed variable will be transferred to the Sandboxed Library process before the call is initiated. |
| `::PtrAfter()` | Synchronizes the memory of the object it points to **after** the sandboxed API function call takes place. This means the remote memory of the pointed variable will be transferred to the Host Code process memory **after** the call has been completed. |
| `::PtrBoth()` | Combines the functionality of `::PtrBefore()` and `::PtrAfter()`. |

The documentation for SAPI pointers can be found
[here](https://github.com/google/sandboxed-api/blob/main/sandboxed_api/var_pointable.h).

### SAPI Struct

The template `::sapi::v::Struct` is documented in
[var_struct.h](https://github.com/google/sandboxed-api/blob/main/sandboxed_api/var_struct.h).
It provides a constructor that can be used to wrap existing structures. SAPI
Struct provides all methods outlined in [SAPI Pointers](https://developers.google.com/code-sandboxing/sandboxed-api/variables#sapi_pointers) to
obtain a `::sapi::v::Ptr` object that can be used for sandboxed library calls.

The code snippet below shows a structure being initiated and then passed to a
sandboxed function call in the [zlib
example](https://github.com/google/sandboxed-api/blob/main/sandboxed_api/examples/zlib/main_zlib.cc):

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

If your existing struct contains pointers, then those pointers will point to
addresses in the Sandboxee. In consequence, you will have to transfer Sandboxee
data before it becomes accessible to the Host Code.

### SAPI Arrays

The template `::sapi::v::Array` is documented in
[var_array.h](https://github.com/google/sandboxed-api/blob/main/sandboxed_api/var_array.h).
It provides two constructors, one that can be used to wrap existing arrays of
elements, and another one to dynamically create an array.

This code snippet (taken from the [sum
example](https://developers.google.com/code-sandboxing/sandboxed-api/examples#sum)) shows the use of the
constructor that wraps around an array which is not owned by this object:

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

This code snippet shows an example of the constructor used to dynamically create
an array:

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

SAPI Array provides all methods outlined in [SAPI Pointers](https://developers.google.com/code-sandboxing/sandboxed-api/variables#sapi_pointers) to
obtain a `::sapi::v::Ptr` object that can be used for sandboxed library calls.