Roll abseil_revision 207ac6d88b..43e07c386b Change Log: https://chromium.googlesource.com/external/github.com/abseil/abseil-cpp/+log/207ac6d88b..43e07c386b Full diff: https://chromium.googlesource.com/external/github.com/abseil/abseil-cpp/+/207ac6d88b..43e07c386b Bug: None Change-Id: Ifeedecba95beae48e68db009f958f9b376644a1c Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/8244069 Commit-Queue: Danil Chapovalov <danilchap@chromium.org> Reviewed-by: Mirko Bonadei <mbonadei@chromium.org> Auto-Submit: Danil Chapovalov <danilchap@chromium.org> Commit-Queue: Mirko Bonadei <mbonadei@chromium.org> Cr-Commit-Position: refs/heads/main@{#1677889} NOKEYCHECK=True GitOrigin-RevId: 9414218439bc77d8da173895acba229e46cef79a
diff --git a/README.chromium b/README.chromium index 69f7629..98acc4a 100644 --- a/README.chromium +++ b/README.chromium
@@ -4,7 +4,7 @@ License: Apache-2.0 License File: LICENSE Version: N/A -Revision: 207ac6d88bea1bb0fd9652238f5e556147f44cb3 +Revision: 43e07c386b832bb4d1d29af61b7c45b59a54a38d Update Mechanism: Manual Security Critical: yes Shipped: yes
diff --git a/absl/base/casts.h b/absl/base/casts.h index 1a85798..8aac0da 100644 --- a/absl/base/casts.h +++ b/absl/base/casts.h
@@ -206,11 +206,11 @@ const char* source_type, const char* target_type); template <typename To, typename From> -inline void ValidateDownCast(From* f ABSL_ATTRIBUTE_UNUSED) { +inline void ValidateDownCast(From* f) { // Assert only if RTTI is enabled and in debug mode or hardened asserts are // enabled. -#ifdef ABSL_INTERNAL_HAS_RTTI -#if !defined(NDEBUG) || (ABSL_OPTION_HARDENED == 1) +#if defined(ABSL_INTERNAL_HAS_RTTI) && \ + (!defined(NDEBUG) || (ABSL_OPTION_HARDENED == 1)) // Suppress erroneous nonnull comparison warning on older GCC. #if defined(__GNUC__) && !defined(__clang__) #pragma GCC diagnostic push @@ -223,7 +223,8 @@ absl::base_internal::BadDownCastCrash( typeid(*f).name(), typeid(std::remove_pointer_t<To>).name()); } -#endif +#else + (void)f; // Denote this as "used" to avoid warning #endif }
diff --git a/absl/base/internal/cpu_detect.cc b/absl/base/internal/cpu_detect.cc index 5275888..070cc86 100644 --- a/absl/base/internal/cpu_detect.cc +++ b/absl/base/internal/cpu_detect.cc
@@ -350,31 +350,34 @@ } bool SupportsArmCRC32PMULL() { + static const bool supported = []() { // Newer XNU kernels support querying all capabilities in a single // sysctlbyname. #if defined(CAP_BIT_CRC32) && defined(CAP_BIT_FEAT_PMULL) - static const std::optional<uint64_t> caps = - ReadSysctlByName<uint64_t>("hw.optional.arm.caps"); - if (caps.has_value()) { - constexpr uint64_t kCrc32AndPmullCaps = - (uint64_t{1} << CAP_BIT_CRC32) | (uint64_t{1} << CAP_BIT_FEAT_PMULL); - return (*caps & kCrc32AndPmullCaps) == kCrc32AndPmullCaps; - } + const std::optional<uint64_t> caps = + ReadSysctlByName<uint64_t>("hw.optional.arm.caps"); + if (caps.has_value()) { + constexpr uint64_t kCrc32AndPmullCaps = + (uint64_t{1} << CAP_BIT_CRC32) | (uint64_t{1} << CAP_BIT_FEAT_PMULL); + return (*caps & kCrc32AndPmullCaps) == kCrc32AndPmullCaps; + } #endif - // https://developer.apple.com/documentation/kernel/1387446-sysctlbyname/determining_instruction_set_characteristics#3915619 - static const std::optional<int> armv8_crc32 = - ReadSysctlByName<int>("hw.optional.armv8_crc32"); - if (armv8_crc32.value_or(0) == 0) { - return false; - } - // https://developer.apple.com/documentation/kernel/1387446-sysctlbyname/determining_instruction_set_characteristics#3918855 - static const std::optional<int> feat_pmull = - ReadSysctlByName<int>("hw.optional.arm.FEAT_PMULL"); - if (feat_pmull.value_or(0) == 0) { - return false; - } - return true; + // https://developer.apple.com/documentation/kernel/1387446-sysctlbyname/determining_instruction_set_characteristics#3915619 + const std::optional<int> armv8_crc32 = + ReadSysctlByName<int>("hw.optional.armv8_crc32"); + if (armv8_crc32.value_or(0) == 0) { + return false; + } + // https://developer.apple.com/documentation/kernel/1387446-sysctlbyname/determining_instruction_set_characteristics#3918855 + const std::optional<int> feat_pmull = + ReadSysctlByName<int>("hw.optional.arm.FEAT_PMULL"); + if (feat_pmull.value_or(0) == 0) { + return false; + } + return true; + }(); + return supported; } bool SupportsBmi2() { return false; }
diff --git a/absl/crc/internal/crc32_x86_arm_combined_simd.h b/absl/crc/internal/crc32_x86_arm_combined_simd.h index 07f5a69..9c287b5 100644 --- a/absl/crc/internal/crc32_x86_arm_combined_simd.h +++ b/absl/crc/internal/crc32_x86_arm_combined_simd.h
@@ -107,6 +107,12 @@ // Produces a XOR operation of |l| and |r|. V128 V128_Xor(const V128 l, const V128 r); +// Produces a 3-way XOR operation of |a|, |b|, and |c|. +// When `kUseEor3` is true, uses the ARMv8.2-A `EOR3` (3-way Exclusive-OR) +// instruction. +template <bool kUseEor3 = false> +V128 V128_Xor3(const V128 a, const V128 b, const V128 c); + // Sets the lower half of a 128 bit register to the given 64-bit value and // zeroes the upper half. // dst[63:0] := |r| @@ -182,6 +188,11 @@ inline V128 V128_Xor(const V128 l, const V128 r) { return _mm_xor_si128(l, r); } +template <bool kUseEor3> +inline V128 V128_Xor3(const V128 a, const V128 b, const V128 c) { + return V128_Xor(V128_Xor(a, b), c); +} + inline V128 V128_From64WithZeroFill(const uint64_t r) { return _mm_set_epi64x(static_cast<int64_t>(0), static_cast<int64_t>(r)); } @@ -266,6 +277,28 @@ inline V128 V128_Xor(const V128 l, const V128 r) { return veorq_u64(l, r); } +template <bool kUseEor3> +inline V128 V128_Xor3(const V128 a, const V128 b, const V128 c) { +#ifndef __ARM_FEATURE_SHA3 + if constexpr (kUseEor3) { + // If the binary is compiled without SHA3 support, we need inline assembly + // to use the EOR3 instruction. We want to only use the below inline + // assembly block when both the CPU supports EOR3 and the binary is built + // without it, since we remove the sha3 extension support after the eor3 + // instruction. + uint64x2_t res; + __asm__ __volatile__( + ".arch_extension sha3 \n\t" + "eor3 %0.16b, %1.16b, %2.16b, %3.16b \n\t" + ".arch_extension nosha3 \n\t" + : "=w"(res) + : "w"(a), "w"(b), "w"(c)); + return res; + } +#endif + return V128_Xor(V128_Xor(a, b), c); +} + inline V128 V128_From64WithZeroFill(const uint64_t r){ constexpr uint64x2_t kZero = {0, 0}; return vsetq_lane_u64(r, kZero, 0);
diff --git a/absl/crc/internal/crc_x86_arm_combined.cc b/absl/crc/internal/crc_x86_arm_combined.cc index de2af4f..edffd36 100644 --- a/absl/crc/internal/crc_x86_arm_combined.cc +++ b/absl/crc/internal/crc_x86_arm_combined.cc
@@ -40,7 +40,9 @@ using ::absl::base_internal::CpuType; using ::absl::base_internal::GetCpuType; +#if defined(__aarch64__) using ::absl::base_internal::SupportsArmCRC32PMULL; +#endif #if defined(ABSL_INTERNAL_CAN_USE_SIMD_CRC32C) @@ -218,6 +220,7 @@ PCLMUL, VPCLMUL, NEON_PCLMUL, + NEON_PCLMUL_EOR3, }; // Base class for CRC32AcceleratedX86ARMCombinedMultipleStreams containing the @@ -234,6 +237,7 @@ // https://www.intel.com/content/dam/www/public/us/en/documents/white-papers/fast-crc-computation-generic-polynomials-pclmulqdq-paper.pdf // We are applying it to CRC32C polynomial. #if defined(ABSL_CRC_INTERNAL_HAVE_ARM_SIMD) + template <bool kUseEor3 = false> ABSL_ATTRIBUTE_ALWAYS_INLINE void Process64BytesNeonPclmul( const uint8_t* p, V128* partialCRC) const { V128 loopMultiplicands = @@ -256,14 +260,10 @@ partialCRC2 = V128_PMulLow(partialCRC2, loopMultiplicands); partialCRC3 = V128_PMulLow(partialCRC3, loopMultiplicands); partialCRC4 = V128_PMulLow(partialCRC4, loopMultiplicands); - partialCRC1 = V128_Xor(tmp1, partialCRC1); - partialCRC2 = V128_Xor(tmp2, partialCRC2); - partialCRC3 = V128_Xor(tmp3, partialCRC3); - partialCRC4 = V128_Xor(tmp4, partialCRC4); - partialCRC1 = V128_Xor(partialCRC1, data1); - partialCRC2 = V128_Xor(partialCRC2, data2); - partialCRC3 = V128_Xor(partialCRC3, data3); - partialCRC4 = V128_Xor(partialCRC4, data4); + partialCRC1 = V128_Xor3<kUseEor3>(tmp1, partialCRC1, data1); + partialCRC2 = V128_Xor3<kUseEor3>(tmp2, partialCRC2, data2); + partialCRC3 = V128_Xor3<kUseEor3>(tmp3, partialCRC3, data3); + partialCRC4 = V128_Xor3<kUseEor3>(tmp4, partialCRC4, data4); partialCRC[0] = partialCRC1; partialCRC[1] = partialCRC2; partialCRC[2] = partialCRC3; @@ -272,6 +272,7 @@ // Reduce partialCRC produced by Process64BytesNeonPclmul into a single value, // that represents crc checksum of all the processed bytes. + template <bool kUseEor3 = false> ABSL_ATTRIBUTE_ALWAYS_INLINE uint64_t FinalizeNeonPclmulStream(V128* partialCRC) const { V128 partialCRC1 = partialCRC[0]; @@ -286,22 +287,19 @@ V128 low = V128_PMulLow(reductionMultiplicands, partialCRC1); V128 high = V128_PMulHi(reductionMultiplicands, partialCRC1); - partialCRC1 = V128_Xor(low, high); - partialCRC1 = V128_Xor(partialCRC1, partialCRC3); + partialCRC1 = V128_Xor3<kUseEor3>(low, high, partialCRC3); low = V128_PMulLow(reductionMultiplicands, partialCRC2); high = V128_PMulHi(reductionMultiplicands, partialCRC2); - partialCRC2 = V128_Xor(low, high); - partialCRC2 = V128_Xor(partialCRC2, partialCRC4); + partialCRC2 = V128_Xor3<kUseEor3>(low, high, partialCRC4); reductionMultiplicands = V128_Load(reinterpret_cast<const V128*>(kFoldAcross128Bits)); low = V128_PMulLow(reductionMultiplicands, partialCRC1); high = V128_PMulHi(reductionMultiplicands, partialCRC1); - V128 fullCRC = V128_Xor(low, high); - fullCRC = V128_Xor(fullCRC, partialCRC2); + V128 fullCRC = V128_Xor3<kUseEor3>(low, high, partialCRC2); // Reduce fullCRC into scalar value. uint32_t crc = 0; @@ -393,9 +391,11 @@ return crc; } + template <bool kUseEor3 = false> ABSL_ATTRIBUTE_ALWAYS_INLINE void Process64BytesNeonPclmul(const uint8_t*, V128*) const {} + template <bool kUseEor3 = false> ABSL_ATTRIBUTE_ALWAYS_INLINE uint64_t FinalizeNeonPclmulStream(V128*) const { return 0; } @@ -796,8 +796,12 @@ V256_Broadcast128(reinterpret_cast<const V128*>(kFoldAcross512Bits)); Process64BytesVpclmul(*pclmul_stream, reinterpret_cast<V256*>(partialCRC), loopMultiplicands); - } else if constexpr (pclmul_stream_type == PclmulStreamType::NEON_PCLMUL) { - Process64BytesNeonPclmul(*pclmul_stream, partialCRC); + } else if constexpr (pclmul_stream_type == PclmulStreamType::NEON_PCLMUL || + pclmul_stream_type == + PclmulStreamType::NEON_PCLMUL_EOR3) { + constexpr bool kUseEor3 = + (pclmul_stream_type == PclmulStreamType::NEON_PCLMUL_EOR3); + Process64BytesNeonPclmul<kUseEor3>(*pclmul_stream, partialCRC); } else { Process64BytesPclmul(*pclmul_stream, partialCRC); } @@ -808,8 +812,12 @@ FinalizePclmulStream(V128* partialCRC) const { if constexpr (pclmul_stream_type == PclmulStreamType::VPCLMUL) { return FinalizeVpclmulStream(reinterpret_cast<V256*>(partialCRC)); - } else if constexpr (pclmul_stream_type == PclmulStreamType::NEON_PCLMUL) { - return FinalizeNeonPclmulStream(partialCRC); + } else if constexpr (pclmul_stream_type == PclmulStreamType::NEON_PCLMUL || + pclmul_stream_type == + PclmulStreamType::NEON_PCLMUL_EOR3) { + constexpr bool kUseEor3 = + (pclmul_stream_type == PclmulStreamType::NEON_PCLMUL_EOR3); + return FinalizeNeonPclmulStream<kUseEor3>(partialCRC); } else { return CRC32AcceleratedX86ARMCombinedMultipleStreamsBase:: FinalizePclmulStream(partialCRC); @@ -869,18 +877,20 @@ return new CRC32AcceleratedX86ARMCombinedMultipleStreams< 3, 0, PclmulStreamType::PCLMUL>(); case CpuType::kArmNeoverseN1: - case CpuType::kArmNeoverseN2: case CpuType::kArmNeoverseV1: + return new CRC32AcceleratedX86ARMCombinedMultipleStreams< + 1, 1, PclmulStreamType::NEON_PCLMUL>(); + case CpuType::kArmNeoverseN2: case CpuType::kArmNeoverseN3: case CpuType::kNvidiaGrace: return new CRC32AcceleratedX86ARMCombinedMultipleStreams< - 1, 1, PclmulStreamType::NEON_PCLMUL>(); + 1, 1, PclmulStreamType::NEON_PCLMUL_EOR3>(); case CpuType::kAmpereSiryn: return new CRC32AcceleratedX86ARMCombinedMultipleStreams< - 3, 2, PclmulStreamType::NEON_PCLMUL>(); + 3, 2, PclmulStreamType::NEON_PCLMUL_EOR3>(); case CpuType::kArmNeoverseV2: return new CRC32AcceleratedX86ARMCombinedMultipleStreams< - 1, 2, PclmulStreamType::NEON_PCLMUL>(); + 1, 2, PclmulStreamType::NEON_PCLMUL_EOR3>(); #if defined(__aarch64__) default: // Not all ARM processors support the needed instructions, so check here
diff --git a/absl/debugging/symbolize_test.cc b/absl/debugging/symbolize_test.cc index 2862394..d216f26 100644 --- a/absl/debugging/symbolize_test.cc +++ b/absl/debugging/symbolize_test.cc
@@ -244,8 +244,8 @@ } static int GetStackConsumptionUpperLimit() { - // Symbolize stack consumption should be within 2kB. - int stack_consumption_upper_limit = 2048; + // Symbolize stack consumption should be within 4kB. + int stack_consumption_upper_limit = 4096; #if defined(ABSL_HAVE_ADDRESS_SANITIZER) || \ defined(ABSL_HAVE_MEMORY_SANITIZER) || defined(ABSL_HAVE_THREAD_SANITIZER) // Account for sanitizer instrumentation requiring additional stack space.
diff --git a/absl/profiling/internal/exponential_biased_test.cc b/absl/profiling/internal/exponential_biased_test.cc index ebfbcad..3dcf105 100644 --- a/absl/profiling/internal/exponential_biased_test.cc +++ b/absl/profiling/internal/exponential_biased_test.cc
@@ -132,6 +132,49 @@ printf("Heads = %d (%f%%)\n", heads, 100.0 * heads / 10000000); } +// In simplified idealized world, `GetSkipCount(m) == 0` translates to +// `-log(X) * m + B <= 1/2`, where X is a uniform random number in (0, 1], +// and B is uniform random number in [-0.5, 0.5). Let U = 0.5 - B, that makes +// U a uniform random number in (0, 1]. After exponentiation we get +// `X >= exp(-U / m)`. Probability of this is `1 - exp(-U / m)`, so we have to +// integrate for all possible values of U: `1 - m * (1 - exp(-1 / m))`. For +// simplicity take just two terms of Taylor series expansion: +// `1/(2*m) - 1/(6*m^2)`. Reciprocal of that is `2*m + 2/3 + O(1/m)`. If we use +// more math tricks we can get "exact" approximation, but result will still be +// `2*m + 2/3 + O(1/m)`. +TEST(ExponentialBiasedTest, OnePerNDemoWithGetSkipCount) { + ExponentialBiased eb; + int n = 22; + int rounds = 220000; + int hits = 0; + for (int i = 0; i < rounds; i++) { + if (eb.GetSkipCount(n / 2) == 0) ++hits; + } + double inverse_hit_rate = rounds / static_cast<double>(hits); + printf("N = %d, rounds = %d, inverse hit rate = %f (should be ~= N + 0.67)\n", + n, rounds, inverse_hit_rate); +} + +// Large requested mean flattens density function near zero, making it almost +// linear. +TEST(ExponentialBiasedTest, OneOfNDemoWithGetSkipCount) { + ExponentialBiased eb; + int n = 6; + int large_mean = 10000000; + int rounds = n * 10000; + std::vector<int> hits(static_cast<size_t>(n), 0); + for (int i = 0; i < rounds; i++) { + int64_t v = eb.GetSkipCount(large_mean); + int64_t a = v % n; + ++hits[static_cast<size_t>(a)]; + } + printf("N = %d, rounds = %d, mean = %d\n", n, rounds, large_mean); + for (int i = 0; i < n; i++) { + printf(" inverse hit rate for %d: %f (should be ~= N)\n", i, + rounds / static_cast<double>(hits[static_cast<size_t>(i)])); + } +} + TEST(ExponentialBiasedTest, SampleDemoWithStride) { ExponentialBiased eb; int64_t stride = eb.GetStride(10);
diff --git a/absl/status/internal/status_internal.h b/absl/status/internal/status_internal.h index 767f88f..03b0663 100644 --- a/absl/status/internal/status_internal.h +++ b/absl/status/internal/status_internal.h
@@ -73,6 +73,7 @@ class StatusPrivateAccessorForStatusBuilder; #endif // !SWIG +#ifndef SWIG // Container for status payloads. struct Payload { std::string type_url; @@ -91,6 +92,7 @@ message_(message_arg), payloads_(std::move(payloads_arg)) {} +#ifndef SWIG template <typename String, typename = std::enable_if_t<std::is_same_v<String, std::string>>> StatusRep(absl::StatusCode code_arg, String&& message_arg, @@ -99,6 +101,7 @@ code_(code_arg), message_(std::forward<String>(message_arg)), payloads_(std::move(payloads_arg)) {} +#endif // SWIG absl::StatusCode code() const { return code_; } const std::string& message() const { return message_; } @@ -172,6 +175,7 @@ const absl::Status* absl_nonnull status, const char* absl_nonnull prefix); } // namespace status_internal +#endif // SWIG ABSL_NAMESPACE_END } // namespace absl
diff --git a/absl/status/status.cc b/absl/status/status.cc index 2d3ccc0..155c5d8 100644 --- a/absl/status/status.cc +++ b/absl/status/status.cc
@@ -130,11 +130,13 @@ return MakeStatusRepImpl<absl::string_view>(inlined_rep, msg, loc); } +#ifndef SWIG uintptr_t Status::MakeRepFromStringRvalue(uintptr_t inlined_rep, std::string&& msg, absl::SourceLocation loc) { return MakeStatusRepImpl<std::string&&>(inlined_rep, std::move(msg), loc); } +#endif // SWIG uintptr_t Status::AddSourceLocationImpl(uintptr_t rep, absl::SourceLocation loc) {
diff --git a/absl/status/status.h b/absl/status/status.h index 10e22d6..3103e79 100644 --- a/absl/status/status.h +++ b/absl/status/status.h
@@ -75,6 +75,10 @@ namespace absl { ABSL_NAMESPACE_BEGIN +#ifndef SWIG // SWIG chokes on enum class +// The following canonical error codes should always be in sync with +// https://github.com/googleapis/googleapis/blob/master/google/rpc/code.proto. + // absl::StatusCode // // An `absl::StatusCode` is an enumerated type indicating either no error ("OK") @@ -352,6 +356,7 @@ lhs = lhs ^ rhs; return lhs; } +#endif // SWIG // absl::Status // @@ -460,6 +465,7 @@ Status(absl::StatusCode code, absl::string_view msg, absl::SourceLocation loc = SourceLocation::current()); +#ifndef SWIG // Same as above but for rvalue string. // Note: using a template to disambiguate the case of matching string_view and // string&& (e.g. char*) as a template lowers the priority of the overload. @@ -467,6 +473,7 @@ typename = std::enable_if_t<std::is_same_v<String, std::string>>> Status(absl::StatusCode code, String&& msg, absl::SourceLocation loc = SourceLocation::current()); +#endif // SWIG // Create a status from a `base_status` and a `loc`. The `loc` will be // appended to the location chain of the new status, iff the `base_status` is @@ -475,19 +482,23 @@ : Status(base_status) { AddSourceLocation(loc); } +#ifndef SWIG Status(Status&& base_status, absl::SourceLocation loc) : Status(std::move(base_status)) { AddSourceLocation(loc); } +#endif // SWIG Status(const Status&); Status& operator=(const Status& x); +#ifndef SWIG // Move operators // The moved-from state is valid but unspecified. Status(Status&&) noexcept; Status& operator=(Status&&) noexcept; +#endif // SWIG ~Status(); @@ -507,7 +518,9 @@ // overall_status.Update(new_status); // void Update(const Status& new_status); +#ifndef SWIG void Update(Status&& new_status); +#endif // SWIG // Status::ok() // @@ -533,6 +546,8 @@ // wire format. Use `Status::code()` for error handling. int raw_code() const; +#ifndef SWIG + // Status::message() // // Returns the error message associated with this error code, if available. @@ -540,10 +555,15 @@ // for the error message to be the empty string. As a result, prefer // `operator<<` or `Status::ToString()` for debug logging. absl::string_view message() const; +#endif // SWIG friend bool operator==(const Status&, const Status&); friend bool operator!=(const Status&, const Status&); +#ifndef SWIG + // `ToString` has stubs in SWIG to remain backward compatible with the old + // format by calling `util::StatusToString`, to save migration cost. + // Status::ToString() // // Returns a string based on the `mode`. By default, it returns combination of @@ -563,6 +583,7 @@ friend void AbslStringify(Sink& sink, const Status& status) { sink.Append(status.ToString(StatusToStringMode::kWithEverything)); } +#endif // SWIG // Status::IgnoreError() // @@ -574,7 +595,11 @@ // swap() // // Swap the contents of one status with another. +#ifndef SWIG friend void swap(Status& a, Status& b) noexcept; +#else + friend void swap(Status& a, Status& b); +#endif // SWIG //---------------------------------------------------------------------------- // Payload Management APIs @@ -639,9 +664,14 @@ // // NOTE: Any mutation on the same 'absl::Status' object during visitation is // forbidden and could result in undefined behavior. + // FunctionRef doesn't work nicely with Swig. + // TODO(b/189736749): Consider making this available once FunctionRef is + // supported. +#ifndef SWIG void ForEachPayload( absl::FunctionRef<void(absl::string_view, const absl::Cord&)> visitor) const; +#endif // SWIG absl::Span<const absl::SourceLocation> GetSourceLocations() const { if (IsInlined(rep_)) return {}; @@ -661,6 +691,8 @@ ABSL_ASSUME(!okay); } +#ifndef SWIG + // Status::WithSourceLocation() // // Returns a copy of the current status, with `loc` appended to its location @@ -695,6 +727,7 @@ AddSourceLocation(loc); return std::move(*this); } +#endif // SWIG private: friend Status CancelledError(); @@ -722,10 +755,12 @@ absl::string_view msg, absl::SourceLocation loc); +#ifndef SWIG // Same as above but for rvalue string. static uintptr_t MakeRepFromStringRvalue(uintptr_t inlined_rep, std::string&& msg, absl::SourceLocation loc); +#endif // SWIG template <typename StringOrView> friend uintptr_t MakeStatusRepImpl(uintptr_t inlined_rep, StringOrView msg, @@ -920,11 +955,13 @@ absl::SourceLocation loc) : Status(MakeRepFromStringView(CodeToInlinedRep(code), msg, loc)) {} +#ifndef SWIG template <typename String, typename> inline Status::Status(absl::StatusCode code, String&& msg, absl::SourceLocation loc) : Status(MakeRepFromStringRvalue(CodeToInlinedRep(code), std::forward<String>(msg), loc)) {} +#endif // SWIG inline Status::Status(const Status& x) : Status(x.rep_) { Ref(rep_); } @@ -938,6 +975,7 @@ return *this; } +#ifndef SWIG inline Status::Status(Status&& x) noexcept : Status(x.rep_) { x.rep_ = MovedFromRep(); } @@ -951,6 +989,7 @@ } return *this; } +#endif // SWIG inline void Status::Update(const Status& new_status) { if (ok()) { @@ -958,11 +997,13 @@ } } +#ifndef SWIG inline void Status::Update(Status&& new_status) { if (ok()) { *this = std::move(new_status); } } +#endif // SWIG inline Status::~Status() { Unref(rep_); } @@ -1005,10 +1046,17 @@ // no-op } +#ifndef SWIG inline void swap(absl::Status& a, absl::Status& b) noexcept { using std::swap; swap(a.rep_, b.rep_); } +#else +inline void swap(absl::Status& a, absl::Status& b) { + using std::swap; + swap(a.rep_, b.rep_); +} +#endif // SWIG inline std::optional<absl::Cord> Status::GetPayload( absl::string_view type_url) const { @@ -1074,7 +1122,9 @@ if (!IsInlined(rep)) RepToPointer(rep)->Unref(); } +#ifndef SWIG inline Status OkStatus() { return Status(); } +#endif // SWIG // Creates a `Status` object with the `absl::StatusCode::kCancelled` error code // and an empty message. It is provided only for efficiency, given that @@ -1095,6 +1145,7 @@ template <int error_code> Status MakeErrorImpl(string_view message, SourceLocation loc); // Make the instantiations extern to reduce bloat on callers. +#ifndef SWIG extern template Status MakeErrorImpl<0>(string_view, SourceLocation); extern template Status MakeErrorImpl<1>(string_view, SourceLocation); extern template Status MakeErrorImpl<2>(string_view, SourceLocation); @@ -1112,6 +1163,7 @@ extern template Status MakeErrorImpl<14>(string_view, SourceLocation); extern template Status MakeErrorImpl<15>(string_view, SourceLocation); extern template Status MakeErrorImpl<16>(string_view, SourceLocation); +#endif // SWIG template <StatusCode error_code> Status MakeError(string_view message, SourceLocation loc) {
diff --git a/absl/status/status_builder.h b/absl/status/status_builder.h index 60b7562..55ab7a8 100644 --- a/absl/status/status_builder.h +++ b/absl/status/status_builder.h
@@ -704,13 +704,13 @@ // would prevent use of operator<<. For example: // // ABSL_RETURN_IF_ERROR(foo(val)) -// .With(util::ExtraMessage("when calling foo()")) +// .With(absl::ExtraMessage("when calling foo()")) // .With(util::TaskReturn(task)); // // or // // ABSL_RETURN_IF_ERROR(foo(val)) -// .With(util::ExtraMessage() << "val: " << val) +// .With(absl::ExtraMessage() << "val: " << val) // .With(util::TaskReturn(task)); // // Note in the above example, the ABSL_RETURN_IF_ERROR macro ensures the
diff --git a/absl/status/statusor.h b/absl/status/statusor.h index 2ee7947..3d7f8c4 100644 --- a/absl/status/statusor.h +++ b/absl/status/statusor.h
@@ -61,6 +61,7 @@ namespace absl { ABSL_NAMESPACE_BEGIN +#ifndef SWIG // BadStatusOrAccess // @@ -111,8 +112,10 @@ mutable absl::once_flag init_what_; mutable std::string what_; }; +#endif // !SWIG // Returned StatusOr objects may not be ignored. +#ifndef SWIG template <typename T> #if ABSL_HAVE_CPP_ATTRIBUTE(nodiscard) // TODO(b/176172494): ABSL_MUST_USE_RESULT should expand to the more strict @@ -121,6 +124,7 @@ #else class ABSL_MUST_USE_RESULT StatusOr; #endif // ABSL_HAVE_CPP_ATTRIBUTE(nodiscard) +#endif // !SWIG // absl::StatusOr<T> // @@ -233,6 +237,8 @@ // assignable. StatusOr& operator=(const StatusOr&) = default; +#ifndef SWIG + // `StatusOr<T>` is move constructible if `T` is move constructible. StatusOr(StatusOr&&) = default; // `StatusOr<T>` is moveAssignable if `T` is move constructible and move @@ -454,6 +460,8 @@ explicit StatusOr(U&& u ABSL_ATTRIBUTE_LIFETIME_BOUND) // NOLINT : StatusOr(std::in_place, std::forward<U>(u)) {} +#endif // SWIG + // StatusOr<T>::ok() // // Returns whether or not this `absl::StatusOr<T>` holds a `T` value. This @@ -475,8 +483,12 @@ // Returns a reference to the current `absl::Status` contained within the // `absl::StatusOr<T>`. If `absl::StatusOr<T>` contains a `T`, then this // function returns `absl::OkStatus()`. +#ifdef SWIG + ABSL_MUST_USE_RESULT const absl::Status& status() const; +#else // SWIG ABSL_MUST_USE_RESULT const Status& status() const&; Status status() &&; +#endif // SWIG absl::Span<const absl::SourceLocation> GetSourceLocations() const { return this->status_.GetSourceLocations(); @@ -488,6 +500,8 @@ this->status_.AddSourceLocation(loc); } +#ifndef SWIG + // StatusOr<T>::WithSourceLocation() // // Appends the `loc` to the current location chain inside the status iff the @@ -507,6 +521,7 @@ AddSourceLocation(loc); return std::move(*this); } +#endif // SWIG // StatusOr<T>::value() // @@ -534,7 +549,13 @@ // // The `std::move` on statusor instead of on the whole expression enables // warnings about possible uses of the statusor object after the move. +#ifdef SWIG + const T& value() const ABSL_ATTRIBUTE_LIFETIME_BOUND; +#else // SWIG using StatusOr::OperatorBase::value; +#endif // SWIG + +#ifndef SWIG // StatusOr<T>:: operator*() // @@ -598,6 +619,7 @@ T value_or(U&& default_value ABSL_ATTRIBUTE_LIFETIME_BOUND) && { return std::move(*this).ValueOrImpl(std::forward<U>(default_value)); } +#endif // SWIG // StatusOr<T>::IgnoreError() // @@ -606,6 +628,8 @@ // the floor. void IgnoreError() const; +#ifndef SWIG + // StatusOr<T>::emplace() // // Reconstructs the inner value T in-place using the provided args, using the @@ -658,13 +682,16 @@ // In optimized builds, passing absl::OkStatus() here will have the effect // of passing absl::StatusCode::kInternal as a fallback. using internal_statusor::StatusOrData<T>::AssignStatus; +#endif // SWIG private: +#ifndef SWIG using internal_statusor::StatusOrData<T>::Assign; template <typename U> void Assign(const absl::StatusOr<U>& other); template <typename U> void Assign(absl::StatusOr<U>&& other); +#endif // SWIG }; // operator==() @@ -722,6 +749,7 @@ } } +#ifndef SWIG //------------------------------------------------------------------------------ // Implementation details for StatusOr<T> //------------------------------------------------------------------------------ @@ -774,6 +802,8 @@ // no-op } +#endif // SWIG + ABSL_NAMESPACE_END } // namespace absl
diff --git a/absl/time/internal/cctz/src/time_zone_info.cc b/absl/time/internal/cctz/src/time_zone_info.cc index f7ed379..1f8f46a 100644 --- a/absl/time/internal/cctz/src/time_zone_info.cc +++ b/absl/time/internal/cctz/src/time_zone_info.cc
@@ -426,17 +426,25 @@ #endif } +// Returns true if c separates path components. Windows accepts either +// form, so a "..\" component walks up a directory just like a "../" one. +inline bool IsPathSeparator(char c) { +#if defined(_WIN32) + return c == '/' || c == '\\'; +#else + return c == '/'; +#endif +} + // Returns true if the zone name starting at pos contains an unsafe path. -inline bool UnsafePath(const std::string& name, std::size_t pos) { - // Path traversal: exact match ".." - if (name.compare(pos, std::string::npos, "..") == 0) return true; - // Path traversal: leading component "../" - if (name.compare(pos, 3, "../") == 0) return true; - // Path traversal: interior component "/../" - if (name.find("/../", pos) != std::string::npos) return true; - // Path traversal: trailing component "/.." - if (name.size() - pos >= 3 && name.compare(name.size() - 3, 3, "/..") == 0) { - return true; +bool UnsafePath(const std::string& name, std::size_t pos) { + // Path traversal: a ".." component that is at the beginning or preceded + // by a separator, and at the end or followed by a separator. + for (auto i = pos; (i = name.find("..", i)) != std::string::npos; i += 2) { + if ((i == pos || IsPathSeparator(name[i - 1])) && + (i == name.size() - 2 || IsPathSeparator(name[i + 2]))) { + return true; + } } return false; } @@ -748,11 +756,6 @@ if (transitions_[i].unix_time < -(1LL << 59) || transitions_[i].unix_time > (1LL << 59)) return false; // out of range - if (i != 0) { - // Check that the transitions are ordered by time (as zic guarantees). - if (!Transition::ByUnixTime()(transitions_[i - 1], transitions_[i])) - return false; // out of order - } } bool seen_type_0 = false; for (std::size_t i = 0; i != hdr.timecnt; ++i) { @@ -867,11 +870,13 @@ ttp = &transition_types_[tr.type_index]; tr.civil_sec = LocalTime(tr.unix_time, *ttp).cs; if (i != 0) { - // Check that the transitions are ordered by civil time. Essentially - // this means that an offset change cannot cross another such change. - // No one does this in practice, and we depend on it in MakeTime(). - if (!Transition::ByCivilTime()(transitions_[i - 1], tr)) + // Check that offset changes don't cross each other. No one + // does this in practice, and we depend on increasing absolute + // and civil times in BreakTime() and MakeTime() respectively. + if (!Transition::ByUnixTime()(transitions_[i - 1], tr) || + !Transition::ByCivilTime()(transitions_[i - 1], tr)) { return false; // out of order + } } }
diff --git a/absl/time/internal/cctz/src/time_zone_lookup_test.cc b/absl/time/internal/cctz/src/time_zone_lookup_test.cc index 1147e93..f53ac03 100644 --- a/absl/time/internal/cctz/src/time_zone_lookup_test.cc +++ b/absl/time/internal/cctz/src/time_zone_lookup_test.cc
@@ -187,12 +187,6 @@ EXPECT_EQ(chrono::system_clock::from_time_t(0), convert(civil_second(1970, 1, 1, 0, 0, 0), tz)); // UTC - // Reject path-traversal components. - EXPECT_FALSE(load_time_zone("file:../etc/passwd", &tz)); - EXPECT_FALSE(load_time_zone("file:../../etc/passwd", &tz)); - EXPECT_FALSE(load_time_zone("file:/../etc/passwd", &tz)); - EXPECT_FALSE(load_time_zone("file:America/../America/Los_Angeles", &tz)); - // Reject a fixed-offset name with a NUL where a digit belongs. for (const int i : {10, 11, 13, 14, 16, 17}) { std::string name = "Fixed/UTC+00:00:00"; @@ -200,10 +194,28 @@ EXPECT_FALSE(load_time_zone(name, &tz)) << "NUL at offset " << i; } - // Reject non-regular files and directories. + // Reject path-traversal components. + EXPECT_FALSE(load_time_zone("file:../etc/passwd", &tz)); + EXPECT_FALSE(load_time_zone("file:../../etc/passwd", &tz)); + EXPECT_FALSE(load_time_zone("file:/../etc/passwd", &tz)); + EXPECT_FALSE(load_time_zone("file:America/../America/Los_Angeles", &tz)); + +#if defined(_WIN32) + // Windows accepts '\' as a path separator, so these escape as well. + // If they were admitted, the second would resolve back into the zoneinfo + // directory and load, failing the test. Elsewhere '\' is an ordinary + // filename character, so these would only fail as nonexistent names. + EXPECT_FALSE(load_time_zone("file:..\\etc\\passwd", &tz)); + EXPECT_FALSE(load_time_zone("file:America\\..\\America/Los_Angeles", &tz)); +#endif + +#if !defined(_MSC_VER) + // Reject non-regular files and directories. The check lives in the + // non-MSVC FOpen(), so only expect it there. EXPECT_FALSE(load_time_zone("file:/dev/null", &tz)); EXPECT_FALSE(load_time_zone("file:/dev/stdin", &tz)); EXPECT_FALSE(load_time_zone("file:/tmp", &tz)); +#endif } TEST(TimeZone, Equality) { @@ -1060,6 +1072,15 @@ new StringZoneInfoSource(MakeExtendedTzif( 0, -5 * 3600, std::string{"EST", 4}, "EST5EDT,M3.2.0,M11.1.0"))); } + if (name == "test:ExtendedOverlappingRules") { + // The daylight time of one year starts more than four days after its + // nominal date, while the next year's ends more than five days before + // its own, so the two years' generated transitions overlap. + return std::unique_ptr<ZoneInfoSource>( + new StringZoneInfoSource(MakeExtendedTzif( + 0, -5 * 3600, std::string{"STD", 4}, + "STD-12:00:00DST12:00:00,358/100:00:00,1/-139:00:00"))); + } if (name == "test:UnterminatedAbbreviation") { // The abbreviation area is missing its final NUL, so the abbreviation // would run into whatever ExtendTransitions() appends behind it. @@ -1094,6 +1115,20 @@ cctz_extension::zone_info_source_factory = prev_factory; } +// A transition time may include a day offset of up to +/-167 hours, so the +// rules for consecutive years can overlap, producing transitions that go +// backward in unix time. BreakTime() binary searches the transitions by +// unix time, so such a zone must be rejected. +TEST(TimeZoneEdgeCase, ExtendedOverlappingRules) { + auto prev_factory = cctz_extension::zone_info_source_factory; + cctz_extension::zone_info_source_factory = ExtendedTestFactory; + + time_zone tz; + EXPECT_FALSE(load_time_zone("test:ExtendedOverlappingRules", &tz)); + + cctz_extension::zone_info_source_factory = prev_factory; +} + // Looking up the maximum time in an extended zone must fold back through the // 400-year cycle without overflowing when BreakTime() computes the shift. TEST(TimeZoneEdgeCase, ExtendedFarFuture) {