• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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_dec.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 BrotliDecoder::InitStructs() {
24   SAPI_ASSIGN_OR_RETURN(
25       BrotliDecoderState * state,
26       api_.BrotliDecoderCreateInstance(nullptr, nullptr, nullptr));
27 
28   state_.SetRemote(state);
29 
30   return absl::OkStatus();
31 }
32 
~BrotliDecoder()33 BrotliDecoder::~BrotliDecoder() {
34   if (state_.GetRemote() != nullptr) {
35     api_.BrotliDecoderDestroyInstance(state_.PtrNone()).IgnoreError();
36   }
37 }
38 
IsInit()39 bool BrotliDecoder::IsInit() {
40   if (state_.GetRemote() == nullptr) {
41     return false;
42   }
43 
44   return true;
45 }
46 
CheckIsInit()47 absl::Status BrotliDecoder::CheckIsInit() {
48   if (!IsInit()) {
49     return absl::UnavailableError("The decoder is not initialized");
50   }
51 
52   return absl::OkStatus();
53 }
54 
SetParameter(enum BrotliDecoderParameter param,uint32_t value)55 absl::Status BrotliDecoder::SetParameter(enum BrotliDecoderParameter param,
56                                          uint32_t value) {
57   SAPI_RETURN_IF_ERROR(CheckIsInit());
58 
59   SAPI_ASSIGN_OR_RETURN(
60       int ret, api_.BrotliDecoderSetParameter(state_.PtrNone(), param, value));
61   if (!ret) {
62     return absl::UnavailableError("Unable to set parameter");
63   }
64 
65   return absl::OkStatus();
66 }
67 
Decompress(std::vector<uint8_t> & buf_in)68 absl::StatusOr<BrotliDecoderResult> BrotliDecoder::Decompress(
69     std::vector<uint8_t>& buf_in) {
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   // BrotliDecoderCompress requires a pointer to a pointer,
76   // as function moves to pointer to indicate how much data
77   // was compressed.
78   // In 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(BrotliDecoderResult ret,
88                         api_.BrotliDecoderDecompressStream(
89                             state_.PtrNone(), sapi_size_in.PtrBefore(),
90                             sapi_opaque_buf_in.PtrBefore(),
91                             sapi_avilable_out.PtrBefore(), nullptr, nullptr));
92 
93   // Ignore output error, as we didn't provide any buffer.
94   if (ret == BROTLI_DECODER_RESULT_NEEDS_MORE_OUTPUT) {
95     ret = BROTLI_DECODER_RESULT_SUCCESS;
96   }
97 
98   return ret;
99 }
100 
TakeOutput()101 absl::StatusOr<std::vector<uint8_t>> BrotliDecoder::TakeOutput() {
102   SAPI_RETURN_IF_ERROR(CheckIsInit());
103 
104   sapi::v::IntBase<size_t> sapi_size_out(0);
105 
106   SAPI_ASSIGN_OR_RETURN(
107       uint8_t * sapi_out_buf_ptr,
108       api_.BrotliDecoderTakeOutput(state_.PtrNone(), sapi_size_out.PtrAfter()));
109   if (sapi_out_buf_ptr == nullptr || sapi_size_out.GetValue() == 0) {
110     return std::vector<uint8_t>(0);
111   }
112   if (sapi_size_out.GetValue() > kFileMaxSize) {
113     return absl::UnavailableError("Output to large");
114   }
115 
116   std::vector<uint8_t> buf_out(sapi_size_out.GetValue());
117   sapi::v::Array<uint8_t> sapi_buf_out(buf_out.data(), buf_out.size());
118   sapi_buf_out.SetRemote(sapi_out_buf_ptr);
119 
120   SAPI_RETURN_IF_ERROR(sandbox_->TransferFromSandboxee(&sapi_buf_out));
121 
122   return buf_out;
123 }
124