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/flag.cc | |
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/flag.cc')
-rw-r--r-- | absl/flags/internal/flag.cc | 131 |
1 files changed, 110 insertions, 21 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; } } |