1*ec63e07aSXin Li // Copyright 2019 Google LLC 2*ec63e07aSXin Li // 3*ec63e07aSXin Li // Licensed under the Apache License, Version 2.0 (the "License"); 4*ec63e07aSXin Li // you may not use this file except in compliance with the License. 5*ec63e07aSXin Li // You may obtain a copy of the License at 6*ec63e07aSXin Li // 7*ec63e07aSXin Li // https://www.apache.org/licenses/LICENSE-2.0 8*ec63e07aSXin Li // 9*ec63e07aSXin Li // Unless required by applicable law or agreed to in writing, software 10*ec63e07aSXin Li // distributed under the License is distributed on an "AS IS" BASIS, 11*ec63e07aSXin Li // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12*ec63e07aSXin Li // See the License for the specific language governing permissions and 13*ec63e07aSXin Li // limitations under the License. 14*ec63e07aSXin Li 15*ec63e07aSXin Li #ifndef SANDBOXED_API_VAR_ARRAY_H_ 16*ec63e07aSXin Li #define SANDBOXED_API_VAR_ARRAY_H_ 17*ec63e07aSXin Li 18*ec63e07aSXin Li #include <algorithm> 19*ec63e07aSXin Li #include <cstdlib> 20*ec63e07aSXin Li #include <cstring> 21*ec63e07aSXin Li #include <memory> 22*ec63e07aSXin Li #include <string> 23*ec63e07aSXin Li #include <type_traits> 24*ec63e07aSXin Li 25*ec63e07aSXin Li #include "absl/base/macros.h" 26*ec63e07aSXin Li #include "absl/log/check.h" 27*ec63e07aSXin Li #include "absl/log/log.h" 28*ec63e07aSXin Li #include "absl/status/status.h" 29*ec63e07aSXin Li #include "absl/strings/str_cat.h" 30*ec63e07aSXin Li #include "absl/strings/string_view.h" 31*ec63e07aSXin Li #include "sandboxed_api/rpcchannel.h" 32*ec63e07aSXin Li #include "sandboxed_api/util/status_macros.h" 33*ec63e07aSXin Li #include "sandboxed_api/var_abstract.h" 34*ec63e07aSXin Li #include "sandboxed_api/var_ptr.h" 35*ec63e07aSXin Li 36*ec63e07aSXin Li namespace sapi::v { 37*ec63e07aSXin Li 38*ec63e07aSXin Li // Class representing an array. 39*ec63e07aSXin Li template <class T> 40*ec63e07aSXin Li class Array : public Var { 41*ec63e07aSXin Li public: 42*ec63e07aSXin Li // The array is not owned by this object. Array(T * arr,size_t nelem)43*ec63e07aSXin Li Array(T* arr, size_t nelem) 44*ec63e07aSXin Li : arr_(arr), 45*ec63e07aSXin Li nelem_(nelem), 46*ec63e07aSXin Li total_size_(nelem_ * sizeof(T)), 47*ec63e07aSXin Li buffer_owned_(false) { 48*ec63e07aSXin Li SetLocal(const_cast<std::remove_const_t<T>*>(arr_)); 49*ec63e07aSXin Li } 50*ec63e07aSXin Li 51*ec63e07aSXin Li // The array is allocated and owned by this object. Array(size_t nelem)52*ec63e07aSXin Li explicit Array(size_t nelem) 53*ec63e07aSXin Li : nelem_(nelem), total_size_(nelem_ * sizeof(T)), buffer_owned_(true) { 54*ec63e07aSXin Li void* storage = malloc(sizeof(T) * nelem); 55*ec63e07aSXin Li CHECK(storage != nullptr); 56*ec63e07aSXin Li SetLocal(storage); 57*ec63e07aSXin Li arr_ = static_cast<T*>(storage); 58*ec63e07aSXin Li } 59*ec63e07aSXin Li ~Array()60*ec63e07aSXin Li virtual ~Array() { 61*ec63e07aSXin Li if (buffer_owned_) { 62*ec63e07aSXin Li free(const_cast<std::remove_const_t<T>*>(arr_)); 63*ec63e07aSXin Li } 64*ec63e07aSXin Li } 65*ec63e07aSXin Li 66*ec63e07aSXin Li T& operator[](size_t v) const { return arr_[v]; } GetData()67*ec63e07aSXin Li T* GetData() const { return arr_; } 68*ec63e07aSXin Li GetNElem()69*ec63e07aSXin Li size_t GetNElem() const { return nelem_; } GetSize()70*ec63e07aSXin Li size_t GetSize() const final { return total_size_; } GetType()71*ec63e07aSXin Li Type GetType() const final { return Type::kArray; } GetTypeString()72*ec63e07aSXin Li std::string GetTypeString() const final { return "Array"; } ToString()73*ec63e07aSXin Li std::string ToString() const override { 74*ec63e07aSXin Li return absl::StrCat("Array, elem size: ", sizeof(T), 75*ec63e07aSXin Li " B., total size: ", total_size_, 76*ec63e07aSXin Li " B., nelems: ", GetNElem()); 77*ec63e07aSXin Li } 78*ec63e07aSXin Li 79*ec63e07aSXin Li // Resizes the local and remote buffer using realloc(). Note that this will 80*ec63e07aSXin Li // make all pointers to the current data (inside and outside of the sandbox) 81*ec63e07aSXin Li // invalid. Resize(RPCChannel * rpc_channel,size_t nelems)82*ec63e07aSXin Li absl::Status Resize(RPCChannel* rpc_channel, size_t nelems) { 83*ec63e07aSXin Li size_t absolute_size = sizeof(T) * nelems; 84*ec63e07aSXin Li // Resize local buffer. 85*ec63e07aSXin Li SAPI_RETURN_IF_ERROR(EnsureOwnedLocalBuffer(absolute_size)); 86*ec63e07aSXin Li 87*ec63e07aSXin Li // Resize remote buffer and update local pointer. 88*ec63e07aSXin Li void* new_addr; 89*ec63e07aSXin Li 90*ec63e07aSXin Li SAPI_RETURN_IF_ERROR( 91*ec63e07aSXin Li rpc_channel->Reallocate(GetRemote(), absolute_size, &new_addr)); 92*ec63e07aSXin Li if (!new_addr) { 93*ec63e07aSXin Li return absl::UnavailableError("Reallocate() returned nullptr"); 94*ec63e07aSXin Li } 95*ec63e07aSXin Li SetRemote(new_addr); 96*ec63e07aSXin Li return absl::OkStatus(); 97*ec63e07aSXin Li } 98*ec63e07aSXin Li 99*ec63e07aSXin Li private: 100*ec63e07aSXin Li friend class LenVal; 101*ec63e07aSXin Li 102*ec63e07aSXin Li // Resizes the internal storage. EnsureOwnedLocalBuffer(size_t size)103*ec63e07aSXin Li absl::Status EnsureOwnedLocalBuffer(size_t size) { 104*ec63e07aSXin Li if (size % sizeof(T)) { 105*ec63e07aSXin Li return absl::FailedPreconditionError( 106*ec63e07aSXin Li "Array size not a multiple of the item size"); 107*ec63e07aSXin Li } 108*ec63e07aSXin Li // Do not (re-)allocate memory if the new size matches our size - except 109*ec63e07aSXin Li // when we don't own that buffer. 110*ec63e07aSXin Li if (size == total_size_ && buffer_owned_) { 111*ec63e07aSXin Li return absl::OkStatus(); 112*ec63e07aSXin Li } 113*ec63e07aSXin Li void* new_addr = nullptr; 114*ec63e07aSXin Li if (buffer_owned_) { 115*ec63e07aSXin Li new_addr = realloc(arr_, size); 116*ec63e07aSXin Li } else { 117*ec63e07aSXin Li new_addr = malloc(size); 118*ec63e07aSXin Li if (new_addr) { 119*ec63e07aSXin Li memcpy(new_addr, arr_, std::min(size, total_size_)); 120*ec63e07aSXin Li buffer_owned_ = true; 121*ec63e07aSXin Li } 122*ec63e07aSXin Li } 123*ec63e07aSXin Li if (!new_addr) { 124*ec63e07aSXin Li return absl::UnavailableError("(Re-)malloc failed"); 125*ec63e07aSXin Li } 126*ec63e07aSXin Li 127*ec63e07aSXin Li arr_ = static_cast<T*>(new_addr); 128*ec63e07aSXin Li total_size_ = size; 129*ec63e07aSXin Li nelem_ = size / sizeof(T); 130*ec63e07aSXin Li SetLocal(new_addr); 131*ec63e07aSXin Li return absl::OkStatus(); 132*ec63e07aSXin Li } 133*ec63e07aSXin Li 134*ec63e07aSXin Li // Pointer to the data, owned by the object if buffer_owned_ is 'true'. 135*ec63e07aSXin Li T* arr_; 136*ec63e07aSXin Li size_t nelem_; // Number of elements 137*ec63e07aSXin Li size_t total_size_; // Total size in bytes 138*ec63e07aSXin Li bool buffer_owned_; // Whether we own the buffer 139*ec63e07aSXin Li }; 140*ec63e07aSXin Li 141*ec63e07aSXin Li // Specialized Array class for representing NUL-terminated C-style strings. The 142*ec63e07aSXin Li // buffer is owned by the class, and is mutable. 143*ec63e07aSXin Li class CStr : public Array<char> { 144*ec63e07aSXin Li public: CStr(absl::string_view cstr)145*ec63e07aSXin Li explicit CStr(absl::string_view cstr) : Array<char>(cstr.size() + 1) { 146*ec63e07aSXin Li std::copy(cstr.begin(), cstr.end(), GetData()); 147*ec63e07aSXin Li GetData()[cstr.size()] = '\0'; 148*ec63e07aSXin Li } 149*ec63e07aSXin Li ToString()150*ec63e07aSXin Li std::string ToString() const final { 151*ec63e07aSXin Li return absl::StrCat("CStr: len(w/o NUL):", strlen(GetData()), ", ['", 152*ec63e07aSXin Li GetData(), "']"); 153*ec63e07aSXin Li } 154*ec63e07aSXin Li }; 155*ec63e07aSXin Li 156*ec63e07aSXin Li // Specialized Array class for representing NUL-terminated C-style strings. The 157*ec63e07aSXin Li // buffer is not owned by the class and is not mutable. 158*ec63e07aSXin Li class ConstCStr : public Array<const char> { 159*ec63e07aSXin Li public: ConstCStr(const char * cstr)160*ec63e07aSXin Li explicit ConstCStr(const char* cstr) 161*ec63e07aSXin Li : Array<const char>(cstr, strlen(cstr) + 1) {} 162*ec63e07aSXin Li ToString()163*ec63e07aSXin Li std::string ToString() const final { 164*ec63e07aSXin Li return absl::StrCat("ConstCStr: len(w/o NUL):", strlen(GetData()), ", ['", 165*ec63e07aSXin Li GetData(), "']"); 166*ec63e07aSXin Li } 167*ec63e07aSXin Li }; 168*ec63e07aSXin Li 169*ec63e07aSXin Li } // namespace sapi::v 170*ec63e07aSXin Li 171*ec63e07aSXin Li #endif // SANDBOXED_API_VAR_ARRAY_H_ 172