1 /*
2  * Copyright (C) 2018 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include "src/traced/probes/ftrace/ftrace_config_utils.h"
18 
19 #include "perfetto/base/logging.h"
20 
21 namespace perfetto {
22 namespace {
23 
24 // Excludes \r, \n, escape sequences and control chars.
IsPrintableASCIIOrSpace(char c)25 bool IsPrintableASCIIOrSpace(char c) {
26   return c >= 32 && c < 127;
27 }
28 
IsValidAtraceEventName(const std::string & str)29 bool IsValidAtraceEventName(const std::string& str) {
30   for (size_t i = 0; i < str.size(); i++) {
31     if (!IsPrintableASCIIOrSpace(str[i]))
32       return false;
33   }
34   return true;
35 }
36 
IsValidFtraceEventName(const std::string & str)37 bool IsValidFtraceEventName(const std::string& str) {
38   int slash_count = 0;
39   for (size_t i = 0; i < str.size(); i++) {
40     if (!IsPrintableASCIIOrSpace(str[i]))
41       return false;
42     if (str[i] == '/') {
43       slash_count++;
44       // At most one '/' allowed and not at the beginning or end.
45       if (slash_count > 1 || i == 0 || i == str.size() - 1)
46         return false;
47     }
48     if (str[i] == '*' && i != str.size() - 1)
49       return false;
50   }
51   return true;
52 }
53 
54 }  // namespace
55 
CreateFtraceConfig(std::set<std::string> names)56 FtraceConfig CreateFtraceConfig(std::set<std::string> names) {
57   FtraceConfig config;
58   for (const std::string& name : names)
59     *config.add_ftrace_events() = name;
60   return config;
61 }
62 
RequiresAtrace(const FtraceConfig & config)63 bool RequiresAtrace(const FtraceConfig& config) {
64   return !config.atrace_categories().empty() || !config.atrace_apps().empty();
65 }
66 
ValidConfig(const FtraceConfig & config)67 bool ValidConfig(const FtraceConfig& config) {
68   for (const std::string& event_name : config.ftrace_events()) {
69     if (!IsValidFtraceEventName(event_name)) {
70       PERFETTO_ELOG("Bad event name '%s'", event_name.c_str());
71       return false;
72     }
73   }
74   for (const std::string& category : config.atrace_categories()) {
75     if (!IsValidAtraceEventName(category)) {
76       PERFETTO_ELOG("Bad category name '%s'", category.c_str());
77       return false;
78     }
79   }
80   for (const std::string& app : config.atrace_apps()) {
81     if (!IsValidAtraceEventName(app)) {
82       PERFETTO_ELOG("Bad app '%s'", app.c_str());
83       return false;
84     }
85   }
86   return true;
87 }
88 
89 }  // namespace perfetto
90