xref: /aosp_15_r20/external/sandboxed-api/sandboxed_api/examples/stringop/stringop.cc (revision ec63e07ab9515d95e79c211197c445ef84cefa6a)
1 // Copyright 2019 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 <sys/ptrace.h>
16 
17 #include <algorithm>
18 #include <cstdlib>
19 #include <string>
20 
21 #include "absl/base/attributes.h"
22 #include "sandboxed_api/examples/stringop/stringop_params.pb.h"
23 #include "sandboxed_api/lenval_core.h"
24 
25 // Protobuf examples.
pb_reverse_string(stringop::StringReverse * pb)26 extern "C" int pb_reverse_string(stringop::StringReverse* pb) {
27   if (pb->payload_case() == pb->kInput) {
28     std::string output = pb->input();
29     std::reverse(output.begin(), output.end());
30     pb->set_output(output);
31     return 1;
32   }
33   return 0;
34 }
35 
pb_duplicate_string(stringop::StringDuplication * pb)36 extern "C" int pb_duplicate_string(stringop::StringDuplication* pb) {
37   if (pb->payload_case() == pb->kInput) {
38     auto output = pb->input();
39     pb->set_output(output + output);
40     return 1;
41   }
42   return 0;
43 }
44 
45 // Examples on raw data - both allocate and replace the data pointer.
reverse_string(sapi::LenValStruct * input)46 extern "C" int reverse_string(sapi::LenValStruct* input) {
47   char* new_buf = static_cast<char*>(malloc(input->size));
48   const char* src_buf = static_cast<const char*>(input->data);
49   input->size = input->size;
50   for (size_t i = 0; i < input->size; i++) {
51     new_buf[i] = src_buf[input->size - i - 1];
52   }
53   // Free old value.
54   free(input->data);
55   // Replace pointer to our new string.
56   input->data = new_buf;
57   return 1;
58 }
59 
duplicate_string(sapi::LenValStruct * input)60 extern "C" int duplicate_string(sapi::LenValStruct* input) {
61   char* new_buf = static_cast<char*>(malloc(2 * input->size));
62   const char* src_buf = static_cast<const char*>(input->data);
63 
64   for (size_t c = 0; c < 2; c++) {
65     for (size_t i = 0; i < input->size; i++) {
66       new_buf[i + input->size * c] = src_buf[i];
67     }
68   }
69 
70   // Free old value.
71   free(input->data);
72   // Update structure.
73   input->size = 2 * input->size;
74   input->data = new_buf;
75   return 1;
76 }
77 
get_raw_c_string()78 extern "C" const void* get_raw_c_string() { return "Ten chars."; }
79 
nop()80 extern "C" void nop() {}
81 
82 // The "no tail-call" annotation and the additional indirection ensure that
83 // either this function or its calling function shows up in the violation stack
84 // trace. Otherwise, depending on optimization level and optimizer
85 // aggressiveness, functions may be inlined, hoisted or omitted (in case of tail
86 // calls).
87 static ABSL_ATTRIBUTE_NOINLINE ABSL_ATTRIBUTE_NO_TAIL_CALL void
ViolateIndirect()88 ViolateIndirect() {
89   ptrace((__ptrace_request)990, 991, 992, 993);
90 }
91 
92 // Using block syntax here, because SAPI's libclang based header generator won't
93 // parse the attribute annotations otherwise.
94 extern "C" {
violate()95 ABSL_ATTRIBUTE_NOINLINE ABSL_ATTRIBUTE_NO_TAIL_CALL void violate() {
96   ViolateIndirect();
97 }
98 }
99