1 // Copyright (C) 2024 The Android Open Source Project
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 // http://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 "src/trace_processor/perfetto_sql/intrinsics/functions/base64.h"
16
17 #include <cstddef>
18 #include <cstdlib>
19 #include <cstring>
20
21 #include "perfetto/base/status.h"
22 #include "perfetto/ext/base/base64.h"
23 #include "perfetto/trace_processor/basic_types.h"
24 #include "src/trace_processor/perfetto_sql/engine/perfetto_sql_engine.h"
25 #include "src/trace_processor/perfetto_sql/intrinsics/functions/sql_function.h"
26 #include "src/trace_processor/sqlite/sqlite_utils.h"
27
28 namespace perfetto::trace_processor {
29
30 namespace {
31
32 struct Base64Decode : public SqlFunction {
Runperfetto::trace_processor::__anon968341900111::Base64Decode33 static base::Status Run(Context*,
34 size_t argc,
35 sqlite3_value** argv,
36 SqlValue& out,
37 Destructors& destructors) {
38 if (argc != 1) {
39 return base::ErrStatus("BASE64: expected one arg but got %zu", argc);
40 }
41
42 auto in = sqlite::utils::SqliteValueToSqlValue(argv[0]);
43
44 const char* src = nullptr;
45 size_t src_size = 0;
46 switch (in.type) {
47 case SqlValue::kNull:
48 return base::OkStatus();
49 case SqlValue::kLong:
50 case SqlValue::kDouble:
51 return base::ErrStatus("BASE64: argument must be string or blob");
52 case SqlValue::kString:
53 src = in.AsString();
54 src_size = strlen(src);
55 break;
56 case SqlValue::kBytes:
57 src = reinterpret_cast<const char*>(in.AsBytes());
58 src_size = in.bytes_count;
59 break;
60 }
61
62 size_t dst_size = base::Base64DecSize(src_size);
63 uint8_t* dst = reinterpret_cast<uint8_t*>(malloc(dst_size));
64 ssize_t res = base::Base64Decode(src, src_size, dst, dst_size);
65 if (res < 0) {
66 free(dst);
67 return base::ErrStatus("BASE64: Invalid input");
68 }
69 dst_size = static_cast<size_t>(res);
70 out = SqlValue::Bytes(dst, dst_size);
71 destructors.bytes_destructor = free;
72 return base::OkStatus();
73 }
74 };
75
76 } // namespace
77
RegisterBase64Functions(PerfettoSqlEngine & engine)78 base::Status RegisterBase64Functions(PerfettoSqlEngine& engine) {
79 return engine.RegisterStaticFunction<Base64Decode>("base64_decode", 1,
80 nullptr, true);
81 }
82
83 } // namespace perfetto::trace_processor
84