xref: /aosp_15_r20/external/sandboxed-api/contrib/brotli/utils/utils_brotli_enc.cc (revision ec63e07ab9515d95e79c211197c445ef84cefa6a)
1 // Copyright 2022 Google LLC
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //     https://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #include "contrib/brotli/utils/utils_brotli_enc.h"
16 
17 #include <fstream>
18 #include <string>
19 
20 #include "contrib/brotli/sandboxed.h"
21 #include "contrib/brotli/utils/utils_brotli.h"
22 
InitStructs()23 absl::Status BrotliEncoder::InitStructs() {
24   SAPI_ASSIGN_OR_RETURN(
25       BrotliEncoderState * state,
26       api_.BrotliEncoderCreateInstance(&null_ptr_, &null_ptr_, &null_ptr_));
27 
28   state_.SetRemote(state);
29 
30   return absl::OkStatus();
31 }
32 
~BrotliEncoder()33 BrotliEncoder::~BrotliEncoder() {
34   if (state_.GetRemote() != nullptr) {
35     api_.BrotliEncoderDestroyInstance(state_.PtrNone()).IgnoreError();
36   }
37 }
38 
IsInit()39 bool BrotliEncoder::IsInit() {
40   if (state_.GetRemote() == nullptr) {
41     return false;
42   }
43 
44   return true;
45 }
46 
CheckIsInit()47 absl::Status BrotliEncoder::CheckIsInit() {
48   if (!IsInit()) {
49     return absl::UnavailableError("The encoder is not initialized");
50   }
51 
52   return absl::OkStatus();
53 }
54 
SetParameter(enum BrotliEncoderParameter param,uint32_t value)55 absl::Status BrotliEncoder::SetParameter(enum BrotliEncoderParameter param,
56                                          uint32_t value) {
57   SAPI_RETURN_IF_ERROR(CheckIsInit());
58 
59   SAPI_ASSIGN_OR_RETURN(
60       int ret, api_.BrotliEncoderSetParameter(state_.PtrNone(), param, value));
61   if (!ret) {
62     return absl::UnavailableError("Unable to set parameter");
63   }
64 
65   return absl::OkStatus();
66 }
67 
Compress(std::vector<uint8_t> & buf_in,BrotliEncoderOperation op)68 absl::Status BrotliEncoder::Compress(std::vector<uint8_t>& buf_in,
69                                      BrotliEncoderOperation op) {
70   SAPI_RETURN_IF_ERROR(CheckIsInit());
71 
72   sapi::v::Array<uint8_t> sapi_buf_in(buf_in.data(), buf_in.size());
73   sapi::v::IntBase<size_t> sapi_size_in(buf_in.size());
74 
75   // BrotliEncoderCompress requires a pointer to a pointer,
76   // as function moves to pointer to indicate how much data
77   // was compressed.
78   // Un this case we compress whole buffer so we don't use it
79   // but we still have to allocate buffer remotely and gets
80   // a pointer.
81   SAPI_RETURN_IF_ERROR(sandbox_->Allocate(&sapi_buf_in));
82   SAPI_RETURN_IF_ERROR(sandbox_->TransferToSandboxee(&sapi_buf_in));
83   sapi::v::GenericPtr sapi_opaque_buf_in(sapi_buf_in.GetRemote());
84 
85   sapi::v::IntBase<size_t> sapi_avilable_out(0);
86 
87   SAPI_ASSIGN_OR_RETURN(
88       bool ret, api_.BrotliEncoderCompressStream(
89                     state_.PtrNone(), op, sapi_size_in.PtrBefore(),
90                     sapi_opaque_buf_in.PtrBefore(),
91                     sapi_avilable_out.PtrBefore(), &null_ptr_, &null_ptr_));
92   if (!ret) {
93     return absl::UnavailableError("Unable to compress input");
94   }
95 
96   return absl::OkStatus();
97 }
98 
TakeOutput()99 absl::StatusOr<std::vector<uint8_t>> BrotliEncoder::TakeOutput() {
100   SAPI_RETURN_IF_ERROR(CheckIsInit());
101 
102   sapi::v::IntBase<size_t> sapi_size_out(0);
103 
104   SAPI_ASSIGN_OR_RETURN(
105       uint8_t * sapi_out_buf_ptr,
106       api_.BrotliEncoderTakeOutput(state_.PtrNone(), sapi_size_out.PtrAfter()));
107   if (sapi_out_buf_ptr == nullptr) {
108     return std::vector<uint8_t>(0);
109   }
110   if (sapi_size_out.GetValue() > kFileMaxSize) {
111     return absl::UnavailableError("Output to large");
112   }
113 
114   std::vector<uint8_t> buf_out(sapi_size_out.GetValue());
115   sapi::v::Array<uint8_t> sapi_buf_out(buf_out.data(), buf_out.size());
116   sapi_buf_out.SetRemote(sapi_out_buf_ptr);
117 
118   SAPI_RETURN_IF_ERROR(sandbox_->TransferFromSandboxee(&sapi_buf_out));
119 
120   return buf_out;
121 }
122