Introducción
Como se explica en la página Descripción general, el código del host realiza llamadas a RPC a la biblioteca en zona de pruebas. El aislamiento en zona de pruebas genera una separación de memoria entre los procesos, por lo que el código del host no puede acceder directamente a la memoria en la biblioteca aislada en zona de pruebas.
Para asegurarse de que el código del host pueda acceder a variables y bloques de memoria en un proceso remoto, y para simplificar la implementación del código de lógica principal, SAPI proporciona un conjunto integral de clases de C++. Sin embargo, en muchos casos, también podrás usar tipos C nativos.
La necesidad de los tipos especiales (tipos de SAPI) surge cuando se pasan punteros a tipos simples y bloques de memoria (estructuras, arrays).
Por ejemplo, cuando se llama a una función que toma un puntero, el puntero debe convertirse en un puntero correspondiente dentro de la memoria de la biblioteca en zona de pruebas.
En el siguiente fragmento de código, se visualiza esta situación. En lugar de un array de tres números enteros, se crea un objeto ::sapi::v::Array<int>
que luego se puede pasar en la llamada a la API de la biblioteca en zona de pruebas:
int arr[3] = {1, 2, 3};
sapi::v::Array<int> sarr(arr, ABSL_ARRAYSIZE(arr));
Para obtener una descripción general completa de todos los tipos de SAPI disponibles, revisa los archivos de encabezado var_*.h
en el código fuente del proyecto de SAPI. Estos archivos de encabezado proporcionan clases y plantillas que representan varios tipos de datos, p.ej.:
::sapi::v::UChar
representa caracteres sin signo conocidos.::sapi::v::Array<int>
representa un array de números enteros.
Tipos de SAPI
En esta sección, se presentan tres tipos de SAPI que se suelen ver en el código del host.
Punteros de la SAPI
Si una función que se debe ejecutar en un entorno de pruebas requiere pasar un puntero, este puntero se debe obtener de uno de los métodos PtrXXX()
que se indican a continuación. Estos métodos se implementan en las clases de variables de la SAPI.
Tipos de puntero | |
---|---|
::PtrNone() |
No sincroniza la memoria subyacente entre el proceso de código del host y el proceso de la biblioteca en zona de pruebas cuando se pasa a una función de la API en zona de pruebas. |
::PtrBefore() |
Sincroniza la memoria del objeto al que apunta antes de que se realice la llamada a la función de la API en zona de pruebas. Esto significa que la memoria local de la variable apuntada se transferirá al proceso de la biblioteca en zona de pruebas antes de que se inicie la llamada. |
::PtrAfter() |
Sincroniza la memoria del objeto al que apunta después de que se realiza la llamada a la función de la API en zona de pruebas. Esto significa que la memoria remota de la variable apuntada se transferirá a la memoria del proceso de Host Code después de que se complete la llamada. |
::PtrBoth() |
Combina la funcionalidad de ::PtrBefore() y ::PtrAfter() . |
Puedes encontrar la documentación de los punteros de la SAPI aquí.
Struct de la SAPI
La plantilla ::sapi::v::Struct
se documenta en var_struct.h y proporciona un constructor que se puede usar para encapsular estructuras existentes. La struct SAPI proporciona todos los métodos descritos en Punteros de SAPI para obtener un objeto ::sapi::v::Ptr
que se puede usar para llamadas a bibliotecas en zona de pruebas.
En el siguiente fragmento de código, se muestra una estructura que se inicia y, luego, se pasa a una llamada de función en zona de pruebas en el ejemplo de 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));
…
Si tu estructura existente contiene punteros, estos apuntarán a direcciones en Sandboxee. En consecuencia, deberás transferir los datos de Sandboxee antes de que sean accesibles para el código del host.
Arrays de la SAPI
La plantilla ::sapi::v::Array
se documenta en var_array.h. Proporciona dos constructores, uno que se puede usar para encapsular arrays existentes de elementos y otro para crear un array de forma dinámica.
En este fragmento de código (tomado del ejemplo de suma), se muestra el uso del constructor que encapsula un array que no es propiedad de este objeto:
int arr[10];
sapi::v::Array<int> iarr(arr, ABSL_ARRAYSIZE(arr));
En este fragmento de código, se muestra un ejemplo del constructor que se usa para crear un array de forma dinámica:
sapi::v::Array<uint8_t> buffer(PNG_IMAGE_SIZE(*image.mutable_data()));
El array de SAPI proporciona todos los métodos que se describen en Punteros de SAPI para obtener un objeto ::sapi::v::Ptr
que se puede usar para llamadas a bibliotecas en zona de pruebas.