mirror of
https://github.com/google/sandboxed-api.git
synced 2024-03-22 13:11:30 +08:00
Merge branch 'main' into c-blosc
This commit is contained in:
commit
c93dae9519
53
.github/workflows/fedora-cmake.yml
vendored
53
.github/workflows/fedora-cmake.yml
vendored
|
@ -13,36 +13,55 @@ jobs:
|
||||||
include:
|
include:
|
||||||
- container: fedora:35
|
- container: fedora:35
|
||||||
compiler: gcc # GCC 11
|
compiler: gcc # GCC 11
|
||||||
ignore-errors: false
|
ignore-errors: true # Stack trace test fails on Fedora (issue #118)
|
||||||
# TODO(cblichmann): Add clang-13 build to matrix (currently fails)
|
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
continue-on-error: ${{ matrix.ignore-errors }}
|
continue-on-error: ${{ matrix.ignore-errors }}
|
||||||
|
|
||||||
container:
|
env:
|
||||||
image: ${{ matrix.container }}
|
RUN_CMD: docker exec --tty ${{matrix.compiler}}-build-container
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v2
|
||||||
|
|
||||||
|
- name: Prepare container
|
||||||
|
# Note: For the sandbox tests to work, we need a privileged, unconfined
|
||||||
|
# container that retains its capabilities.
|
||||||
|
run: |
|
||||||
|
docker run --name ${{matrix.compiler}}-build-container \
|
||||||
|
--tty \
|
||||||
|
--privileged \
|
||||||
|
--cap-add ALL \
|
||||||
|
--security-opt apparmor:unconfined \
|
||||||
|
-v $GITHUB_WORKSPACE:$GITHUB_WORKSPACE \
|
||||||
|
-e TERM=dumb \
|
||||||
|
-e BUILD_TYPE \
|
||||||
|
-e GITHUB_WORKSPACE \
|
||||||
|
-d ${{matrix.container}} \
|
||||||
|
sleep infinity
|
||||||
|
|
||||||
- name: Install build tools
|
- name: Install build tools
|
||||||
run: |
|
run: |
|
||||||
dnf update -y
|
$RUN_CMD dnf update -y --quiet
|
||||||
dnf install -y git make automake patch glibc-static libstdc++-static \
|
$RUN_CMD dnf install -y --quiet git make automake patch glibc-static \
|
||||||
cmake ninja-build python3 python3-pip clang-devel libcap-devel
|
libstdc++-static cmake ninja-build python3 python3-pip clang-devel \
|
||||||
|
libcap-devel
|
||||||
- name: Install/configure Clang compiler toolchain
|
|
||||||
if: matrix.compiler == 'clang'
|
|
||||||
run: |
|
|
||||||
echo "CXX=clang++" >> $GITHUB_ENV
|
|
||||||
echo "CC=clang" >> $GITHUB_ENV
|
|
||||||
|
|
||||||
- name: Create Build Environment
|
- name: Create Build Environment
|
||||||
run: |
|
run: |
|
||||||
pip3 install absl-py clang
|
$RUN_CMD pip3 install --progress-bar=off absl-py clang
|
||||||
cmake -E make_directory $GITHUB_WORKSPACE/build
|
$RUN_CMD cmake -E make_directory $GITHUB_WORKSPACE/build
|
||||||
|
|
||||||
- name: Configure CMake
|
- name: Configure CMake
|
||||||
run: cmake $GITHUB_WORKSPACE -G Ninja -DCMAKE_BUILD_TYPE=$BUILD_TYPE
|
run: |
|
||||||
|
$RUN_CMD cmake -S $GITHUB_WORKSPACE -B $GITHUB_WORKSPACE/build \
|
||||||
|
-G Ninja -DCMAKE_BUILD_TYPE=$BUILD_TYPE
|
||||||
|
|
||||||
- name: Build
|
- name: Build
|
||||||
run: cmake --build $GITHUB_WORKSPACE --config $BUILD_TYPE
|
run: |
|
||||||
|
$RUN_CMD cmake --build $GITHUB_WORKSPACE/build --config $BUILD_TYPE
|
||||||
|
|
||||||
|
- name: Test
|
||||||
|
run: |
|
||||||
|
$RUN_CMD ctest --test-dir $GITHUB_WORKSPACE/build -C $BUILD_TYPE \
|
||||||
|
--output-on-failure \
|
||||||
|
-R SapiTest
|
||||||
|
|
18
.github/workflows/ubuntu-cmake.yml
vendored
18
.github/workflows/ubuntu-cmake.yml
vendored
|
@ -62,17 +62,17 @@ jobs:
|
||||||
- name: Create Build Environment
|
- name: Create Build Environment
|
||||||
run: |
|
run: |
|
||||||
pip3 install absl-py clang
|
pip3 install absl-py clang
|
||||||
cmake -E make_directory ${{runner.workspace}}/build
|
cmake -E make_directory $GITHUB_WORKSPACE/build
|
||||||
|
|
||||||
- name: Configure CMake
|
- name: Configure CMake
|
||||||
working-directory: ${{runner.workspace}}/build
|
run: |
|
||||||
run: cmake $GITHUB_WORKSPACE -G Ninja -DCMAKE_BUILD_TYPE=$BUILD_TYPE
|
cmake $GITHUB_WORKSPACE -G Ninja -DCMAKE_BUILD_TYPE=$BUILD_TYPE
|
||||||
|
|
||||||
- name: Build
|
- name: Build
|
||||||
working-directory: ${{runner.workspace}}/build
|
run: |
|
||||||
run: cmake --build . --config $BUILD_TYPE
|
cmake --build $GITHUB_WORKSPACE --config $BUILD_TYPE
|
||||||
|
|
||||||
# TODO(cblichmann): Before enabling this, make sure all OSS tests pass
|
- name: Test
|
||||||
#- name: Test
|
run: |
|
||||||
# working-directory: ${{runner.workspace}}/build
|
ctest $GITHUB_WORKSPACE -C $BUILD_TYPE --output-on-failure \
|
||||||
# run: ctest -C $BUILD_TYPE
|
-R SapiTest
|
||||||
|
|
3
.gitmodules
vendored
3
.gitmodules
vendored
|
@ -4,9 +4,6 @@
|
||||||
[submodule "oss-internship-2020/openjpeg/openjpeg"]
|
[submodule "oss-internship-2020/openjpeg/openjpeg"]
|
||||||
path = oss-internship-2020/openjpeg/openjpeg
|
path = oss-internship-2020/openjpeg/openjpeg
|
||||||
url = https://github.com/uclouvain/openjpeg.git
|
url = https://github.com/uclouvain/openjpeg.git
|
||||||
[submodule "oss-internship-2020/pffft/master"]
|
|
||||||
path = oss-internship-2020/pffft/master
|
|
||||||
url = https://bitbucket.org/jpommier/pffft/src/master/
|
|
||||||
[submodule "oss-internship-2020/gdal/gdal"]
|
[submodule "oss-internship-2020/gdal/gdal"]
|
||||||
path = oss-internship-2020/gdal/gdal
|
path = oss-internship-2020/gdal/gdal
|
||||||
url = https://github.com/OSGeo/gdal/
|
url = https://github.com/OSGeo/gdal/
|
||||||
|
|
|
@ -100,8 +100,7 @@ function(add_sapi_library)
|
||||||
list(APPEND _sapi_exported_funcs "LINKER:--export-dynamic-symbol,${func}")
|
list(APPEND _sapi_exported_funcs "LINKER:--export-dynamic-symbol,${func}")
|
||||||
endforeach()
|
endforeach()
|
||||||
if(NOT _sapi_exported_funcs)
|
if(NOT _sapi_exported_funcs)
|
||||||
set(_sapi_exported_funcs LINKER:--whole-archive
|
set(_sapi_exported_funcs LINKER:--allow-multiple-definition)
|
||||||
LINKER:--allow-multiple-definition)
|
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# The sandboxed binary
|
# The sandboxed binary
|
||||||
|
@ -112,7 +111,7 @@ function(add_sapi_library)
|
||||||
add_executable("${_sapi_bin}" "${_sapi_force_cxx_linkage}")
|
add_executable("${_sapi_bin}" "${_sapi_force_cxx_linkage}")
|
||||||
target_link_libraries("${_sapi_bin}" PRIVATE
|
target_link_libraries("${_sapi_bin}" PRIVATE
|
||||||
-fuse-ld=gold
|
-fuse-ld=gold
|
||||||
"${_sapi_LIBRARY}"
|
-Wl,--whole-archive "${_sapi_LIBRARY}" -Wl,--no-whole-archive
|
||||||
sapi::client
|
sapi::client
|
||||||
${CMAKE_DL_LIBS}
|
${CMAKE_DL_LIBS}
|
||||||
)
|
)
|
||||||
|
|
|
@ -14,7 +14,12 @@
|
||||||
|
|
||||||
# Append to this list whenever a new sandboxed library is added to `contrib/`.
|
# Append to this list whenever a new sandboxed library is added to `contrib/`.
|
||||||
set(SAPI_CONTRIB_SANDBOXES
|
set(SAPI_CONTRIB_SANDBOXES
|
||||||
|
hunspell
|
||||||
jsonnet
|
jsonnet
|
||||||
|
libidn2
|
||||||
|
pffft
|
||||||
|
turbojpeg
|
||||||
|
zopfli
|
||||||
zstd
|
zstd
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -5,12 +5,16 @@ libraries.
|
||||||
|
|
||||||
## Projects Sandboxed
|
## Projects Sandboxed
|
||||||
|
|
||||||
Directory | Project | Home Page | Integration
|
Directory | Project | Home Page | Integration
|
||||||
----------- | --------------------------------------------------------------- | -------------------------------------------------------------------- | -----------
|
------------ | ----------------------------------------------------------------- | ------------------------------------------------------------------------------------ | -----------
|
||||||
`c-blosc/` | c-blosc A blocking, shuffling and loss-less compression library | [github.com/Blosc/c-blosc](https://github.com/Blosc/c-blosc) | CMake
|
`c-blosc/` | c-blosc - A blocking, shuffling and loss-less compression library | [github.com/Blosc/c-blosc](https://github.com/Blosc/c-blosc) | CMake
|
||||||
`jsonnet/` | Jsonnet - The Data Templating Language | [github.com/google/jsonnet](https://github.com/google/jsonnet) | CMake
|
`hunspell/` | Hunspell - The most popular spellchecking library | [github.com/hunspell/hunspell](https://github.com/hunspell/hunspell) | CMake
|
||||||
`hunspell/` | Hunspell - The most popular spellchecking library | [github.com/hunspell/hunspell](https://github.com/hunspell/hunspell) | CMake
|
`jsonnet/` | Jsonnet - The Data Templating Language | [github.com/google/jsonnet](https://github.com/google/jsonnet) | CMake
|
||||||
`zstd/` | Zstandard - Fast real-time compression algorithm | [github.com/facebook/zstd](https://github.com/facebook/zstd) | CMake
|
`pffft/` | PFFFT - a pretty fast Fourier Transform | [bitbucket.org/jpommier/pffft.git](https://bitbucket.org/jpommier/pffft.git) | CMake
|
||||||
|
`zopfli` | Zopfli - Compression Algorithm | [github.com/google/zopfli](https://github.com/google/zopfli) | CMake
|
||||||
|
`zstd/` | Zstandard - Fast real-time compression algorithm | [github.com/facebook/zstd](https://github.com/facebook/zstd) | CMake
|
||||||
|
`libidn2/` | libidn2 - GNU IDN library | [www.gnu.org/software/libidn/#libidn2](https://www.gnu.org/software/libidn/#libidn2) | CMake
|
||||||
|
`turbojpeg/` | High-level JPEG library | [libjpeg-turbo.org/About/TurboJPEG](https://libjpeg-turbo.org/About/TurboJPEG) | CMake
|
||||||
|
|
||||||
## Projects Shipping with Sandboxed API Sandboxes
|
## Projects Shipping with Sandboxed API Sandboxes
|
||||||
|
|
||||||
|
|
|
@ -21,15 +21,14 @@ set(CMAKE_CXX_STANDARD_REQUIRED True)
|
||||||
|
|
||||||
set(SAPI_ROOT "" CACHE PATH "Path to the Sandboxed API source tree")
|
set(SAPI_ROOT "" CACHE PATH "Path to the Sandboxed API source tree")
|
||||||
|
|
||||||
add_subdirectory(
|
if(NOT TARGET sapi::sapi)
|
||||||
"${SAPI_ROOT}"
|
set(SAPI_ROOT "../.." CACHE PATH "Path to the Sandboxed API source tree")
|
||||||
"${CMAKE_BINARY_DIR}/sandboxed-api-build"
|
add_subdirectory("${SAPI_ROOT}"
|
||||||
EXCLUDE_FROM_ALL
|
"${CMAKE_BINARY_DIR}/sandboxed-api-build"
|
||||||
)
|
EXCLUDE_FROM_ALL)
|
||||||
|
endif()
|
||||||
FetchContent_Declare(
|
|
||||||
libhunspell
|
|
||||||
|
|
||||||
|
FetchContent_Declare(libhunspell
|
||||||
GIT_REPOSITORY https://github.com/hunspell/hunspell.git
|
GIT_REPOSITORY https://github.com/hunspell/hunspell.git
|
||||||
GIT_TAG 31e6d6323026a3bef12c5912ce032d88bfef2091
|
GIT_TAG 31e6d6323026a3bef12c5912ce032d88bfef2091
|
||||||
)
|
)
|
||||||
|
@ -44,13 +43,23 @@ if(NOT libhunspell_POPULATED)
|
||||||
if(NOT _sapi_CONFIG_STATUS STREQUAL "${libhunspell_CONFIG_STATUS}")
|
if(NOT _sapi_CONFIG_STATUS STREQUAL "${libhunspell_CONFIG_STATUS}")
|
||||||
message("-- Configuring libhunspell...")
|
message("-- Configuring libhunspell...")
|
||||||
execute_process(
|
execute_process(
|
||||||
COMMAND autoreconf -vfi
|
COMMAND autoreconf -i
|
||||||
COMMAND ./configure --disable-dependency-tracking
|
|
||||||
WORKING_DIRECTORY "${libhunspell_SOURCE_DIR}"
|
WORKING_DIRECTORY "${libhunspell_SOURCE_DIR}"
|
||||||
RESULT_VARIABLE libhunspell_config_result
|
RESULT_VARIABLE _sapi_libhunspell_autoreconf_result
|
||||||
)
|
)
|
||||||
if(NOT libhunspell_config_result EQUAL "0")
|
if(NOT _sapi_libhunspell_autoreconf_result EQUAL "0")
|
||||||
message(FATAL_ERROR "Configuration for libhunspell failed")
|
message(FATAL_ERROR "Configuration for libhunspell failed: "
|
||||||
|
"${_sapi_libhunspell_autoreconf_result}")
|
||||||
|
endif()
|
||||||
|
execute_process(
|
||||||
|
COMMAND ./configure --disable-dependency-tracking
|
||||||
|
--quiet
|
||||||
|
WORKING_DIRECTORY "${libhunspell_SOURCE_DIR}"
|
||||||
|
RESULT_VARIABLE _sapi_libhunspell_config_result
|
||||||
|
)
|
||||||
|
if(NOT _sapi_libhunspell_config_result EQUAL "0")
|
||||||
|
message(FATAL_ERROR "Configuration for libhunspell failed: "
|
||||||
|
"${_sapi_libhunspell_config_result}")
|
||||||
endif()
|
endif()
|
||||||
file(SHA256 "${libhunspell_SOURCE_DIR}/config.status" _sapi_CONFIG_STATUS)
|
file(SHA256 "${libhunspell_SOURCE_DIR}/config.status" _sapi_CONFIG_STATUS)
|
||||||
set(libhunspell_CONFIG_STATUS "${_sapi_CONFIG_STATUS}" CACHE INTERNAL "")
|
set(libhunspell_CONFIG_STATUS "${_sapi_CONFIG_STATUS}" CACHE INTERNAL "")
|
||||||
|
@ -58,37 +67,37 @@ if(NOT libhunspell_POPULATED)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
add_library(hunspell STATIC
|
add_library(hunspell STATIC
|
||||||
${libhunspell_SOURCE_DIR}/src/hunspell/affentry.cxx
|
"${libhunspell_SOURCE_DIR}/src/hunspell/affentry.cxx"
|
||||||
${libhunspell_SOURCE_DIR}/src/hunspell/affentry.hxx
|
"${libhunspell_SOURCE_DIR}/src/hunspell/affentry.hxx"
|
||||||
${libhunspell_SOURCE_DIR}/src/hunspell/affixmgr.cxx
|
"${libhunspell_SOURCE_DIR}/src/hunspell/affixmgr.cxx"
|
||||||
${libhunspell_SOURCE_DIR}/src/hunspell/affixmgr.hxx
|
"${libhunspell_SOURCE_DIR}/src/hunspell/affixmgr.hxx"
|
||||||
${libhunspell_SOURCE_DIR}/src/hunspell/atypes.hxx
|
"${libhunspell_SOURCE_DIR}/src/hunspell/atypes.hxx"
|
||||||
${libhunspell_SOURCE_DIR}/src/hunspell/baseaffix.hxx
|
"${libhunspell_SOURCE_DIR}/src/hunspell/baseaffix.hxx"
|
||||||
${libhunspell_SOURCE_DIR}/src/hunspell/csutil.cxx
|
"${libhunspell_SOURCE_DIR}/src/hunspell/csutil.cxx"
|
||||||
${libhunspell_SOURCE_DIR}/src/hunspell/csutil.hxx
|
"${libhunspell_SOURCE_DIR}/src/hunspell/csutil.hxx"
|
||||||
${libhunspell_SOURCE_DIR}/src/hunspell/filemgr.cxx
|
"${libhunspell_SOURCE_DIR}/src/hunspell/filemgr.cxx"
|
||||||
${libhunspell_SOURCE_DIR}/src/hunspell/filemgr.hxx
|
"${libhunspell_SOURCE_DIR}/src/hunspell/filemgr.hxx"
|
||||||
${libhunspell_SOURCE_DIR}/src/hunspell/hashmgr.cxx
|
"${libhunspell_SOURCE_DIR}/src/hunspell/hashmgr.cxx"
|
||||||
${libhunspell_SOURCE_DIR}/src/hunspell/hashmgr.hxx
|
"${libhunspell_SOURCE_DIR}/src/hunspell/hashmgr.hxx"
|
||||||
${libhunspell_SOURCE_DIR}/src/hunspell/htypes.hxx
|
"${libhunspell_SOURCE_DIR}/src/hunspell/htypes.hxx"
|
||||||
${libhunspell_SOURCE_DIR}/src/hunspell/hunspell.cxx
|
"${libhunspell_SOURCE_DIR}/src/hunspell/hunspell.cxx"
|
||||||
${libhunspell_SOURCE_DIR}/src/hunspell/hunspell.h
|
"${libhunspell_SOURCE_DIR}/src/hunspell/hunspell.h"
|
||||||
${libhunspell_SOURCE_DIR}/src/hunspell/hunspell.hxx
|
"${libhunspell_SOURCE_DIR}/src/hunspell/hunspell.hxx"
|
||||||
${libhunspell_SOURCE_DIR}/src/hunspell/hunzip.cxx
|
"${libhunspell_SOURCE_DIR}/src/hunspell/hunzip.cxx"
|
||||||
${libhunspell_SOURCE_DIR}/src/hunspell/hunzip.hxx
|
"${libhunspell_SOURCE_DIR}/src/hunspell/hunzip.hxx"
|
||||||
${libhunspell_SOURCE_DIR}/src/hunspell/langnum.hxx
|
"${libhunspell_SOURCE_DIR}/src/hunspell/langnum.hxx"
|
||||||
${libhunspell_SOURCE_DIR}/src/hunspell/phonet.cxx
|
"${libhunspell_SOURCE_DIR}/src/hunspell/phonet.cxx"
|
||||||
${libhunspell_SOURCE_DIR}/src/hunspell/phonet.hxx
|
"${libhunspell_SOURCE_DIR}/src/hunspell/phonet.hxx"
|
||||||
${libhunspell_SOURCE_DIR}/src/hunspell/replist.cxx
|
"${libhunspell_SOURCE_DIR}/src/hunspell/replist.cxx"
|
||||||
${libhunspell_SOURCE_DIR}/src/hunspell/replist.hxx
|
"${libhunspell_SOURCE_DIR}/src/hunspell/replist.hxx"
|
||||||
${libhunspell_SOURCE_DIR}/src/hunspell/suggestmgr.cxx
|
"${libhunspell_SOURCE_DIR}/src/hunspell/suggestmgr.cxx"
|
||||||
${libhunspell_SOURCE_DIR}/src/hunspell/suggestmgr.hxx
|
"${libhunspell_SOURCE_DIR}/src/hunspell/suggestmgr.hxx"
|
||||||
${libhunspell_SOURCE_DIR}/src/hunspell/utf_info.hxx
|
"${libhunspell_SOURCE_DIR}/src/hunspell/utf_info.hxx"
|
||||||
${libhunspell_SOURCE_DIR}/src/hunspell/w_char.hxx
|
"${libhunspell_SOURCE_DIR}/src/hunspell/w_char.hxx"
|
||||||
)
|
)
|
||||||
|
|
||||||
target_include_directories(hunspell PUBLIC
|
target_include_directories(hunspell PUBLIC
|
||||||
${libhunspell_SOURCE_DIR}/src/hunspell
|
"${libhunspell_SOURCE_DIR}/src/hunspell"
|
||||||
)
|
)
|
||||||
|
|
||||||
set(libhunspell_INCLUDE_DIR "${libhunspell_SOURCE_DIR}/src/hunspell")
|
set(libhunspell_INCLUDE_DIR "${libhunspell_SOURCE_DIR}/src/hunspell")
|
||||||
|
@ -112,7 +121,7 @@ add_sapi_library(
|
||||||
|
|
||||||
Hunspell_free_list
|
Hunspell_free_list
|
||||||
INPUTS
|
INPUTS
|
||||||
${libhunspell_INCLUDE_DIR}/hunspell.h
|
"${libhunspell_INCLUDE_DIR}/hunspell.h"
|
||||||
|
|
||||||
LIBRARY hunspell
|
LIBRARY hunspell
|
||||||
LIBRARY_NAME Hunspell
|
LIBRARY_NAME Hunspell
|
||||||
|
|
|
@ -35,6 +35,7 @@ class HunspellSapiSandbox : public HunspellSandbox {
|
||||||
.AllowOpen()
|
.AllowOpen()
|
||||||
.AllowRead()
|
.AllowRead()
|
||||||
.AllowWrite()
|
.AllowWrite()
|
||||||
|
.AllowGetPIDs()
|
||||||
.AllowSystemMalloc()
|
.AllowSystemMalloc()
|
||||||
.AllowExit()
|
.AllowExit()
|
||||||
.AllowSyscalls({
|
.AllowSyscalls({
|
||||||
|
|
|
@ -1,6 +1,9 @@
|
||||||
# Jsonnet Sandboxed API
|
# Jsonnet Sandboxed API
|
||||||
|
|
||||||
This library provides a sandboxed version of the
|
This library was sandboxed as part of Google's summer 2020 internship program
|
||||||
|
([blog post](https://security.googleblog.com/2020/12/improving-open-source-security-during.html)).
|
||||||
|
|
||||||
|
This directory contains a sandbox for the
|
||||||
[Jsonnet](https://github.com/google/jsonnet) library.
|
[Jsonnet](https://github.com/google/jsonnet) library.
|
||||||
|
|
||||||
## How to use from an existing Project
|
## How to use from an existing Project
|
||||||
|
|
|
@ -12,50 +12,48 @@
|
||||||
# See the License for the specific language governing permissions and
|
# See the License for the specific language governing permissions and
|
||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
|
|
||||||
cmake_minimum_required(VERSION 3.10)
|
cmake_minimum_required(VERSION 3.13..3.22)
|
||||||
|
|
||||||
project(pffft CXX C)
|
project(pffft CXX C)
|
||||||
|
|
||||||
set(CMAKE_CXX_STANDARD 17)
|
set(CMAKE_CXX_STANDARD 17)
|
||||||
set(CMAKE_CXX_STANDARD_REQUIRED True)
|
set(CMAKE_CXX_STANDARD_REQUIRED True)
|
||||||
|
|
||||||
|
if(NOT TARGET sapi::sapi)
|
||||||
|
set(SAPI_ROOT "../.." CACHE PATH "Path to the Sandboxed API source tree")
|
||||||
|
add_subdirectory("${SAPI_ROOT}"
|
||||||
|
"${CMAKE_BINARY_DIR}/sandboxed-api-build"
|
||||||
|
EXCLUDE_FROM_ALL)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
include(CheckLibraryExists)
|
||||||
|
|
||||||
|
FetchContent_Declare(pffft
|
||||||
|
GIT_REPOSITORY https://bitbucket.org/jpommier/pffft.git
|
||||||
|
GIT_TAG 988259a41d1522047a9420e6265a6ba8289c1654 # 2021-12-02
|
||||||
|
)
|
||||||
|
FetchContent_MakeAvailable(pffft)
|
||||||
|
|
||||||
add_library(pffft STATIC
|
add_library(pffft STATIC
|
||||||
master/pffft.c
|
"${pffft_SOURCE_DIR}/pffft.c"
|
||||||
master/pffft.h
|
"${pffft_SOURCE_DIR}/pffft.h"
|
||||||
master/fftpack.c
|
"${pffft_SOURCE_DIR}/fftpack.c"
|
||||||
master/fftpack.h
|
"${pffft_SOURCE_DIR}/fftpack.h"
|
||||||
)
|
)
|
||||||
|
|
||||||
add_executable(pffft_main
|
add_executable(pffft_main
|
||||||
master/test_pffft.c
|
"${pffft_SOURCE_DIR}/test_pffft.c"
|
||||||
)
|
)
|
||||||
|
|
||||||
target_link_libraries(pffft_main PRIVATE
|
target_link_libraries(pffft_main PRIVATE
|
||||||
pffft
|
pffft
|
||||||
)
|
)
|
||||||
|
|
||||||
set(MATH_LIBS "")
|
check_library_exists(m sin "" _sapi_HAVE_LIBM)
|
||||||
include(CheckLibraryExists)
|
if(_sapi_HAVE_LIBM)
|
||||||
check_library_exists(m sin "" LIBM)
|
target_link_libraries(pffft PUBLIC
|
||||||
if(LIBM)
|
m
|
||||||
list(APPEND MATH_LIBS "m")
|
)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
target_link_libraries(pffft PUBLIC ${MATH_LIBS})
|
|
||||||
|
|
||||||
# Adding dependencies
|
|
||||||
set(SAPI_ROOT "../.." CACHE PATH "Path to the Sandboxed API source tree")
|
|
||||||
# Then configure:
|
|
||||||
# mkdir -p build && cd build
|
|
||||||
# cmake .. -G Ninja -DSAPI_ROOT=$HOME/sapi_root
|
|
||||||
|
|
||||||
set(SAPI_ENABLE_EXAMPLES OFF CACHE BOOL "")
|
|
||||||
set(SAPI_ENABLE_TESTS OFF CACHE BOOL "")
|
|
||||||
add_subdirectory("${SAPI_ROOT}"
|
|
||||||
"${CMAKE_BINARY_DIR}/sandboxed-api-build"
|
|
||||||
# Omit this to have the full Sandboxed API in IDE
|
|
||||||
EXCLUDE_FROM_ALL)
|
|
||||||
|
|
||||||
add_sapi_library(pffft_sapi
|
add_sapi_library(pffft_sapi
|
||||||
FUNCTIONS pffft_new_setup
|
FUNCTIONS pffft_new_setup
|
||||||
pffft_destroy_setup
|
pffft_destroy_setup
|
||||||
|
@ -83,22 +81,23 @@ add_sapi_library(pffft_sapi
|
||||||
sinti
|
sinti
|
||||||
sint
|
sint
|
||||||
|
|
||||||
INPUTS master/pffft.h master/fftpack.h
|
INPUTS "${pffft_SOURCE_DIR}/pffft.h"
|
||||||
|
"${pffft_SOURCE_DIR}/fftpack.h"
|
||||||
LIBRARY pffft
|
LIBRARY pffft
|
||||||
LIBRARY_NAME Pffft
|
LIBRARY_NAME Pffft
|
||||||
|
|
||||||
NAMESPACE ""
|
NAMESPACE ""
|
||||||
)
|
)
|
||||||
|
add_library(sapi_contrib::pffft ALIAS pffft_sapi)
|
||||||
target_include_directories(pffft_sapi INTERFACE
|
target_include_directories(pffft_sapi INTERFACE
|
||||||
"${PROJECT_BINARY_DIR}"
|
"${PROJECT_BINARY_DIR}"
|
||||||
|
"${SAPI_SOURCE_DIR}"
|
||||||
)
|
)
|
||||||
|
|
||||||
add_executable(pffft_sandboxed
|
add_executable(pffft_sandboxed
|
||||||
main_pffft_sandboxed.cc
|
main_pffft_sandboxed.cc
|
||||||
)
|
)
|
||||||
|
|
||||||
target_link_libraries(pffft_sandboxed PRIVATE
|
target_link_libraries(pffft_sandboxed PRIVATE
|
||||||
pffft_sapi
|
sapi_contrib::pffft
|
||||||
sapi::sapi
|
sapi::sapi
|
||||||
)
|
)
|
|
@ -1,16 +1,35 @@
|
||||||
# Sandboxing PFFFT library
|
# Sandboxing PFFFT library
|
||||||
|
|
||||||
|
This library was sandboxed as part of Google's summer 2020 internship program
|
||||||
|
([blog post](https://security.googleblog.com/2020/12/improving-open-source-security-during.html)).
|
||||||
|
|
||||||
Build System: CMake
|
Build System: CMake
|
||||||
OS: Linux
|
OS: Linux
|
||||||
|
|
||||||
### Check out the PFFFT library & CMake set up
|
### How to use from an existing Project
|
||||||
```
|
|
||||||
git submodule update --init --recursive
|
|
||||||
|
|
||||||
mkdir -p build && cd build
|
If your project does not include Sandboxed API as a dependency yet, add the
|
||||||
cmake .. -G Ninja -DPFFFT_ROOT_DIR=$PWD
|
following lines to the main `CMakeLists.txt`:
|
||||||
ninjas
|
|
||||||
|
```cmake
|
||||||
|
include(FetchContent)
|
||||||
|
|
||||||
|
FetchContent_Declare(sandboxed-api
|
||||||
|
GIT_REPOSITORY https://github.com/google/sandboxed-api
|
||||||
|
GIT_TAG main # Or pin a specific commit/tag
|
||||||
|
)
|
||||||
|
FetchContent_MakeAvailable(sandboxed-api) # CMake 3.14 or higher
|
||||||
|
|
||||||
|
add_sapi_subdirectory(contrib/pffft)
|
||||||
```
|
```
|
||||||
|
|
||||||
|
The `add_sapi_subdirectory()` macro sets up the source and binary directories
|
||||||
|
for the sandboxed jsonnet targets.
|
||||||
|
|
||||||
|
Afterwards your project's code can link to `sapi_contrib::pffft` and use the
|
||||||
|
generated header `pffft_sapi.sapi.h`. An example sandbox policy can be found
|
||||||
|
in `main_pffft_sandboxed.cc`.
|
||||||
|
|
||||||
### For testing:
|
### For testing:
|
||||||
`cd build`, then `./pffft_sandboxed`
|
`cd build`, then `./pffft_sandboxed`
|
||||||
|
|
||||||
|
@ -19,14 +38,15 @@ display custom info with
|
||||||
`./pffft_sandboxed --logtostderr`
|
`./pffft_sandboxed --logtostderr`
|
||||||
|
|
||||||
## ***About the project***
|
## ***About the project***
|
||||||
*PFFFT library is concerned with 1D Fast-Fourier Transformations finding a
|
|
||||||
|
PFFFT library is concerned with 1D Fast-Fourier Transformations finding a
|
||||||
compromise between accuracy and speed. It deals with real and complex
|
compromise between accuracy and speed. It deals with real and complex
|
||||||
vectors, both cases being illustrated in the testing part (`test_pffft.c`
|
vectors, both cases being illustrated in the testing part (`test_pffft.c`
|
||||||
for initially and original version, `main_pffft_sandboxed.cc` for our
|
for initially and original version, `main_pffft_sandboxed.cc` for our
|
||||||
currently implemented sandboxed version).
|
currently implemented sandboxed version).
|
||||||
The original files can be found at: https://bitbucket.org/jpommier/pffft/src.*
|
The original files can be found at: https://bitbucket.org/jpommier/pffft/src.*
|
||||||
|
|
||||||
*The purpose of sandboxing is to limit the permissions and capabilities of
|
The purpose of sandboxing is to limit the permissions and capabilities of
|
||||||
library’s methods, in order to secure the usage of them.
|
library’s methods, in order to secure the usage of them.
|
||||||
After obtaining the sandbox, the functions will be called through an
|
After obtaining the sandbox, the functions will be called through an
|
||||||
Sandbox API (being called `api` in the current test) and so, the
|
Sandbox API (being called `api` in the current test) and so, the
|
||||||
|
@ -50,10 +70,12 @@ Without using this type of argument when running, the output format is set
|
||||||
by default.*
|
by default.*
|
||||||
|
|
||||||
#### CMake observations resume:
|
#### CMake observations resume:
|
||||||
|
|
||||||
* linking pffft and fftpack (which contains necessary functions for pffft)
|
* linking pffft and fftpack (which contains necessary functions for pffft)
|
||||||
* set math library
|
* set math library
|
||||||
|
|
||||||
#### Sandboxed main observations resume:
|
#### Sandboxed main observations resume:
|
||||||
|
|
||||||
* containing two testing parts (fft / pffft benchmarks)
|
* containing two testing parts (fft / pffft benchmarks)
|
||||||
* showing the performance of the transformations implies
|
* showing the performance of the transformations implies
|
||||||
testing them through various FFT dimenstions.
|
testing them through various FFT dimenstions.
|
|
@ -12,7 +12,7 @@
|
||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
#include <gflags/gflags.h>
|
#include <syscall.h>
|
||||||
|
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
|
@ -21,6 +21,7 @@
|
||||||
#include <ctime>
|
#include <ctime>
|
||||||
|
|
||||||
#include <glog/logging.h>
|
#include <glog/logging.h>
|
||||||
|
#include "gflags/gflags.h"
|
||||||
#include "pffft_sapi.sapi.h" // NOLINT(build/include)
|
#include "pffft_sapi.sapi.h" // NOLINT(build/include)
|
||||||
#include "sandboxed_api/util/flag.h"
|
#include "sandboxed_api/util/flag.h"
|
||||||
#include "sandboxed_api/vars.h"
|
#include "sandboxed_api/vars.h"
|
44
contrib/turbojpeg/CMakeLists.txt
Normal file
44
contrib/turbojpeg/CMakeLists.txt
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
# Copyright 2022 Google LLC
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
# you may not use this file except in compliance with the License.
|
||||||
|
# You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
|
||||||
|
cmake_minimum_required(VERSION 3.13..3.22)
|
||||||
|
project(turbojpeg-sapi CXX C)
|
||||||
|
|
||||||
|
set(CMAKE_CXX_STANDARD 17)
|
||||||
|
set(CMAKE_CXX_STANDARD_REQUIRED True)
|
||||||
|
|
||||||
|
if(NOT TARGET sapi::sapi)
|
||||||
|
set(SAPI_ROOT "../.." CACHE PATH "Path to the Sandboxed API source tree")
|
||||||
|
add_subdirectory("${SAPI_ROOT}"
|
||||||
|
"${CMAKE_BINARY_DIR}/sandboxed-api-build"
|
||||||
|
EXCLUDE_FROM_ALL)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
find_package(PkgConfig REQUIRED)
|
||||||
|
pkg_check_modules(TURBOJPEG REQUIRED IMPORTED_TARGET libturbojpeg)
|
||||||
|
|
||||||
|
add_sapi_library(turbojpeg_sapi
|
||||||
|
INPUTS "${TURBOJPEG_INCLUDEDIR}/turbojpeg.h"
|
||||||
|
LIBRARY turbojpeg
|
||||||
|
LIBRARY_NAME TurboJPEG
|
||||||
|
NAMESPACE "turbojpeg_sapi"
|
||||||
|
)
|
||||||
|
add_library(sapi_contrib::turbojpeg ALIAS turbojpeg_sapi)
|
||||||
|
target_include_directories(turbojpeg_sapi INTERFACE
|
||||||
|
"${PROJECT_BINARY_DIR}"
|
||||||
|
)
|
||||||
|
|
||||||
|
if(SAPI_ENABLE_TESTS)
|
||||||
|
add_subdirectory(tests)
|
||||||
|
endif()
|
26
contrib/turbojpeg/tests/CMakeLists.txt
Normal file
26
contrib/turbojpeg/tests/CMakeLists.txt
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
# Copyright 2022 Google LLC
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
# you may not use this file except in compliance with the License.
|
||||||
|
# You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
|
||||||
|
include(GoogleTest)
|
||||||
|
|
||||||
|
add_executable(turbojpeg_sapi_test turbojpeg_sapi_test.cc)
|
||||||
|
|
||||||
|
target_link_libraries(turbojpeg_sapi_test PRIVATE
|
||||||
|
turbojpeg_sapi
|
||||||
|
sapi::base
|
||||||
|
gtest
|
||||||
|
gmock
|
||||||
|
)
|
||||||
|
|
||||||
|
gtest_discover_tests(turbojpeg_sapi_test PROPERTIES ENVIRONMENT "TEST_FILES_DIR=${PROJECT_SOURCE_DIR}/tests")
|
BIN
contrib/turbojpeg/tests/sample.jpeg
Normal file
BIN
contrib/turbojpeg/tests/sample.jpeg
Normal file
Binary file not shown.
After Width: | Height: | Size: 257 B |
BIN
contrib/turbojpeg/tests/sample.rgb
Normal file
BIN
contrib/turbojpeg/tests/sample.rgb
Normal file
Binary file not shown.
181
contrib/turbojpeg/tests/turbojpeg_sapi_test.cc
Normal file
181
contrib/turbojpeg/tests/turbojpeg_sapi_test.cc
Normal file
|
@ -0,0 +1,181 @@
|
||||||
|
// Copyright 2022 Google LLC
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
#define _GNU_SOURCE 1
|
||||||
|
#include "../turbojpeg_sapi.h" // NOLINT(build/include)
|
||||||
|
|
||||||
|
#include <turbojpeg.h>
|
||||||
|
|
||||||
|
#include <cerrno>
|
||||||
|
#include <cstdlib>
|
||||||
|
#include <fstream>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
#include "gflags/gflags.h"
|
||||||
|
#include "glog/logging.h"
|
||||||
|
#include "gmock/gmock.h"
|
||||||
|
#include "gtest/gtest.h"
|
||||||
|
#include "sandboxed_api/testing.h"
|
||||||
|
#include "sandboxed_api/util/fileops.h"
|
||||||
|
#include "sandboxed_api/util/path.h"
|
||||||
|
#include "sandboxed_api/util/status_matchers.h"
|
||||||
|
#include "turbojpeg_sapi.sapi.h" // NOLINT(build/include)
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
using ::sapi::IsOk;
|
||||||
|
using ::testing::Eq;
|
||||||
|
using ::testing::Gt;
|
||||||
|
using ::testing::Not;
|
||||||
|
using ::testing::NotNull;
|
||||||
|
using ::testing::StrEq;
|
||||||
|
|
||||||
|
class TurboJpegSapiSandboxTest : public testing::Test {
|
||||||
|
protected:
|
||||||
|
static void SetUpTestSuite() {
|
||||||
|
ASSERT_THAT(getenv("TEST_FILES_DIR"), NotNull());
|
||||||
|
sandbox_ = new TurboJpegSapiSandbox();
|
||||||
|
ASSERT_THAT(sandbox_->Init(), IsOk());
|
||||||
|
api_ = new turbojpeg_sapi::TurboJPEGApi(sandbox_);
|
||||||
|
}
|
||||||
|
static void TearDownTestSuite() {
|
||||||
|
delete api_;
|
||||||
|
delete sandbox_;
|
||||||
|
}
|
||||||
|
|
||||||
|
static std::string GetTurboJpegErrorStr(sapi::v::Ptr* handle) {
|
||||||
|
auto errmsg_ptr = api_->tjGetErrorStr2(handle);
|
||||||
|
if (!errmsg_ptr.ok()) return "Error getting error message";
|
||||||
|
auto errmsg =
|
||||||
|
sandbox_->GetCString(sapi::v::RemotePtr(errmsg_ptr.value()), 256);
|
||||||
|
if (!errmsg.ok()) return "Error getting error message";
|
||||||
|
return errmsg.value();
|
||||||
|
}
|
||||||
|
static turbojpeg_sapi::TurboJPEGApi* api_;
|
||||||
|
static TurboJpegSapiSandbox* sandbox_;
|
||||||
|
};
|
||||||
|
|
||||||
|
turbojpeg_sapi::TurboJPEGApi* TurboJpegSapiSandboxTest::api_;
|
||||||
|
TurboJpegSapiSandbox* TurboJpegSapiSandboxTest::sandbox_;
|
||||||
|
|
||||||
|
std::string GetTestFilePath(const std::string& filename) {
|
||||||
|
return sapi::file::JoinPath(getenv("TEST_FILES_DIR"), filename);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::streamsize GetStreamSize(std::ifstream& stream) {
|
||||||
|
stream.seekg(0, std::ios_base::end);
|
||||||
|
std::streamsize ssize = stream.tellg();
|
||||||
|
stream.seekg(0, std::ios_base::beg);
|
||||||
|
|
||||||
|
return ssize;
|
||||||
|
}
|
||||||
|
|
||||||
|
absl::StatusOr<std::vector<uint8_t>> ReadFile(const std::string& in_file,
|
||||||
|
size_t expected_size = SIZE_MAX) {
|
||||||
|
std::ifstream f(GetTestFilePath(in_file));
|
||||||
|
if (!f.is_open()) {
|
||||||
|
return absl::UnavailableError("File could not be opened");
|
||||||
|
}
|
||||||
|
std::streamsize ssize = GetStreamSize(f);
|
||||||
|
if (expected_size != SIZE_MAX && ssize != expected_size) {
|
||||||
|
return absl::UnavailableError("Incorrect size of file");
|
||||||
|
}
|
||||||
|
std::vector<uint8_t> inbuf(ssize);
|
||||||
|
f.read(reinterpret_cast<char*>(inbuf.data()), ssize);
|
||||||
|
if (ssize != f.gcount()) {
|
||||||
|
return absl::UnavailableError("Premature end of file");
|
||||||
|
}
|
||||||
|
if (f.fail() || f.eof()) {
|
||||||
|
return absl::UnavailableError("Error reading file");
|
||||||
|
}
|
||||||
|
return inbuf;
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(TurboJpegSapiSandboxTest, Compressor) {
|
||||||
|
absl::StatusOr<void*> compression_handle_raw = api_->tjInitCompress();
|
||||||
|
ASSERT_THAT(compression_handle_raw, IsOk());
|
||||||
|
ASSERT_THAT(compression_handle_raw.value(), NotNull());
|
||||||
|
sapi::v::RemotePtr compression_handle{compression_handle_raw.value()};
|
||||||
|
auto result = ReadFile("sample.rgb", 12 * 67 * 3);
|
||||||
|
ASSERT_THAT(result, IsOk());
|
||||||
|
sapi::v::Array array(result->data(), result->size());
|
||||||
|
|
||||||
|
sapi::v::GenericPtr buffer;
|
||||||
|
{
|
||||||
|
sapi::v::ULong length{0};
|
||||||
|
auto result = api_->tjCompress2(&compression_handle, array.PtrBefore(), 12,
|
||||||
|
36, 67, TJPF_RGB, buffer.PtrAfter(),
|
||||||
|
length.PtrBoth(), TJSAMP_444, 10, 0);
|
||||||
|
ASSERT_THAT(result, IsOk());
|
||||||
|
ASSERT_THAT(result.value(), Eq(0))
|
||||||
|
<< "Error from sandboxee: "
|
||||||
|
<< GetTurboJpegErrorStr(&compression_handle);
|
||||||
|
ASSERT_TRUE(buffer.GetValue());
|
||||||
|
ASSERT_TRUE(buffer.GetRemote());
|
||||||
|
ASSERT_THAT(length.GetValue(), Gt(0));
|
||||||
|
}
|
||||||
|
auto value = buffer.GetValue();
|
||||||
|
|
||||||
|
auto destroy_result = api_->tjDestroy(&compression_handle);
|
||||||
|
ASSERT_THAT(destroy_result, IsOk());
|
||||||
|
ASSERT_THAT(destroy_result.value(), Eq(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(TurboJpegSapiSandboxTest, Decompressor) {
|
||||||
|
absl::StatusOr<void*> decompression_handle_raw = api_->tjInitDecompress();
|
||||||
|
ASSERT_THAT(decompression_handle_raw, IsOk());
|
||||||
|
ASSERT_THAT(decompression_handle_raw.value(), NotNull());
|
||||||
|
sapi::v::RemotePtr decompression_handle{decompression_handle_raw.value()};
|
||||||
|
auto result = ReadFile("sample.jpeg");
|
||||||
|
ASSERT_THAT(result, IsOk());
|
||||||
|
sapi::v::Array array(result->data(), result->size());
|
||||||
|
|
||||||
|
sapi::v::Int width{0};
|
||||||
|
sapi::v::Int height{0};
|
||||||
|
sapi::v::Int subsamp{0};
|
||||||
|
sapi::v::Int colorspace{0};
|
||||||
|
auto decompress_result = api_->tjDecompressHeader3(
|
||||||
|
&decompression_handle, array.PtrBefore(), result->size(),
|
||||||
|
width.PtrAfter(), height.PtrAfter(), subsamp.PtrAfter(),
|
||||||
|
colorspace.PtrAfter());
|
||||||
|
ASSERT_THAT(decompress_result, IsOk());
|
||||||
|
ASSERT_THAT(decompress_result.value(), Eq(0))
|
||||||
|
<< "Error from sandboxee: "
|
||||||
|
<< GetTurboJpegErrorStr(&decompression_handle);
|
||||||
|
|
||||||
|
ASSERT_THAT(width.GetValue(), Eq(67));
|
||||||
|
ASSERT_THAT(height.GetValue(), Eq(12));
|
||||||
|
ASSERT_THAT(subsamp.GetValue(), Eq(TJSAMP_GRAY));
|
||||||
|
ASSERT_THAT(colorspace.GetValue(), Eq(TJCS_GRAY));
|
||||||
|
|
||||||
|
auto arr = sapi::v::Array<unsigned char>(12 * 67 * 3);
|
||||||
|
decompress_result = api_->tjDecompress2(
|
||||||
|
&decompression_handle, array.PtrBefore(), result->size(), arr.PtrAfter(),
|
||||||
|
12, 36, 67, TJCS_RGB, 0);
|
||||||
|
ASSERT_THAT(decompress_result, IsOk());
|
||||||
|
EXPECT_THAT(decompress_result.value(), Eq(0))
|
||||||
|
<< "Error from sandboxee: "
|
||||||
|
<< GetTurboJpegErrorStr(&decompression_handle);
|
||||||
|
|
||||||
|
decompress_result = api_->tjDestroy(&decompression_handle);
|
||||||
|
ASSERT_THAT(decompress_result, IsOk());
|
||||||
|
ASSERT_THAT(decompress_result.value(), Eq(0));
|
||||||
|
}
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
int main(int argc, char* argv[]) {
|
||||||
|
::google::InitGoogleLogging(program_invocation_short_name);
|
||||||
|
::testing::InitGoogleTest(&argc, argv);
|
||||||
|
return RUN_ALL_TESTS();
|
||||||
|
}
|
44
contrib/turbojpeg/turbojpeg_sapi.h
Normal file
44
contrib/turbojpeg/turbojpeg_sapi.h
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
// Copyright 2022 Google LLC
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
#ifndef CONTRIB_TURBOJPEG_TURBOJPEG_SAPI_H_
|
||||||
|
#define CONTRIB_TURBOJPEG_TURBOJPEG_SAPI_H_
|
||||||
|
|
||||||
|
#include <syscall.h>
|
||||||
|
|
||||||
|
#include "sandboxed_api/util/fileops.h"
|
||||||
|
#include "turbojpeg_sapi.sapi.h" // NOLINT(build/include)
|
||||||
|
class TurboJpegSapiSandbox : public turbojpeg_sapi::TurboJPEGSandbox {
|
||||||
|
public:
|
||||||
|
std::unique_ptr<sandbox2::Policy> ModifyPolicy(
|
||||||
|
sandbox2::PolicyBuilder*) override {
|
||||||
|
return sandbox2::PolicyBuilder()
|
||||||
|
.AllowSystemMalloc()
|
||||||
|
.AllowRead()
|
||||||
|
.AllowStat()
|
||||||
|
.AllowWrite()
|
||||||
|
.AllowExit()
|
||||||
|
.AllowSyscalls({
|
||||||
|
__NR_futex,
|
||||||
|
__NR_close,
|
||||||
|
__NR_lseek,
|
||||||
|
__NR_getpid,
|
||||||
|
__NR_clock_gettime,
|
||||||
|
})
|
||||||
|
.AllowLlvmSanitizers()
|
||||||
|
.BuildOrDie();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // CONTRIB_TURBOJPEG_TURBOJPEG_SAPI_H_
|
68
contrib/zopfli/CMakeLists.txt
Normal file
68
contrib/zopfli/CMakeLists.txt
Normal file
|
@ -0,0 +1,68 @@
|
||||||
|
# Copyright 2022 Google LLC
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
# you may not use this file except in compliance with the License.
|
||||||
|
# You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
|
||||||
|
cmake_minimum_required(VERSION 3.13..3.22)
|
||||||
|
|
||||||
|
project(sapi_zopfli CXX)
|
||||||
|
|
||||||
|
set(CMAKE_CXX_STANDARD 17)
|
||||||
|
set(CMAKE_CXX_STANDARD_REQUIRED True)
|
||||||
|
|
||||||
|
if(NOT TARGET sapi::sapi)
|
||||||
|
set(SAPI_ROOT "../.." CACHE PATH "Path to the Sandboxed API source tree")
|
||||||
|
add_subdirectory("${SAPI_ROOT}"
|
||||||
|
"${CMAKE_BINARY_DIR}/sandboxed-api-build"
|
||||||
|
EXCLUDE_FROM_ALL)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
FetchContent_Declare(zopfli
|
||||||
|
GIT_REPOSITORY https://github.com/google/zopfli.git
|
||||||
|
GIT_TAG 831773bc28e318b91a3255fa12c9fcde1606058b
|
||||||
|
)
|
||||||
|
FetchContent_MakeAvailable(zopfli)
|
||||||
|
|
||||||
|
add_sapi_library(
|
||||||
|
sapi_zopfli
|
||||||
|
|
||||||
|
FUNCTIONS
|
||||||
|
ZopfliInitOptions
|
||||||
|
|
||||||
|
ZopfliCompress
|
||||||
|
|
||||||
|
ZopfliDeflate
|
||||||
|
ZopfliZlibCompress
|
||||||
|
ZopfliGzipCompress
|
||||||
|
|
||||||
|
INPUTS
|
||||||
|
${zopfli_SOURCE_DIR}/src/zopfli/deflate.h
|
||||||
|
${zopfli_SOURCE_DIR}/src/zopfli/gzip_container.h
|
||||||
|
${zopfli_SOURCE_DIR}/src/zopfli/zlib_container.h
|
||||||
|
|
||||||
|
LIBRARY Zopfli::libzopfli
|
||||||
|
LIBRARY_NAME Zopfli
|
||||||
|
NAMESPACE ""
|
||||||
|
)
|
||||||
|
add_library(sapi_contrib::zopfli ALIAS sapi_zopfli)
|
||||||
|
target_include_directories(sapi_zopfli INTERFACE
|
||||||
|
"${PROJECT_BINARY_DIR}"
|
||||||
|
"${SAPI_SOURCE_DIR}"
|
||||||
|
)
|
||||||
|
|
||||||
|
if(SAPI_ENABLE_EXAMPLES)
|
||||||
|
add_subdirectory(example)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(SAPI_ENABLE_TESTS)
|
||||||
|
add_subdirectory(test)
|
||||||
|
endif()
|
23
contrib/zopfli/example/CMakeLists.txt
Normal file
23
contrib/zopfli/example/CMakeLists.txt
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
# Copyright 2022 Google LLC
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
# you may not use this file except in compliance with the License.
|
||||||
|
# You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
|
||||||
|
add_executable(sapi_minizopfli
|
||||||
|
main.cc
|
||||||
|
../utils/utils_zopfli.cc
|
||||||
|
)
|
||||||
|
target_link_libraries(sapi_minizopfli PRIVATE
|
||||||
|
sapi_contrib::zopfli
|
||||||
|
sapi::sapi
|
||||||
|
absl::flags_parse
|
||||||
|
)
|
73
contrib/zopfli/example/main.cc
Normal file
73
contrib/zopfli/example/main.cc
Normal file
|
@ -0,0 +1,73 @@
|
||||||
|
// Copyright 2022 Google LLC
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include <fstream>
|
||||||
|
#include <iostream>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include "sandboxed_api/util/flag.h"
|
||||||
|
#include "absl/flags/parse.h"
|
||||||
|
#include "contrib/zopfli/sandboxed.h"
|
||||||
|
#include "contrib/zopfli/utils/utils_zopfli.h"
|
||||||
|
|
||||||
|
ABSL_FLAG(bool, zlib, false, "zlib compression");
|
||||||
|
ABSL_FLAG(bool, gzip, false, "gzip compression");
|
||||||
|
|
||||||
|
int main(int argc, char* argv[]) {
|
||||||
|
std::string prog_name(argv[0]);
|
||||||
|
google::InitGoogleLogging(argv[0]);
|
||||||
|
std::vector<char*> args = absl::ParseCommandLine(argc, argv);
|
||||||
|
|
||||||
|
if (args.size() != 3) {
|
||||||
|
std::cerr << "Usage:\n " << prog_name << " INPUT OUTPUT\n";
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::ifstream infile(args[1], std::ios::binary);
|
||||||
|
if (!infile.is_open()) {
|
||||||
|
std::cerr << "Unable to open " << args[1] << std::endl;
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
std::ofstream outfile(args[2], std::ios::binary);
|
||||||
|
if (!outfile.is_open()) {
|
||||||
|
std::cerr << "Unable to open " << args[2] << std::endl;
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
ZopfliSapiSandbox sandbox;
|
||||||
|
if (!sandbox.Init().ok()) {
|
||||||
|
std::cerr << "Unable to start sandbox\n";
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
ZopfliApi api(&sandbox);
|
||||||
|
|
||||||
|
ZopfliFormat format = ZOPFLI_FORMAT_DEFLATE;
|
||||||
|
if (absl::GetFlag(FLAGS_zlib)) {
|
||||||
|
format = ZOPFLI_FORMAT_ZLIB;
|
||||||
|
} else if (absl::GetFlag(FLAGS_gzip)) {
|
||||||
|
format = ZOPFLI_FORMAT_GZIP;
|
||||||
|
}
|
||||||
|
|
||||||
|
absl::Status status = Compress(api, infile, outfile, format);
|
||||||
|
if (!status.ok()) {
|
||||||
|
std::cerr << "Unable to compress file.\n";
|
||||||
|
std::cerr << status << std::endl;
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return EXIT_SUCCESS;
|
||||||
|
}
|
BIN
contrib/zopfli/files/binary
Normal file
BIN
contrib/zopfli/files/binary
Normal file
Binary file not shown.
2000
contrib/zopfli/files/text
Normal file
2000
contrib/zopfli/files/text
Normal file
File diff suppressed because it is too large
Load Diff
49
contrib/zopfli/sandboxed.h
Normal file
49
contrib/zopfli/sandboxed.h
Normal file
|
@ -0,0 +1,49 @@
|
||||||
|
// Copyright 2022 Google LLC
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
#ifndef CONTRIB_ZOPFLI_SANDBOXED_
|
||||||
|
#define CONTRIB_ZOPFLI_SANDBOXED_
|
||||||
|
|
||||||
|
#include <libgen.h>
|
||||||
|
#include <syscall.h>
|
||||||
|
|
||||||
|
#include <cerrno>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
#include "sapi_zopfli.sapi.h" // NOLINT(build/include)
|
||||||
|
|
||||||
|
class ZopfliSapiSandbox : public ZopfliSandbox {
|
||||||
|
public:
|
||||||
|
std::unique_ptr<sandbox2::Policy> ModifyPolicy(
|
||||||
|
sandbox2::PolicyBuilder *) override {
|
||||||
|
return sandbox2::PolicyBuilder()
|
||||||
|
.AllowStaticStartup()
|
||||||
|
.AllowWrite()
|
||||||
|
.AllowExit()
|
||||||
|
.AllowMmap()
|
||||||
|
.AllowSystemMalloc()
|
||||||
|
.AllowSyscalls({
|
||||||
|
__NR_sysinfo,
|
||||||
|
})
|
||||||
|
#ifdef __NR_open
|
||||||
|
.BlockSyscallWithErrno(__NR_open, ENOENT)
|
||||||
|
#endif
|
||||||
|
#ifdef __NR_openat
|
||||||
|
.BlockSyscallWithErrno(__NR_openat, ENOENT)
|
||||||
|
#endif
|
||||||
|
.BuildOrDie();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // CONTRIB_ZOPFLI_SANDBOXED_
|
28
contrib/zopfli/test/CMakeLists.txt
Normal file
28
contrib/zopfli/test/CMakeLists.txt
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
# Copyright 2022 Google LLC
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
# you may not use this file except in compliance with the License.
|
||||||
|
# You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
|
||||||
|
include(GoogleTest)
|
||||||
|
|
||||||
|
add_executable(sapi_zopfli_test
|
||||||
|
zopfli_test.cc
|
||||||
|
../utils/utils_zopfli.cc
|
||||||
|
)
|
||||||
|
target_link_libraries(sapi_zopfli_test PRIVATE
|
||||||
|
sapi_contrib::zopfli
|
||||||
|
sapi::temp_file
|
||||||
|
sapi::test_main
|
||||||
|
)
|
||||||
|
gtest_discover_tests(sapi_zopfli_test PROPERTIES
|
||||||
|
ENVIRONMENT "TEST_FILES_DIR=${PROJECT_SOURCE_DIR}/files"
|
||||||
|
)
|
98
contrib/zopfli/test/zopfli_test.cc
Normal file
98
contrib/zopfli/test/zopfli_test.cc
Normal file
|
@ -0,0 +1,98 @@
|
||||||
|
// Copyright 2022 Google LLC
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
#include <fstream>
|
||||||
|
|
||||||
|
#include "contrib/zopfli/sandboxed.h"
|
||||||
|
#include "contrib/zopfli/utils/utils_zopfli.h"
|
||||||
|
#include "sandboxed_api/util/path.h"
|
||||||
|
#include "sandboxed_api/util/status_matchers.h"
|
||||||
|
#include "sandboxed_api/util/temp_file.h"
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
using ::sapi::IsOk;
|
||||||
|
using ::testing::IsEmpty;
|
||||||
|
using ::testing::Not;
|
||||||
|
|
||||||
|
std::string GetTestFilePath(const std::string& filename) {
|
||||||
|
return sapi::file::JoinPath(getenv("TEST_FILES_DIR"), filename);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string GetTemporaryFile(const std::string& filename) {
|
||||||
|
absl::StatusOr<std::string> tmp_file =
|
||||||
|
sapi::CreateNamedTempFileAndClose(filename);
|
||||||
|
if (!tmp_file.ok()) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
return sapi::file::JoinPath(sapi::file_util::fileops::GetCWD(), *tmp_file);
|
||||||
|
}
|
||||||
|
|
||||||
|
class TestText : public testing::TestWithParam<ZopfliFormat> {};
|
||||||
|
|
||||||
|
class TestBinary : public testing::TestWithParam<ZopfliFormat> {};
|
||||||
|
|
||||||
|
TEST_P(TestText, Compress) {
|
||||||
|
ZopfliSapiSandbox sandbox;
|
||||||
|
ASSERT_THAT(sandbox.Init(), IsOk()) << "Couldn't initialize Sandboxed API";
|
||||||
|
ZopfliApi api(&sandbox);
|
||||||
|
|
||||||
|
std::string infile_s = GetTestFilePath("text");
|
||||||
|
std::string outfile_s = GetTemporaryFile("text.out");
|
||||||
|
ASSERT_THAT(outfile_s, Not(IsEmpty()));
|
||||||
|
|
||||||
|
std::ifstream infile(infile_s, std::ios::binary);
|
||||||
|
ASSERT_TRUE(infile.is_open());
|
||||||
|
|
||||||
|
std::ofstream outfile(outfile_s, std::ios::binary);
|
||||||
|
ASSERT_TRUE(outfile.is_open());
|
||||||
|
|
||||||
|
absl::Status status = Compress(api, infile, outfile, GetParam());
|
||||||
|
ASSERT_THAT(status, IsOk()) << "Unable to compress file";
|
||||||
|
|
||||||
|
ASSERT_LT(outfile.tellp(), infile.tellg());
|
||||||
|
}
|
||||||
|
|
||||||
|
INSTANTIATE_TEST_SUITE_P(SandboxTest, TestText,
|
||||||
|
testing::Values(ZOPFLI_FORMAT_DEFLATE,
|
||||||
|
ZOPFLI_FORMAT_GZIP,
|
||||||
|
ZOPFLI_FORMAT_ZLIB));
|
||||||
|
|
||||||
|
TEST_P(TestBinary, Compress) {
|
||||||
|
ZopfliSapiSandbox sandbox;
|
||||||
|
ASSERT_THAT(sandbox.Init(), IsOk()) << "Couldn't initialize Sandboxed API";
|
||||||
|
ZopfliApi api(&sandbox);
|
||||||
|
|
||||||
|
std::string infile_s = GetTestFilePath("binary");
|
||||||
|
std::string outfile_s = GetTemporaryFile("binary.out");
|
||||||
|
ASSERT_THAT(outfile_s, Not(IsEmpty()));
|
||||||
|
|
||||||
|
std::ifstream infile(infile_s, std::ios::binary);
|
||||||
|
ASSERT_TRUE(infile.is_open());
|
||||||
|
|
||||||
|
std::ofstream outfile(outfile_s, std::ios::binary);
|
||||||
|
ASSERT_TRUE(outfile.is_open());
|
||||||
|
|
||||||
|
absl::Status status = Compress(api, infile, outfile, GetParam());
|
||||||
|
ASSERT_THAT(status, IsOk()) << "Unable to compress file";
|
||||||
|
|
||||||
|
ASSERT_LT(outfile.tellp(), infile.tellg());
|
||||||
|
}
|
||||||
|
|
||||||
|
INSTANTIATE_TEST_SUITE_P(SandboxTest, TestBinary,
|
||||||
|
testing::Values(ZOPFLI_FORMAT_DEFLATE,
|
||||||
|
ZOPFLI_FORMAT_GZIP,
|
||||||
|
ZOPFLI_FORMAT_ZLIB));
|
||||||
|
} // namespace
|
56
contrib/zopfli/utils/utils_zopfli.cc
Normal file
56
contrib/zopfli/utils/utils_zopfli.cc
Normal file
|
@ -0,0 +1,56 @@
|
||||||
|
// Copyright 2022 Google LLC
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
#include "contrib/zopfli/utils/utils_zopfli.h"
|
||||||
|
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include <fstream>
|
||||||
|
|
||||||
|
absl::Status Compress(ZopfliApi& api, std::ifstream& instream,
|
||||||
|
std::ofstream& outstream, ZopfliFormat format) {
|
||||||
|
// Get size of Stream
|
||||||
|
instream.seekg(0, std::ios_base::end);
|
||||||
|
std::streamsize ssize = instream.tellg();
|
||||||
|
instream.seekg(0, std::ios_base::beg);
|
||||||
|
|
||||||
|
// Read data
|
||||||
|
sapi::v::Array<uint8_t> inbuf(ssize);
|
||||||
|
instream.read(reinterpret_cast<char*>(inbuf.GetData()), ssize);
|
||||||
|
if (instream.gcount() != ssize) {
|
||||||
|
return absl::UnavailableError("Unable to read file");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Compress
|
||||||
|
sapi::v::Struct<ZopfliOptions> options;
|
||||||
|
SAPI_RETURN_IF_ERROR(api.ZopfliInitOptions(options.PtrAfter()));
|
||||||
|
|
||||||
|
sapi::v::GenericPtr outptr;
|
||||||
|
sapi::v::IntBase<size_t> outsize(0);
|
||||||
|
|
||||||
|
SAPI_RETURN_IF_ERROR(
|
||||||
|
api.ZopfliCompress(options.PtrBefore(), format, inbuf.PtrBefore(), ssize,
|
||||||
|
outptr.PtrAfter(), outsize.PtrBoth()));
|
||||||
|
|
||||||
|
// Get and save data
|
||||||
|
sapi::v::Array<int8_t> outbuf(outsize.GetValue());
|
||||||
|
outbuf.SetRemote(reinterpret_cast<void*>(outptr.GetValue()));
|
||||||
|
SAPI_RETURN_IF_ERROR(api.GetSandbox()->TransferFromSandboxee(&outbuf));
|
||||||
|
|
||||||
|
outstream.write(reinterpret_cast<char*>(outbuf.GetData()), outbuf.GetSize());
|
||||||
|
if (!outstream.good()) {
|
||||||
|
return absl::UnavailableError("Unable to write file");
|
||||||
|
}
|
||||||
|
return absl::OkStatus();
|
||||||
|
}
|
26
contrib/zopfli/utils/utils_zopfli.h
Normal file
26
contrib/zopfli/utils/utils_zopfli.h
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
// Copyright 2022 Google LLC
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
#ifndef CONTRIB_ZOPFLI_UTILS_UTILS_ZOPFLI_H_
|
||||||
|
#define CONTRIB_ZOPFLI_UTILS_UTILS_ZOPFLI_H_
|
||||||
|
|
||||||
|
#include <fstream>
|
||||||
|
|
||||||
|
#include "absl/status/status.h"
|
||||||
|
#include "contrib/zopfli/sandboxed.h"
|
||||||
|
|
||||||
|
absl::Status Compress(ZopfliApi& api, std::ifstream& instream,
|
||||||
|
std::ofstream& outstream, ZopfliFormat format);
|
||||||
|
|
||||||
|
#endif // CONTRIB_ZOPFLI_UTILS_UTILS_ZOPFLI_H_
|
|
@ -34,6 +34,8 @@ FetchContent_Declare(libzstd
|
||||||
FetchContent_MakeAvailable(libzstd)
|
FetchContent_MakeAvailable(libzstd)
|
||||||
|
|
||||||
set(libzstd_INCLUDE_DIR "${libzstd_SOURCE_DIR}/lib")
|
set(libzstd_INCLUDE_DIR "${libzstd_SOURCE_DIR}/lib")
|
||||||
|
add_subdirectory(wrapper)
|
||||||
|
|
||||||
add_sapi_library(
|
add_sapi_library(
|
||||||
sapi_zstd
|
sapi_zstd
|
||||||
|
|
||||||
|
@ -70,10 +72,16 @@ add_sapi_library(
|
||||||
|
|
||||||
ZSTD_getFrameContentSize
|
ZSTD_getFrameContentSize
|
||||||
|
|
||||||
|
ZSTD_compress_fd
|
||||||
|
ZSTD_compressStream_fd
|
||||||
|
|
||||||
|
ZSTD_decompress_fd
|
||||||
|
ZSTD_decompressStream_fd
|
||||||
INPUTS
|
INPUTS
|
||||||
${libzstd_INCLUDE_DIR}/zstd.h
|
${libzstd_INCLUDE_DIR}/zstd.h
|
||||||
|
wrapper/wrapper_zstd.h
|
||||||
|
|
||||||
LIBRARY libzstd_static
|
LIBRARY wrapper_zstd
|
||||||
LIBRARY_NAME Zstd
|
LIBRARY_NAME Zstd
|
||||||
NAMESPACE ""
|
NAMESPACE ""
|
||||||
)
|
)
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
|
#include <fcntl.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
|
@ -25,10 +26,56 @@
|
||||||
#include "contrib/zstd/sandboxed.h"
|
#include "contrib/zstd/sandboxed.h"
|
||||||
#include "contrib/zstd/utils/utils_zstd.h"
|
#include "contrib/zstd/utils/utils_zstd.h"
|
||||||
|
|
||||||
|
ABSL_FLAG(bool, stream, false, "stream data to sandbox");
|
||||||
ABSL_FLAG(bool, decompress, false, "decompress");
|
ABSL_FLAG(bool, decompress, false, "decompress");
|
||||||
ABSL_FLAG(bool, memory_mode, false, "in memory operations");
|
ABSL_FLAG(bool, memory_mode, false, "in memory operations");
|
||||||
ABSL_FLAG(uint32_t, level, 0, "compression level");
|
ABSL_FLAG(uint32_t, level, 0, "compression level");
|
||||||
|
|
||||||
|
absl::Status Stream(ZstdApi& api, std::string infile_s, std::string outfile_s) {
|
||||||
|
std::ifstream infile(infile_s, std::ios::binary);
|
||||||
|
if (!infile.is_open()) {
|
||||||
|
return absl::UnavailableError(absl::StrCat("Unable to open ", infile_s));
|
||||||
|
}
|
||||||
|
std::ofstream outfile(outfile_s, std::ios::binary);
|
||||||
|
if (!outfile.is_open()) {
|
||||||
|
return absl::UnavailableError(absl::StrCat("Unable to open ", outfile_s));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (absl::GetFlag(FLAGS_memory_mode)) {
|
||||||
|
if (absl::GetFlag(FLAGS_decompress)) {
|
||||||
|
return DecompressInMemory(api, infile, outfile);
|
||||||
|
}
|
||||||
|
return CompressInMemory(api, infile, outfile, absl::GetFlag(FLAGS_level));
|
||||||
|
}
|
||||||
|
if (absl::GetFlag(FLAGS_decompress)) {
|
||||||
|
return DecompressStream(api, infile, outfile);
|
||||||
|
}
|
||||||
|
return CompressStream(api, infile, outfile, absl::GetFlag(FLAGS_level));
|
||||||
|
}
|
||||||
|
|
||||||
|
absl::Status FileDescriptor(ZstdApi& api, std::string infile_s,
|
||||||
|
std::string outfile_s) {
|
||||||
|
sapi::v::Fd infd(open(infile_s.c_str(), O_RDONLY));
|
||||||
|
if (infd.GetValue() < 0) {
|
||||||
|
return absl::UnavailableError(absl::StrCat("Unable to open ", infile_s));
|
||||||
|
}
|
||||||
|
sapi::v::Fd outfd(open(outfile_s.c_str(), O_WRONLY | O_CREAT));
|
||||||
|
if (outfd.GetValue() < 0) {
|
||||||
|
return absl::UnavailableError(absl::StrCat("Unable to open ", outfile_s));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (absl::GetFlag(FLAGS_memory_mode)) {
|
||||||
|
if (absl::GetFlag(FLAGS_decompress)) {
|
||||||
|
return DecompressInMemoryFD(api, infd, outfd);
|
||||||
|
}
|
||||||
|
return CompressInMemoryFD(api, infd, outfd, absl::GetFlag(FLAGS_level));
|
||||||
|
}
|
||||||
|
if (absl::GetFlag(FLAGS_decompress)) {
|
||||||
|
return DecompressStreamFD(api, infd, outfd);
|
||||||
|
}
|
||||||
|
return CompressStreamFD(api, infd, outfd, absl::GetFlag(FLAGS_level));
|
||||||
|
}
|
||||||
|
|
||||||
int main(int argc, char* argv[]) {
|
int main(int argc, char* argv[]) {
|
||||||
std::string prog_name(argv[0]);
|
std::string prog_name(argv[0]);
|
||||||
google::InitGoogleLogging(argv[0]);
|
google::InitGoogleLogging(argv[0]);
|
||||||
|
@ -39,17 +86,6 @@ int main(int argc, char* argv[]) {
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::ifstream infile(args[1], std::ios::binary);
|
|
||||||
if (!infile.is_open()) {
|
|
||||||
std::cerr << "Unable to open " << args[1] << std::endl;
|
|
||||||
return EXIT_FAILURE;
|
|
||||||
}
|
|
||||||
std::ofstream outfile(args[2], std::ios::binary);
|
|
||||||
if (!outfile.is_open()) {
|
|
||||||
std::cerr << "Unable to open " << args[2] << std::endl;
|
|
||||||
return EXIT_FAILURE;
|
|
||||||
}
|
|
||||||
|
|
||||||
ZstdSapiSandbox sandbox;
|
ZstdSapiSandbox sandbox;
|
||||||
if (!sandbox.Init().ok()) {
|
if (!sandbox.Init().ok()) {
|
||||||
std::cerr << "Unable to start sandbox\n";
|
std::cerr << "Unable to start sandbox\n";
|
||||||
|
@ -59,16 +95,10 @@ int main(int argc, char* argv[]) {
|
||||||
ZstdApi api(&sandbox);
|
ZstdApi api(&sandbox);
|
||||||
|
|
||||||
absl::Status status;
|
absl::Status status;
|
||||||
if (absl::GetFlag(FLAGS_memory_mode) && absl::GetFlag(FLAGS_decompress)) {
|
if (absl::GetFlag(FLAGS_stream)) {
|
||||||
status = DecompressInMemory(api, infile, outfile);
|
status = Stream(api, argv[1], argv[2]);
|
||||||
} else if (absl::GetFlag(FLAGS_memory_mode) &&
|
|
||||||
!absl::GetFlag(FLAGS_decompress)) {
|
|
||||||
status = CompressInMemory(api, infile, outfile, absl::GetFlag(FLAGS_level));
|
|
||||||
} else if (!absl::GetFlag(FLAGS_memory_mode) &&
|
|
||||||
absl::GetFlag(FLAGS_decompress)) {
|
|
||||||
status = DecompressStream(api, infile, outfile);
|
|
||||||
} else {
|
} else {
|
||||||
status = CompressStream(api, infile, outfile, absl::GetFlag(FLAGS_level));
|
status = FileDescriptor(api, argv[1], argv[2]);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!status.ok()) {
|
if (!status.ok()) {
|
||||||
|
|
|
@ -27,10 +27,12 @@ class ZstdSapiSandbox : public ZstdSandbox {
|
||||||
std::unique_ptr<sandbox2::Policy> ModifyPolicy(
|
std::unique_ptr<sandbox2::Policy> ModifyPolicy(
|
||||||
sandbox2::PolicyBuilder*) override {
|
sandbox2::PolicyBuilder*) override {
|
||||||
return sandbox2::PolicyBuilder()
|
return sandbox2::PolicyBuilder()
|
||||||
|
.AllowDynamicStartup()
|
||||||
.AllowRead()
|
.AllowRead()
|
||||||
.AllowWrite()
|
.AllowWrite()
|
||||||
.AllowSystemMalloc()
|
.AllowSystemMalloc()
|
||||||
.AllowExit()
|
.AllowExit()
|
||||||
|
.AllowSyscalls({__NR_recvmsg})
|
||||||
.BuildOrDie();
|
.BuildOrDie();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -12,6 +12,9 @@
|
||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
|
@ -101,11 +104,10 @@ TEST(SandboxTest, CheckCompressInMemory) {
|
||||||
|
|
||||||
std::string infile_s = GetTestFilePath("text");
|
std::string infile_s = GetTestFilePath("text");
|
||||||
|
|
||||||
absl::StatusOr<std::string> path =
|
SAPI_ASSERT_OK_AND_ASSIGN(std::string path,
|
||||||
sapi::CreateNamedTempFileAndClose("out.zstd");
|
sapi::CreateNamedTempFileAndClose("out.zstd"));
|
||||||
ASSERT_THAT(path, IsOk()) << "Could not create temp output file";
|
|
||||||
std::string outfile_s =
|
std::string outfile_s =
|
||||||
sapi::file::JoinPath(sapi::file_util::fileops::GetCWD(), *path);
|
sapi::file::JoinPath(sapi::file_util::fileops::GetCWD(), path);
|
||||||
|
|
||||||
std::ifstream infile(infile_s, std::ios::binary);
|
std::ifstream infile(infile_s, std::ios::binary);
|
||||||
ASSERT_TRUE(infile.is_open());
|
ASSERT_TRUE(infile.is_open());
|
||||||
|
@ -126,10 +128,10 @@ TEST(SandboxTest, CheckDecompressInMemory) {
|
||||||
|
|
||||||
std::string infile_s = GetTestFilePath("text.blob.zstd");
|
std::string infile_s = GetTestFilePath("text.blob.zstd");
|
||||||
|
|
||||||
absl::StatusOr<std::string> path = sapi::CreateNamedTempFileAndClose("out");
|
SAPI_ASSERT_OK_AND_ASSIGN(std::string path,
|
||||||
ASSERT_THAT(path, IsOk()) << "Could not create temp output file";
|
sapi::CreateNamedTempFileAndClose("out"));
|
||||||
std::string outfile_s =
|
std::string outfile_s =
|
||||||
sapi::file::JoinPath(sapi::file_util::fileops::GetCWD(), *path);
|
sapi::file::JoinPath(sapi::file_util::fileops::GetCWD(), path);
|
||||||
|
|
||||||
std::ifstream infile(infile_s, std::ios::binary);
|
std::ifstream infile(infile_s, std::ios::binary);
|
||||||
ASSERT_TRUE(infile.is_open());
|
ASSERT_TRUE(infile.is_open());
|
||||||
|
@ -153,16 +155,15 @@ TEST(SandboxTest, CheckCompressAndDecompressInMemory) {
|
||||||
|
|
||||||
std::string infile_s = GetTestFilePath("text");
|
std::string infile_s = GetTestFilePath("text");
|
||||||
|
|
||||||
absl::StatusOr<std::string> path_middle =
|
SAPI_ASSERT_OK_AND_ASSIGN(std::string path_middle,
|
||||||
sapi::CreateNamedTempFileAndClose("middle.zstd");
|
sapi::CreateNamedTempFileAndClose("middle.zstd"));
|
||||||
ASSERT_THAT(path_middle, IsOk()) << "Could not create temp output file";
|
|
||||||
std::string middle_s =
|
std::string middle_s =
|
||||||
sapi::file::JoinPath(sapi::file_util::fileops::GetCWD(), *path_middle);
|
sapi::file::JoinPath(sapi::file_util::fileops::GetCWD(), path_middle);
|
||||||
|
|
||||||
absl::StatusOr<std::string> path = sapi::CreateNamedTempFileAndClose("out");
|
SAPI_ASSERT_OK_AND_ASSIGN(std::string path,
|
||||||
ASSERT_THAT(path, IsOk()) << "Could not create temp output file";
|
sapi::CreateNamedTempFileAndClose("out"));
|
||||||
std::string outfile_s =
|
std::string outfile_s =
|
||||||
sapi::file::JoinPath(sapi::file_util::fileops::GetCWD(), *path);
|
sapi::file::JoinPath(sapi::file_util::fileops::GetCWD(), path);
|
||||||
|
|
||||||
std::ifstream infile(infile_s, std::ios::binary);
|
std::ifstream infile(infile_s, std::ios::binary);
|
||||||
ASSERT_TRUE(infile.is_open());
|
ASSERT_TRUE(infile.is_open());
|
||||||
|
@ -193,12 +194,10 @@ TEST(SandboxTest, CheckCompressStream) {
|
||||||
ZstdApi api = ZstdApi(&sandbox);
|
ZstdApi api = ZstdApi(&sandbox);
|
||||||
|
|
||||||
std::string infile_s = GetTestFilePath("text");
|
std::string infile_s = GetTestFilePath("text");
|
||||||
|
SAPI_ASSERT_OK_AND_ASSIGN(std::string path,
|
||||||
absl::StatusOr<std::string> path =
|
sapi::CreateNamedTempFileAndClose("out.zstd"));
|
||||||
sapi::CreateNamedTempFileAndClose("out.zstd");
|
|
||||||
ASSERT_THAT(path, IsOk()) << "Could not create temp output file";
|
|
||||||
std::string outfile_s =
|
std::string outfile_s =
|
||||||
sapi::file::JoinPath(sapi::file_util::fileops::GetCWD(), *path);
|
sapi::file::JoinPath(sapi::file_util::fileops::GetCWD(), path);
|
||||||
|
|
||||||
std::ifstream infile(infile_s, std::ios::binary);
|
std::ifstream infile(infile_s, std::ios::binary);
|
||||||
ASSERT_TRUE(infile.is_open());
|
ASSERT_TRUE(infile.is_open());
|
||||||
|
@ -220,11 +219,10 @@ TEST(SandboxTest, CheckDecompressStream) {
|
||||||
ZstdApi api = ZstdApi(&sandbox);
|
ZstdApi api = ZstdApi(&sandbox);
|
||||||
|
|
||||||
std::string infile_s = GetTestFilePath("text.stream.zstd");
|
std::string infile_s = GetTestFilePath("text.stream.zstd");
|
||||||
|
SAPI_ASSERT_OK_AND_ASSIGN(std::string path,
|
||||||
absl::StatusOr<std::string> path = sapi::CreateNamedTempFileAndClose("out");
|
sapi::CreateNamedTempFileAndClose("out"));
|
||||||
ASSERT_THAT(path, IsOk()) << "Could not create temp output file";
|
|
||||||
std::string outfile_s =
|
std::string outfile_s =
|
||||||
sapi::file::JoinPath(sapi::file_util::fileops::GetCWD(), *path);
|
sapi::file::JoinPath(sapi::file_util::fileops::GetCWD(), path);
|
||||||
|
|
||||||
std::ifstream infile(infile_s, std::ios::binary);
|
std::ifstream infile(infile_s, std::ios::binary);
|
||||||
ASSERT_TRUE(infile.is_open());
|
ASSERT_TRUE(infile.is_open());
|
||||||
|
@ -248,16 +246,15 @@ TEST(SandboxTest, CheckCompressAndDecompressStream) {
|
||||||
|
|
||||||
std::string infile_s = GetTestFilePath("text");
|
std::string infile_s = GetTestFilePath("text");
|
||||||
|
|
||||||
absl::StatusOr<std::string> path_middle =
|
SAPI_ASSERT_OK_AND_ASSIGN(std::string path_middle,
|
||||||
sapi::CreateNamedTempFileAndClose("middle.zstd");
|
sapi::CreateNamedTempFileAndClose("middle.zstd"));
|
||||||
ASSERT_THAT(path_middle, IsOk()) << "Could not create temp output file";
|
|
||||||
std::string middle_s =
|
std::string middle_s =
|
||||||
sapi::file::JoinPath(sapi::file_util::fileops::GetCWD(), *path_middle);
|
sapi::file::JoinPath(sapi::file_util::fileops::GetCWD(), path_middle);
|
||||||
|
|
||||||
absl::StatusOr<std::string> path = sapi::CreateNamedTempFileAndClose("out");
|
SAPI_ASSERT_OK_AND_ASSIGN(std::string path,
|
||||||
ASSERT_THAT(path, IsOk()) << "Could not create temp output file";
|
sapi::CreateNamedTempFileAndClose("out"));
|
||||||
std::string outfile_s =
|
std::string outfile_s =
|
||||||
sapi::file::JoinPath(sapi::file_util::fileops::GetCWD(), *path);
|
sapi::file::JoinPath(sapi::file_util::fileops::GetCWD(), path);
|
||||||
|
|
||||||
std::ifstream infile(infile_s, std::ios::binary);
|
std::ifstream infile(infile_s, std::ios::binary);
|
||||||
ASSERT_TRUE(infile.is_open());
|
ASSERT_TRUE(infile.is_open());
|
||||||
|
@ -278,8 +275,235 @@ TEST(SandboxTest, CheckCompressAndDecompressStream) {
|
||||||
ASSERT_TRUE(outfile.is_open());
|
ASSERT_TRUE(outfile.is_open());
|
||||||
|
|
||||||
status = DecompressStream(api, inmiddle, outfile);
|
status = DecompressStream(api, inmiddle, outfile);
|
||||||
|
ASSERT_THAT(status, IsOk()) << "Unable to decompress";
|
||||||
|
|
||||||
|
ASSERT_TRUE(CompareFiles(infile_s, outfile_s));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(SandboxTest, CheckCompressInMemoryFD) {
|
||||||
|
ZstdSapiSandbox sandbox;
|
||||||
|
ASSERT_THAT(sandbox.Init(), IsOk()) << "Couldn't initialize Sandboxed API";
|
||||||
|
ZstdApi api = ZstdApi(&sandbox);
|
||||||
|
|
||||||
|
std::string infile_s = GetTestFilePath("text");
|
||||||
|
|
||||||
|
SAPI_ASSERT_OK_AND_ASSIGN(std::string path,
|
||||||
|
sapi::CreateNamedTempFileAndClose("out.zstd"));
|
||||||
|
std::string outfile_s =
|
||||||
|
sapi::file::JoinPath(sapi::file_util::fileops::GetCWD(), path);
|
||||||
|
|
||||||
|
sapi::v::Fd infd(open(infile_s.c_str(), O_RDONLY));
|
||||||
|
ASSERT_GE(infd.GetValue(), 0);
|
||||||
|
sapi::v::Fd outfd(open(outfile_s.c_str(), O_WRONLY));
|
||||||
|
ASSERT_GE(outfd.GetValue(), 0);
|
||||||
|
|
||||||
|
absl::Status status = CompressInMemoryFD(api, infd, outfd, 0);
|
||||||
|
ASSERT_THAT(status, IsOk()) << "Unable to compress file in memory";
|
||||||
|
|
||||||
|
off_t inpos = lseek(infd.GetValue(), 0, SEEK_END);
|
||||||
|
EXPECT_GE(inpos, 0);
|
||||||
|
off_t outpos = lseek(outfd.GetValue(), 0, SEEK_END);
|
||||||
|
EXPECT_GE(outpos, 0);
|
||||||
|
|
||||||
|
EXPECT_LT(outpos, inpos);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(SandboxTest, CheckDecompressInMemoryFD) {
|
||||||
|
ZstdSapiSandbox sandbox;
|
||||||
|
ASSERT_THAT(sandbox.Init(), IsOk()) << "Couldn't initialize Sandboxed API";
|
||||||
|
ZstdApi api = ZstdApi(&sandbox);
|
||||||
|
|
||||||
|
std::string infile_s = GetTestFilePath("text.blob.zstd");
|
||||||
|
sapi::v::Fd infd(open(infile_s.c_str(), O_RDONLY));
|
||||||
|
ASSERT_GE(infd.GetValue(), 0);
|
||||||
|
|
||||||
|
SAPI_ASSERT_OK_AND_ASSIGN(std::string path,
|
||||||
|
sapi::CreateNamedTempFileAndClose("out"));
|
||||||
|
std::string outfile_s =
|
||||||
|
sapi::file::JoinPath(sapi::file_util::fileops::GetCWD(), path);
|
||||||
|
sapi::v::Fd outfd(open(outfile_s.c_str(), O_WRONLY));
|
||||||
|
ASSERT_GE(outfd.GetValue(), 0);
|
||||||
|
|
||||||
|
absl::Status status = DecompressInMemoryFD(api, infd, outfd);
|
||||||
|
ASSERT_THAT(status, IsOk()) << "Unable to compress file in memory";
|
||||||
|
|
||||||
|
off_t inpos = lseek(infd.GetValue(), 0, SEEK_END);
|
||||||
|
EXPECT_GE(inpos, 0);
|
||||||
|
|
||||||
|
off_t outpos = lseek(outfd.GetValue(), 0, SEEK_END);
|
||||||
|
EXPECT_GE(outpos, 0);
|
||||||
|
|
||||||
|
EXPECT_GT(outpos, inpos);
|
||||||
|
|
||||||
|
ASSERT_TRUE(CompareFiles(GetTestFilePath("text"), outfile_s));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(SandboxTest, CheckCompressAndDecompressInMemoryFD) {
|
||||||
|
ZstdSapiSandbox sandbox;
|
||||||
|
absl::Status status;
|
||||||
|
int ret;
|
||||||
|
ASSERT_THAT(sandbox.Init(), IsOk()) << "Couldn't initialize Sandboxed API";
|
||||||
|
ZstdApi api = ZstdApi(&sandbox);
|
||||||
|
|
||||||
|
std::string infile_s = GetTestFilePath("text");
|
||||||
|
|
||||||
|
SAPI_ASSERT_OK_AND_ASSIGN(std::string path_middle,
|
||||||
|
sapi::CreateNamedTempFileAndClose("middle.zstd"));
|
||||||
|
std::string middle_s =
|
||||||
|
sapi::file::JoinPath(sapi::file_util::fileops::GetCWD(), path_middle);
|
||||||
|
|
||||||
|
SAPI_ASSERT_OK_AND_ASSIGN(std::string path,
|
||||||
|
sapi::CreateNamedTempFileAndClose("out"));
|
||||||
|
std::string outfile_s =
|
||||||
|
sapi::file::JoinPath(sapi::file_util::fileops::GetCWD(), path);
|
||||||
|
|
||||||
|
sapi::v::Fd infd(open(infile_s.c_str(), O_RDONLY));
|
||||||
|
ASSERT_GE(infd.GetValue(), 0);
|
||||||
|
|
||||||
|
sapi::v::Fd outmiddlefd(open(middle_s.c_str(), O_WRONLY));
|
||||||
|
ASSERT_GE(outmiddlefd.GetValue(), 0);
|
||||||
|
|
||||||
|
status = CompressInMemoryFD(api, infd, outmiddlefd, 0);
|
||||||
|
ASSERT_THAT(status, IsOk()) << "Unable to compress file in memory";
|
||||||
|
|
||||||
|
off_t inpos = lseek(infd.GetValue(), 0, SEEK_END);
|
||||||
|
EXPECT_GE(inpos, 0);
|
||||||
|
|
||||||
|
off_t outpos = lseek(outmiddlefd.GetValue(), 0, SEEK_END);
|
||||||
|
EXPECT_GE(outpos, 0);
|
||||||
|
|
||||||
|
EXPECT_LT(outpos, inpos);
|
||||||
|
|
||||||
|
infd.CloseLocalFd();
|
||||||
|
outmiddlefd.CloseLocalFd();
|
||||||
|
|
||||||
|
sapi::v::Fd inmiddlefd(open(middle_s.c_str(), O_RDONLY));
|
||||||
|
ASSERT_GE(inmiddlefd.GetValue(), 0);
|
||||||
|
|
||||||
|
sapi::v::Fd outfd(open(outfile_s.c_str(), O_WRONLY));
|
||||||
|
ASSERT_GE(outfd.GetValue(), 0);
|
||||||
|
|
||||||
|
status = DecompressInMemoryFD(api, inmiddlefd, outfd);
|
||||||
ASSERT_THAT(status, IsOk()) << "Unable to decompress file in memory";
|
ASSERT_THAT(status, IsOk()) << "Unable to decompress file in memory";
|
||||||
|
|
||||||
|
outfd.CloseLocalFd();
|
||||||
|
inmiddlefd.CloseLocalFd();
|
||||||
|
|
||||||
|
ASSERT_TRUE(CompareFiles(infile_s, outfile_s));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(SandboxTest, CheckCompressStreamFD) {
|
||||||
|
absl::Status status;
|
||||||
|
ZstdSapiSandbox sandbox;
|
||||||
|
ASSERT_THAT(sandbox.Init(), IsOk()) << "Couldn't initialize Sandboxed API";
|
||||||
|
ZstdApi api = ZstdApi(&sandbox);
|
||||||
|
|
||||||
|
std::string infile_s = GetTestFilePath("text");
|
||||||
|
|
||||||
|
SAPI_ASSERT_OK_AND_ASSIGN(std::string path,
|
||||||
|
sapi::CreateNamedTempFileAndClose("out.zstd"));
|
||||||
|
std::string outfile_s =
|
||||||
|
sapi::file::JoinPath(sapi::file_util::fileops::GetCWD(), path);
|
||||||
|
|
||||||
|
sapi::v::Fd infd(open(infile_s.c_str(), O_RDONLY));
|
||||||
|
ASSERT_GE(infd.GetValue(), 0);
|
||||||
|
|
||||||
|
sapi::v::Fd outfd(open(outfile_s.c_str(), O_WRONLY));
|
||||||
|
ASSERT_GE(outfd.GetValue(), 0);
|
||||||
|
|
||||||
|
status = CompressStreamFD(api, infd, outfd, 0);
|
||||||
|
ASSERT_THAT(status, IsOk()) << "Unable to compress stream";
|
||||||
|
|
||||||
|
off_t inpos = lseek(infd.GetValue(), 0, SEEK_END);
|
||||||
|
EXPECT_GE(inpos, 0);
|
||||||
|
|
||||||
|
off_t outpos = lseek(outfd.GetValue(), 0, SEEK_END);
|
||||||
|
EXPECT_GE(outpos, 0);
|
||||||
|
|
||||||
|
EXPECT_LT(outpos, inpos);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(SandboxTest, CheckDecompressStreamFD) {
|
||||||
|
absl::Status status;
|
||||||
|
ZstdSapiSandbox sandbox;
|
||||||
|
ASSERT_THAT(sandbox.Init(), IsOk()) << "Couldn't initialize Sandboxed API";
|
||||||
|
ZstdApi api = ZstdApi(&sandbox);
|
||||||
|
|
||||||
|
std::string infile_s = GetTestFilePath("text.stream.zstd");
|
||||||
|
|
||||||
|
SAPI_ASSERT_OK_AND_ASSIGN(std::string path,
|
||||||
|
sapi::CreateNamedTempFileAndClose("out"));
|
||||||
|
std::string outfile_s =
|
||||||
|
sapi::file::JoinPath(sapi::file_util::fileops::GetCWD(), path);
|
||||||
|
|
||||||
|
sapi::v::Fd infd(open(infile_s.c_str(), O_RDONLY));
|
||||||
|
ASSERT_GE(infd.GetValue(), 0);
|
||||||
|
|
||||||
|
sapi::v::Fd outfd(open(outfile_s.c_str(), O_WRONLY));
|
||||||
|
ASSERT_GE(outfd.GetValue(), 0);
|
||||||
|
|
||||||
|
status = DecompressStreamFD(api, infd, outfd);
|
||||||
|
ASSERT_THAT(status, IsOk()) << "Unable to decompress stream";
|
||||||
|
|
||||||
|
off_t inpos = lseek(infd.GetValue(), 0, SEEK_END);
|
||||||
|
EXPECT_GE(inpos, 0);
|
||||||
|
|
||||||
|
off_t outpos = lseek(outfd.GetValue(), 0, SEEK_END);
|
||||||
|
EXPECT_GE(outpos, 0);
|
||||||
|
|
||||||
|
EXPECT_GT(outpos, inpos);
|
||||||
|
|
||||||
|
ASSERT_TRUE(CompareFiles(GetTestFilePath("text"), outfile_s));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(SandboxTest, CheckCompressAndDecompressStreamFD) {
|
||||||
|
ZstdSapiSandbox sandbox;
|
||||||
|
absl::Status status;
|
||||||
|
int ret;
|
||||||
|
ASSERT_THAT(sandbox.Init(), IsOk()) << "Couldn't initialize Sandboxed API";
|
||||||
|
ZstdApi api = ZstdApi(&sandbox);
|
||||||
|
|
||||||
|
std::string infile_s = GetTestFilePath("text");
|
||||||
|
|
||||||
|
SAPI_ASSERT_OK_AND_ASSIGN(std::string path_middle,
|
||||||
|
sapi::CreateNamedTempFileAndClose("middle.zstd"));
|
||||||
|
std::string middle_s =
|
||||||
|
sapi::file::JoinPath(sapi::file_util::fileops::GetCWD(), path_middle);
|
||||||
|
|
||||||
|
SAPI_ASSERT_OK_AND_ASSIGN(std::string path,
|
||||||
|
sapi::CreateNamedTempFileAndClose("out"));
|
||||||
|
std::string outfile_s =
|
||||||
|
sapi::file::JoinPath(sapi::file_util::fileops::GetCWD(), path);
|
||||||
|
|
||||||
|
sapi::v::Fd infd(open(infile_s.c_str(), O_RDONLY));
|
||||||
|
ASSERT_GE(infd.GetValue(), 0);
|
||||||
|
|
||||||
|
sapi::v::Fd outmiddlefd(open(middle_s.c_str(), O_WRONLY));
|
||||||
|
ASSERT_GE(outmiddlefd.GetValue(), 0);
|
||||||
|
|
||||||
|
status = CompressStreamFD(api, infd, outmiddlefd, 0);
|
||||||
|
ASSERT_THAT(status, IsOk()) << "Unable to compress stream";
|
||||||
|
|
||||||
|
off_t inpos = lseek(infd.GetValue(), 0, SEEK_END);
|
||||||
|
EXPECT_GE(inpos, 0);
|
||||||
|
|
||||||
|
off_t outmiddlepos = lseek(outmiddlefd.GetValue(), 0, SEEK_END);
|
||||||
|
EXPECT_GE(outmiddlepos, 0);
|
||||||
|
|
||||||
|
EXPECT_LT(outmiddlepos, inpos);
|
||||||
|
|
||||||
|
infd.CloseLocalFd();
|
||||||
|
outmiddlefd.CloseLocalFd();
|
||||||
|
|
||||||
|
sapi::v::Fd inmiddlefd(open(middle_s.c_str(), O_RDONLY));
|
||||||
|
ASSERT_GE(inmiddlefd.GetValue(), 0);
|
||||||
|
|
||||||
|
sapi::v::Fd outfd(open(outfile_s.c_str(), O_WRONLY));
|
||||||
|
ASSERT_GE(outfd.GetValue(), 0);
|
||||||
|
|
||||||
|
status = DecompressStreamFD(api, inmiddlefd, outfd);
|
||||||
|
ASSERT_THAT(status, IsOk()) << "Unable to decompress stream";
|
||||||
|
|
||||||
ASSERT_TRUE(CompareFiles(infile_s, outfile_s));
|
ASSERT_TRUE(CompareFiles(infile_s, outfile_s));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -241,3 +241,95 @@ absl::Status DecompressStream(ZstdApi& api, std::ifstream& in_stream,
|
||||||
|
|
||||||
return absl::OkStatus();
|
return absl::OkStatus();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
absl::Status CompressInMemoryFD(ZstdApi& api, sapi::v::Fd& infd,
|
||||||
|
sapi::v::Fd& outfd, int level) {
|
||||||
|
SAPI_RETURN_IF_ERROR(api.GetSandbox()->TransferToSandboxee(&infd));
|
||||||
|
SAPI_RETURN_IF_ERROR(api.GetSandbox()->TransferToSandboxee(&outfd));
|
||||||
|
|
||||||
|
SAPI_ASSIGN_OR_RETURN(
|
||||||
|
int iserr,
|
||||||
|
api.ZSTD_compress_fd(infd.GetRemoteFd(), outfd.GetRemoteFd(), 0));
|
||||||
|
SAPI_ASSIGN_OR_RETURN(iserr, api.ZSTD_isError(iserr))
|
||||||
|
if (iserr) {
|
||||||
|
return absl::UnavailableError("Unable to compress file");
|
||||||
|
}
|
||||||
|
|
||||||
|
infd.CloseRemoteFd(api.GetSandbox()->rpc_channel()).IgnoreError();
|
||||||
|
outfd.CloseRemoteFd(api.GetSandbox()->rpc_channel()).IgnoreError();
|
||||||
|
|
||||||
|
return absl::OkStatus();
|
||||||
|
}
|
||||||
|
|
||||||
|
absl::Status DecompressInMemoryFD(ZstdApi& api, sapi::v::Fd& infd,
|
||||||
|
sapi::v::Fd& outfd) {
|
||||||
|
SAPI_RETURN_IF_ERROR(api.GetSandbox()->TransferToSandboxee(&infd));
|
||||||
|
SAPI_RETURN_IF_ERROR(api.GetSandbox()->TransferToSandboxee(&outfd));
|
||||||
|
|
||||||
|
SAPI_ASSIGN_OR_RETURN(int iserr, api.ZSTD_decompress_fd(infd.GetRemoteFd(),
|
||||||
|
outfd.GetRemoteFd()));
|
||||||
|
SAPI_ASSIGN_OR_RETURN(iserr, api.ZSTD_isError(iserr))
|
||||||
|
if (iserr) {
|
||||||
|
return absl::UnavailableError("Unable to compress file");
|
||||||
|
}
|
||||||
|
|
||||||
|
infd.CloseRemoteFd(api.GetSandbox()->rpc_channel()).IgnoreError();
|
||||||
|
outfd.CloseRemoteFd(api.GetSandbox()->rpc_channel()).IgnoreError();
|
||||||
|
|
||||||
|
return absl::OkStatus();
|
||||||
|
}
|
||||||
|
|
||||||
|
absl::Status CompressStreamFD(ZstdApi& api, sapi::v::Fd& infd,
|
||||||
|
sapi::v::Fd& outfd, int level) {
|
||||||
|
SAPI_ASSIGN_OR_RETURN(ZSTD_CCtx * cctx, api.ZSTD_createCCtx());
|
||||||
|
sapi::v::RemotePtr rcctx(cctx);
|
||||||
|
|
||||||
|
int iserr;
|
||||||
|
SAPI_ASSIGN_OR_RETURN(iserr, api.ZSTD_CCtx_setParameter(
|
||||||
|
&rcctx, ZSTD_c_compressionLevel, level));
|
||||||
|
SAPI_ASSIGN_OR_RETURN(iserr, api.ZSTD_isError(iserr));
|
||||||
|
if (iserr) {
|
||||||
|
return absl::UnavailableError("Unable to set parameter l");
|
||||||
|
}
|
||||||
|
SAPI_ASSIGN_OR_RETURN(
|
||||||
|
iserr, api.ZSTD_CCtx_setParameter(&rcctx, ZSTD_c_checksumFlag, 1));
|
||||||
|
SAPI_ASSIGN_OR_RETURN(iserr, api.ZSTD_isError(iserr));
|
||||||
|
if (iserr) {
|
||||||
|
return absl::UnavailableError("Unable to set parameter c");
|
||||||
|
}
|
||||||
|
|
||||||
|
SAPI_RETURN_IF_ERROR(api.GetSandbox()->TransferToSandboxee(&infd));
|
||||||
|
SAPI_RETURN_IF_ERROR(api.GetSandbox()->TransferToSandboxee(&outfd));
|
||||||
|
|
||||||
|
SAPI_ASSIGN_OR_RETURN(iserr,
|
||||||
|
api.ZSTD_compressStream_fd(&rcctx, infd.GetRemoteFd(),
|
||||||
|
outfd.GetRemoteFd()));
|
||||||
|
if (iserr) {
|
||||||
|
return absl::UnavailableError("Unable to compress");
|
||||||
|
}
|
||||||
|
|
||||||
|
infd.CloseRemoteFd(api.GetSandbox()->rpc_channel()).IgnoreError();
|
||||||
|
outfd.CloseRemoteFd(api.GetSandbox()->rpc_channel()).IgnoreError();
|
||||||
|
|
||||||
|
return absl::OkStatus();
|
||||||
|
}
|
||||||
|
|
||||||
|
absl::Status DecompressStreamFD(ZstdApi& api, sapi::v::Fd& infd,
|
||||||
|
sapi::v::Fd& outfd) {
|
||||||
|
SAPI_ASSIGN_OR_RETURN(ZSTD_DCtx * dctx, api.ZSTD_createDCtx());
|
||||||
|
sapi::v::RemotePtr rdctx(dctx);
|
||||||
|
|
||||||
|
SAPI_RETURN_IF_ERROR(api.GetSandbox()->TransferToSandboxee(&infd));
|
||||||
|
SAPI_RETURN_IF_ERROR(api.GetSandbox()->TransferToSandboxee(&outfd));
|
||||||
|
|
||||||
|
SAPI_ASSIGN_OR_RETURN(int iserr,
|
||||||
|
api.ZSTD_decompressStream_fd(&rdctx, infd.GetRemoteFd(),
|
||||||
|
outfd.GetRemoteFd()));
|
||||||
|
if (iserr) {
|
||||||
|
return absl::UnavailableError("Unable to decompress");
|
||||||
|
}
|
||||||
|
infd.CloseRemoteFd(api.GetSandbox()->rpc_channel()).IgnoreError();
|
||||||
|
outfd.CloseRemoteFd(api.GetSandbox()->rpc_channel()).IgnoreError();
|
||||||
|
|
||||||
|
return absl::OkStatus();
|
||||||
|
}
|
||||||
|
|
|
@ -24,10 +24,18 @@ absl::Status CompressInMemory(ZstdApi& api, std::ifstream& in_stream,
|
||||||
std::ofstream& out_stream, int level);
|
std::ofstream& out_stream, int level);
|
||||||
absl::Status DecompressInMemory(ZstdApi& api, std::ifstream& in_stream,
|
absl::Status DecompressInMemory(ZstdApi& api, std::ifstream& in_stream,
|
||||||
std::ofstream& out_stream);
|
std::ofstream& out_stream);
|
||||||
|
absl::Status CompressInMemoryFD(ZstdApi& api, sapi::v::Fd& infd,
|
||||||
|
sapi::v::Fd& outfd, int level);
|
||||||
|
absl::Status DecompressInMemoryFD(ZstdApi& api, sapi::v::Fd& infd,
|
||||||
|
sapi::v::Fd& outfd);
|
||||||
|
|
||||||
absl::Status CompressStream(ZstdApi& api, std::ifstream& in_stream,
|
absl::Status CompressStream(ZstdApi& api, std::ifstream& in_stream,
|
||||||
std::ofstream& out_stream, int level);
|
std::ofstream& out_stream, int level);
|
||||||
absl::Status DecompressStream(ZstdApi& api, std::ifstream& in_stream,
|
absl::Status DecompressStream(ZstdApi& api, std::ifstream& in_stream,
|
||||||
std::ofstream& out_stream);
|
std::ofstream& out_stream);
|
||||||
|
absl::Status CompressStreamFD(ZstdApi& api, sapi::v::Fd& infd,
|
||||||
|
sapi::v::Fd& outfd, int level);
|
||||||
|
absl::Status DecompressStreamFD(ZstdApi& api, sapi::v::Fd& infd,
|
||||||
|
sapi::v::Fd& outfd);
|
||||||
|
|
||||||
#endif // CONTRIB_ZSTD_UTILS_UTILS_ZSTD_H_
|
#endif // CONTRIB_ZSTD_UTILS_UTILS_ZSTD_H_
|
||||||
|
|
24
contrib/zstd/wrapper/CMakeLists.txt
Normal file
24
contrib/zstd/wrapper/CMakeLists.txt
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
# Copyright 2022 Google LLC
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
# you may not use this file except in compliance with the License.
|
||||||
|
# You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
|
||||||
|
add_library(wrapper_zstd STATIC
|
||||||
|
wrapper_zstd.cc
|
||||||
|
)
|
||||||
|
target_link_libraries(wrapper_zstd PUBLIC
|
||||||
|
libzstd_static
|
||||||
|
)
|
||||||
|
target_include_directories(wrapper_zstd PUBLIC
|
||||||
|
"${SAPI_SOURCE_DIR}"
|
||||||
|
"${libzstd_INCLUDE_DIR}"
|
||||||
|
)
|
182
contrib/zstd/wrapper/wrapper_zstd.cc
Normal file
182
contrib/zstd/wrapper/wrapper_zstd.cc
Normal file
|
@ -0,0 +1,182 @@
|
||||||
|
// Copyright 2022 Google LLC
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
#include "contrib/zstd/wrapper/wrapper_zstd.h"
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include <cstdio>
|
||||||
|
#include <cstdlib>
|
||||||
|
#include <iostream>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
constexpr size_t kFileMaxSize = 1024 * 1024 * 1024; // 1GB
|
||||||
|
|
||||||
|
off_t FDGetSize(int fd) {
|
||||||
|
off_t size = lseek(fd, 0, SEEK_END);
|
||||||
|
if (size < 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (lseek(fd, 0, SEEK_SET) < 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ZSTD_compress_fd(int fdin, int fdout, int level) {
|
||||||
|
off_t sizein = FDGetSize(fdin);
|
||||||
|
if (sizein <= 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t sizeout = ZSTD_compressBound(sizein);
|
||||||
|
|
||||||
|
auto bufin = std::make_unique<int8_t[]>(sizein);
|
||||||
|
auto bufout = std::make_unique<int8_t[]>(sizeout);
|
||||||
|
|
||||||
|
if (read(fdin, bufin.get(), sizein) != sizein) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int retsize =
|
||||||
|
ZSTD_compress(bufout.get(), sizeout, bufin.get(), sizein, level);
|
||||||
|
if (ZSTD_isError(retsize)) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (write(fdout, bufout.get(), retsize) != retsize) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ZSTD_compressStream_fd(ZSTD_CCtx* cctx, int fdin, int fdout) {
|
||||||
|
size_t sizein = ZSTD_CStreamInSize();
|
||||||
|
size_t sizeout = ZSTD_CStreamOutSize();
|
||||||
|
|
||||||
|
auto bufin = std::make_unique<int8_t[]>(sizein);
|
||||||
|
auto bufout = std::make_unique<int8_t[]>(sizeout);
|
||||||
|
|
||||||
|
ssize_t size;
|
||||||
|
while ((size = read(fdin, bufin.get(), sizein)) > 0) {
|
||||||
|
ZSTD_inBuffer_s struct_in;
|
||||||
|
struct_in.src = bufin.get();
|
||||||
|
struct_in.pos = 0;
|
||||||
|
struct_in.size = size;
|
||||||
|
|
||||||
|
ZSTD_EndDirective mode = ZSTD_e_continue;
|
||||||
|
if (size < sizein) {
|
||||||
|
mode = ZSTD_e_end;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isdone = false;
|
||||||
|
while (!isdone) {
|
||||||
|
ZSTD_outBuffer_s struct_out;
|
||||||
|
struct_out.dst = bufout.get();
|
||||||
|
struct_out.pos = 0;
|
||||||
|
struct_out.size = sizeout;
|
||||||
|
|
||||||
|
size_t remaining =
|
||||||
|
ZSTD_compressStream2(cctx, &struct_out, &struct_in, mode);
|
||||||
|
if (ZSTD_isError(remaining)) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (write(fdout, bufout.get(), struct_out.pos) != struct_out.pos) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mode == ZSTD_e_continue) {
|
||||||
|
isdone = (struct_in.pos == size);
|
||||||
|
} else {
|
||||||
|
isdone = (remaining == 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (size != 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ZSTD_decompress_fd(int fdin, int fdout) {
|
||||||
|
off_t sizein = FDGetSize(fdin);
|
||||||
|
if (sizein <= 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
auto bufin = std::make_unique<int8_t[]>(sizein);
|
||||||
|
if (read(fdin, bufin.get(), sizein) != sizein) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t sizeout = ZSTD_getFrameContentSize(bufin.get(), sizein);
|
||||||
|
if (ZSTD_isError(sizeout) || sizeout > kFileMaxSize) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto bufout = std::make_unique<int8_t[]>(sizeout);
|
||||||
|
|
||||||
|
size_t desize = ZSTD_decompress(bufout.get(), sizeout, bufin.get(), sizein);
|
||||||
|
if (ZSTD_isError(desize) || desize != sizeout) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (write(fdout, bufout.get(), sizeout) != sizeout) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ZSTD_decompressStream_fd(ZSTD_DCtx* dctx, int fdin, int fdout) {
|
||||||
|
size_t sizein = ZSTD_CStreamInSize();
|
||||||
|
size_t sizeout = ZSTD_CStreamOutSize();
|
||||||
|
|
||||||
|
auto bufin = std::make_unique<int8_t[]>(sizein);
|
||||||
|
auto bufout = std::make_unique<int8_t[]>(sizeout);
|
||||||
|
|
||||||
|
ssize_t size;
|
||||||
|
while ((size = read(fdin, bufin.get(), sizein)) > 0) {
|
||||||
|
ZSTD_inBuffer_s struct_in;
|
||||||
|
struct_in.src = bufin.get();
|
||||||
|
struct_in.pos = 0;
|
||||||
|
struct_in.size = size;
|
||||||
|
|
||||||
|
while (struct_in.pos < size) {
|
||||||
|
ZSTD_outBuffer_s struct_out;
|
||||||
|
struct_out.dst = bufout.get();
|
||||||
|
struct_out.pos = 0;
|
||||||
|
struct_out.size = sizeout;
|
||||||
|
|
||||||
|
size_t ret = ZSTD_decompressStream(dctx, &struct_out, &struct_in);
|
||||||
|
if (ZSTD_isError(ret)) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (write(fdout, bufout.get(), struct_out.pos) != struct_out.pos) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (size != 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
28
contrib/zstd/wrapper/wrapper_zstd.h
Normal file
28
contrib/zstd/wrapper/wrapper_zstd.h
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
// Copyright 2022 Google LLC
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
#ifndef CONTRIB_ZSTD_WRAPPER_WRAPPER_ZSTD_H_
|
||||||
|
#define CONTRIB_ZSTD_WRAPPER_WRAPPER_ZSTD_H_
|
||||||
|
|
||||||
|
#include <zstd.h>
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
int ZSTD_compress_fd(int fdin, int fdout, int level);
|
||||||
|
int ZSTD_compressStream_fd(ZSTD_CCtx* cctx, int fdin, int fdout);
|
||||||
|
|
||||||
|
int ZSTD_decompress_fd(int fdin, int fdout);
|
||||||
|
int ZSTD_decompressStream_fd(ZSTD_DCtx* dctx, int fdin, int fdout);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // CONTRIB_ZSTD_WRAPPER_WRAPPER_ZSTD_H_
|
3
oss-internship-2020/pffft/.gitignore
vendored
3
oss-internship-2020/pffft/.gitignore
vendored
|
@ -1,3 +0,0 @@
|
||||||
*.o
|
|
||||||
*.a
|
|
||||||
pffft_main
|
|
|
@ -36,7 +36,7 @@ sapi_library(
|
||||||
cc_binary(
|
cc_binary(
|
||||||
name = "main_zlib",
|
name = "main_zlib",
|
||||||
srcs = ["main_zlib.cc"],
|
srcs = ["main_zlib.cc"],
|
||||||
copts = sapi_platform_copts(["-Wframe-larger-than=65536"]),
|
copts = sapi_platform_copts(),
|
||||||
deps = [
|
deps = [
|
||||||
":zlib-sapi",
|
":zlib-sapi",
|
||||||
":zlib-sapi_embed",
|
":zlib-sapi_embed",
|
||||||
|
|
|
@ -17,7 +17,7 @@ add_sapi_library(zlib-sapi
|
||||||
FUNCTIONS deflateInit_
|
FUNCTIONS deflateInit_
|
||||||
deflate
|
deflate
|
||||||
deflateEnd
|
deflateEnd
|
||||||
INPUTS ${ZLIB_INCLUDE_DIRS}/zlib.h
|
INPUTS "${ZLIB_INCLUDE_DIRS}/zlib.h"
|
||||||
LIBRARY ZLIB::ZLIB
|
LIBRARY ZLIB::ZLIB
|
||||||
LIBRARY_NAME Zlib
|
LIBRARY_NAME Zlib
|
||||||
NAMESPACE "sapi::zlib"
|
NAMESPACE "sapi::zlib"
|
||||||
|
|
|
@ -555,9 +555,11 @@ bool Comms::Recv(void* data, size_t len) {
|
||||||
// Internal helper method (low level).
|
// Internal helper method (low level).
|
||||||
bool Comms::RecvTL(uint32_t* tag, size_t* length) {
|
bool Comms::RecvTL(uint32_t* tag, size_t* length) {
|
||||||
if (!Recv(reinterpret_cast<uint8_t*>(tag), sizeof(*tag))) {
|
if (!Recv(reinterpret_cast<uint8_t*>(tag), sizeof(*tag))) {
|
||||||
|
SAPI_RAW_VLOG(2, "RecvTL: Can't read tag");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (!Recv(reinterpret_cast<uint8_t*>(length), sizeof(*length))) {
|
if (!Recv(reinterpret_cast<uint8_t*>(length), sizeof(*length))) {
|
||||||
|
SAPI_RAW_VLOG(2, "RecvTL: Can't read length for tag %u", *tag);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (*length > GetMaxMsgSize()) {
|
if (*length > GetMaxMsgSize()) {
|
||||||
|
|
|
@ -57,4 +57,5 @@ sh_test(
|
||||||
name = "static_sandbox_test",
|
name = "static_sandbox_test",
|
||||||
srcs = ["static_sandbox_test.sh"],
|
srcs = ["static_sandbox_test.sh"],
|
||||||
data = [":static_sandbox"],
|
data = [":static_sandbox"],
|
||||||
|
tags = ["no_qemu_user_mode"],
|
||||||
)
|
)
|
||||||
|
|
|
@ -37,9 +37,6 @@ cc_binary(
|
||||||
name = "zpipe",
|
name = "zpipe",
|
||||||
srcs = ["zpipe.c"],
|
srcs = ["zpipe.c"],
|
||||||
copts = sapi_platform_copts(),
|
copts = sapi_platform_copts(),
|
||||||
features = [
|
features = ["fully_static_link"],
|
||||||
"fully_static_link", # link libc statically
|
|
||||||
],
|
|
||||||
linkstatic = 1,
|
|
||||||
deps = ["@net_zlib//:zlib"],
|
deps = ["@net_zlib//:zlib"],
|
||||||
)
|
)
|
||||||
|
|
|
@ -24,7 +24,6 @@ target_link_libraries(sandbox2_zpipe_sandbox PRIVATE
|
||||||
absl::memory
|
absl::memory
|
||||||
sandbox2::bpf_helper
|
sandbox2::bpf_helper
|
||||||
sandbox2::comms
|
sandbox2::comms
|
||||||
# sandbox2::ipc
|
|
||||||
sapi::runfiles
|
sapi::runfiles
|
||||||
sandbox2::sandbox2
|
sandbox2::sandbox2
|
||||||
sapi::base
|
sapi::base
|
||||||
|
@ -38,5 +37,6 @@ add_executable(sandbox2_zpipe
|
||||||
set_target_properties(sandbox2_zpipe PROPERTIES OUTPUT_NAME zpipe)
|
set_target_properties(sandbox2_zpipe PROPERTIES OUTPUT_NAME zpipe)
|
||||||
add_executable(sandbox2::zpipe ALIAS sandbox2_zpipe)
|
add_executable(sandbox2::zpipe ALIAS sandbox2_zpipe)
|
||||||
target_link_libraries(sandbox2_zpipe PRIVATE
|
target_link_libraries(sandbox2_zpipe PRIVATE
|
||||||
|
-static
|
||||||
ZLIB::ZLIB
|
ZLIB::ZLIB
|
||||||
)
|
)
|
||||||
|
|
|
@ -54,7 +54,7 @@ std::unique_ptr<sandbox2::Policy> GetPolicy() {
|
||||||
// Allow write on STDOUT / STDERR.
|
// Allow write on STDOUT / STDERR.
|
||||||
.AddPolicyOnSyscall(__NR_write,
|
.AddPolicyOnSyscall(__NR_write,
|
||||||
{ARG_32(0), JEQ32(1, ALLOW), JEQ32(2, ALLOW)})
|
{ARG_32(0), JEQ32(1, ALLOW), JEQ32(2, ALLOW)})
|
||||||
.AllowSyscall(__NR_fstat)
|
.AllowStat()
|
||||||
.AllowStaticStartup()
|
.AllowStaticStartup()
|
||||||
.AllowSystemMalloc()
|
.AllowSystemMalloc()
|
||||||
.AllowExit()
|
.AllowExit()
|
||||||
|
|
|
@ -653,12 +653,10 @@ PolicyBuilder& PolicyBuilder::AllowStaticStartup() {
|
||||||
BlockSyscallWithErrno(__NR_readlink, ENOENT);
|
BlockSyscallWithErrno(__NR_readlink, ENOENT);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if constexpr (sapi::host_cpu::IsArm()) {
|
AddPolicyOnSyscall(__NR_mprotect, {
|
||||||
AddPolicyOnSyscall(__NR_mprotect, {
|
ARG_32(2),
|
||||||
ARG_32(2),
|
JEQ32(PROT_READ, ALLOW),
|
||||||
JEQ32(PROT_READ, ALLOW),
|
});
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
@ -884,7 +882,7 @@ PolicyBuilder& PolicyBuilder::AddFile(absl::string_view path, bool is_ro) {
|
||||||
|
|
||||||
PolicyBuilder& PolicyBuilder::AddFileAt(absl::string_view outside,
|
PolicyBuilder& PolicyBuilder::AddFileAt(absl::string_view outside,
|
||||||
absl::string_view inside, bool is_ro) {
|
absl::string_view inside, bool is_ro) {
|
||||||
EnableNamespaces();
|
EnableNamespaces(); // NOLINT(clang-diagnostic-deprecated-declarations)
|
||||||
|
|
||||||
auto valid_outside = ValidateAbsolutePath(outside);
|
auto valid_outside = ValidateAbsolutePath(outside);
|
||||||
if (!valid_outside.ok()) {
|
if (!valid_outside.ok()) {
|
||||||
|
@ -912,7 +910,7 @@ PolicyBuilder& PolicyBuilder::AddFileAt(absl::string_view outside,
|
||||||
|
|
||||||
PolicyBuilder& PolicyBuilder::AddLibrariesForBinary(
|
PolicyBuilder& PolicyBuilder::AddLibrariesForBinary(
|
||||||
absl::string_view path, absl::string_view ld_library_path) {
|
absl::string_view path, absl::string_view ld_library_path) {
|
||||||
EnableNamespaces();
|
EnableNamespaces(); // NOLINT(clang-diagnostic-deprecated-declarations)
|
||||||
|
|
||||||
auto valid_path = ValidatePath(path);
|
auto valid_path = ValidatePath(path);
|
||||||
if (!valid_path.ok()) {
|
if (!valid_path.ok()) {
|
||||||
|
@ -941,7 +939,7 @@ PolicyBuilder& PolicyBuilder::AddDirectory(absl::string_view path, bool is_ro) {
|
||||||
PolicyBuilder& PolicyBuilder::AddDirectoryAt(absl::string_view outside,
|
PolicyBuilder& PolicyBuilder::AddDirectoryAt(absl::string_view outside,
|
||||||
absl::string_view inside,
|
absl::string_view inside,
|
||||||
bool is_ro) {
|
bool is_ro) {
|
||||||
EnableNamespaces();
|
EnableNamespaces(); // NOLINT(clang-diagnostic-deprecated-declarations)
|
||||||
|
|
||||||
auto valid_outside = ValidateAbsolutePath(outside);
|
auto valid_outside = ValidateAbsolutePath(outside);
|
||||||
if (!valid_outside.ok()) {
|
if (!valid_outside.ok()) {
|
||||||
|
@ -969,7 +967,7 @@ PolicyBuilder& PolicyBuilder::AddDirectoryAt(absl::string_view outside,
|
||||||
}
|
}
|
||||||
|
|
||||||
PolicyBuilder& PolicyBuilder::AddTmpfs(absl::string_view inside, size_t size) {
|
PolicyBuilder& PolicyBuilder::AddTmpfs(absl::string_view inside, size_t size) {
|
||||||
EnableNamespaces();
|
EnableNamespaces(); // NOLINT(clang-diagnostic-deprecated-declarations)
|
||||||
|
|
||||||
if (auto status = mounts_.AddTmpfs(inside, size); !status.ok()) {
|
if (auto status = mounts_.AddTmpfs(inside, size); !status.ok()) {
|
||||||
SetError(absl::InternalError(absl::StrCat("Could not mount tmpfs ", inside,
|
SetError(absl::InternalError(absl::StrCat("Could not mount tmpfs ", inside,
|
||||||
|
@ -979,14 +977,14 @@ PolicyBuilder& PolicyBuilder::AddTmpfs(absl::string_view inside, size_t size) {
|
||||||
}
|
}
|
||||||
|
|
||||||
PolicyBuilder& PolicyBuilder::AllowUnrestrictedNetworking() {
|
PolicyBuilder& PolicyBuilder::AllowUnrestrictedNetworking() {
|
||||||
EnableNamespaces();
|
EnableNamespaces(); // NOLINT(clang-diagnostic-deprecated-declarations)
|
||||||
allow_unrestricted_networking_ = true;
|
allow_unrestricted_networking_ = true;
|
||||||
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
PolicyBuilder& PolicyBuilder::SetHostname(absl::string_view hostname) {
|
PolicyBuilder& PolicyBuilder::SetHostname(absl::string_view hostname) {
|
||||||
EnableNamespaces();
|
EnableNamespaces(); // NOLINT(clang-diagnostic-deprecated-declarations)
|
||||||
hostname_ = std::string(hostname);
|
hostname_ = std::string(hostname);
|
||||||
|
|
||||||
return *this;
|
return *this;
|
||||||
|
@ -1089,7 +1087,7 @@ PolicyBuilder& PolicyBuilder::AddNetworkProxyHandlerPolicy() {
|
||||||
}
|
}
|
||||||
|
|
||||||
PolicyBuilder& PolicyBuilder::SetRootWritable() {
|
PolicyBuilder& PolicyBuilder::SetRootWritable() {
|
||||||
EnableNamespaces();
|
EnableNamespaces(); // NOLINT(clang-diagnostic-deprecated-declarations)
|
||||||
mounts_.SetRootWritable();
|
mounts_.SetRootWritable();
|
||||||
|
|
||||||
return *this;
|
return *this;
|
||||||
|
|
|
@ -286,9 +286,6 @@ absl::StatusOr<UnwindResult> StackTracePeer::LaunchLibunwindSandbox(
|
||||||
|
|
||||||
absl::StatusOr<std::vector<std::string>> GetStackTrace(const Regs* regs,
|
absl::StatusOr<std::vector<std::string>> GetStackTrace(const Regs* regs,
|
||||||
const Mounts& mounts) {
|
const Mounts& mounts) {
|
||||||
if constexpr (sapi::host_cpu::IsArm64()) {
|
|
||||||
return absl::UnavailableError("Stack traces unavailable on Aarch64");
|
|
||||||
}
|
|
||||||
if (absl::GetFlag(FLAGS_sandbox_disable_all_stack_traces)) {
|
if (absl::GetFlag(FLAGS_sandbox_disable_all_stack_traces)) {
|
||||||
return absl::UnavailableError("Stacktraces disabled");
|
return absl::UnavailableError("Stacktraces disabled");
|
||||||
}
|
}
|
||||||
|
|
|
@ -62,6 +62,7 @@ cc_library(
|
||||||
"//sandboxed_api/util:raw_logging",
|
"//sandboxed_api/util:raw_logging",
|
||||||
"//sandboxed_api/util:status",
|
"//sandboxed_api/util:status",
|
||||||
"//sandboxed_api/util:strerror",
|
"//sandboxed_api/util:strerror",
|
||||||
|
"@com_google_absl//absl/cleanup",
|
||||||
"@com_google_absl//absl/status:statusor",
|
"@com_google_absl//absl/status:statusor",
|
||||||
"@com_google_absl//absl/strings",
|
"@com_google_absl//absl/strings",
|
||||||
"@org_gnu_libunwind//:unwind-ptrace-wrapped",
|
"@org_gnu_libunwind//:unwind-ptrace-wrapped",
|
||||||
|
|
|
@ -30,6 +30,7 @@ add_library(sandbox2_unwind STATIC
|
||||||
)
|
)
|
||||||
add_library(sandbox2::unwind ALIAS sandbox2_unwind)
|
add_library(sandbox2::unwind ALIAS sandbox2_unwind)
|
||||||
target_link_libraries(sandbox2_unwind PRIVATE
|
target_link_libraries(sandbox2_unwind PRIVATE
|
||||||
|
absl::cleanup
|
||||||
absl::statusor
|
absl::statusor
|
||||||
absl::strings
|
absl::strings
|
||||||
sandbox2::comms
|
sandbox2::comms
|
||||||
|
|
|
@ -19,11 +19,13 @@
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
|
#include <cstdlib>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
#include "absl/cleanup/cleanup.h"
|
||||||
#include "absl/status/statusor.h"
|
#include "absl/status/statusor.h"
|
||||||
#include "absl/strings/match.h"
|
#include "absl/strings/match.h"
|
||||||
#include "absl/strings/str_cat.h"
|
#include "absl/strings/str_cat.h"
|
||||||
|
@ -55,21 +57,20 @@ std::string DemangleSymbol(const std::string& maybe_mangled) {
|
||||||
}
|
}
|
||||||
|
|
||||||
absl::StatusOr<std::vector<uintptr_t>> RunLibUnwind(pid_t pid, int max_frames) {
|
absl::StatusOr<std::vector<uintptr_t>> RunLibUnwind(pid_t pid, int max_frames) {
|
||||||
unw_cursor_t cursor;
|
|
||||||
static unw_addr_space_t as =
|
static unw_addr_space_t as =
|
||||||
unw_create_addr_space(&_UPT_accessors, 0 /* byte order */);
|
unw_create_addr_space(&_UPT_accessors, 0 /* byte order */);
|
||||||
if (as == nullptr) {
|
if (as == nullptr) {
|
||||||
return absl::InternalError("unw_create_addr_space() failed");
|
return absl::InternalError("unw_create_addr_space() failed");
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<struct UPT_info, void (*)(void*)> ui(
|
void* context = _UPT_create(pid);
|
||||||
reinterpret_cast<struct UPT_info*>(_UPT_create(pid)), _UPT_destroy);
|
if (context == nullptr) {
|
||||||
if (ui == nullptr) {
|
|
||||||
return absl::InternalError("_UPT_create() failed");
|
return absl::InternalError("_UPT_create() failed");
|
||||||
}
|
}
|
||||||
|
absl::Cleanup context_cleanup = [&context] { _UPT_destroy(context); };
|
||||||
|
|
||||||
int rc = unw_init_remote(&cursor, as, ui.get());
|
unw_cursor_t cursor;
|
||||||
if (rc < 0) {
|
if (int rc = unw_init_remote(&cursor, as, context); rc < 0) {
|
||||||
// Could be UNW_EINVAL (8), UNW_EUNSPEC (1) or UNW_EBADREG (3).
|
// Could be UNW_EINVAL (8), UNW_EUNSPEC (1) or UNW_EBADREG (3).
|
||||||
return absl::InternalError(
|
return absl::InternalError(
|
||||||
absl::StrCat("unw_init_remote() failed with error ", rc));
|
absl::StrCat("unw_init_remote() failed with error ", rc));
|
||||||
|
@ -78,7 +79,7 @@ absl::StatusOr<std::vector<uintptr_t>> RunLibUnwind(pid_t pid, int max_frames) {
|
||||||
std::vector<uintptr_t> ips;
|
std::vector<uintptr_t> ips;
|
||||||
for (int i = 0; i < max_frames; ++i) {
|
for (int i = 0; i < max_frames; ++i) {
|
||||||
unw_word_t ip;
|
unw_word_t ip;
|
||||||
rc = unw_get_reg(&cursor, UNW_REG_IP, &ip);
|
int rc = unw_get_reg(&cursor, UNW_REG_IP, &ip);
|
||||||
if (rc < 0) {
|
if (rc < 0) {
|
||||||
// Could be UNW_EUNSPEC or UNW_EBADREG.
|
// Could be UNW_EUNSPEC or UNW_EBADREG.
|
||||||
SAPI_RAW_LOG(WARNING, "unw_get_reg() failed with error %d", rc);
|
SAPI_RAW_LOG(WARNING, "unw_get_reg() failed with error %d", rc);
|
||||||
|
@ -176,8 +177,10 @@ absl::StatusOr<SymbolMap> LoadSymbolsMap(pid_t pid) {
|
||||||
|
|
||||||
for (const ElfFile::Symbol& symbol : elf->symbols()) {
|
for (const ElfFile::Symbol& symbol : elf->symbols()) {
|
||||||
if (elf->position_independent()) {
|
if (elf->position_independent()) {
|
||||||
if (symbol.address < entry.end - entry.start) {
|
if (symbol.address >= entry.pgoff &&
|
||||||
addr_to_symbol[symbol.address + entry.start] = symbol.name;
|
symbol.address - entry.pgoff < entry.end - entry.start) {
|
||||||
|
addr_to_symbol[symbol.address + entry.start - entry.pgoff] =
|
||||||
|
symbol.name;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (symbol.address >= entry.start && symbol.address < entry.end) {
|
if (symbol.address >= entry.start && symbol.address < entry.end) {
|
||||||
|
|
|
@ -26,13 +26,14 @@
|
||||||
#include "sandboxed_api/util/file_helpers.h"
|
#include "sandboxed_api/util/file_helpers.h"
|
||||||
#include "sandboxed_api/util/status_matchers.h"
|
#include "sandboxed_api/util/status_matchers.h"
|
||||||
|
|
||||||
extern "C" void ExportedFunctionName() {
|
extern "C" void ExportedFunction() {
|
||||||
// Don't do anything - used to generate a symbol.
|
// Don't do anything - used to generate a symbol.
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace file = ::sapi::file;
|
namespace file = ::sapi::file;
|
||||||
using ::sapi::GetTestSourcePath;
|
using ::sapi::GetTestSourcePath;
|
||||||
using ::sapi::IsOk;
|
using ::sapi::IsOk;
|
||||||
|
using ::testing::ElementsAre;
|
||||||
using ::testing::Eq;
|
using ::testing::Eq;
|
||||||
using ::testing::IsTrue;
|
using ::testing::IsTrue;
|
||||||
using ::testing::Ne;
|
using ::testing::Ne;
|
||||||
|
@ -65,19 +66,20 @@ TEST(MinielfTest, SymbolResolutionWorks) {
|
||||||
ParseProcMaps(maps_buffer));
|
ParseProcMaps(maps_buffer));
|
||||||
|
|
||||||
// Find maps entry that covers this entry.
|
// Find maps entry that covers this entry.
|
||||||
uint64_t function_address = reinterpret_cast<uint64_t>(ExportedFunctionName);
|
uint64_t function_address = reinterpret_cast<uint64_t>(&ExportedFunction);
|
||||||
auto function_entry =
|
auto entry =
|
||||||
absl::c_find_if(maps, [function_address](const MapsEntry& entry) {
|
absl::c_find_if(maps, [function_address](const MapsEntry& entry) {
|
||||||
return entry.start <= function_address && entry.end > function_address;
|
return entry.start <= function_address && entry.end > function_address;
|
||||||
});
|
});
|
||||||
ASSERT_THAT(function_entry, Ne(maps.end()));
|
ASSERT_THAT(entry, Ne(maps.end()));
|
||||||
function_address -= function_entry->start;
|
|
||||||
|
|
||||||
auto function_symbol =
|
auto function_symbol =
|
||||||
absl::c_find_if(elf.symbols(), [](const ElfFile::Symbol& symbol) {
|
absl::c_find_if(elf.symbols(), [](const ElfFile::Symbol& symbol) {
|
||||||
return symbol.name == "ExportedFunctionName";
|
return symbol.name == "ExportedFunction";
|
||||||
});
|
});
|
||||||
ASSERT_THAT(function_symbol, Ne(elf.symbols().end()));
|
ASSERT_THAT(function_symbol, Ne(elf.symbols().end()));
|
||||||
|
|
||||||
|
function_address -= entry->start - entry->pgoff;
|
||||||
EXPECT_THAT(function_symbol->address, Eq(function_address));
|
EXPECT_THAT(function_symbol->address, Eq(function_address));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -86,8 +88,7 @@ TEST(MinielfTest, ImportedLibraries) {
|
||||||
ElfFile elf, ElfFile::ParseFromFile(
|
ElfFile elf, ElfFile::ParseFromFile(
|
||||||
GetTestSourcePath("sandbox2/util/testdata/hello_world"),
|
GetTestSourcePath("sandbox2/util/testdata/hello_world"),
|
||||||
ElfFile::kLoadImportedLibraries));
|
ElfFile::kLoadImportedLibraries));
|
||||||
std::vector<std::string> imported_libraries = {"libc.so.6"};
|
EXPECT_THAT(elf.imported_libraries(), ElementsAre("libc.so.6"));
|
||||||
EXPECT_THAT(elf.imported_libraries(), Eq(imported_libraries));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
|
@ -31,8 +31,11 @@ void SaveStatusToProto(const absl::Status& status, StatusProto* out) {
|
||||||
absl::Status MakeStatusFromProto(const StatusProto& proto) {
|
absl::Status MakeStatusFromProto(const StatusProto& proto) {
|
||||||
absl::Status status(static_cast<absl::StatusCode>(proto.code()),
|
absl::Status status(static_cast<absl::StatusCode>(proto.code()),
|
||||||
proto.message());
|
proto.message());
|
||||||
for (const auto& [type_key, payload] : proto.payloads()) {
|
// Note: Using C++17 structured bindings instead of `entry` crashes Clang 6.0
|
||||||
status.SetPayload(type_key, absl::Cord(payload));
|
// on Ubuntu 18.04 (bionic).
|
||||||
|
for (const auto& entry : proto.payloads()) {
|
||||||
|
status.SetPayload(/*type_url=*/entry.first,
|
||||||
|
/*payload=*/absl::Cord(entry.second));
|
||||||
}
|
}
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user