parent
7e5962d3bc
commit
afbe9cc9b5
10 changed files with 4 additions and 384 deletions
@ -1,57 +0,0 @@ |
||||
load("@rules_cc//cc:defs.bzl", "cc_library", "cc_test") |
||||
load("//build_defs:cpp_opts.bzl", "COPTS") |
||||
|
||||
package(default_visibility = ["//visibility:private"]) |
||||
|
||||
cc_library( |
||||
name = "allowlist", |
||||
hdrs = ["allowlist.h"], |
||||
copts = COPTS, |
||||
strip_include_prefix = "/src", |
||||
deps = [ |
||||
"//src/google/protobuf/stubs", |
||||
"@com_google_absl//absl/algorithm:container", |
||||
"@com_google_absl//absl/base:core_headers", |
||||
"@com_google_absl//absl/container:flat_hash_set", |
||||
"@com_google_absl//absl/strings", |
||||
"@com_google_absl//absl/types:span", |
||||
], |
||||
) |
||||
|
||||
cc_library( |
||||
name = "allowlists", |
||||
srcs = [ |
||||
"open_enum.cc", |
||||
], |
||||
hdrs = ["allowlists.h"], |
||||
copts = COPTS, |
||||
strip_include_prefix = "/src", |
||||
visibility = ["//src/google/protobuf:__subpackages__"], |
||||
deps = [ |
||||
":allowlist", |
||||
"@com_google_absl//absl/strings", |
||||
], |
||||
) |
||||
|
||||
cc_test( |
||||
name = "allowlist_test", |
||||
srcs = ["allowlist_test.cc"], |
||||
copts = COPTS, |
||||
deps = [ |
||||
":allowlist", |
||||
"@com_google_googletest//:gtest", |
||||
"@com_google_googletest//:gtest_main", |
||||
], |
||||
) |
||||
|
||||
filegroup( |
||||
name = "test_srcs", |
||||
srcs = glob( |
||||
[ |
||||
"*_test.cc", |
||||
"*unittest.cc", |
||||
], |
||||
allow_empty = True, |
||||
), |
||||
visibility = ["//src/google/protobuf/compiler:__pkg__"], |
||||
) |
@ -1,146 +0,0 @@ |
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
//
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file or at
|
||||
// https://developers.google.com/open-source/licenses/bsd
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_COMPILER_ALLOWLISTS_ALLOWLIST_H__ |
||||
#define GOOGLE_PROTOBUF_COMPILER_ALLOWLISTS_ALLOWLIST_H__ |
||||
|
||||
#include <cstddef> |
||||
#include <cstring> |
||||
#include <string> |
||||
#include <type_traits> |
||||
|
||||
#include "absl/algorithm/container.h" |
||||
#include "google/protobuf/stubs/common.h" |
||||
#include "absl/container/flat_hash_set.h" |
||||
#include "absl/strings/match.h" |
||||
#include "absl/strings/string_view.h" |
||||
#include "absl/types/span.h" |
||||
|
||||
// Must be included last.
|
||||
#include "google/protobuf/port_def.inc" |
||||
|
||||
namespace google { |
||||
namespace protobuf { |
||||
namespace compiler { |
||||
namespace internal { |
||||
enum AllowlistFlags : unsigned int { |
||||
kNone = 0, |
||||
kMatchPrefix = 1 << 1, |
||||
kAllowAllInOss = 1 << 2, |
||||
kAllowAllWhenEmpty = 1 << 3, |
||||
kMatchRegex = 1 << 4, |
||||
}; |
||||
|
||||
|
||||
#if !defined(__GNUC__) || defined(__clang__) || PROTOBUF_GNUC_MIN(9, 1) |
||||
using maybe_string_view = absl::string_view; |
||||
#else |
||||
// In GCC versions before 9.1, template substitution fails because of the
|
||||
// implicit conversion between `const char*` and absl::string_view. In these
|
||||
// cases we can just use a raw string and convert later. See
|
||||
// https://godbolt.org/z/r57fx37d1 for an example of the failure.
|
||||
using maybe_string_view = const char*; |
||||
#endif |
||||
|
||||
// An allowlist of things (messages, files, targets) that are allowed to violate
|
||||
// some constraint.
|
||||
//
|
||||
// This is fundamentally a simple API over a set of static strings. It should
|
||||
// only ever be used as a `static const` variable.
|
||||
//
|
||||
// These allowlists are usually only used internally within Google, and contain
|
||||
// the names of internal files and Protobufs. In open source, these lists become
|
||||
// no-ops (either they always or never allow everything).
|
||||
template <size_t n> |
||||
class Allowlist final { |
||||
public: |
||||
template <size_t m = n, typename = std::enable_if_t<m != 0>> |
||||
constexpr Allowlist(const maybe_string_view (&list)[n], AllowlistFlags flags) |
||||
: flags_(flags) { |
||||
for (size_t i = 0; i < n; ++i) { |
||||
list_[i] = list[i]; |
||||
if (i != 0) { |
||||
ABSL_ASSERT(list_[i - 1] < list_[i] && "Allowlist must be sorted!"); |
||||
} |
||||
} |
||||
} |
||||
|
||||
template <size_t m = n, typename = std::enable_if_t<m == 0>> |
||||
explicit constexpr Allowlist(AllowlistFlags flags) |
||||
: list_(nullptr, 0), flags_(flags) {} |
||||
|
||||
// Checks if the element is allowed by this allowlist.
|
||||
bool Allows(absl::string_view name) const { |
||||
if (flags_ & AllowlistFlags::kAllowAllInOss) return true; |
||||
|
||||
// Convert to a span to get access to standard algorithms without resorting
|
||||
// to horrible things like std::end().
|
||||
absl::Span<const absl::string_view> list = list_; |
||||
|
||||
auto bound = absl::c_lower_bound(list, name); |
||||
if (bound == list.end()) { |
||||
// If this string has the last element as a prefix, it will appear as if
|
||||
// the element is not present in the list; we can take care of this case
|
||||
// by manually checking the last element.
|
||||
//
|
||||
// This will also spuriously fire if a string sorts before everything in
|
||||
// the list, but in that case the check will still return false as
|
||||
// expected.
|
||||
if (flags_ & AllowlistFlags::kMatchPrefix && !list.empty()) { |
||||
return absl::StartsWith(name, list.back()); |
||||
} |
||||
|
||||
return false; |
||||
} |
||||
|
||||
if (name == *bound) return true; |
||||
|
||||
if (flags_ & AllowlistFlags::kMatchPrefix && bound != list.begin()) { |
||||
return absl::StartsWith(name, bound[-1]); |
||||
} |
||||
|
||||
return false; |
||||
} |
||||
|
||||
private: |
||||
constexpr absl::Span<const absl::string_view> list() const { return list_; } |
||||
|
||||
// NOTE: std::array::operator[] is *not* constexpr before C++17.
|
||||
//
|
||||
// In order for a zero-element list to work, we replace the array with a
|
||||
// null string view when the size is zero.
|
||||
std::conditional_t<n != 0, absl::string_view[n], |
||||
absl::Span<absl::string_view>> |
||||
list_; |
||||
AllowlistFlags flags_; |
||||
}; |
||||
|
||||
struct EmptyAllowlistSentinel {}; |
||||
|
||||
// This overload picks up MakeAllowlist({}), since zero-length arrays are not
|
||||
// a thing in C++.
|
||||
constexpr Allowlist<0> MakeAllowlist( |
||||
EmptyAllowlistSentinel, // This binds to `{}`.
|
||||
AllowlistFlags flags = AllowlistFlags::kNone) { |
||||
return Allowlist<0>(flags); |
||||
} |
||||
|
||||
template <size_t n> |
||||
constexpr Allowlist<n> MakeAllowlist( |
||||
const maybe_string_view (&list)[n], |
||||
AllowlistFlags flags = AllowlistFlags::kNone) { |
||||
return Allowlist<n>(list, flags); |
||||
} |
||||
|
||||
} // namespace internal
|
||||
} // namespace compiler
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
#include "google/protobuf/port_undef.inc" |
||||
|
||||
#endif // GOOGLE_PROTOBUF_COMPILER_ALLOWLISTS_ALLOWLIST_H__
|
@ -1,97 +0,0 @@ |
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
//
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file or at
|
||||
// https://developers.google.com/open-source/licenses/bsd
|
||||
|
||||
#include "google/protobuf/compiler/allowlists/allowlist.h" |
||||
|
||||
#include <gtest/gtest.h> |
||||
|
||||
namespace google { |
||||
namespace protobuf { |
||||
namespace compiler { |
||||
namespace internal { |
||||
namespace { |
||||
|
||||
TEST(AllowlistTest, Smoke) { |
||||
static const auto kList = MakeAllowlist({ |
||||
"bar", |
||||
"baz", |
||||
"foo", |
||||
}); |
||||
|
||||
EXPECT_TRUE(kList.Allows("bar")); |
||||
EXPECT_TRUE(kList.Allows("baz")); |
||||
EXPECT_TRUE(kList.Allows("foo")); |
||||
EXPECT_FALSE(kList.Allows("barf")); |
||||
EXPECT_FALSE(kList.Allows("baq")); |
||||
EXPECT_FALSE(kList.Allows("bak")); |
||||
EXPECT_FALSE(kList.Allows("foob")); |
||||
} |
||||
|
||||
TEST(AllowlistTest, Empty) { |
||||
static const auto kList = MakeAllowlist({}); |
||||
|
||||
EXPECT_FALSE(kList.Allows("bar")); |
||||
EXPECT_FALSE(kList.Allows("baz")); |
||||
EXPECT_FALSE(kList.Allows("foo")); |
||||
EXPECT_FALSE(kList.Allows("barf")); |
||||
EXPECT_FALSE(kList.Allows("baq")); |
||||
EXPECT_FALSE(kList.Allows("bak")); |
||||
EXPECT_FALSE(kList.Allows("foob")); |
||||
} |
||||
|
||||
TEST(AllowlistTest, Prefix) { |
||||
static const auto kList = MakeAllowlist( |
||||
{ |
||||
"bar", |
||||
"baz", |
||||
"foo", |
||||
}, |
||||
AllowlistFlags::kMatchPrefix); |
||||
|
||||
EXPECT_TRUE(kList.Allows("bar")); |
||||
EXPECT_TRUE(kList.Allows("baz")); |
||||
EXPECT_TRUE(kList.Allows("foo")); |
||||
EXPECT_TRUE(kList.Allows("barf")); |
||||
EXPECT_TRUE(kList.Allows("foon")); |
||||
EXPECT_TRUE(kList.Allows("bazaar")); |
||||
EXPECT_FALSE(kList.Allows("baq")); |
||||
EXPECT_FALSE(kList.Allows("bbr")); |
||||
EXPECT_FALSE(kList.Allows("fbar")); |
||||
EXPECT_FALSE(kList.Allows("ba")); |
||||
EXPECT_FALSE(kList.Allows("fon")); |
||||
EXPECT_FALSE(kList.Allows("fop")); |
||||
} |
||||
|
||||
TEST(AllowlistTest, Oss) { |
||||
static const auto kList = MakeAllowlist( |
||||
{ |
||||
"bar", |
||||
"baz", |
||||
"foo", |
||||
}, |
||||
AllowlistFlags::kAllowAllInOss); |
||||
|
||||
EXPECT_TRUE(kList.Allows("bar")); |
||||
EXPECT_TRUE(kList.Allows("baz")); |
||||
EXPECT_TRUE(kList.Allows("foo")); |
||||
EXPECT_TRUE(kList.Allows("barf")); |
||||
EXPECT_TRUE(kList.Allows("baq")); |
||||
EXPECT_TRUE(kList.Allows("bak")); |
||||
EXPECT_TRUE(kList.Allows("foob")); |
||||
} |
||||
|
||||
#if GTEST_HAS_DEATH_TEST && !defined(NDEBUG) |
||||
TEST(AllowlistTest, Unsorted) { |
||||
EXPECT_DEATH(MakeAllowlist({"foo", "bar"}), "Allowlist must be sorted!"); |
||||
} |
||||
#endif |
||||
|
||||
} // namespace
|
||||
} // namespace internal
|
||||
} // namespace compiler
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
@ -1,43 +0,0 @@ |
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
//
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file or at
|
||||
// https://developers.google.com/open-source/licenses/bsd
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_COMPILER_ALLOWLISTS_ALLOWLISTS_H__ |
||||
#define GOOGLE_PROTOBUF_COMPILER_ALLOWLISTS_ALLOWLISTS_H__ |
||||
|
||||
#include "absl/strings/string_view.h" |
||||
|
||||
namespace google { |
||||
namespace protobuf { |
||||
namespace compiler { |
||||
|
||||
// Returns whether a file can use the `import weak` syntax.
|
||||
bool IsWeakImportFile(absl::string_view file); |
||||
|
||||
// Returns whether a file can have an empty package.
|
||||
bool IsEmptyPackageFile(absl::string_view file); |
||||
|
||||
// Returns whether a file can contain a cc_open_enum.
|
||||
bool IsOpenEnumFile(absl::string_view file); |
||||
|
||||
// Returns whether a message can contain a cc_open_enum.
|
||||
bool IsOpenEnumMessage(absl::string_view msg); |
||||
|
||||
// Returns whether a file can contain an unused import.
|
||||
bool IsUnusedImportFile(absl::string_view file); |
||||
|
||||
// Returns whether a file has early access to editions.
|
||||
bool IsEarlyEditionsFile(absl::string_view file); |
||||
|
||||
// Returns whether a file allows required fields.
|
||||
bool IsRequiredFieldFile(absl::string_view file); |
||||
|
||||
|
||||
} // namespace compiler
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
#endif // GOOGLE_PROTOBUF_ALLOWLISTS_COMPILER_ALLOWLISTS_H__
|
@ -1,36 +0,0 @@ |
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
//
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file or at
|
||||
// https://developers.google.com/open-source/licenses/bsd
|
||||
|
||||
#include "absl/strings/string_view.h" |
||||
#include "google/protobuf/compiler/allowlists/allowlist.h" |
||||
#include "google/protobuf/compiler/allowlists/allowlists.h" |
||||
|
||||
namespace google { |
||||
namespace protobuf { |
||||
namespace compiler { |
||||
|
||||
// NOTE: Allowlists in this file are not accepting new entries unless otherwise
|
||||
// specified.
|
||||
|
||||
static constexpr auto kOpenEnumFiles = internal::MakeAllowlist({ |
||||
// Intentionally left blank.
|
||||
}); |
||||
|
||||
static constexpr auto kOpenEnumMessages = internal::MakeAllowlist({ |
||||
// Intentionally left blank.
|
||||
}); |
||||
|
||||
bool IsOpenEnumFile(absl::string_view file) { |
||||
return kOpenEnumFiles.Allows(file); |
||||
} |
||||
|
||||
bool IsOpenEnumMessage(absl::string_view msg) { |
||||
return kOpenEnumMessages.Allows(msg); |
||||
} |
||||
} // namespace compiler
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
Loading…
Reference in new issue