tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

BaseAndGeckoProfilerDetail.cpp (2933B)


      1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
      2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
      3 /* This Source Code Form is subject to the terms of the Mozilla Public
      4 * License, v. 2.0. If a copy of the MPL was not distributed with this
      5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      6 
      7 #include "mozilla/BaseAndGeckoProfilerDetail.h"
      8 
      9 #include <limits>
     10 #include <string_view>
     11 
     12 namespace mozilla::profiler::detail {
     13 
     14 constexpr std::string_view scPidPrefix = "pid:";
     15 
     16 // Convert a C string to a BaseProfilerProcessId. Return unspecified
     17 // BaseProfilerProcessId if the string is not exactly a valid pid.
     18 static baseprofiler::BaseProfilerProcessId StringToPid(const char* aString) {
     19  if (!aString || aString[0] == '\0') {
     20    // Null or empty.
     21    return baseprofiler::BaseProfilerProcessId{};
     22  }
     23 
     24  if (aString[0] == '0') {
     25    if (aString[1] != '\0') {
     26      // Don't accept leading zeroes.
     27      return baseprofiler::BaseProfilerProcessId{};
     28    }
     29    return baseprofiler::BaseProfilerProcessId::FromNumber(0);
     30  }
     31 
     32  using PidNumber = baseprofiler::BaseProfilerProcessId::NumberType;
     33  PidNumber pid = 0;
     34  for (;;) {
     35    const char c = *aString;
     36    if (c == '\0') {
     37      break;
     38    }
     39    if (c < '0' || c > '9') {
     40      // Only accept decimal digits.
     41      return baseprofiler::BaseProfilerProcessId{};
     42    }
     43    static_assert(!std::numeric_limits<PidNumber>::is_signed,
     44                  "The following relies on unsigned arithmetic");
     45    PidNumber newPid = pid * 10u + PidNumber(c - '0');
     46    if (newPid < pid) {
     47      // Unsigned overflow.
     48      return baseprofiler::BaseProfilerProcessId{};
     49    }
     50    pid = newPid;
     51    ++aString;
     52  }
     53  return baseprofiler::BaseProfilerProcessId::FromNumber(pid);
     54 }
     55 
     56 [[nodiscard]] MFBT_API bool FilterHasPid(
     57    const char* aFilter, baseprofiler::BaseProfilerProcessId aPid) {
     58  if (strncmp(aFilter, scPidPrefix.data(), scPidPrefix.length()) != 0) {
     59    // The filter is not starting with "pid:".
     60    return false;
     61  }
     62 
     63  return StringToPid(aFilter + scPidPrefix.length()) == aPid;
     64 }
     65 
     66 [[nodiscard]] MFBT_API bool FiltersExcludePid(
     67    Span<const char* const> aFilters,
     68    baseprofiler::BaseProfilerProcessId aPid) {
     69  if (aFilters.empty()) {
     70    return false;
     71  }
     72 
     73  // First, check if the list only contains "pid:..." strings.
     74  for (const char* const filter : aFilters) {
     75    if (strncmp(filter, scPidPrefix.data(), scPidPrefix.length()) != 0) {
     76      // At least one filter is *not* a "pid:...", our pid is not excluded.
     77      return false;
     78    }
     79  }
     80 
     81  // Here, all filters start with "pid:". Check if the given pid is included.
     82  for (const char* const filter : aFilters) {
     83    if (StringToPid(filter + scPidPrefix.length()) == aPid) {
     84      // Our pid is present, so it's not excluded.
     85      return false;
     86    }
     87  }
     88  // Our pid was not in a list of only pids, so it's excluded.
     89  return true;
     90 }
     91 
     92 }  // namespace mozilla::profiler::detail