diff options
author | Abseil Team <absl-team@google.com> | 2020-03-23T20·16-0700 |
---|---|---|
committer | Xiaoyi Zhang <zhangxy@google.com> | 2020-03-23T20·24-0400 |
commit | 518f17501e6156f7921fbb9b68a1e420bcb10bc5 (patch) | |
tree | 615cb6be894145feaa79ff3e341f2d483022f336 /absl/flags/internal | |
parent | 092ed9793a1ad0e7e418f32c057bf3159a71cd04 (diff) |
Export of internal Abseil changes
-- 79913a12f0cad4baf948430315aabf53f03b6475 by Abseil Team <absl-team@google.com>: Don't inline (Un)LockSlow. PiperOrigin-RevId: 302502344 -- 6b340e80f0690655f24799c8de6707b3a95b8579 by Derek Mauro <dmauro@google.com>: Add hardening assertions to absl::optional's dereference operators PiperOrigin-RevId: 302492862 -- a9951bf4852d8c1aec472cb4b539830411270e4c by Derek Mauro <dmauro@google.com>: Correctly add hardware AES compiler flags under Linux X86-64 Fixes #643 PiperOrigin-RevId: 302490673 -- 314c3621ee4d57b6bc8d64338a1f1d48a69741d1 by Derek Mauro <dmauro@google.com>: Upgrade to hardening assertions in absl::Span::remove_prefix and absl::Span::remove_suffix PiperOrigin-RevId: 302481191 -- a142b8c6c62705c5f0d4fe3113150f0c0b7822b9 by Derek Mauro <dmauro@google.com>: Update docker containers to Bazel 2.2.0, GCC 9.3, and new Clang snapshot PiperOrigin-RevId: 302454042 -- afedeb70a2adc87010030c9ba6f06fe35ec26407 by Derek Mauro <dmauro@google.com>: Add hardening assertions for the preconditions of absl::FixedArray PiperOrigin-RevId: 302441767 -- 44442bfbc0a9a742df32f07cee86a47712efb8b4 by Derek Mauro <dmauro@google.com>: Fix new Clang warning about SpinLock doing operations on enums of different types PiperOrigin-RevId: 302430387 -- 69eaff7f97231779f696321c2ba8b88debf6dd9e by Derek Mauro <dmauro@google.com>: Convert precondition assertions to ABSL_HARDENING_ASSERT for absl::InlinedVector PiperOrigin-RevId: 302427894 -- 26b6db906a0942fd18583dc2cdd1bab32919d964 by Gennadiy Rozental <rogeeff@google.com>: Internal change PiperOrigin-RevId: 302425283 -- e62e81422979e922505d2cd9000e1de58123c088 by Derek Mauro <dmauro@google.com>: Add an option to build Abseil in hardened mode In hardened mode, the ABSL_HARDENING_ASSERT() macro is active even when NDEBUG is defined. This allows Abseil to perform runtime checks even in release mode. This should be used to implement things like bounds checks that could otherwise lead to security vulnerabilities. Use the new assertion in absl::string_view and absl::Span to test it. PiperOrigin-RevId: 302119187 GitOrigin-RevId: 79913a12f0cad4baf948430315aabf53f03b6475 Change-Id: I0cc3341fd333a1df313167bab72dc5a759c4a048
Diffstat (limited to 'absl/flags/internal')
-rw-r--r-- | absl/flags/internal/flag.cc | 131 | ||||
-rw-r--r-- | absl/flags/internal/flag.h | 166 |
2 files changed, 162 insertions, 135 deletions
diff --git a/absl/flags/internal/flag.cc b/absl/flags/internal/flag.cc index a45e883e071c..56a5ed2bc468 100644 --- a/absl/flags/internal/flag.cc +++ b/absl/flags/internal/flag.cc @@ -74,6 +74,59 @@ class MutexRelock { } // namespace +/////////////////////////////////////////////////////////////////////////////// +// Persistent state of the flag data. + +class FlagImpl; + +class FlagState : public flags_internal::FlagStateInterface { + public: + template <typename V> + FlagState(FlagImpl* flag_impl, const V& v, bool modified, + bool on_command_line, int64_t counter) + : flag_impl_(flag_impl), + value_(v), + modified_(modified), + on_command_line_(on_command_line), + counter_(counter) {} + + ~FlagState() override { + if (flag_impl_->ValueStorageKind() != FlagValueStorageKind::kHeapAllocated) + return; + flags_internal::Delete(flag_impl_->op_, value_.dynamic); + } + + private: + friend class FlagImpl; + + // Restores the flag to the saved state. + void Restore() const override { + if (!flag_impl_->RestoreState(*this)) return; + + ABSL_INTERNAL_LOG( + INFO, absl::StrCat("Restore saved value of ", flag_impl_->Name(), + " to: ", flag_impl_->CurrentValue())); + } + + // Flag and saved flag data. + FlagImpl* flag_impl_; + union SavedValue { + explicit SavedValue(void* v) : dynamic(v) {} + explicit SavedValue(int64_t v) : one_word(v) {} + explicit SavedValue(flags_internal::AlignedTwoWords v) : two_words(v) {} + + void* dynamic; + int64_t one_word; + flags_internal::AlignedTwoWords two_words; + } value_; + bool modified_; + bool on_command_line_; + int64_t counter_; +}; + +/////////////////////////////////////////////////////////////////////////////// +// Flag implementation, which does not depend on flag value type. + void FlagImpl::Init() { new (&data_guard_) absl::Mutex; @@ -86,13 +139,13 @@ void FlagImpl::Init() { break; case FlagValueStorageKind::kOneWordAtomic: { int64_t atomic_value; - std::memcpy(&atomic_value, init_value.get(), Sizeof(op_)); + std::memcpy(&atomic_value, init_value.get(), flags_internal::Sizeof(op_)); value_.one_word_atomic.store(atomic_value, std::memory_order_release); break; } case FlagValueStorageKind::kTwoWordsAtomic: { AlignedTwoWords atomic_value{0, 0}; - std::memcpy(&atomic_value, init_value.get(), Sizeof(op_)); + std::memcpy(&atomic_value, init_value.get(), flags_internal::Sizeof(op_)); value_.two_words_atomic.store(atomic_value, std::memory_order_release); break; } @@ -145,17 +198,17 @@ std::unique_ptr<void, DynValueDeleter> FlagImpl::MakeInitValue() const { void FlagImpl::StoreValue(const void* src) { switch (ValueStorageKind()) { case FlagValueStorageKind::kHeapAllocated: - Copy(op_, src, value_.dynamic); + flags_internal::Copy(op_, src, value_.dynamic); break; case FlagValueStorageKind::kOneWordAtomic: { int64_t one_word_val; - std::memcpy(&one_word_val, src, Sizeof(op_)); + std::memcpy(&one_word_val, src, flags_internal::Sizeof(op_)); value_.one_word_atomic.store(one_word_val, std::memory_order_release); break; } case FlagValueStorageKind::kTwoWordsAtomic: { AlignedTwoWords two_words_val{0, 0}; - std::memcpy(&two_words_val, src, Sizeof(op_)); + std::memcpy(&two_words_val, src, flags_internal::Sizeof(op_)); value_.two_words_atomic.store(two_words_val, std::memory_order_release); break; } @@ -172,11 +225,17 @@ std::string FlagImpl::Filename() const { return flags_internal::GetUsageConfig().normalize_filename(filename_); } +absl::string_view FlagImpl::Typename() const { return ""; } + std::string FlagImpl::Help() const { return HelpSourceKind() == FlagHelpKind::kLiteral ? help_.literal : help_.gen_func(); } +FlagStaticTypeId FlagImpl::TypeId() const { + return flags_internal::StaticTypeId(op_); +} + bool FlagImpl::IsModified() const { absl::MutexLock l(DataGuard()); return modified_; @@ -195,10 +254,10 @@ std::string FlagImpl::DefaultValue() const { } std::string FlagImpl::CurrentValue() const { - DataGuard(); // Make sure flag initialized + auto* guard = DataGuard(); // Make sure flag initialized switch (ValueStorageKind()) { case FlagValueStorageKind::kHeapAllocated: { - absl::MutexLock l(DataGuard()); + absl::MutexLock l(guard); return flags_internal::Unparse(op_, value_.dynamic); } case FlagValueStorageKind::kOneWordAtomic: { @@ -250,23 +309,53 @@ void FlagImpl::InvokeCallback() const { cb(); } -bool FlagImpl::RestoreState(const void* value, bool modified, - bool on_command_line, int64_t counter) { - { - absl::MutexLock l(DataGuard()); +std::unique_ptr<FlagStateInterface> FlagImpl::SaveState() { + absl::MutexLock l(DataGuard()); - if (counter_ == counter) return false; + bool modified = modified_; + bool on_command_line = on_command_line_; + switch (ValueStorageKind()) { + case FlagValueStorageKind::kHeapAllocated: { + return absl::make_unique<FlagState>( + this, flags_internal::Clone(op_, value_.dynamic), modified, + on_command_line, counter_); + } + case FlagValueStorageKind::kOneWordAtomic: { + return absl::make_unique<FlagState>( + this, value_.one_word_atomic.load(std::memory_order_acquire), + modified, on_command_line, counter_); + } + case FlagValueStorageKind::kTwoWordsAtomic: { + return absl::make_unique<FlagState>( + this, value_.two_words_atomic.load(std::memory_order_acquire), + modified, on_command_line, counter_); + } } + return nullptr; +} - Write(value); +bool FlagImpl::RestoreState(const FlagState& flag_state) { + absl::MutexLock l(DataGuard()); - { - absl::MutexLock l(DataGuard()); + if (flag_state.counter_ == counter_) { + return false; + } - modified_ = modified; - on_command_line_ = on_command_line; + switch (ValueStorageKind()) { + case FlagValueStorageKind::kHeapAllocated: + StoreValue(flag_state.value_.dynamic); + break; + case FlagValueStorageKind::kOneWordAtomic: + StoreValue(&flag_state.value_.one_word); + break; + case FlagValueStorageKind::kTwoWordsAtomic: + StoreValue(&flag_state.value_.two_words); + break; } + modified_ = flag_state.modified_; + on_command_line_ = flag_state.on_command_line_; + return true; } @@ -290,10 +379,10 @@ std::unique_ptr<void, DynValueDeleter> FlagImpl::TryParse( } void FlagImpl::Read(void* dst) const { - DataGuard(); // Make sure flag initialized + auto* guard = DataGuard(); // Make sure flag initialized switch (ValueStorageKind()) { case FlagValueStorageKind::kHeapAllocated: { - absl::MutexLock l(DataGuard()); + absl::MutexLock l(guard); flags_internal::CopyConstruct(op_, value_.dynamic, dst); break; @@ -301,13 +390,13 @@ void FlagImpl::Read(void* dst) const { case FlagValueStorageKind::kOneWordAtomic: { const auto one_word_val = value_.one_word_atomic.load(std::memory_order_acquire); - std::memcpy(dst, &one_word_val, Sizeof(op_)); + std::memcpy(dst, &one_word_val, flags_internal::Sizeof(op_)); break; } case FlagValueStorageKind::kTwoWordsAtomic: { const auto two_words_val = value_.two_words_atomic.load(std::memory_order_acquire); - std::memcpy(dst, &two_words_val, Sizeof(op_)); + std::memcpy(dst, &two_words_val, flags_internal::Sizeof(op_)); break; } } diff --git a/absl/flags/internal/flag.h b/absl/flags/internal/flag.h index 2c4aba680a6e..f27e558b25a4 100644 --- a/absl/flags/internal/flag.h +++ b/absl/flags/internal/flag.h @@ -40,9 +40,6 @@ namespace absl { ABSL_NAMESPACE_BEGIN namespace flags_internal { -template <typename T> -class Flag; - /////////////////////////////////////////////////////////////////////////////// // Flag value type operations, eg., parsing, copying, etc. are provided // by function specific to that type with a signature matching FlagOpFn. @@ -149,36 +146,6 @@ inline FlagStaticTypeId StaticTypeId(FlagOpFn op) { } /////////////////////////////////////////////////////////////////////////////// -// Persistent state of the flag data. - -template <typename T> -class FlagState : public flags_internal::FlagStateInterface { - public: - FlagState(Flag<T>* flag, T&& cur, bool modified, bool on_command_line, - int64_t counter) - : flag_(flag), - cur_value_(std::move(cur)), - modified_(modified), - on_command_line_(on_command_line), - counter_(counter) {} - - ~FlagState() override = default; - - private: - friend class Flag<T>; - - // Restores the flag to the saved state. - void Restore() const override; - - // Flag and saved flag data. - Flag<T>* flag_; - T cur_value_; - bool modified_; - bool on_command_line_; - int64_t counter_; -}; - -/////////////////////////////////////////////////////////////////////////////// // Flag help auxiliary structs. // This is help argument for absl::Flag encapsulating the string literal pointer @@ -341,13 +308,15 @@ struct FlagCallback { struct DynValueDeleter { explicit DynValueDeleter(FlagOpFn op_arg = nullptr) : op(op_arg) {} void operator()(void* ptr) const { - if (op != nullptr) Delete(op, ptr); + if (op != nullptr) flags_internal::Delete(op, ptr); } FlagOpFn op; }; -class FlagImpl { +class FlagState; + +class FlagImpl final : public flags_internal::CommandLineFlag { public: constexpr FlagImpl(const char* name, const char* filename, FlagOpFn op, FlagHelpArg help, FlagValueStorageKind value_kind, @@ -368,15 +337,7 @@ class FlagImpl { data_guard_{} {} // Constant access methods - absl::string_view Name() const; - std::string Filename() const; - std::string Help() const; - bool IsModified() const ABSL_LOCKS_EXCLUDED(*DataGuard()); - bool IsSpecifiedOnCommandLine() const ABSL_LOCKS_EXCLUDED(*DataGuard()); - std::string DefaultValue() const ABSL_LOCKS_EXCLUDED(*DataGuard()); - std::string CurrentValue() const ABSL_LOCKS_EXCLUDED(*DataGuard()); - void Read(void* dst) const ABSL_LOCKS_EXCLUDED(*DataGuard()); - + void Read(void* dst) const override ABSL_LOCKS_EXCLUDED(*DataGuard()); template <typename T, typename std::enable_if<FlagUseHeapStorage<T>::value, int>::type = 0> void Get(T* dst) const { @@ -404,34 +365,12 @@ class FlagImpl { // Mutating access methods void Write(const void* src) ABSL_LOCKS_EXCLUDED(*DataGuard()); - bool ParseFrom(absl::string_view value, FlagSettingMode set_mode, - ValueSource source, std::string* err) - ABSL_LOCKS_EXCLUDED(*DataGuard()); // Interfaces to operate on callbacks. void SetCallback(const FlagCallbackFunc mutation_callback) ABSL_LOCKS_EXCLUDED(*DataGuard()); void InvokeCallback() const ABSL_EXCLUSIVE_LOCKS_REQUIRED(*DataGuard()); - // Interfaces to save/restore mutable flag data - template <typename T> - std::unique_ptr<FlagStateInterface> SaveState(Flag<T>* flag) const - ABSL_LOCKS_EXCLUDED(*DataGuard()) { - T&& cur_value = flag->Get(); - absl::MutexLock l(DataGuard()); - - return absl::make_unique<FlagState<T>>( - flag, std::move(cur_value), modified_, on_command_line_, counter_); - } - bool RestoreState(const void* value, bool modified, bool on_command_line, - int64_t counter) ABSL_LOCKS_EXCLUDED(*DataGuard()); - - // Value validation interfaces. - void CheckDefaultValueParsingRoundtrip() const - ABSL_LOCKS_EXCLUDED(*DataGuard()); - bool ValidateInputValue(absl::string_view value) const - ABSL_LOCKS_EXCLUDED(*DataGuard()); - // Used in read/write operations to validate source/target has correct type. // For example if flag is declared as absl::Flag<int> FLAGS_foo, a call to // absl::GetFlag(FLAGS_foo) validates that the type of FLAGS_foo is indeed @@ -441,6 +380,10 @@ class FlagImpl { void AssertValidType(FlagStaticTypeId type_id) const; private: + template <typename T> + friend class Flag; + friend class FlagState; + // Ensures that `data_guard_` is initialized and returns it. absl::Mutex* DataGuard() const ABSL_LOCK_RETURNED((absl::Mutex*)&data_guard_); // Returns heap allocated value of type T initialized with default value. @@ -467,6 +410,37 @@ class FlagImpl { return static_cast<FlagDefaultKind>(def_kind_); } + // CommandLineFlag interface implementation + absl::string_view Name() const override; + std::string Filename() const override; + absl::string_view Typename() const override; + std::string Help() const override; + FlagStaticTypeId TypeId() const override; + bool IsModified() const override ABSL_LOCKS_EXCLUDED(*DataGuard()); + bool IsSpecifiedOnCommandLine() const override + ABSL_LOCKS_EXCLUDED(*DataGuard()); + std::string DefaultValue() const override ABSL_LOCKS_EXCLUDED(*DataGuard()); + std::string CurrentValue() const override ABSL_LOCKS_EXCLUDED(*DataGuard()); + bool ValidateInputValue(absl::string_view value) const override + ABSL_LOCKS_EXCLUDED(*DataGuard()); + void CheckDefaultValueParsingRoundtrip() const override + ABSL_LOCKS_EXCLUDED(*DataGuard()); + + // Interfaces to save and restore flags to/from persistent state. + // Returns current flag state or nullptr if flag does not support + // saving and restoring a state. + std::unique_ptr<FlagStateInterface> SaveState() override + ABSL_LOCKS_EXCLUDED(*DataGuard()); + + // Restores the flag state to the supplied state object. If there is + // nothing to restore returns false. Otherwise returns true. + bool RestoreState(const FlagState& flag_state) + ABSL_LOCKS_EXCLUDED(*DataGuard()); + + bool ParseFrom(absl::string_view value, FlagSettingMode set_mode, + ValueSource source, std::string* error) override + ABSL_LOCKS_EXCLUDED(*DataGuard()); + // Immutable flag's state. // Flags name passed to ABSL_FLAG as second arg. @@ -536,7 +510,7 @@ class FlagImpl { // flag reflection handle interface. template <typename T> -class Flag final : public flags_internal::CommandLineFlag { +class Flag { public: constexpr Flag(const char* name, const char* filename, const FlagHelpArg help, const FlagDfltGenFunc default_value_gen) @@ -568,60 +542,24 @@ class Flag final : public flags_internal::CommandLineFlag { } // CommandLineFlag interface - absl::string_view Name() const override { return impl_.Name(); } - std::string Filename() const override { return impl_.Filename(); } - absl::string_view Typename() const override { return ""; } - std::string Help() const override { return impl_.Help(); } - bool IsModified() const override { return impl_.IsModified(); } - bool IsSpecifiedOnCommandLine() const override { + absl::string_view Name() const { return impl_.Name(); } + std::string Filename() const { return impl_.Filename(); } + absl::string_view Typename() const { return ""; } + std::string Help() const { return impl_.Help(); } + bool IsModified() const { return impl_.IsModified(); } + bool IsSpecifiedOnCommandLine() const { return impl_.IsSpecifiedOnCommandLine(); } - std::string DefaultValue() const override { return impl_.DefaultValue(); } - std::string CurrentValue() const override { return impl_.CurrentValue(); } - bool ValidateInputValue(absl::string_view value) const override { - return impl_.ValidateInputValue(value); - } - - // Interfaces to save and restore flags to/from persistent state. - // Returns current flag state or nullptr if flag does not support - // saving and restoring a state. - std::unique_ptr<FlagStateInterface> SaveState() override { - return impl_.SaveState(this); - } - - // Restores the flag state to the supplied state object. If there is - // nothing to restore returns false. Otherwise returns true. - bool RestoreState(const FlagState<T>& flag_state) { - return impl_.RestoreState(&flag_state.cur_value_, flag_state.modified_, - flag_state.on_command_line_, flag_state.counter_); - } - bool ParseFrom(absl::string_view value, FlagSettingMode set_mode, - ValueSource source, std::string* error) override { - return impl_.ParseFrom(value, set_mode, source, error); - } - void CheckDefaultValueParsingRoundtrip() const override { - impl_.CheckDefaultValueParsingRoundtrip(); - } + std::string DefaultValue() const { return impl_.DefaultValue(); } + std::string CurrentValue() const { return impl_.CurrentValue(); } private: - friend class FlagState<T>; - - void Read(void* dst) const override { impl_.Read(dst); } - FlagStaticTypeId TypeId() const override { return &FlagStaticTypeIdGen<T>; } - + template <typename U, bool do_register> + friend class FlagRegistrar; // Flag's data FlagImpl impl_; }; -template <typename T> -void FlagState<T>::Restore() const { - if (flag_->RestoreState(*this)) { - ABSL_INTERNAL_LOG(INFO, - absl::StrCat("Restore saved value of ", flag_->Name(), - " to: ", flag_->CurrentValue())); - } -} - // This class facilitates Flag object registration and tail expression-based // flag definition, for example: // ABSL_FLAG(int, foo, 42, "Foo help").OnUpdate(NotifyFooWatcher); @@ -629,7 +567,7 @@ template <typename T, bool do_register> class FlagRegistrar { public: explicit FlagRegistrar(Flag<T>* flag) : flag_(flag) { - if (do_register) flags_internal::RegisterCommandLineFlag(flag_); + if (do_register) flags_internal::RegisterCommandLineFlag(&flag_->impl_); } FlagRegistrar& OnUpdate(FlagCallbackFunc cb) && { |