• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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