author | Bob Owen <bobowencode@gmail.com> |
Wed, 11 Feb 2015 08:22:02 +0000 | |
changeset 228642 | 38d12afdc7b15e8499a4951f8e7cd0495c600c92 |
parent 228605 | 0ebc9ae84e41d2eb6d21f0670a433605ac017dce |
child 228643 | efa7518e43b0912889a6722d3f2abc91092af601 |
push id | 28267 |
push user | ryanvm@gmail.com |
push date | Wed, 11 Feb 2015 21:28:56 +0000 |
treeherder | mozilla-central@650863f6987b [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | aklotz, jld |
bugs | 1102195 |
milestone | 38.0a1 |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
--- a/security/sandbox/chromium-shim/base/logging.cpp +++ b/security/sandbox/chromium-shim/base/logging.cpp @@ -37,30 +37,27 @@ int min_log_level = 0; int GetMinLogLevel() { return min_log_level; } int GetVlogLevelHelper(const char* file, size_t N) { return 0; } -// MSVC doesn't like complex extern templates and DLLs. -#if !defined(COMPILER_MSVC) // Explicit instantiations for commonly used comparisons. template std::string* MakeCheckOpString<int, int>( const int&, const int&, const char* names); template std::string* MakeCheckOpString<unsigned long, unsigned long>( const unsigned long&, const unsigned long&, const char* names); template std::string* MakeCheckOpString<unsigned long, unsigned int>( const unsigned long&, const unsigned int&, const char* names); template std::string* MakeCheckOpString<unsigned int, unsigned long>( const unsigned int&, const unsigned long&, const char* names); template std::string* MakeCheckOpString<std::string, std::string>( const std::string&, const std::string&, const char* name); -#endif #if defined(OS_WIN) LogMessage::SaveLastError::SaveLastError() : last_error_(::GetLastError()) { } LogMessage::SaveLastError::~SaveLastError() { ::SetLastError(last_error_); } @@ -100,16 +97,27 @@ Win32ErrorLogMessage::Win32ErrorLogMessa LogSeverity severity, SystemErrorCode err) : err_(err), log_message_(file, line, severity) { } Win32ErrorLogMessage::~Win32ErrorLogMessage() { } +#elif defined(OS_POSIX) +ErrnoLogMessage::ErrnoLogMessage(const char* file, + int line, + LogSeverity severity, + SystemErrorCode err) + : err_(err), + log_message_(file, line, severity) { +} + +ErrnoLogMessage::~ErrnoLogMessage() { +} #endif // OS_WIN void RawLog(int level, const char* message) { } } // namespace logging #if defined(OS_WIN)
deleted file mode 100644 --- a/security/sandbox/chromium-shim/base/threading/thread_local_storage.h +++ /dev/null @@ -1,10 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim: set ts=2 et sw=2 tw=80: */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -// Blank header file as thread_local.h includes a file that should only be -// included on Android. -// Chromium issue 431339 raised. -// https://code.google.com/p/chromium/issues/detail?id=431339
--- a/security/sandbox/chromium/base/atomic_ref_count.h +++ b/security/sandbox/chromium/base/atomic_ref_count.h @@ -7,17 +7,16 @@ // // The implementation includes annotations to avoid some false positives // when using data race detection tools. #ifndef BASE_ATOMIC_REF_COUNT_H_ #define BASE_ATOMIC_REF_COUNT_H_ #include "base/atomicops.h" -#include "base/third_party/dynamic_annotations/dynamic_annotations.h" namespace base { typedef subtle::Atomic32 AtomicRefCount; // Increment a reference count by "increment", which must exceed 0. inline void AtomicRefCountIncN(volatile AtomicRefCount *ptr, AtomicRefCount increment) { @@ -25,21 +24,17 @@ inline void AtomicRefCountIncN(volatile } // Decrement a reference count by "decrement", which must exceed 0, // and return whether the result is non-zero. // Insert barriers to ensure that state written before the reference count // became zero will be visible to a thread that has just made the count zero. inline bool AtomicRefCountDecN(volatile AtomicRefCount *ptr, AtomicRefCount decrement) { - ANNOTATE_HAPPENS_BEFORE(ptr); bool res = (subtle::Barrier_AtomicIncrement(ptr, -decrement) != 0); - if (!res) { - ANNOTATE_HAPPENS_AFTER(ptr); - } return res; } // Increment a reference count by 1. inline void AtomicRefCountInc(volatile AtomicRefCount *ptr) { base::AtomicRefCountIncN(ptr, 1); } @@ -53,28 +48,22 @@ inline bool AtomicRefCountDec(volatile A // Return whether the reference count is one. If the reference count is used // in the conventional way, a refrerence count of 1 implies that the current // thread owns the reference and no other thread shares it. This call performs // the test for a reference count of one, and performs the memory barrier // needed for the owning thread to act on the object, knowing that it has // exclusive access to the object. inline bool AtomicRefCountIsOne(volatile AtomicRefCount *ptr) { bool res = (subtle::Acquire_Load(ptr) == 1); - if (res) { - ANNOTATE_HAPPENS_AFTER(ptr); - } return res; } // Return whether the reference count is zero. With conventional object // referencing counting, the object will be destroyed, so the reference count // should never be zero. Hence this is generally used for a debug check. inline bool AtomicRefCountIsZero(volatile AtomicRefCount *ptr) { bool res = (subtle::Acquire_Load(ptr) == 0); - if (res) { - ANNOTATE_HAPPENS_AFTER(ptr); - } return res; } } // namespace base #endif // BASE_ATOMIC_REF_COUNT_H_
--- a/security/sandbox/chromium/base/atomicops.h +++ b/security/sandbox/chromium/base/atomicops.h @@ -23,18 +23,21 @@ // NoBarrier_Load() // Although there are currently no compiler enforcement, you are encouraged // to use these. // #ifndef BASE_ATOMICOPS_H_ #define BASE_ATOMICOPS_H_ +#include <cassert> // Small C++ header which defines implementation specific + // macros used to identify the STL implementation. #include <stdint.h> +#include "base/base_export.h" #include "build/build_config.h" #if defined(OS_WIN) && defined(ARCH_CPU_64_BITS) // windows.h #defines this (only on x64). This causes problems because the // public API also uses MemoryBarrier at the public name for this fence. So, on // X64, undef it, and call its documented // (http://msdn.microsoft.com/en-us/library/windows/desktop/ms684208.aspx) // implementation directly. @@ -132,36 +135,75 @@ void Release_Store(volatile Atomic64* pt Atomic64 NoBarrier_Load(volatile const Atomic64* ptr); Atomic64 Acquire_Load(volatile const Atomic64* ptr); Atomic64 Release_Load(volatile const Atomic64* ptr); #endif // ARCH_CPU_64_BITS } // namespace subtle } // namespace base -// Include our platform specific implementation. -#if defined(THREAD_SANITIZER) -#include "base/atomicops_internals_tsan.h" -#elif defined(OS_WIN) && defined(COMPILER_MSVC) && defined(ARCH_CPU_X86_FAMILY) -#include "base/atomicops_internals_x86_msvc.h" -#elif defined(OS_MACOSX) -#include "base/atomicops_internals_mac.h" -#elif defined(OS_NACL) -#include "base/atomicops_internals_gcc.h" -#elif defined(COMPILER_GCC) && defined(ARCH_CPU_ARMEL) -#include "base/atomicops_internals_arm_gcc.h" -#elif defined(COMPILER_GCC) && defined(ARCH_CPU_ARM64) -#include "base/atomicops_internals_arm64_gcc.h" -#elif defined(COMPILER_GCC) && defined(ARCH_CPU_X86_FAMILY) -#include "base/atomicops_internals_x86_gcc.h" -#elif defined(COMPILER_GCC) && defined(ARCH_CPU_MIPS_FAMILY) -#include "base/atomicops_internals_mips_gcc.h" -#else -#error "Atomic operations are not supported on your platform" +// The following x86 CPU features are used in atomicops_internals_x86_gcc.h, but +// this file is duplicated inside of Chrome: protobuf and tcmalloc rely on the +// struct being present at link time. Some parts of Chrome can currently use the +// portable interface whereas others still use GCC one. The include guards are +// the same as in atomicops_internals_x86_gcc.cc. +#if defined(__i386__) || defined(__x86_64__) +// This struct is not part of the public API of this module; clients may not +// use it. (However, it's exported via BASE_EXPORT because clients implicitly +// do use it at link time by inlining these functions.) +// Features of this x86. Values may not be correct before main() is run, +// but are set conservatively. +struct AtomicOps_x86CPUFeatureStruct { + bool has_amd_lock_mb_bug; // Processor has AMD memory-barrier bug; do lfence + // after acquire compare-and-swap. + // The following fields are unused by Chrome's base implementation but are + // still used by copies of the same code in other parts of the code base. This + // causes an ODR violation, and the other code is likely reading invalid + // memory. + // TODO(jfb) Delete these fields once the rest of the Chrome code base doesn't + // depend on them. + bool has_sse2; // Processor has SSE2. + bool has_cmpxchg16b; // Processor supports cmpxchg16b instruction. +}; +BASE_EXPORT extern struct AtomicOps_x86CPUFeatureStruct + AtomicOps_Internalx86CPUFeatures; #endif +// Try to use a portable implementation based on C++11 atomics. +// +// Some toolchains support C++11 language features without supporting library +// features (recent compiler, older STL). Whitelist libstdc++ and libc++ that we +// know will have <atomic> when compiling C++11. +#if ((__cplusplus >= 201103L) && \ + ((defined(__GLIBCXX__) && (__GLIBCXX__ > 20110216)) || \ + (defined(_LIBCPP_VERSION) && (_LIBCPP_STD_VER >= 11)))) +# include "base/atomicops_internals_portable.h" +#else // Otherwise use a platform specific implementation. +# if defined(THREAD_SANITIZER) +# error "Thread sanitizer must use the portable atomic operations" +# elif (defined(OS_WIN) && defined(COMPILER_MSVC) && \ + defined(ARCH_CPU_X86_FAMILY)) +# include "base/atomicops_internals_x86_msvc.h" +# elif defined(OS_MACOSX) +# include "base/atomicops_internals_mac.h" +# elif defined(OS_NACL) +# include "base/atomicops_internals_gcc.h" +# elif defined(COMPILER_GCC) && defined(ARCH_CPU_ARMEL) +# include "base/atomicops_internals_arm_gcc.h" +# elif defined(COMPILER_GCC) && defined(ARCH_CPU_ARM64) +# include "base/atomicops_internals_arm64_gcc.h" +# elif defined(COMPILER_GCC) && defined(ARCH_CPU_X86_FAMILY) +# include "base/atomicops_internals_x86_gcc.h" +# elif (defined(COMPILER_GCC) && \ + (defined(ARCH_CPU_MIPS_FAMILY) || defined(ARCH_CPU_MIPS64_FAMILY))) +# include "base/atomicops_internals_mips_gcc.h" +# else +# error "Atomic operations are not supported on your platform" +# endif +#endif // Portable / non-portable includes. + // On some platforms we need additional declarations to make // AtomicWord compatible with our other Atomic* types. #if defined(OS_MACOSX) || defined(OS_OPENBSD) #include "base/atomicops_internals_atomicword_compat.h" #endif #endif // BASE_ATOMICOPS_H_
new file mode 100644 --- /dev/null +++ b/security/sandbox/chromium/base/atomicops_internals_arm_gcc.h @@ -0,0 +1,294 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// This file is an internal atomic implementation, use base/atomicops.h instead. +// +// LinuxKernelCmpxchg and Barrier_AtomicIncrement are from Google Gears. + +#ifndef BASE_ATOMICOPS_INTERNALS_ARM_GCC_H_ +#define BASE_ATOMICOPS_INTERNALS_ARM_GCC_H_ + +#if defined(OS_QNX) +#include <sys/cpuinline.h> +#endif + +namespace base { +namespace subtle { + +// Memory barriers on ARM are funky, but the kernel is here to help: +// +// * ARMv5 didn't support SMP, there is no memory barrier instruction at +// all on this architecture, or when targeting its machine code. +// +// * Some ARMv6 CPUs support SMP. A full memory barrier can be produced by +// writing a random value to a very specific coprocessor register. +// +// * On ARMv7, the "dmb" instruction is used to perform a full memory +// barrier (though writing to the co-processor will still work). +// However, on single core devices (e.g. Nexus One, or Nexus S), +// this instruction will take up to 200 ns, which is huge, even though +// it's completely un-needed on these devices. +// +// * There is no easy way to determine at runtime if the device is +// single or multi-core. However, the kernel provides a useful helper +// function at a fixed memory address (0xffff0fa0), which will always +// perform a memory barrier in the most efficient way. I.e. on single +// core devices, this is an empty function that exits immediately. +// On multi-core devices, it implements a full memory barrier. +// +// * This source could be compiled to ARMv5 machine code that runs on a +// multi-core ARMv6 or ARMv7 device. In this case, memory barriers +// are needed for correct execution. Always call the kernel helper, even +// when targeting ARMv5TE. +// + +inline void MemoryBarrier() { +#if defined(OS_LINUX) || defined(OS_ANDROID) + // Note: This is a function call, which is also an implicit compiler barrier. + typedef void (*KernelMemoryBarrierFunc)(); + ((KernelMemoryBarrierFunc)0xffff0fa0)(); +#elif defined(OS_QNX) + __cpu_membarrier(); +#else +#error MemoryBarrier() is not implemented on this platform. +#endif +} + +// An ARM toolchain would only define one of these depending on which +// variant of the target architecture is being used. This tests against +// any known ARMv6 or ARMv7 variant, where it is possible to directly +// use ldrex/strex instructions to implement fast atomic operations. +#if defined(__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__) || \ + defined(__ARM_ARCH_7R__) || defined(__ARM_ARCH_7M__) || \ + defined(__ARM_ARCH_6__) || defined(__ARM_ARCH_6J__) || \ + defined(__ARM_ARCH_6K__) || defined(__ARM_ARCH_6Z__) || \ + defined(__ARM_ARCH_6ZK__) || defined(__ARM_ARCH_6T2__) + +inline Atomic32 NoBarrier_CompareAndSwap(volatile Atomic32* ptr, + Atomic32 old_value, + Atomic32 new_value) { + Atomic32 prev_value; + int reloop; + do { + // The following is equivalent to: + // + // prev_value = LDREX(ptr) + // reloop = 0 + // if (prev_value != old_value) + // reloop = STREX(ptr, new_value) + __asm__ __volatile__(" ldrex %0, [%3]\n" + " mov %1, #0\n" + " cmp %0, %4\n" +#ifdef __thumb2__ + " it eq\n" +#endif + " strexeq %1, %5, [%3]\n" + : "=&r"(prev_value), "=&r"(reloop), "+m"(*ptr) + : "r"(ptr), "r"(old_value), "r"(new_value) + : "cc", "memory"); + } while (reloop != 0); + return prev_value; +} + +inline Atomic32 Acquire_CompareAndSwap(volatile Atomic32* ptr, + Atomic32 old_value, + Atomic32 new_value) { + Atomic32 result = NoBarrier_CompareAndSwap(ptr, old_value, new_value); + MemoryBarrier(); + return result; +} + +inline Atomic32 Release_CompareAndSwap(volatile Atomic32* ptr, + Atomic32 old_value, + Atomic32 new_value) { + MemoryBarrier(); + return NoBarrier_CompareAndSwap(ptr, old_value, new_value); +} + +inline Atomic32 NoBarrier_AtomicIncrement(volatile Atomic32* ptr, + Atomic32 increment) { + Atomic32 value; + int reloop; + do { + // Equivalent to: + // + // value = LDREX(ptr) + // value += increment + // reloop = STREX(ptr, value) + // + __asm__ __volatile__(" ldrex %0, [%3]\n" + " add %0, %0, %4\n" + " strex %1, %0, [%3]\n" + : "=&r"(value), "=&r"(reloop), "+m"(*ptr) + : "r"(ptr), "r"(increment) + : "cc", "memory"); + } while (reloop); + return value; +} + +inline Atomic32 Barrier_AtomicIncrement(volatile Atomic32* ptr, + Atomic32 increment) { + // TODO(digit): Investigate if it's possible to implement this with + // a single MemoryBarrier() operation between the LDREX and STREX. + // See http://crbug.com/246514 + MemoryBarrier(); + Atomic32 result = NoBarrier_AtomicIncrement(ptr, increment); + MemoryBarrier(); + return result; +} + +inline Atomic32 NoBarrier_AtomicExchange(volatile Atomic32* ptr, + Atomic32 new_value) { + Atomic32 old_value; + int reloop; + do { + // old_value = LDREX(ptr) + // reloop = STREX(ptr, new_value) + __asm__ __volatile__(" ldrex %0, [%3]\n" + " strex %1, %4, [%3]\n" + : "=&r"(old_value), "=&r"(reloop), "+m"(*ptr) + : "r"(ptr), "r"(new_value) + : "cc", "memory"); + } while (reloop != 0); + return old_value; +} + +// This tests against any known ARMv5 variant. +#elif defined(__ARM_ARCH_5__) || defined(__ARM_ARCH_5T__) || \ + defined(__ARM_ARCH_5TE__) || defined(__ARM_ARCH_5TEJ__) + +// The kernel also provides a helper function to perform an atomic +// compare-and-swap operation at the hard-wired address 0xffff0fc0. +// On ARMv5, this is implemented by a special code path that the kernel +// detects and treats specially when thread pre-emption happens. +// On ARMv6 and higher, it uses LDREX/STREX instructions instead. +// +// Note that this always perform a full memory barrier, there is no +// need to add calls MemoryBarrier() before or after it. It also +// returns 0 on success, and 1 on exit. +// +// Available and reliable since Linux 2.6.24. Both Android and ChromeOS +// use newer kernel revisions, so this should not be a concern. +namespace { + +inline int LinuxKernelCmpxchg(Atomic32 old_value, + Atomic32 new_value, + volatile Atomic32* ptr) { + typedef int (*KernelCmpxchgFunc)(Atomic32, Atomic32, volatile Atomic32*); + return ((KernelCmpxchgFunc)0xffff0fc0)(old_value, new_value, ptr); +} + +} // namespace + +inline Atomic32 NoBarrier_CompareAndSwap(volatile Atomic32* ptr, + Atomic32 old_value, + Atomic32 new_value) { + Atomic32 prev_value; + for (;;) { + prev_value = *ptr; + if (prev_value != old_value) + return prev_value; + if (!LinuxKernelCmpxchg(old_value, new_value, ptr)) + return old_value; + } +} + +inline Atomic32 NoBarrier_AtomicExchange(volatile Atomic32* ptr, + Atomic32 new_value) { + Atomic32 old_value; + do { + old_value = *ptr; + } while (LinuxKernelCmpxchg(old_value, new_value, ptr)); + return old_value; +} + +inline Atomic32 NoBarrier_AtomicIncrement(volatile Atomic32* ptr, + Atomic32 increment) { + return Barrier_AtomicIncrement(ptr, increment); +} + +inline Atomic32 Barrier_AtomicIncrement(volatile Atomic32* ptr, + Atomic32 increment) { + for (;;) { + // Atomic exchange the old value with an incremented one. + Atomic32 old_value = *ptr; + Atomic32 new_value = old_value + increment; + if (!LinuxKernelCmpxchg(old_value, new_value, ptr)) { + // The exchange took place as expected. + return new_value; + } + // Otherwise, *ptr changed mid-loop and we need to retry. + } +} + +inline Atomic32 Acquire_CompareAndSwap(volatile Atomic32* ptr, + Atomic32 old_value, + Atomic32 new_value) { + Atomic32 prev_value; + for (;;) { + prev_value = *ptr; + if (prev_value != old_value) { + // Always ensure acquire semantics. + MemoryBarrier(); + return prev_value; + } + if (!LinuxKernelCmpxchg(old_value, new_value, ptr)) + return old_value; + } +} + +inline Atomic32 Release_CompareAndSwap(volatile Atomic32* ptr, + Atomic32 old_value, + Atomic32 new_value) { + // This could be implemented as: + // MemoryBarrier(); + // return NoBarrier_CompareAndSwap(); + // + // But would use 3 barriers per succesful CAS. To save performance, + // use Acquire_CompareAndSwap(). Its implementation guarantees that: + // - A succesful swap uses only 2 barriers (in the kernel helper). + // - An early return due to (prev_value != old_value) performs + // a memory barrier with no store, which is equivalent to the + // generic implementation above. + return Acquire_CompareAndSwap(ptr, old_value, new_value); +} + +#else +# error "Your CPU's ARM architecture is not supported yet" +#endif + +// NOTE: Atomicity of the following load and store operations is only +// guaranteed in case of 32-bit alignement of |ptr| values. + +inline void NoBarrier_Store(volatile Atomic32* ptr, Atomic32 value) { + *ptr = value; +} + +inline void Acquire_Store(volatile Atomic32* ptr, Atomic32 value) { + *ptr = value; + MemoryBarrier(); +} + +inline void Release_Store(volatile Atomic32* ptr, Atomic32 value) { + MemoryBarrier(); + *ptr = value; +} + +inline Atomic32 NoBarrier_Load(volatile const Atomic32* ptr) { return *ptr; } + +inline Atomic32 Acquire_Load(volatile const Atomic32* ptr) { + Atomic32 value = *ptr; + MemoryBarrier(); + return value; +} + +inline Atomic32 Release_Load(volatile const Atomic32* ptr) { + MemoryBarrier(); + return *ptr; +} + +} // namespace base::subtle +} // namespace base + +#endif // BASE_ATOMICOPS_INTERNALS_ARM_GCC_H_
new file mode 100644 --- /dev/null +++ b/security/sandbox/chromium/base/atomicops_internals_portable.h @@ -0,0 +1,227 @@ +// Copyright (c) 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// This file is an internal atomic implementation, use atomicops.h instead. +// +// This implementation uses C++11 atomics' member functions. The code base is +// currently written assuming atomicity revolves around accesses instead of +// C++11's memory locations. The burden is on the programmer to ensure that all +// memory locations accessed atomically are never accessed non-atomically (tsan +// should help with this). +// +// TODO(jfb) Modify the atomicops.h API and user code to declare atomic +// locations as truly atomic. See the static_assert below. +// +// Of note in this implementation: +// * All NoBarrier variants are implemented as relaxed. +// * All Barrier variants are implemented as sequentially-consistent. +// * Compare exchange's failure ordering is always the same as the success one +// (except for release, which fails as relaxed): using a weaker ordering is +// only valid under certain uses of compare exchange. +// * Acquire store doesn't exist in the C11 memory model, it is instead +// implemented as a relaxed store followed by a sequentially consistent +// fence. +// * Release load doesn't exist in the C11 memory model, it is instead +// implemented as sequentially consistent fence followed by a relaxed load. +// * Atomic increment is expected to return the post-incremented value, whereas +// C11 fetch add returns the previous value. The implementation therefore +// needs to increment twice (which the compiler should be able to detect and +// optimize). + +#ifndef BASE_ATOMICOPS_INTERNALS_PORTABLE_H_ +#define BASE_ATOMICOPS_INTERNALS_PORTABLE_H_ + +#include <atomic> + +namespace base { +namespace subtle { + +// This implementation is transitional and maintains the original API for +// atomicops.h. This requires casting memory locations to the atomic types, and +// assumes that the API and the C++11 implementation are layout-compatible, +// which isn't true for all implementations or hardware platforms. The static +// assertion should detect this issue, were it to fire then this header +// shouldn't be used. +// +// TODO(jfb) If this header manages to stay committed then the API should be +// modified, and all call sites updated. +typedef volatile std::atomic<Atomic32>* AtomicLocation32; +static_assert(sizeof(*(AtomicLocation32) nullptr) == sizeof(Atomic32), + "incompatible 32-bit atomic layout"); + +inline void MemoryBarrier() { +#if defined(__GLIBCXX__) + // Work around libstdc++ bug 51038 where atomic_thread_fence was declared but + // not defined, leading to the linker complaining about undefined references. + __atomic_thread_fence(std::memory_order_seq_cst); +#else + std::atomic_thread_fence(std::memory_order_seq_cst); +#endif +} + +inline Atomic32 NoBarrier_CompareAndSwap(volatile Atomic32* ptr, + Atomic32 old_value, + Atomic32 new_value) { + ((AtomicLocation32)ptr) + ->compare_exchange_strong(old_value, + new_value, + std::memory_order_relaxed, + std::memory_order_relaxed); + return old_value; +} + +inline Atomic32 NoBarrier_AtomicExchange(volatile Atomic32* ptr, + Atomic32 new_value) { + return ((AtomicLocation32)ptr) + ->exchange(new_value, std::memory_order_relaxed); +} + +inline Atomic32 NoBarrier_AtomicIncrement(volatile Atomic32* ptr, + Atomic32 increment) { + return increment + + ((AtomicLocation32)ptr) + ->fetch_add(increment, std::memory_order_relaxed); +} + +inline Atomic32 Barrier_AtomicIncrement(volatile Atomic32* ptr, + Atomic32 increment) { + return increment + ((AtomicLocation32)ptr)->fetch_add(increment); +} + +inline Atomic32 Acquire_CompareAndSwap(volatile Atomic32* ptr, + Atomic32 old_value, + Atomic32 new_value) { + ((AtomicLocation32)ptr) + ->compare_exchange_strong(old_value, + new_value, + std::memory_order_acquire, + std::memory_order_acquire); + return old_value; +} + +inline Atomic32 Release_CompareAndSwap(volatile Atomic32* ptr, + Atomic32 old_value, + Atomic32 new_value) { + ((AtomicLocation32)ptr) + ->compare_exchange_strong(old_value, + new_value, + std::memory_order_release, + std::memory_order_relaxed); + return old_value; +} + +inline void NoBarrier_Store(volatile Atomic32* ptr, Atomic32 value) { + ((AtomicLocation32)ptr)->store(value, std::memory_order_relaxed); +} + +inline void Acquire_Store(volatile Atomic32* ptr, Atomic32 value) { + ((AtomicLocation32)ptr)->store(value, std::memory_order_relaxed); + MemoryBarrier(); +} + +inline void Release_Store(volatile Atomic32* ptr, Atomic32 value) { + ((AtomicLocation32)ptr)->store(value, std::memory_order_release); +} + +inline Atomic32 NoBarrier_Load(volatile const Atomic32* ptr) { + return ((AtomicLocation32)ptr)->load(std::memory_order_relaxed); +} + +inline Atomic32 Acquire_Load(volatile const Atomic32* ptr) { + return ((AtomicLocation32)ptr)->load(std::memory_order_acquire); +} + +inline Atomic32 Release_Load(volatile const Atomic32* ptr) { + MemoryBarrier(); + return ((AtomicLocation32)ptr)->load(std::memory_order_relaxed); +} + +#if defined(ARCH_CPU_64_BITS) + +typedef volatile std::atomic<Atomic64>* AtomicLocation64; +static_assert(sizeof(*(AtomicLocation64) nullptr) == sizeof(Atomic64), + "incompatible 64-bit atomic layout"); + +inline Atomic64 NoBarrier_CompareAndSwap(volatile Atomic64* ptr, + Atomic64 old_value, + Atomic64 new_value) { + ((AtomicLocation64)ptr) + ->compare_exchange_strong(old_value, + new_value, + std::memory_order_relaxed, + std::memory_order_relaxed); + return old_value; +} + +inline Atomic64 NoBarrier_AtomicExchange(volatile Atomic64* ptr, + Atomic64 new_value) { + return ((AtomicLocation64)ptr) + ->exchange(new_value, std::memory_order_relaxed); +} + +inline Atomic64 NoBarrier_AtomicIncrement(volatile Atomic64* ptr, + Atomic64 increment) { + return increment + + ((AtomicLocation64)ptr) + ->fetch_add(increment, std::memory_order_relaxed); +} + +inline Atomic64 Barrier_AtomicIncrement(volatile Atomic64* ptr, + Atomic64 increment) { + return increment + ((AtomicLocation64)ptr)->fetch_add(increment); +} + +inline Atomic64 Acquire_CompareAndSwap(volatile Atomic64* ptr, + Atomic64 old_value, + Atomic64 new_value) { + ((AtomicLocation64)ptr) + ->compare_exchange_strong(old_value, + new_value, + std::memory_order_acquire, + std::memory_order_acquire); + return old_value; +} + +inline Atomic64 Release_CompareAndSwap(volatile Atomic64* ptr, + Atomic64 old_value, + Atomic64 new_value) { + ((AtomicLocation64)ptr) + ->compare_exchange_strong(old_value, + new_value, + std::memory_order_release, + std::memory_order_relaxed); + return old_value; +} + +inline void NoBarrier_Store(volatile Atomic64* ptr, Atomic64 value) { + ((AtomicLocation64)ptr)->store(value, std::memory_order_relaxed); +} + +inline void Acquire_Store(volatile Atomic64* ptr, Atomic64 value) { + ((AtomicLocation64)ptr)->store(value, std::memory_order_relaxed); + MemoryBarrier(); +} + +inline void Release_Store(volatile Atomic64* ptr, Atomic64 value) { + ((AtomicLocation64)ptr)->store(value, std::memory_order_release); +} + +inline Atomic64 NoBarrier_Load(volatile const Atomic64* ptr) { + return ((AtomicLocation64)ptr)->load(std::memory_order_relaxed); +} + +inline Atomic64 Acquire_Load(volatile const Atomic64* ptr) { + return ((AtomicLocation64)ptr)->load(std::memory_order_acquire); +} + +inline Atomic64 Release_Load(volatile const Atomic64* ptr) { + MemoryBarrier(); + return ((AtomicLocation64)ptr)->load(std::memory_order_relaxed); +} + +#endif // defined(ARCH_CPU_64_BITS) +} +} // namespace base::subtle + +#endif // BASE_ATOMICOPS_INTERNALS_PORTABLE_H_
deleted file mode 100644 --- a/security/sandbox/chromium/base/atomicops_internals_tsan.h +++ /dev/null @@ -1,186 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// This file is an internal atomic implementation for compiler-based -// ThreadSanitizer. Use base/atomicops.h instead. - -#ifndef BASE_ATOMICOPS_INTERNALS_TSAN_H_ -#define BASE_ATOMICOPS_INTERNALS_TSAN_H_ - -#include <sanitizer/tsan_interface_atomic.h> - -namespace base { -namespace subtle { - -inline Atomic32 NoBarrier_CompareAndSwap(volatile Atomic32* ptr, - Atomic32 old_value, - Atomic32 new_value) { - Atomic32 cmp = old_value; - __tsan_atomic32_compare_exchange_strong(ptr, &cmp, new_value, - __tsan_memory_order_relaxed, __tsan_memory_order_relaxed); - return cmp; -} - -inline Atomic32 NoBarrier_AtomicExchange(volatile Atomic32* ptr, - Atomic32 new_value) { - return __tsan_atomic32_exchange(ptr, new_value, - __tsan_memory_order_relaxed); -} - -inline Atomic32 Acquire_AtomicExchange(volatile Atomic32* ptr, - Atomic32 new_value) { - return __tsan_atomic32_exchange(ptr, new_value, - __tsan_memory_order_acquire); -} - -inline Atomic32 Release_AtomicExchange(volatile Atomic32* ptr, - Atomic32 new_value) { - return __tsan_atomic32_exchange(ptr, new_value, - __tsan_memory_order_release); -} - -inline Atomic32 NoBarrier_AtomicIncrement(volatile Atomic32* ptr, - Atomic32 increment) { - return increment + __tsan_atomic32_fetch_add(ptr, increment, - __tsan_memory_order_relaxed); -} - -inline Atomic32 Barrier_AtomicIncrement(volatile Atomic32* ptr, - Atomic32 increment) { - return increment + __tsan_atomic32_fetch_add(ptr, increment, - __tsan_memory_order_acq_rel); -} - -inline Atomic32 Acquire_CompareAndSwap(volatile Atomic32* ptr, - Atomic32 old_value, - Atomic32 new_value) { - Atomic32 cmp = old_value; - __tsan_atomic32_compare_exchange_strong(ptr, &cmp, new_value, - __tsan_memory_order_acquire, __tsan_memory_order_acquire); - return cmp; -} - -inline Atomic32 Release_CompareAndSwap(volatile Atomic32* ptr, - Atomic32 old_value, - Atomic32 new_value) { - Atomic32 cmp = old_value; - __tsan_atomic32_compare_exchange_strong(ptr, &cmp, new_value, - __tsan_memory_order_release, __tsan_memory_order_relaxed); - return cmp; -} - -inline void NoBarrier_Store(volatile Atomic32* ptr, Atomic32 value) { - __tsan_atomic32_store(ptr, value, __tsan_memory_order_relaxed); -} - -inline void Acquire_Store(volatile Atomic32* ptr, Atomic32 value) { - __tsan_atomic32_store(ptr, value, __tsan_memory_order_relaxed); - __tsan_atomic_thread_fence(__tsan_memory_order_seq_cst); -} - -inline void Release_Store(volatile Atomic32* ptr, Atomic32 value) { - __tsan_atomic32_store(ptr, value, __tsan_memory_order_release); -} - -inline Atomic32 NoBarrier_Load(volatile const Atomic32* ptr) { - return __tsan_atomic32_load(ptr, __tsan_memory_order_relaxed); -} - -inline Atomic32 Acquire_Load(volatile const Atomic32* ptr) { - return __tsan_atomic32_load(ptr, __tsan_memory_order_acquire); -} - -inline Atomic32 Release_Load(volatile const Atomic32* ptr) { - __tsan_atomic_thread_fence(__tsan_memory_order_seq_cst); - return __tsan_atomic32_load(ptr, __tsan_memory_order_relaxed); -} - -inline Atomic64 NoBarrier_CompareAndSwap(volatile Atomic64* ptr, - Atomic64 old_value, - Atomic64 new_value) { - Atomic64 cmp = old_value; - __tsan_atomic64_compare_exchange_strong(ptr, &cmp, new_value, - __tsan_memory_order_relaxed, __tsan_memory_order_relaxed); - return cmp; -} - -inline Atomic64 NoBarrier_AtomicExchange(volatile Atomic64* ptr, - Atomic64 new_value) { - return __tsan_atomic64_exchange(ptr, new_value, __tsan_memory_order_relaxed); -} - -inline Atomic64 Acquire_AtomicExchange(volatile Atomic64* ptr, - Atomic64 new_value) { - return __tsan_atomic64_exchange(ptr, new_value, __tsan_memory_order_acquire); -} - -inline Atomic64 Release_AtomicExchange(volatile Atomic64* ptr, - Atomic64 new_value) { - return __tsan_atomic64_exchange(ptr, new_value, __tsan_memory_order_release); -} - -inline Atomic64 NoBarrier_AtomicIncrement(volatile Atomic64* ptr, - Atomic64 increment) { - return increment + __tsan_atomic64_fetch_add(ptr, increment, - __tsan_memory_order_relaxed); -} - -inline Atomic64 Barrier_AtomicIncrement(volatile Atomic64* ptr, - Atomic64 increment) { - return increment + __tsan_atomic64_fetch_add(ptr, increment, - __tsan_memory_order_acq_rel); -} - -inline void NoBarrier_Store(volatile Atomic64* ptr, Atomic64 value) { - __tsan_atomic64_store(ptr, value, __tsan_memory_order_relaxed); -} - -inline void Acquire_Store(volatile Atomic64* ptr, Atomic64 value) { - __tsan_atomic64_store(ptr, value, __tsan_memory_order_relaxed); - __tsan_atomic_thread_fence(__tsan_memory_order_seq_cst); -} - -inline void Release_Store(volatile Atomic64* ptr, Atomic64 value) { - __tsan_atomic64_store(ptr, value, __tsan_memory_order_release); -} - -inline Atomic64 NoBarrier_Load(volatile const Atomic64* ptr) { - return __tsan_atomic64_load(ptr, __tsan_memory_order_relaxed); -} - -inline Atomic64 Acquire_Load(volatile const Atomic64* ptr) { - return __tsan_atomic64_load(ptr, __tsan_memory_order_acquire); -} - -inline Atomic64 Release_Load(volatile const Atomic64* ptr) { - __tsan_atomic_thread_fence(__tsan_memory_order_seq_cst); - return __tsan_atomic64_load(ptr, __tsan_memory_order_relaxed); -} - -inline Atomic64 Acquire_CompareAndSwap(volatile Atomic64* ptr, - Atomic64 old_value, - Atomic64 new_value) { - Atomic64 cmp = old_value; - __tsan_atomic64_compare_exchange_strong(ptr, &cmp, new_value, - __tsan_memory_order_acquire, __tsan_memory_order_acquire); - return cmp; -} - -inline Atomic64 Release_CompareAndSwap(volatile Atomic64* ptr, - Atomic64 old_value, - Atomic64 new_value) { - Atomic64 cmp = old_value; - __tsan_atomic64_compare_exchange_strong(ptr, &cmp, new_value, - __tsan_memory_order_release, __tsan_memory_order_relaxed); - return cmp; -} - -inline void MemoryBarrier() { - __tsan_atomic_thread_fence(__tsan_memory_order_seq_cst); -} - -} // namespace base::subtle -} // namespace base - -#endif // BASE_ATOMICOPS_INTERNALS_TSAN_H_
--- a/security/sandbox/chromium/base/atomicops_internals_x86_gcc.h +++ b/security/sandbox/chromium/base/atomicops_internals_x86_gcc.h @@ -2,30 +2,16 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // This file is an internal atomic implementation, use base/atomicops.h instead. #ifndef BASE_ATOMICOPS_INTERNALS_X86_GCC_H_ #define BASE_ATOMICOPS_INTERNALS_X86_GCC_H_ -#include "base/base_export.h" - -// This struct is not part of the public API of this module; clients may not -// use it. (However, it's exported via BASE_EXPORT because clients implicitly -// do use it at link time by inlining these functions.) -// Features of this x86. Values may not be correct before main() is run, -// but are set conservatively. -struct AtomicOps_x86CPUFeatureStruct { - bool has_amd_lock_mb_bug; // Processor has AMD memory-barrier bug; do lfence - // after acquire compare-and-swap. -}; -BASE_EXPORT extern struct AtomicOps_x86CPUFeatureStruct - AtomicOps_Internalx86CPUFeatures; - #define ATOMICOPS_COMPILER_BARRIER() __asm__ __volatile__("" : : : "memory") namespace base { namespace subtle { // 32-bit low-level operations on any platform. inline Atomic32 NoBarrier_CompareAndSwap(volatile Atomic32* ptr,
--- a/security/sandbox/chromium/base/base_paths_win.h +++ b/security/sandbox/chromium/base/base_paths_win.h @@ -20,30 +20,27 @@ enum { DIR_PROGRAM_FILESX86, // Usually c:\program files or c:\program files (x86) DIR_IE_INTERNET_CACHE, // Temporary Internet Files directory. DIR_COMMON_START_MENU, // Usually "C:\Documents and Settings\All Users\ // Start Menu\Programs" DIR_START_MENU, // Usually "C:\Documents and Settings\<user>\ // Start Menu\Programs" DIR_APP_DATA, // Application Data directory under the user profile. - DIR_LOCAL_APP_DATA_LOW, // Local AppData directory for low integrity level. DIR_LOCAL_APP_DATA, // "Local Settings\Application Data" directory under // the user profile. DIR_COMMON_APP_DATA, // W2K, XP, W2K3: "C:\Documents and Settings\ // All Users\Application Data". // Vista, W2K8 and above: "C:\ProgramData". DIR_APP_SHORTCUTS, // Where tiles on the start screen are stored, only // for Windows 8. Maps to "Local\AppData\Microsoft\ // Windows\Application Shortcuts\". DIR_COMMON_DESKTOP, // Directory for the common desktop (visible // on all user's Desktop). DIR_USER_QUICK_LAUNCH, // Directory for the quick launch shortcuts. - DIR_DEFAULT_USER_QUICK_LAUNCH, // Directory for the quick launch shortcuts - // of the Default user. DIR_TASKBAR_PINS, // Directory for the shortcuts pinned to taskbar via // base::win::TaskbarPinShortcutLink(). DIR_WINDOWS_FONTS, // Usually C:\Windows\Fonts. PATH_WIN_END }; } // namespace base
--- a/security/sandbox/chromium/base/base_switches.cc +++ b/security/sandbox/chromium/base/base_switches.cc @@ -45,16 +45,24 @@ const char kV[] const char kVModule[] = "vmodule"; // Will wait for 60 seconds for a debugger to come to attach to the process. const char kWaitForDebugger[] = "wait-for-debugger"; // Sends a pretty-printed version of tracing info to the console. const char kTraceToConsole[] = "trace-to-console"; +// Sends trace events from these categories to a file. +// --trace-to-file on its own sends to default categories. +const char kTraceToFile[] = "trace-to-file"; + +// Specifies the file name for --trace-to-file. If unspecified, it will +// go to a default file name. +const char kTraceToFileName[] = "trace-to-file-name"; + // Configure whether chrome://profiler will contain timing information. This // option is enabled by default. A value of "0" will disable profiler timing, // while all other values will enable it. const char kProfilerTiming[] = "profiler-timing"; // Value of the --profiler-timing flag that will disable timing information for // chrome://profiler. const char kProfilerTimingDisabledValue[] = "0";
--- a/security/sandbox/chromium/base/base_switches.h +++ b/security/sandbox/chromium/base/base_switches.h @@ -15,16 +15,18 @@ extern const char kDisableBreakpad[]; extern const char kEnableCrashReporter[]; extern const char kFullMemoryCrashReport[]; extern const char kLowEndDeviceMode[]; extern const char kNoErrorDialogs[]; extern const char kProfilerTiming[]; extern const char kProfilerTimingDisabledValue[]; extern const char kTestChildProcess[]; extern const char kTraceToConsole[]; +extern const char kTraceToFile[]; +extern const char kTraceToFileName[]; extern const char kV[]; extern const char kVModule[]; extern const char kWaitForDebugger[]; #if defined(OS_POSIX) extern const char kEnableCrashReporterForTesting[]; #endif
--- a/security/sandbox/chromium/base/basictypes.h +++ b/security/sandbox/chromium/base/basictypes.h @@ -17,34 +17,21 @@ #include "base/macros.h" #include "base/port.h" // Types that only need exist on certain systems. // DEPRECATED: Please use (u)int{8,16,32,64}_t instead (and include <stdint.h>). typedef int8_t int8; typedef uint8_t uint8; typedef int16_t int16; +typedef uint16_t uint16; typedef int32_t int32; -typedef uint16_t uint16; typedef uint32_t uint32; - -// TODO(vtl): Figure what's up with the 64-bit types. Can we just define them as -// |int64_t|/|uint64_t|? -// The NSPR system headers define 64-bit as |long| when possible, except on -// Mac OS X. In order to not have typedef mismatches, we do the same on LP64. -// -// On Mac OS X, |long long| is used for 64-bit types for compatibility with -// <inttypes.h> format macros even in the LP64 model. -#if defined(__LP64__) && !defined(OS_MACOSX) && !defined(OS_OPENBSD) -typedef long int64; -typedef unsigned long uint64; -#else -typedef long long int64; -typedef unsigned long long uint64; -#endif +typedef int64_t int64; +typedef uint64_t uint64; // DEPRECATED: Please use std::numeric_limits (from <limits>) instead. const uint8 kuint8max = 0xFF; const uint16 kuint16max = 0xFFFF; const uint32 kuint32max = 0xFFFFFFFF; const uint64 kuint64max = 0xFFFFFFFFFFFFFFFFULL; const int8 kint8min = -0x7F - 1; const int8 kint8max = 0x7F;
--- a/security/sandbox/chromium/base/bind_helpers.h +++ b/security/sandbox/chromium/base/bind_helpers.h @@ -246,17 +246,17 @@ class SupportsAddRefAndRelease { template <typename C> static No& Check(Helper<&C::AddRef>*); template <typename > static Yes& Check(...); public: - static const bool value = sizeof(Check<Base>(0)) == sizeof(Yes); + enum { value = sizeof(Check<Base>(0)) == sizeof(Yes) }; }; // Helpers to assert that arguments of a recounted type are bound with a // scoped_refptr. template <bool IsClasstype, typename T> struct UnsafeBindtoRefCountedArgHelper : false_type { }; @@ -281,17 +281,17 @@ class HasIsMethodTag { template <typename U> static Yes& Check(typename U::IsMethod*); template <typename U> static No& Check(...); public: - static const bool value = sizeof(Check<T>(0)) == sizeof(Yes); + enum { value = sizeof(Check<T>(0)) == sizeof(Yes) }; }; template <typename T> class UnretainedWrapper { public: explicit UnretainedWrapper(T* o) : ptr_(o) {} T* get() const { return ptr_; } private:
--- a/security/sandbox/chromium/base/bind_internal_win.h +++ b/security/sandbox/chromium/base/bind_internal_win.h @@ -1,13 +1,8 @@ -// This file was GENERATED by command: -// pump.py bind_internal_win.h.pump -// DO NOT EDIT BY HAND!!! - - // Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // Specializations of RunnableAdapter<> for Windows specific calling // conventions. Please see base/bind_internal.h for more info. #ifndef BASE_BIND_INTERNAL_WIN_H_ @@ -19,350 +14,50 @@ #if !defined(ARCH_CPU_X86_64) namespace base { namespace internal { template <typename Functor> class RunnableAdapter; -// __stdcall Function: Arity 0. -template <typename R> -class RunnableAdapter<R(__stdcall *)()> { - public: - typedef R (RunType)(); - - explicit RunnableAdapter(R(__stdcall *function)()) - : function_(function) { - } - - R Run() { - return function_(); - } - - private: - R (__stdcall *function_)(); -}; - -// __fastcall Function: Arity 0. -template <typename R> -class RunnableAdapter<R(__fastcall *)()> { +// __stdcall Function. +template <typename R, typename... Args> +class RunnableAdapter<R(__stdcall *)(Args...)> { public: - typedef R (RunType)(); - - explicit RunnableAdapter(R(__fastcall *function)()) - : function_(function) { - } - - R Run() { - return function_(); - } - - private: - R (__fastcall *function_)(); -}; - -// __stdcall Function: Arity 1. -template <typename R, typename A1> -class RunnableAdapter<R(__stdcall *)(A1)> { - public: - typedef R (RunType)(A1); - - explicit RunnableAdapter(R(__stdcall *function)(A1)) - : function_(function) { - } - - R Run(typename CallbackParamTraits<A1>::ForwardType a1) { - return function_(a1); - } - - private: - R (__stdcall *function_)(A1); -}; - -// __fastcall Function: Arity 1. -template <typename R, typename A1> -class RunnableAdapter<R(__fastcall *)(A1)> { - public: - typedef R (RunType)(A1); - - explicit RunnableAdapter(R(__fastcall *function)(A1)) - : function_(function) { - } - - R Run(typename CallbackParamTraits<A1>::ForwardType a1) { - return function_(a1); - } - - private: - R (__fastcall *function_)(A1); -}; - -// __stdcall Function: Arity 2. -template <typename R, typename A1, typename A2> -class RunnableAdapter<R(__stdcall *)(A1, A2)> { - public: - typedef R (RunType)(A1, A2); + typedef R (RunType)(Args...); - explicit RunnableAdapter(R(__stdcall *function)(A1, A2)) - : function_(function) { - } - - R Run(typename CallbackParamTraits<A1>::ForwardType a1, - typename CallbackParamTraits<A2>::ForwardType a2) { - return function_(a1, a2); - } - - private: - R (__stdcall *function_)(A1, A2); -}; - -// __fastcall Function: Arity 2. -template <typename R, typename A1, typename A2> -class RunnableAdapter<R(__fastcall *)(A1, A2)> { - public: - typedef R (RunType)(A1, A2); - - explicit RunnableAdapter(R(__fastcall *function)(A1, A2)) - : function_(function) { - } - - R Run(typename CallbackParamTraits<A1>::ForwardType a1, - typename CallbackParamTraits<A2>::ForwardType a2) { - return function_(a1, a2); - } - - private: - R (__fastcall *function_)(A1, A2); -}; - -// __stdcall Function: Arity 3. -template <typename R, typename A1, typename A2, typename A3> -class RunnableAdapter<R(__stdcall *)(A1, A2, A3)> { - public: - typedef R (RunType)(A1, A2, A3); - - explicit RunnableAdapter(R(__stdcall *function)(A1, A2, A3)) - : function_(function) { - } - - R Run(typename CallbackParamTraits<A1>::ForwardType a1, - typename CallbackParamTraits<A2>::ForwardType a2, - typename CallbackParamTraits<A3>::ForwardType a3) { - return function_(a1, a2, a3); - } - - private: - R (__stdcall *function_)(A1, A2, A3); -}; - -// __fastcall Function: Arity 3. -template <typename R, typename A1, typename A2, typename A3> -class RunnableAdapter<R(__fastcall *)(A1, A2, A3)> { - public: - typedef R (RunType)(A1, A2, A3); - - explicit RunnableAdapter(R(__fastcall *function)(A1, A2, A3)) - : function_(function) { - } - - R Run(typename CallbackParamTraits<A1>::ForwardType a1, - typename CallbackParamTraits<A2>::ForwardType a2, - typename CallbackParamTraits<A3>::ForwardType a3) { - return function_(a1, a2, a3); - } - - private: - R (__fastcall *function_)(A1, A2, A3); -}; - -// __stdcall Function: Arity 4. -template <typename R, typename A1, typename A2, typename A3, typename A4> -class RunnableAdapter<R(__stdcall *)(A1, A2, A3, A4)> { - public: - typedef R (RunType)(A1, A2, A3, A4); - - explicit RunnableAdapter(R(__stdcall *function)(A1, A2, A3, A4)) + explicit RunnableAdapter(R(__stdcall *function)(Args...)) : function_(function) { } - R Run(typename CallbackParamTraits<A1>::ForwardType a1, - typename CallbackParamTraits<A2>::ForwardType a2, - typename CallbackParamTraits<A3>::ForwardType a3, - typename CallbackParamTraits<A4>::ForwardType a4) { - return function_(a1, a2, a3, a4); - } - - private: - R (__stdcall *function_)(A1, A2, A3, A4); -}; - -// __fastcall Function: Arity 4. -template <typename R, typename A1, typename A2, typename A3, typename A4> -class RunnableAdapter<R(__fastcall *)(A1, A2, A3, A4)> { - public: - typedef R (RunType)(A1, A2, A3, A4); - - explicit RunnableAdapter(R(__fastcall *function)(A1, A2, A3, A4)) - : function_(function) { - } - - R Run(typename CallbackParamTraits<A1>::ForwardType a1, - typename CallbackParamTraits<A2>::ForwardType a2, - typename CallbackParamTraits<A3>::ForwardType a3, - typename CallbackParamTraits<A4>::ForwardType a4) { - return function_(a1, a2, a3, a4); - } - - private: - R (__fastcall *function_)(A1, A2, A3, A4); -}; - -// __stdcall Function: Arity 5. -template <typename R, typename A1, typename A2, typename A3, typename A4, - typename A5> -class RunnableAdapter<R(__stdcall *)(A1, A2, A3, A4, A5)> { - public: - typedef R (RunType)(A1, A2, A3, A4, A5); - - explicit RunnableAdapter(R(__stdcall *function)(A1, A2, A3, A4, A5)) - : function_(function) { - } - - R Run(typename CallbackParamTraits<A1>::ForwardType a1, - typename CallbackParamTraits<A2>::ForwardType a2, - typename CallbackParamTraits<A3>::ForwardType a3, - typename CallbackParamTraits<A4>::ForwardType a4, - typename CallbackParamTraits<A5>::ForwardType a5) { - return function_(a1, a2, a3, a4, a5); - } - - private: - R (__stdcall *function_)(A1, A2, A3, A4, A5); -}; - -// __fastcall Function: Arity 5. -template <typename R, typename A1, typename A2, typename A3, typename A4, - typename A5> -class RunnableAdapter<R(__fastcall *)(A1, A2, A3, A4, A5)> { - public: - typedef R (RunType)(A1, A2, A3, A4, A5); - - explicit RunnableAdapter(R(__fastcall *function)(A1, A2, A3, A4, A5)) - : function_(function) { - } - - R Run(typename CallbackParamTraits<A1>::ForwardType a1, - typename CallbackParamTraits<A2>::ForwardType a2, - typename CallbackParamTraits<A3>::ForwardType a3, - typename CallbackParamTraits<A4>::ForwardType a4, - typename CallbackParamTraits<A5>::ForwardType a5) { - return function_(a1, a2, a3, a4, a5); + R Run(typename CallbackParamTraits<Args>::ForwardType... args) { + return function_(args...); } private: - R (__fastcall *function_)(A1, A2, A3, A4, A5); + R (__stdcall *function_)(Args...); }; -// __stdcall Function: Arity 6. -template <typename R, typename A1, typename A2, typename A3, typename A4, - typename A5, typename A6> -class RunnableAdapter<R(__stdcall *)(A1, A2, A3, A4, A5, A6)> { +// __fastcall Function. +template <typename R, typename... Args> +class RunnableAdapter<R(__fastcall *)(Args...)> { public: - typedef R (RunType)(A1, A2, A3, A4, A5, A6); + typedef R (RunType)(Args...); - explicit RunnableAdapter(R(__stdcall *function)(A1, A2, A3, A4, A5, A6)) + explicit RunnableAdapter(R(__fastcall *function)(Args...)) : function_(function) { } - R Run(typename CallbackParamTraits<A1>::ForwardType a1, - typename CallbackParamTraits<A2>::ForwardType a2, - typename CallbackParamTraits<A3>::ForwardType a3, - typename CallbackParamTraits<A4>::ForwardType a4, - typename CallbackParamTraits<A5>::ForwardType a5, - typename CallbackParamTraits<A6>::ForwardType a6) { - return function_(a1, a2, a3, a4, a5, a6); - } - - private: - R (__stdcall *function_)(A1, A2, A3, A4, A5, A6); -}; - -// __fastcall Function: Arity 6. -template <typename R, typename A1, typename A2, typename A3, typename A4, - typename A5, typename A6> -class RunnableAdapter<R(__fastcall *)(A1, A2, A3, A4, A5, A6)> { - public: - typedef R (RunType)(A1, A2, A3, A4, A5, A6); - - explicit RunnableAdapter(R(__fastcall *function)(A1, A2, A3, A4, A5, A6)) - : function_(function) { - } - - R Run(typename CallbackParamTraits<A1>::ForwardType a1, - typename CallbackParamTraits<A2>::ForwardType a2, - typename CallbackParamTraits<A3>::ForwardType a3, - typename CallbackParamTraits<A4>::ForwardType a4, - typename CallbackParamTraits<A5>::ForwardType a5, - typename CallbackParamTraits<A6>::ForwardType a6) { - return function_(a1, a2, a3, a4, a5, a6); + R Run(typename CallbackParamTraits<Args>::ForwardType... args) { + return function_(args...); } private: - R (__fastcall *function_)(A1, A2, A3, A4, A5, A6); -}; - -// __stdcall Function: Arity 7. -template <typename R, typename A1, typename A2, typename A3, typename A4, - typename A5, typename A6, typename A7> -class RunnableAdapter<R(__stdcall *)(A1, A2, A3, A4, A5, A6, A7)> { - public: - typedef R (RunType)(A1, A2, A3, A4, A5, A6, A7); - - explicit RunnableAdapter(R(__stdcall *function)(A1, A2, A3, A4, A5, A6, A7)) - : function_(function) { - } - - R Run(typename CallbackParamTraits<A1>::ForwardType a1, - typename CallbackParamTraits<A2>::ForwardType a2, - typename CallbackParamTraits<A3>::ForwardType a3, - typename CallbackParamTraits<A4>::ForwardType a4, - typename CallbackParamTraits<A5>::ForwardType a5, - typename CallbackParamTraits<A6>::ForwardType a6, - typename CallbackParamTraits<A7>::ForwardType a7) { - return function_(a1, a2, a3, a4, a5, a6, a7); - } - - private: - R (__stdcall *function_)(A1, A2, A3, A4, A5, A6, A7); -}; - -// __fastcall Function: Arity 7. -template <typename R, typename A1, typename A2, typename A3, typename A4, - typename A5, typename A6, typename A7> -class RunnableAdapter<R(__fastcall *)(A1, A2, A3, A4, A5, A6, A7)> { - public: - typedef R (RunType)(A1, A2, A3, A4, A5, A6, A7); - - explicit RunnableAdapter(R(__fastcall *function)(A1, A2, A3, A4, A5, A6, A7)) - : function_(function) { - } - - R Run(typename CallbackParamTraits<A1>::ForwardType a1, - typename CallbackParamTraits<A2>::ForwardType a2, - typename CallbackParamTraits<A3>::ForwardType a3, - typename CallbackParamTraits<A4>::ForwardType a4, - typename CallbackParamTraits<A5>::ForwardType a5, - typename CallbackParamTraits<A6>::ForwardType a6, - typename CallbackParamTraits<A7>::ForwardType a7) { - return function_(a1, a2, a3, a4, a5, a6, a7); - } - - private: - R (__fastcall *function_)(A1, A2, A3, A4, A5, A6, A7); + R (__fastcall *function_)(Args...); }; } // namespace internal } // namespace base #endif // !defined(ARCH_CPU_X86_64) #endif // BASE_BIND_INTERNAL_WIN_H_
--- a/security/sandbox/chromium/base/callback_internal.cc +++ b/security/sandbox/chromium/base/callback_internal.cc @@ -4,20 +4,16 @@ #include "base/callback_internal.h" #include "base/logging.h" namespace base { namespace internal { -bool CallbackBase::is_null() const { - return bind_state_.get() == NULL; -} - void CallbackBase::Reset() { polymorphic_invoke_ = NULL; // NULL the bind_state_ last, since it may be holding the last ref to whatever // object owns us, and we may be deleted after that. bind_state_ = NULL; } bool CallbackBase::Equals(const CallbackBase& other) const {
--- a/security/sandbox/chromium/base/callback_internal.h +++ b/security/sandbox/chromium/base/callback_internal.h @@ -32,17 +32,17 @@ class BindStateBase : public RefCountedT virtual ~BindStateBase() {} }; // Holds the Callback methods that don't require specialization to reduce // template bloat. class BASE_EXPORT CallbackBase { public: // Returns true if Callback is null (doesn't refer to anything). - bool is_null() const; + bool is_null() const { return bind_state_.get() == NULL; } // Returns the Callback into an uninitialized state. void Reset(); protected: // In C++, it is safe to cast function pointers to function pointers of // another type. It is not okay to use void*. We create a InvokeFuncStorage // that that can store our function pointer, and then cast it back to @@ -72,17 +72,17 @@ class BASE_EXPORT CallbackBase { // destructive way. template <typename T> struct IsMoveOnlyType { template <typename U> static YesType Test(const typename U::MoveOnlyTypeForCPP03*); template <typename U> static NoType Test(...); - static const bool value = sizeof(Test<T>(0)) == sizeof(YesType) && + static const bool value = sizeof((Test<T>(0))) == sizeof(YesType) && !is_const<T>::value; }; // This is a typetraits object that's used to take an argument type, and // extract a suitable type for storing and forwarding arguments. // // In particular, it strips off references, and converts arrays to // pointers for storage; and it avoids accidentally trying to create a
--- a/security/sandbox/chromium/base/compiler_specific.h +++ b/security/sandbox/chromium/base/compiler_specific.h @@ -89,21 +89,27 @@ #else #define STATIC_CONST_MEMBER_DEFINITION #endif // Annotate a variable indicating it's ok if the variable is not used. // (Typically used to silence a compiler warning when the assignment // is important for some other reason.) // Use like: -// int x ALLOW_UNUSED = ...; +// int x = ...; +// ALLOW_UNUSED_LOCAL(x); +#define ALLOW_UNUSED_LOCAL(x) false ? (void)x : (void)0 + +// Annotate a typedef or function indicating it's ok if it's not used. +// Use like: +// typedef Foo Bar ALLOW_UNUSED_TYPE; #if defined(COMPILER_GCC) -#define ALLOW_UNUSED __attribute__((unused)) +#define ALLOW_UNUSED_TYPE __attribute__((unused)) #else -#define ALLOW_UNUSED +#define ALLOW_UNUSED_TYPE #endif // Annotate a function indicating it should not be inlined. // Use like: // NOINLINE void DoStuff() { ... } #if defined(COMPILER_GCC) #define NOINLINE __attribute__((noinline)) #elif defined(COMPILER_MSVC) @@ -128,50 +134,16 @@ // Use like: // ALIGNOF(int32) // this would be 4 #if defined(COMPILER_MSVC) #define ALIGNOF(type) (sizeof(type) - sizeof(type) + __alignof(type)) #elif defined(COMPILER_GCC) #define ALIGNOF(type) __alignof__(type) #endif -// Annotate a virtual method indicating it must be overriding a virtual -// method in the parent class. -// Use like: -// virtual void foo() OVERRIDE; -#if defined(COMPILER_MSVC) -#define OVERRIDE override -#elif defined(__clang__) -#define OVERRIDE override -#elif defined(COMPILER_GCC) && __cplusplus >= 201103 && \ - (__GNUC__ * 10000 + __GNUC_MINOR__ * 100) >= 40700 -// GCC 4.7 supports explicit virtual overrides when C++11 support is enabled. -#define OVERRIDE override -#else -#define OVERRIDE -#endif - -// Annotate a virtual method indicating that subclasses must not override it, -// or annotate a class to indicate that it cannot be subclassed. -// Use like: -// virtual void foo() FINAL; -// class B FINAL : public A {}; -#if defined(__clang__) -#define FINAL final -#elif defined(COMPILER_MSVC) -// TODO(jered): Change this to "final" when chromium no longer uses MSVC 2010. -#define FINAL sealed -#elif defined(COMPILER_GCC) && __cplusplus >= 201103 && \ - (__GNUC__ * 10000 + __GNUC_MINOR__ * 100) >= 40700 -// GCC 4.7 supports explicit virtual overrides when C++11 support is enabled. -#define FINAL final -#else -#define FINAL -#endif - // Annotate a function indicating the caller must examine the return value. // Use like: // int foo() WARN_UNUSED_RESULT; // To explicitly ignore a result, see |ignore_result()| in <base/basictypes.h>. #if defined(COMPILER_GCC) #define WARN_UNUSED_RESULT __attribute__((warn_unused_result)) #else #define WARN_UNUSED_RESULT
--- a/security/sandbox/chromium/base/containers/hash_tables.h +++ b/security/sandbox/chromium/base/containers/hash_tables.h @@ -23,57 +23,72 @@ #include <utility> #include "base/basictypes.h" #include "base/strings/string16.h" #include "build/build_config.h" #if defined(COMPILER_MSVC) +#include <unordered_map> +#include <unordered_set> -#pragma push_macro("_SILENCE_STDEXT_HASH_DEPRECATION_WARNINGS") -#define _SILENCE_STDEXT_HASH_DEPRECATION_WARNINGS -#include <hash_map> -#include <hash_set> -#pragma pop_macro("_SILENCE_STDEXT_HASH_DEPRECATION_WARNINGS") - -#define BASE_HASH_NAMESPACE stdext +#define BASE_HASH_NAMESPACE std #elif defined(COMPILER_GCC) -#if defined(OS_ANDROID) -#define BASE_HASH_NAMESPACE std -#else -#define BASE_HASH_NAMESPACE __gnu_cxx -#endif + +#define BASE_HASH_NAMESPACE base_hash // This is a hack to disable the gcc 4.4 warning about hash_map and hash_set // being deprecated. We can get rid of this when we upgrade to VS2008 and we // can use <tr1/unordered_map> and <tr1/unordered_set>. #ifdef __DEPRECATED #define CHROME_OLD__DEPRECATED __DEPRECATED #undef __DEPRECATED #endif #if defined(OS_ANDROID) #include <hash_map> #include <hash_set> +#define BASE_HASH_IMPL_NAMESPACE std #else #include <ext/hash_map> #include <ext/hash_set> +#define BASE_HASH_IMPL_NAMESPACE __gnu_cxx #endif #include <string> #ifdef CHROME_OLD__DEPRECATED #define __DEPRECATED CHROME_OLD__DEPRECATED #undef CHROME_OLD__DEPRECATED #endif namespace BASE_HASH_NAMESPACE { +// The pre-standard hash behaves like C++11's std::hash, except around pointers. +// const char* is specialized to hash the C string and hash functions for +// general T* are missing. Define a BASE_HASH_NAMESPACE::hash which aligns with +// the C++11 behavior. + +template<typename T> +struct hash { + std::size_t operator()(const T& value) const { + return BASE_HASH_IMPL_NAMESPACE::hash<T>()(value); + } +}; + +template<typename T> +struct hash<T*> { + std::size_t operator()(T* value) const { + return BASE_HASH_IMPL_NAMESPACE::hash<uintptr_t>()( + reinterpret_cast<uintptr_t>(value)); + } +}; + #if !defined(OS_ANDROID) // The GNU C++ library provides identity hash functions for many integral types, // but not for |long long|. This hash function will truncate if |size_t| is // narrower than |long long|. This is probably good enough for what we will // use it for. #define DEFINE_TRIVIAL_HASH(integral_type) \ template<> \ @@ -113,20 +128,77 @@ DEFINE_STRING_HASH(base::string16); } // namespace BASE_HASH_NAMESPACE #else // COMPILER #error define BASE_HASH_NAMESPACE for your compiler #endif // COMPILER namespace base { -using BASE_HASH_NAMESPACE::hash_map; -using BASE_HASH_NAMESPACE::hash_multimap; -using BASE_HASH_NAMESPACE::hash_multiset; -using BASE_HASH_NAMESPACE::hash_set; + +// On MSVC, use the C++11 containers. +#if defined(COMPILER_MSVC) + +template<class Key, class T, + class Hash = std::hash<Key>, + class Pred = std::equal_to<Key>, + class Alloc = std::allocator<std::pair<const Key, T>>> +using hash_map = std::unordered_map<Key, T, Hash, Pred, Alloc>; + +template<class Key, class T, + class Hash = std::hash<Key>, + class Pred = std::equal_to<Key>, + class Alloc = std::allocator<std::pair<const Key, T>>> +using hash_multimap = std::unordered_multimap<Key, T, Hash, Pred, Alloc>; + +template<class Key, + class Hash = std::hash<Key>, + class Pred = std::equal_to<Key>, + class Alloc = std::allocator<Key>> +using hash_multiset = std::unordered_multiset<Key, Hash, Pred, Alloc>; + +template<class Key, + class Hash = std::hash<Key>, + class Pred = std::equal_to<Key>, + class Alloc = std::allocator<Key>> +using hash_set = std::unordered_set<Key, Hash, Pred, Alloc>; + +#else // !COMPILER_MSVC + +// Otherwise, use the pre-standard ones, but override the default hash to match +// C++11. +template<class Key, class T, + class Hash = BASE_HASH_NAMESPACE::hash<Key>, + class Pred = std::equal_to<Key>, + class Alloc = std::allocator<std::pair<const Key, T>>> +using hash_map = BASE_HASH_IMPL_NAMESPACE::hash_map<Key, T, Hash, Pred, Alloc>; + +template<class Key, class T, + class Hash = BASE_HASH_NAMESPACE::hash<Key>, + class Pred = std::equal_to<Key>, + class Alloc = std::allocator<std::pair<const Key, T>>> +using hash_multimap = + BASE_HASH_IMPL_NAMESPACE::hash_multimap<Key, T, Hash, Pred, Alloc>; + +template<class Key, + class Hash = BASE_HASH_NAMESPACE::hash<Key>, + class Pred = std::equal_to<Key>, + class Alloc = std::allocator<Key>> +using hash_multiset = + BASE_HASH_IMPL_NAMESPACE::hash_multiset<Key, Hash, Pred, Alloc>; + +template<class Key, + class Hash = BASE_HASH_NAMESPACE::hash<Key>, + class Pred = std::equal_to<Key>, + class Alloc = std::allocator<Key>> +using hash_set = BASE_HASH_IMPL_NAMESPACE::hash_set<Key, Hash, Pred, Alloc>; + +#undef BASE_HASH_IMPL_NAMESPACE + +#endif // COMPILER_MSVC // Implement hashing for pairs of at-most 32 bit integer values. // When size_t is 32 bits, we turn the 64-bit hash code into 32 bits by using // multiply-add hashing. This algorithm, as described in // Theorem 4.3.3 of the thesis "Über die Komplexität der Multiplikation in // eingeschränkten Branchingprogrammmodellen" by Woelfel, is: // // h32(x32, y32) = (h64(x32, y32) * rand_odd64 + rand16 * 2^16) % 2^64 / 2^32 @@ -236,33 +308,21 @@ DEFINE_64BIT_PAIR_HASH(uint64, uint64); #undef DEFINE_64BIT_PAIR_HASH } // namespace base namespace BASE_HASH_NAMESPACE { // Implement methods for hashing a pair of integers, so they can be used as // keys in STL containers. -#if defined(COMPILER_MSVC) - -template<typename Type1, typename Type2> -inline std::size_t hash_value(const std::pair<Type1, Type2>& value) { - return base::HashPair(value.first, value.second); -} - -#elif defined(COMPILER_GCC) template<typename Type1, typename Type2> struct hash<std::pair<Type1, Type2> > { std::size_t operator()(std::pair<Type1, Type2> value) const { return base::HashPair(value.first, value.second); } }; -#else -#error define hash<std::pair<Type1, Type2> > for your compiler -#endif // COMPILER - } #undef DEFINE_PAIR_HASH_FUNCTION_START #undef DEFINE_PAIR_HASH_FUNCTION_END #endif // BASE_CONTAINERS_HASH_TABLES_H_
--- a/security/sandbox/chromium/base/cpu.cc +++ b/security/sandbox/chromium/base/cpu.cc @@ -1,23 +1,25 @@ // Copyright (c) 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "base/cpu.h" +#include <stdlib.h> #include <string.h> #include <algorithm> #include "base/basictypes.h" +#include "base/strings/string_piece.h" #include "build/build_config.h" #if defined(ARCH_CPU_ARM_FAMILY) && (defined(OS_ANDROID) || defined(OS_LINUX)) -#include "base/file_util.h" +#include "base/files/file_util.h" #include "base/lazy_instance.h" #endif #if defined(ARCH_CPU_X86_FAMILY) #if defined(_MSC_VER) #include <intrin.h> #include <immintrin.h> // For _xgetbv() #endif @@ -39,33 +41,24 @@ CPU::CPU() has_sse3_(false), has_ssse3_(false), has_sse41_(false), has_sse42_(false), has_avx_(false), has_avx_hardware_(false), has_aesni_(false), has_non_stop_time_stamp_counter_(false), + has_broken_neon_(false), cpu_vendor_("unknown") { Initialize(); } namespace { #if defined(ARCH_CPU_X86_FAMILY) -#if defined(_MSC_VER) && (_MSC_FULL_VER < 160040219) -// Prior to VS2010 SP1, _xgetbv is not defined in immintrin.h, so we need to -// define our own version using the assembly operation. -// By using __fastcall we ensure that xcr is already in register ecx for xgetbv -// and xgetbv populates the correct registers (eax edx) for our return value. -uint64_t __fastcall _xgetbv(uint32_t xcr) { - __asm xgetbv; -} -#endif - #ifndef _MSC_VER #if defined(__pic__) && defined(__i386__) void __cpuid(int cpu_info[4], int info_type) { __asm__ volatile ( "mov %%ebx, %%edi\n" "cpuid\n" @@ -95,62 +88,109 @@ uint64 _xgetbv(uint32 xcr) { __asm__ volatile ("xgetbv" : "=a" (eax), "=d" (edx) : "c" (xcr)); return (static_cast<uint64>(edx) << 32) | eax; } #endif // !_MSC_VER #endif // ARCH_CPU_X86_FAMILY #if defined(ARCH_CPU_ARM_FAMILY) && (defined(OS_ANDROID) || defined(OS_LINUX)) +class LazyCpuInfoValue { + public: + LazyCpuInfoValue() : has_broken_neon_(false) { + // This function finds the value from /proc/cpuinfo under the key "model + // name" or "Processor". "model name" is used in Linux 3.8 and later (3.7 + // and later for arm64) and is shown once per CPU. "Processor" is used in + // earler versions and is shown only once at the top of /proc/cpuinfo + // regardless of the number CPUs. + const char kModelNamePrefix[] = "model name\t: "; + const char kProcessorPrefix[] = "Processor\t: "; -// Returns the string found in /proc/cpuinfo under the key "model name" or -// "Processor". "model name" is used in Linux 3.8 and later (3.7 and later for -// arm64) and is shown once per CPU. "Processor" is used in earler versions and -// is shown only once at the top of /proc/cpuinfo regardless of the number CPUs. -std::string ParseCpuInfo() { - const char kModelNamePrefix[] = "model name\t: "; - const char kProcessorPrefix[] = "Processor\t: "; - std::string contents; - ReadFileToString(FilePath("/proc/cpuinfo"), &contents); - DCHECK(!contents.empty()); - std::string cpu_brand; - if (!contents.empty()) { + // This function also calculates whether we believe that this CPU has a + // broken NEON unit based on these fields from cpuinfo: + unsigned implementer = 0, architecture = 0, variant = 0, part = 0, + revision = 0; + const struct { + const char key[17]; + unsigned *result; + } kUnsignedValues[] = { + {"CPU implementer", &implementer}, + {"CPU architecture", &architecture}, + {"CPU variant", &variant}, + {"CPU part", &part}, + {"CPU revision", &revision}, + }; + + std::string contents; + ReadFileToString(FilePath("/proc/cpuinfo"), &contents); + DCHECK(!contents.empty()); + if (contents.empty()) { + return; + } + std::istringstream iss(contents); std::string line; while (std::getline(iss, line)) { - if (line.compare(0, strlen(kModelNamePrefix), kModelNamePrefix) == 0) { - cpu_brand.assign(line.substr(strlen(kModelNamePrefix))); - break; + if (brand_.empty() && + (line.compare(0, strlen(kModelNamePrefix), kModelNamePrefix) == 0 || + line.compare(0, strlen(kProcessorPrefix), kProcessorPrefix) == 0)) { + brand_.assign(line.substr(strlen(kModelNamePrefix))); } - if (line.compare(0, strlen(kProcessorPrefix), kProcessorPrefix) == 0) { - cpu_brand.assign(line.substr(strlen(kProcessorPrefix))); - break; + + for (size_t i = 0; i < arraysize(kUnsignedValues); i++) { + const char *key = kUnsignedValues[i].key; + const size_t len = strlen(key); + + if (line.compare(0, len, key) == 0 && + line.size() >= len + 1 && + (line[len] == '\t' || line[len] == ' ' || line[len] == ':')) { + size_t colon_pos = line.find(':', len); + if (colon_pos == std::string::npos) { + continue; + } + + const StringPiece line_sp(line); + StringPiece value_sp = line_sp.substr(colon_pos + 1); + while (!value_sp.empty() && + (value_sp[0] == ' ' || value_sp[0] == '\t')) { + value_sp = value_sp.substr(1); + } + + // The string may have leading "0x" or not, so we use strtoul to + // handle that. + char *endptr; + std::string value(value_sp.as_string()); + unsigned long int result = strtoul(value.c_str(), &endptr, 0); + if (*endptr == 0 && result <= UINT_MAX) { + *kUnsignedValues[i].result = result; + } + } } } - } - return cpu_brand; -} -class LazyCpuInfoValue { - public: - LazyCpuInfoValue() : value_(ParseCpuInfo()) {} - const std::string& value() { return value_; } + has_broken_neon_ = + implementer == 0x51 && + architecture == 7 && + variant == 1 && + part == 0x4d && + revision == 0; + } + + const std::string& brand() const { return brand_; } + bool has_broken_neon() const { return has_broken_neon_; } private: - const std::string value_; + std::string brand_; + bool has_broken_neon_; DISALLOW_COPY_AND_ASSIGN(LazyCpuInfoValue); }; -base::LazyInstance<LazyCpuInfoValue> g_lazy_cpu_brand = +base::LazyInstance<LazyCpuInfoValue>::Leaky g_lazy_cpuinfo = LAZY_INSTANCE_INITIALIZER; -const std::string& CpuBrandInfo() { - return g_lazy_cpu_brand.Get().value(); -} - #endif // defined(ARCH_CPU_ARM_FAMILY) && (defined(OS_ANDROID) || // defined(OS_LINUX)) } // anonymous namespace void CPU::Initialize() { #if defined(ARCH_CPU_X86_FAMILY) int cpu_info[4] = {-1}; @@ -224,17 +264,18 @@ void CPU::Initialize() { } const int parameter_containing_non_stop_time_stamp_counter = 0x80000007; if (max_parameter >= parameter_containing_non_stop_time_stamp_counter) { __cpuid(cpu_info, parameter_containing_non_stop_time_stamp_counter); has_non_stop_time_stamp_counter_ = (cpu_info[3] & (1 << 8)) != 0; } #elif defined(ARCH_CPU_ARM_FAMILY) && (defined(OS_ANDROID) || defined(OS_LINUX)) - cpu_brand_.assign(CpuBrandInfo()); + cpu_brand_.assign(g_lazy_cpuinfo.Get().brand()); + has_broken_neon_ = g_lazy_cpuinfo.Get().has_broken_neon(); #endif } CPU::IntelMicroArchitecture CPU::GetIntelMicroArchitecture() const { if (has_avx()) return AVX; if (has_sse42()) return SSE42; if (has_sse41()) return SSE41; if (has_ssse3()) return SSSE3;
--- a/security/sandbox/chromium/base/cpu.h +++ b/security/sandbox/chromium/base/cpu.h @@ -51,16 +51,21 @@ class BASE_EXPORT CPU { // operating system support needed to actually call AVX instuctions. // Note: you should never need to call this function. It was added in order // to workaround a bug in NSS but |has_avx()| is what you want. bool has_avx_hardware() const { return has_avx_hardware_; } bool has_aesni() const { return has_aesni_; } bool has_non_stop_time_stamp_counter() const { return has_non_stop_time_stamp_counter_; } + // has_broken_neon is only valid on ARM chips. If true, it indicates that we + // believe that the NEON unit on the current CPU is flawed and cannot execute + // some code. See https://code.google.com/p/chromium/issues/detail?id=341598 + bool has_broken_neon() const { return has_broken_neon_; } + IntelMicroArchitecture GetIntelMicroArchitecture() const; const std::string& cpu_brand() const { return cpu_brand_; } private: // Query the processor for CPUID information. void Initialize(); int signature_; // raw form of type, family, model, and stepping @@ -76,15 +81,16 @@ class BASE_EXPORT CPU { bool has_sse3_; bool has_ssse3_; bool has_sse41_; bool has_sse42_; bool has_avx_; bool has_avx_hardware_; bool has_aesni_; bool has_non_stop_time_stamp_counter_; + bool has_broken_neon_; std::string cpu_vendor_; std::string cpu_brand_; }; } // namespace base #endif // BASE_CPU_H_
--- a/security/sandbox/chromium/base/file_descriptor_posix.h +++ b/security/sandbox/chromium/base/file_descriptor_posix.h @@ -1,16 +1,17 @@ // Copyright (c) 2006-2009 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #ifndef BASE_FILE_DESCRIPTOR_POSIX_H_ #define BASE_FILE_DESCRIPTOR_POSIX_H_ #include "base/files/file.h" +#include "base/files/scoped_file.h" namespace base { // ----------------------------------------------------------------------------- // We introduct a special structure for file descriptors in order that we are // able to use template specialisation to special-case their handling. // // WARNING: (Chromium only) There are subtleties to consider if serialising @@ -19,16 +20,17 @@ namespace base { // ----------------------------------------------------------------------------- struct FileDescriptor { FileDescriptor() : fd(-1), auto_close(false) {} FileDescriptor(int ifd, bool iauto_close) : fd(ifd), auto_close(iauto_close) { } FileDescriptor(File file) : fd(file.TakePlatformFile()), auto_close(true) {} + explicit FileDescriptor(ScopedFD fd) : fd(fd.release()), auto_close(true) {} bool operator==(const FileDescriptor& other) const { return (fd == other.fd && auto_close == other.auto_close); } bool operator!=(const FileDescriptor& other) const { return !operator==(other); }
deleted file mode 100644 --- a/security/sandbox/chromium/base/file_util.h +++ /dev/null @@ -1,459 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// This file contains utility functions for dealing with the local -// filesystem. - -#ifndef BASE_FILE_UTIL_H_ -#define BASE_FILE_UTIL_H_ - -#include "build/build_config.h" - -#if defined(OS_WIN) -#include <windows.h> -#elif defined(OS_POSIX) -#include <sys/stat.h> -#include <unistd.h> -#endif - -#include <stdio.h> - -#include <set> -#include <string> -#include <vector> - -#include "base/base_export.h" -#include "base/basictypes.h" -#include "base/files/file.h" -#include "base/files/file_path.h" -#include "base/memory/scoped_ptr.h" -#include "base/strings/string16.h" - -#if defined(OS_POSIX) -#include "base/file_descriptor_posix.h" -#include "base/logging.h" -#include "base/posix/eintr_wrapper.h" -#endif - -namespace base { - -class Time; - -//----------------------------------------------------------------------------- -// Functions that involve filesystem access or modification: - -// Returns an absolute version of a relative path. Returns an empty path on -// error. On POSIX, this function fails if the path does not exist. This -// function can result in I/O so it can be slow. -BASE_EXPORT FilePath MakeAbsoluteFilePath(const FilePath& input); - -// Returns the total number of bytes used by all the files under |root_path|. -// If the path does not exist the function returns 0. -// -// This function is implemented using the FileEnumerator class so it is not -// particularly speedy in any platform. -BASE_EXPORT int64 ComputeDirectorySize(const FilePath& root_path); - -// Deletes the given path, whether it's a file or a directory. -// If it's a directory, it's perfectly happy to delete all of the -// directory's contents. Passing true to recursive deletes -// subdirectories and their contents as well. -// Returns true if successful, false otherwise. It is considered successful -// to attempt to delete a file that does not exist. -// -// In posix environment and if |path| is a symbolic link, this deletes only -// the symlink. (even if the symlink points to a non-existent file) -// -// WARNING: USING THIS WITH recursive==true IS EQUIVALENT -// TO "rm -rf", SO USE WITH CAUTION. -BASE_EXPORT bool DeleteFile(const FilePath& path, bool recursive); - -#if defined(OS_WIN) -// Schedules to delete the given path, whether it's a file or a directory, until -// the operating system is restarted. -// Note: -// 1) The file/directory to be deleted should exist in a temp folder. -// 2) The directory to be deleted must be empty. -BASE_EXPORT bool DeleteFileAfterReboot(const FilePath& path); -#endif - -// Moves the given path, whether it's a file or a directory. -// If a simple rename is not possible, such as in the case where the paths are -// on different volumes, this will attempt to copy and delete. Returns -// true for success. -// This function fails if either path contains traversal components ('..'). -BASE_EXPORT bool Move(const FilePath& from_path, const FilePath& to_path); - -// Renames file |from_path| to |to_path|. Both paths must be on the same -// volume, or the function will fail. Destination file will be created -// if it doesn't exist. Prefer this function over Move when dealing with -// temporary files. On Windows it preserves attributes of the target file. -// Returns true on success, leaving *error unchanged. -// Returns false on failure and sets *error appropriately, if it is non-NULL. -BASE_EXPORT bool ReplaceFile(const FilePath& from_path, - const FilePath& to_path, - File::Error* error); - -// Copies a single file. Use CopyDirectory to copy directories. -// This function fails if either path contains traversal components ('..'). -// -// This function keeps the metadata on Windows. The read only bit on Windows is -// not kept. -BASE_EXPORT bool CopyFile(const FilePath& from_path, const FilePath& to_path); - -// Copies the given path, and optionally all subdirectories and their contents -// as well. -// -// If there are files existing under to_path, always overwrite. Returns true -// if successful, false otherwise. Wildcards on the names are not supported. -// -// This function calls into CopyFile() so the same behavior w.r.t. metadata -// applies. -// -// If you only need to copy a file use CopyFile, it's faster. -BASE_EXPORT bool CopyDirectory(const FilePath& from_path, - const FilePath& to_path, - bool recursive); - -// Returns true if the given path exists on the local filesystem, -// false otherwise. -BASE_EXPORT bool PathExists(const FilePath& path); - -// Returns true if the given path is writable by the user, false otherwise. -BASE_EXPORT bool PathIsWritable(const FilePath& path); - -// Returns true if the given path exists and is a directory, false otherwise. -BASE_EXPORT bool DirectoryExists(const FilePath& path); - -// Returns true if the contents of the two files given are equal, false -// otherwise. If either file can't be read, returns false. -BASE_EXPORT bool ContentsEqual(const FilePath& filename1, - const FilePath& filename2); - -// Returns true if the contents of the two text files given are equal, false -// otherwise. This routine treats "\r\n" and "\n" as equivalent. -BASE_EXPORT bool TextContentsEqual(const FilePath& filename1, - const FilePath& filename2); - -// Reads the file at |path| into |contents| and returns true on success and -// false on error. For security reasons, a |path| containing path traversal -// components ('..') is treated as a read error and |contents| is set to empty. -// In case of I/O error, |contents| holds the data that could be read from the -// file before the error occurred. -// |contents| may be NULL, in which case this function is useful for its side -// effect of priming the disk cache (could be used for unit tests). -BASE_EXPORT bool ReadFileToString(const FilePath& path, std::string* contents); - -// Reads the file at |path| into |contents| and returns true on success and -// false on error. For security reasons, a |path| containing path traversal -// components ('..') is treated as a read error and |contents| is set to empty. -// In case of I/O error, |contents| holds the data that could be read from the -// file before the error occurred. When the file size exceeds |max_size|, the -// function returns false with |contents| holding the file truncated to -// |max_size|. -// |contents| may be NULL, in which case this function is useful for its side -// effect of priming the disk cache (could be used for unit tests). -BASE_EXPORT bool ReadFileToString(const FilePath& path, - std::string* contents, - size_t max_size); - -#if defined(OS_POSIX) - -// Read exactly |bytes| bytes from file descriptor |fd|, storing the result -// in |buffer|. This function is protected against EINTR and partial reads. -// Returns true iff |bytes| bytes have been successfully read from |fd|. -BASE_EXPORT bool ReadFromFD(int fd, char* buffer, size_t bytes); - -// Creates a symbolic link at |symlink| pointing to |target|. Returns -// false on failure. -BASE_EXPORT bool CreateSymbolicLink(const FilePath& target, - const FilePath& symlink); - -// Reads the given |symlink| and returns where it points to in |target|. -// Returns false upon failure. -BASE_EXPORT bool ReadSymbolicLink(const FilePath& symlink, FilePath* target); - -// Bits and masks of the file permission. -enum FilePermissionBits { - FILE_PERMISSION_MASK = S_IRWXU | S_IRWXG | S_IRWXO, - FILE_PERMISSION_USER_MASK = S_IRWXU, - FILE_PERMISSION_GROUP_MASK = S_IRWXG, - FILE_PERMISSION_OTHERS_MASK = S_IRWXO, - - FILE_PERMISSION_READ_BY_USER = S_IRUSR, - FILE_PERMISSION_WRITE_BY_USER = S_IWUSR, - FILE_PERMISSION_EXECUTE_BY_USER = S_IXUSR, - FILE_PERMISSION_READ_BY_GROUP = S_IRGRP, - FILE_PERMISSION_WRITE_BY_GROUP = S_IWGRP, - FILE_PERMISSION_EXECUTE_BY_GROUP = S_IXGRP, - FILE_PERMISSION_READ_BY_OTHERS = S_IROTH, - FILE_PERMISSION_WRITE_BY_OTHERS = S_IWOTH, - FILE_PERMISSION_EXECUTE_BY_OTHERS = S_IXOTH, -}; - -// Reads the permission of the given |path|, storing the file permission -// bits in |mode|. If |path| is symbolic link, |mode| is the permission of -// a file which the symlink points to. -BASE_EXPORT bool GetPosixFilePermissions(const FilePath& path, int* mode); -// Sets the permission of the given |path|. If |path| is symbolic link, sets -// the permission of a file which the symlink points to. -BASE_EXPORT bool SetPosixFilePermissions(const FilePath& path, int mode); - -#endif // OS_POSIX - -// Returns true if the given directory is empty -BASE_EXPORT bool IsDirectoryEmpty(const FilePath& dir_path); - -// Get the temporary directory provided by the system. -// -// WARNING: In general, you should use CreateTemporaryFile variants below -// instead of this function. Those variants will ensure that the proper -// permissions are set so that other users on the system can't edit them while -// they're open (which can lead to security issues). -BASE_EXPORT bool GetTempDir(FilePath* path); - -// Get the home directory. This is more complicated than just getenv("HOME") -// as it knows to fall back on getpwent() etc. -// -// You should not generally call this directly. Instead use DIR_HOME with the -// path service which will use this function but cache the value. -// Path service may also override DIR_HOME. -BASE_EXPORT FilePath GetHomeDir(); - -// Creates a temporary file. The full path is placed in |path|, and the -// function returns true if was successful in creating the file. The file will -// be empty and all handles closed after this function returns. -BASE_EXPORT bool CreateTemporaryFile(FilePath* path); - -// Same as CreateTemporaryFile but the file is created in |dir|. -BASE_EXPORT bool CreateTemporaryFileInDir(const FilePath& dir, - FilePath* temp_file); - -// Create and open a temporary file. File is opened for read/write. -// The full path is placed in |path|. -// Returns a handle to the opened file or NULL if an error occurred. -BASE_EXPORT FILE* CreateAndOpenTemporaryFile(FilePath* path); - -// Similar to CreateAndOpenTemporaryFile, but the file is created in |dir|. -BASE_EXPORT FILE* CreateAndOpenTemporaryFileInDir(const FilePath& dir, - FilePath* path); - -// Create a new directory. If prefix is provided, the new directory name is in -// the format of prefixyyyy. -// NOTE: prefix is ignored in the POSIX implementation. -// If success, return true and output the full path of the directory created. -BASE_EXPORT bool CreateNewTempDirectory(const FilePath::StringType& prefix, - FilePath* new_temp_path); - -// Create a directory within another directory. -// Extra characters will be appended to |prefix| to ensure that the -// new directory does not have the same name as an existing directory. -BASE_EXPORT bool CreateTemporaryDirInDir(const FilePath& base_dir, - const FilePath::StringType& prefix, - FilePath* new_dir); - -// Creates a directory, as well as creating any parent directories, if they -// don't exist. Returns 'true' on successful creation, or if the directory -// already exists. The directory is only readable by the current user. -// Returns true on success, leaving *error unchanged. -// Returns false on failure and sets *error appropriately, if it is non-NULL. -BASE_EXPORT bool CreateDirectoryAndGetError(const FilePath& full_path, - File::Error* error); - -// Backward-compatible convenience method for the above. -BASE_EXPORT bool CreateDirectory(const FilePath& full_path); - -// Returns the file size. Returns true on success. -BASE_EXPORT bool GetFileSize(const FilePath& file_path, int64* file_size); - -// Sets |real_path| to |path| with symbolic links and junctions expanded. -// On windows, make sure the path starts with a lettered drive. -// |path| must reference a file. Function will fail if |path| points to -// a directory or to a nonexistent path. On windows, this function will -// fail if |path| is a junction or symlink that points to an empty file, -// or if |real_path| would be longer than MAX_PATH characters. -BASE_EXPORT bool NormalizeFilePath(const FilePath& path, FilePath* real_path); - -#if defined(OS_WIN) - -// Given a path in NT native form ("\Device\HarddiskVolumeXX\..."), -// return in |drive_letter_path| the equivalent path that starts with -// a drive letter ("C:\..."). Return false if no such path exists. -BASE_EXPORT bool DevicePathToDriveLetterPath(const FilePath& device_path, - FilePath* drive_letter_path); - -// Given an existing file in |path|, set |real_path| to the path -// in native NT format, of the form "\Device\HarddiskVolumeXX\..". -// Returns false if the path can not be found. Empty files cannot -// be resolved with this function. -BASE_EXPORT bool NormalizeToNativeFilePath(const FilePath& path, - FilePath* nt_path); -#endif - -// This function will return if the given file is a symlink or not. -BASE_EXPORT bool IsLink(const FilePath& file_path); - -// Returns information about the given file path. -BASE_EXPORT bool GetFileInfo(const FilePath& file_path, File::Info* info); - -// Sets the time of the last access and the time of the last modification. -BASE_EXPORT bool TouchFile(const FilePath& path, - const Time& last_accessed, - const Time& last_modified); - -// Wrapper for fopen-like calls. Returns non-NULL FILE* on success. -BASE_EXPORT FILE* OpenFile(const FilePath& filename, const char* mode); - -// Closes file opened by OpenFile. Returns true on success. -BASE_EXPORT bool CloseFile(FILE* file); - -// Associates a standard FILE stream with an existing File. Note that this -// functions take ownership of the existing File. -BASE_EXPORT FILE* FileToFILE(File file, const char* mode); - -// Truncates an open file to end at the location of the current file pointer. -// This is a cross-platform analog to Windows' SetEndOfFile() function. -BASE_EXPORT bool TruncateFile(FILE* file); - -// Reads at most the given number of bytes from the file into the buffer. -// Returns the number of read bytes, or -1 on error. -BASE_EXPORT int ReadFile(const FilePath& filename, char* data, int max_size); - -// Writes the given buffer into the file, overwriting any data that was -// previously there. Returns the number of bytes written, or -1 on error. -BASE_EXPORT int WriteFile(const FilePath& filename, const char* data, - int size); - -#if defined(OS_POSIX) -// Append the data to |fd|. Does not close |fd| when done. -BASE_EXPORT int WriteFileDescriptor(const int fd, const char* data, int size); -#endif - -// Append the given buffer into the file. Returns the number of bytes written, -// or -1 on error. -BASE_EXPORT int AppendToFile(const FilePath& filename, - const char* data, int size); - -// Gets the current working directory for the process. -BASE_EXPORT bool GetCurrentDirectory(FilePath* path); - -// Sets the current working directory for the process. -BASE_EXPORT bool SetCurrentDirectory(const FilePath& path); - -// Attempts to find a number that can be appended to the |path| to make it -// unique. If |path| does not exist, 0 is returned. If it fails to find such -// a number, -1 is returned. If |suffix| is not empty, also checks the -// existence of it with the given suffix. -BASE_EXPORT int GetUniquePathNumber(const FilePath& path, - const FilePath::StringType& suffix); - -#if defined(OS_POSIX) -// Test that |path| can only be changed by a given user and members of -// a given set of groups. -// Specifically, test that all parts of |path| under (and including) |base|: -// * Exist. -// * Are owned by a specific user. -// * Are not writable by all users. -// * Are owned by a member of a given set of groups, or are not writable by -// their group. -// * Are not symbolic links. -// This is useful for checking that a config file is administrator-controlled. -// |base| must contain |path|. -BASE_EXPORT bool VerifyPathControlledByUser(const base::FilePath& base, - const base::FilePath& path, - uid_t owner_uid, - const std::set<gid_t>& group_gids); -#endif // defined(OS_POSIX) - -#if defined(OS_MACOSX) && !defined(OS_IOS) -// Is |path| writable only by a user with administrator privileges? -// This function uses Mac OS conventions. The super user is assumed to have -// uid 0, and the administrator group is assumed to be named "admin". -// Testing that |path|, and every parent directory including the root of -// the filesystem, are owned by the superuser, controlled by the group -// "admin", are not writable by all users, and contain no symbolic links. -// Will return false if |path| does not exist. -BASE_EXPORT bool VerifyPathControlledByAdmin(const base::FilePath& path); -#endif // defined(OS_MACOSX) && !defined(OS_IOS) - -// Returns the maximum length of path component on the volume containing -// the directory |path|, in the number of FilePath::CharType, or -1 on failure. -BASE_EXPORT int GetMaximumPathComponentLength(const base::FilePath& path); - -#if defined(OS_LINUX) -// Broad categories of file systems as returned by statfs() on Linux. -enum FileSystemType { - FILE_SYSTEM_UNKNOWN, // statfs failed. - FILE_SYSTEM_0, // statfs.f_type == 0 means unknown, may indicate AFS. - FILE_SYSTEM_ORDINARY, // on-disk filesystem like ext2 - FILE_SYSTEM_NFS, - FILE_SYSTEM_SMB, - FILE_SYSTEM_CODA, - FILE_SYSTEM_MEMORY, // in-memory file system - FILE_SYSTEM_CGROUP, // cgroup control. - FILE_SYSTEM_OTHER, // any other value. - FILE_SYSTEM_TYPE_COUNT -}; - -// Attempts determine the FileSystemType for |path|. -// Returns false if |path| doesn't exist. -BASE_EXPORT bool GetFileSystemType(const FilePath& path, FileSystemType* type); -#endif - -#if defined(OS_POSIX) -// Get a temporary directory for shared memory files. The directory may depend -// on whether the destination is intended for executable files, which in turn -// depends on how /dev/shmem was mounted. As a result, you must supply whether -// you intend to create executable shmem segments so this function can find -// an appropriate location. -BASE_EXPORT bool GetShmemTempDir(bool executable, FilePath* path); -#endif - -} // namespace base - -// ----------------------------------------------------------------------------- - -namespace file_util { - -// Functor for |ScopedFILE| (below). -struct ScopedFILEClose { - inline void operator()(FILE* x) const { - if (x) - fclose(x); - } -}; - -// Automatically closes |FILE*|s. -typedef scoped_ptr<FILE, ScopedFILEClose> ScopedFILE; - -} // namespace file_util - -// Internal -------------------------------------------------------------------- - -namespace base { -namespace internal { - -// Same as Move but allows paths with traversal components. -// Use only with extreme care. -BASE_EXPORT bool MoveUnsafe(const FilePath& from_path, - const FilePath& to_path); - -// Same as CopyFile but allows paths with traversal components. -// Use only with extreme care. -BASE_EXPORT bool CopyFileUnsafe(const FilePath& from_path, - const FilePath& to_path); - -#if defined(OS_WIN) -// Copy from_path to to_path recursively and then delete from_path recursively. -// Returns true if all operations succeed. -// This function simulates Move(), but unlike Move() it works across volumes. -// This function is not transactional. -BASE_EXPORT bool CopyAndDeleteDirectory(const FilePath& from_path, - const FilePath& to_path); -#endif // defined(OS_WIN) - -} // namespace internal -} // namespace base - -#endif // BASE_FILE_UTIL_H_
deleted file mode 100644 --- a/security/sandbox/chromium/base/file_util_win.cc +++ /dev/null @@ -1,810 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "base/file_util.h" - -#include <windows.h> -#include <io.h> -#include <psapi.h> -#include <shellapi.h> -#include <shlobj.h> -#include <time.h> - -#include <algorithm> -#include <limits> -#include <string> - -#include "base/files/file_enumerator.h" -#include "base/files/file_path.h" -#include "base/logging.h" -#include "base/metrics/histogram.h" -#include "base/process/process_handle.h" -#include "base/rand_util.h" -#include "base/strings/string_number_conversions.h" -#include "base/strings/string_util.h" -#include "base/strings/utf_string_conversions.h" -#include "base/threading/thread_restrictions.h" -#include "base/time/time.h" -#include "base/win/scoped_handle.h" -#include "base/win/windows_version.h" - -namespace base { - -namespace { - -const DWORD kFileShareAll = - FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE; - -} // namespace - -FilePath MakeAbsoluteFilePath(const FilePath& input) { - ThreadRestrictions::AssertIOAllowed(); - wchar_t file_path[MAX_PATH]; - if (!_wfullpath(file_path, input.value().c_str(), MAX_PATH)) - return FilePath(); - return FilePath(file_path); -} - -bool DeleteFile(const FilePath& path, bool recursive) { - ThreadRestrictions::AssertIOAllowed(); - - if (path.value().length() >= MAX_PATH) - return false; - - // On XP SHFileOperation will return ERROR_ACCESS_DENIED instead of - // ERROR_FILE_NOT_FOUND, so just shortcut this here. - if (path.empty()) - return true; - - if (!recursive) { - // If not recursing, then first check to see if |path| is a directory. - // If it is, then remove it with RemoveDirectory. - File::Info file_info; - if (GetFileInfo(path, &file_info) && file_info.is_directory) - return RemoveDirectory(path.value().c_str()) != 0; - - // Otherwise, it's a file, wildcard or non-existant. Try DeleteFile first - // because it should be faster. If DeleteFile fails, then we fall through - // to SHFileOperation, which will do the right thing. - if (::DeleteFile(path.value().c_str()) != 0) - return true; - } - - // SHFILEOPSTRUCT wants the path to be terminated with two NULLs, - // so we have to use wcscpy because wcscpy_s writes non-NULLs - // into the rest of the buffer. - wchar_t double_terminated_path[MAX_PATH + 1] = {0}; -#pragma warning(suppress:4996) // don't complain about wcscpy deprecation - wcscpy(double_terminated_path, path.value().c_str()); - - SHFILEOPSTRUCT file_operation = {0}; - file_operation.wFunc = FO_DELETE; - file_operation.pFrom = double_terminated_path; - file_operation.fFlags = FOF_NOERRORUI | FOF_SILENT | FOF_NOCONFIRMATION; - if (!recursive) - file_operation.fFlags |= FOF_NORECURSION | FOF_FILESONLY; - int err = SHFileOperation(&file_operation); - - // Since we're passing flags to the operation telling it to be silent, - // it's possible for the operation to be aborted/cancelled without err - // being set (although MSDN doesn't give any scenarios for how this can - // happen). See MSDN for SHFileOperation and SHFILEOPTSTRUCT. - if (file_operation.fAnyOperationsAborted) - return false; - - // Some versions of Windows return ERROR_FILE_NOT_FOUND (0x2) when deleting - // an empty directory and some return 0x402 when they should be returning - // ERROR_FILE_NOT_FOUND. MSDN says Vista and up won't return 0x402. Windows 7 - // can return DE_INVALIDFILES (0x7C) for nonexistent directories. - return (err == 0 || err == ERROR_FILE_NOT_FOUND || err == 0x402 || - err == 0x7C); -} - -bool DeleteFileAfterReboot(const FilePath& path) { - ThreadRestrictions::AssertIOAllowed(); - - if (path.value().length() >= MAX_PATH) - return false; - - return MoveFileEx(path.value().c_str(), NULL, - MOVEFILE_DELAY_UNTIL_REBOOT | - MOVEFILE_REPLACE_EXISTING) != FALSE; -} - -bool ReplaceFile(const FilePath& from_path, - const FilePath& to_path, - File::Error* error) { - ThreadRestrictions::AssertIOAllowed(); - // Try a simple move first. It will only succeed when |to_path| doesn't - // already exist. - if (::MoveFile(from_path.value().c_str(), to_path.value().c_str())) - return true; - // Try the full-blown replace if the move fails, as ReplaceFile will only - // succeed when |to_path| does exist. When writing to a network share, we may - // not be able to change the ACLs. Ignore ACL errors then - // (REPLACEFILE_IGNORE_MERGE_ERRORS). - if (::ReplaceFile(to_path.value().c_str(), from_path.value().c_str(), NULL, - REPLACEFILE_IGNORE_MERGE_ERRORS, NULL, NULL)) { - return true; - } - if (error) - *error = File::OSErrorToFileError(GetLastError()); - return false; -} - -bool CopyDirectory(const FilePath& from_path, const FilePath& to_path, - bool recursive) { - // NOTE(maruel): Previous version of this function used to call - // SHFileOperation(). This used to copy the file attributes and extended - // attributes, OLE structured storage, NTFS file system alternate data - // streams, SECURITY_DESCRIPTOR. In practice, this is not what we want, we - // want the containing directory to propagate its SECURITY_DESCRIPTOR. - ThreadRestrictions::AssertIOAllowed(); - - // NOTE: I suspect we could support longer paths, but that would involve - // analyzing all our usage of files. - if (from_path.value().length() >= MAX_PATH || - to_path.value().length() >= MAX_PATH) { - return false; - } - - // This function does not properly handle destinations within the source. - FilePath real_to_path = to_path; - if (PathExists(real_to_path)) { - real_to_path = MakeAbsoluteFilePath(real_to_path); - if (real_to_path.empty()) - return false; - } else { - real_to_path = MakeAbsoluteFilePath(real_to_path.DirName()); - if (real_to_path.empty()) - return false; - } - FilePath real_from_path = MakeAbsoluteFilePath(from_path); - if (real_from_path.empty()) - return false; - if (real_to_path.value().size() >= real_from_path.value().size() && - real_to_path.value().compare(0, real_from_path.value().size(), - real_from_path.value()) == 0) { - return false; - } - - int traverse_type = FileEnumerator::FILES; - if (recursive) - traverse_type |= FileEnumerator::DIRECTORIES; - FileEnumerator traversal(from_path, recursive, traverse_type); - - if (!PathExists(from_path)) { - DLOG(ERROR) << "CopyDirectory() couldn't stat source directory: " - << from_path.value().c_str(); - return false; - } - // TODO(maruel): This is not necessary anymore. - DCHECK(recursive || DirectoryExists(from_path)); - - FilePath current = from_path; - bool from_is_dir = DirectoryExists(from_path); - bool success = true; - FilePath from_path_base = from_path; - if (recursive && DirectoryExists(to_path)) { - // If the destination already exists and is a directory, then the - // top level of source needs to be copied. - from_path_base = from_path.DirName(); - } - - while (success && !current.empty()) { - // current is the source path, including from_path, so append - // the suffix after from_path to to_path to create the target_path. - FilePath target_path(to_path); - if (from_path_base != current) { - if (!from_path_base.AppendRelativePath(current, &target_path)) { - success = false; - break; - } - } - - if (from_is_dir) { - if (!DirectoryExists(target_path) && - !::CreateDirectory(target_path.value().c_str(), NULL)) { - DLOG(ERROR) << "CopyDirectory() couldn't create directory: " - << target_path.value().c_str(); - success = false; - } - } else if (!internal::CopyFileUnsafe(current, target_path)) { - DLOG(ERROR) << "CopyDirectory() couldn't create file: " - << target_path.value().c_str(); - success = false; - } - - current = traversal.Next(); - if (!current.empty()) - from_is_dir = traversal.GetInfo().IsDirectory(); - } - - return success; -} - -bool PathExists(const FilePath& path) { - ThreadRestrictions::AssertIOAllowed(); - return (GetFileAttributes(path.value().c_str()) != INVALID_FILE_ATTRIBUTES); -} - -bool PathIsWritable(const FilePath& path) { - ThreadRestrictions::AssertIOAllowed(); - HANDLE dir = - CreateFile(path.value().c_str(), FILE_ADD_FILE, kFileShareAll, - NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL); - - if (dir == INVALID_HANDLE_VALUE) - return false; - - CloseHandle(dir); - return true; -} - -bool DirectoryExists(const FilePath& path) { - ThreadRestrictions::AssertIOAllowed(); - DWORD fileattr = GetFileAttributes(path.value().c_str()); - if (fileattr != INVALID_FILE_ATTRIBUTES) - return (fileattr & FILE_ATTRIBUTE_DIRECTORY) != 0; - return false; -} - -bool GetTempDir(FilePath* path) { - wchar_t temp_path[MAX_PATH + 1]; - DWORD path_len = ::GetTempPath(MAX_PATH, temp_path); - if (path_len >= MAX_PATH || path_len <= 0) - return false; - // TODO(evanm): the old behavior of this function was to always strip the - // trailing slash. We duplicate this here, but it shouldn't be necessary - // when everyone is using the appropriate FilePath APIs. - *path = FilePath(temp_path).StripTrailingSeparators(); - return true; -} - -FilePath GetHomeDir() { - char16 result[MAX_PATH]; - if (SUCCEEDED(SHGetFolderPath(NULL, CSIDL_PROFILE, NULL, SHGFP_TYPE_CURRENT, - result)) && - result[0]) { - return FilePath(result); - } - - // Fall back to the temporary directory on failure. - FilePath temp; - if (GetTempDir(&temp)) - return temp; - - // Last resort. - return FilePath(L"C:\\"); -} - -bool CreateTemporaryFile(FilePath* path) { - ThreadRestrictions::AssertIOAllowed(); - - FilePath temp_file; - - if (!GetTempDir(path)) - return false; - - if (CreateTemporaryFileInDir(*path, &temp_file)) { - *path = temp_file; - return true; - } - - return false; -} - -// On POSIX we have semantics to create and open a temporary file -// atomically. -// TODO(jrg): is there equivalent call to use on Windows instead of -// going 2-step? -FILE* CreateAndOpenTemporaryFileInDir(const FilePath& dir, FilePath* path) { - ThreadRestrictions::AssertIOAllowed(); - if (!CreateTemporaryFileInDir(dir, path)) { - return NULL; - } - // Open file in binary mode, to avoid problems with fwrite. On Windows - // it replaces \n's with \r\n's, which may surprise you. - // Reference: http://msdn.microsoft.com/en-us/library/h9t88zwz(VS.71).aspx - return OpenFile(*path, "wb+"); -} - -bool CreateTemporaryFileInDir(const FilePath& dir, FilePath* temp_file) { - ThreadRestrictions::AssertIOAllowed(); - - wchar_t temp_name[MAX_PATH + 1]; - - if (!GetTempFileName(dir.value().c_str(), L"", 0, temp_name)) { - DPLOG(WARNING) << "Failed to get temporary file name in " - << UTF16ToUTF8(dir.value()); - return false; - } - - wchar_t long_temp_name[MAX_PATH + 1]; - DWORD long_name_len = GetLongPathName(temp_name, long_temp_name, MAX_PATH); - if (long_name_len > MAX_PATH || long_name_len == 0) { - // GetLongPathName() failed, but we still have a temporary file. - *temp_file = FilePath(temp_name); - return true; - } - - FilePath::StringType long_temp_name_str; - long_temp_name_str.assign(long_temp_name, long_name_len); - *temp_file = FilePath(long_temp_name_str); - return true; -} - -bool CreateTemporaryDirInDir(const FilePath& base_dir, - const FilePath::StringType& prefix, - FilePath* new_dir) { - ThreadRestrictions::AssertIOAllowed(); - - FilePath path_to_create; - - for (int count = 0; count < 50; ++count) { - // Try create a new temporary directory with random generated name. If - // the one exists, keep trying another path name until we reach some limit. - string16 new_dir_name; - new_dir_name.assign(prefix); - new_dir_name.append(IntToString16(GetCurrentProcId())); - new_dir_name.push_back('_'); - new_dir_name.append(IntToString16(RandInt(0, kint16max))); - - path_to_create = base_dir.Append(new_dir_name); - if (::CreateDirectory(path_to_create.value().c_str(), NULL)) { - *new_dir = path_to_create; - return true; - } - } - - return false; -} - -bool CreateNewTempDirectory(const FilePath::StringType& prefix, - FilePath* new_temp_path) { - ThreadRestrictions::AssertIOAllowed(); - - FilePath system_temp_dir; - if (!GetTempDir(&system_temp_dir)) - return false; - - return CreateTemporaryDirInDir(system_temp_dir, prefix, new_temp_path); -} - -bool CreateDirectoryAndGetError(const FilePath& full_path, - File::Error* error) { - ThreadRestrictions::AssertIOAllowed(); - - // If the path exists, we've succeeded if it's a directory, failed otherwise. - const wchar_t* full_path_str = full_path.value().c_str(); - DWORD fileattr = ::GetFileAttributes(full_path_str); - if (fileattr != INVALID_FILE_ATTRIBUTES) { - if ((fileattr & FILE_ATTRIBUTE_DIRECTORY) != 0) { - DVLOG(1) << "CreateDirectory(" << full_path_str << "), " - << "directory already exists."; - return true; - } - DLOG(WARNING) << "CreateDirectory(" << full_path_str << "), " - << "conflicts with existing file."; - if (error) { - *error = File::FILE_ERROR_NOT_A_DIRECTORY; - } - return false; - } - - // Invariant: Path does not exist as file or directory. - - // Attempt to create the parent recursively. This will immediately return - // true if it already exists, otherwise will create all required parent - // directories starting with the highest-level missing parent. - FilePath parent_path(full_path.DirName()); - if (parent_path.value() == full_path.value()) { - if (error) { - *error = File::FILE_ERROR_NOT_FOUND; - } - return false; - } - if (!CreateDirectoryAndGetError(parent_path, error)) { - DLOG(WARNING) << "Failed to create one of the parent directories."; - if (error) { - DCHECK(*error != File::FILE_OK); - } - return false; - } - - if (!::CreateDirectory(full_path_str, NULL)) { - DWORD error_code = ::GetLastError(); - if (error_code == ERROR_ALREADY_EXISTS && DirectoryExists(full_path)) { - // This error code ERROR_ALREADY_EXISTS doesn't indicate whether we - // were racing with someone creating the same directory, or a file - // with the same path. If DirectoryExists() returns true, we lost the - // race to create the same directory. - return true; - } else { - if (error) - *error = File::OSErrorToFileError(error_code); - DLOG(WARNING) << "Failed to create directory " << full_path_str - << ", last error is " << error_code << "."; - return false; - } - } else { - return true; - } -} - -bool NormalizeFilePath(const FilePath& path, FilePath* real_path) { - ThreadRestrictions::AssertIOAllowed(); - FilePath mapped_file; - if (!NormalizeToNativeFilePath(path, &mapped_file)) - return false; - // NormalizeToNativeFilePath() will return a path that starts with - // "\Device\Harddisk...". Helper DevicePathToDriveLetterPath() - // will find a drive letter which maps to the path's device, so - // that we return a path starting with a drive letter. - return DevicePathToDriveLetterPath(mapped_file, real_path); -} - -bool DevicePathToDriveLetterPath(const FilePath& nt_device_path, - FilePath* out_drive_letter_path) { - ThreadRestrictions::AssertIOAllowed(); - - // Get the mapping of drive letters to device paths. - const int kDriveMappingSize = 1024; - wchar_t drive_mapping[kDriveMappingSize] = {'\0'}; - if (!::GetLogicalDriveStrings(kDriveMappingSize - 1, drive_mapping)) { - DLOG(ERROR) << "Failed to get drive mapping."; - return false; - } - - // The drive mapping is a sequence of null terminated strings. - // The last string is empty. - wchar_t* drive_map_ptr = drive_mapping; - wchar_t device_path_as_string[MAX_PATH]; - wchar_t drive[] = L" :"; - - // For each string in the drive mapping, get the junction that links - // to it. If that junction is a prefix of |device_path|, then we - // know that |drive| is the real path prefix. - while (*drive_map_ptr) { - drive[0] = drive_map_ptr[0]; // Copy the drive letter. - - if (QueryDosDevice(drive, device_path_as_string, MAX_PATH)) { - FilePath device_path(device_path_as_string); - if (device_path == nt_device_path || - device_path.IsParent(nt_device_path)) { - *out_drive_letter_path = FilePath(drive + - nt_device_path.value().substr(wcslen(device_path_as_string))); - return true; - } - } - // Move to the next drive letter string, which starts one - // increment after the '\0' that terminates the current string. - while (*drive_map_ptr++); - } - - // No drive matched. The path does not start with a device junction - // that is mounted as a drive letter. This means there is no drive - // letter path to the volume that holds |device_path|, so fail. - return false; -} - -bool NormalizeToNativeFilePath(const FilePath& path, FilePath* nt_path) { - ThreadRestrictions::AssertIOAllowed(); - // In Vista, GetFinalPathNameByHandle() would give us the real path - // from a file handle. If we ever deprecate XP, consider changing the - // code below to a call to GetFinalPathNameByHandle(). The method this - // function uses is explained in the following msdn article: - // http://msdn.microsoft.com/en-us/library/aa366789(VS.85).aspx - base::win::ScopedHandle file_handle( - ::CreateFile(path.value().c_str(), - GENERIC_READ, - kFileShareAll, - NULL, - OPEN_EXISTING, - FILE_ATTRIBUTE_NORMAL, - NULL)); - if (!file_handle) - return false; - - // Create a file mapping object. Can't easily use MemoryMappedFile, because - // we only map the first byte, and need direct access to the handle. You can - // not map an empty file, this call fails in that case. - base::win::ScopedHandle file_map_handle( - ::CreateFileMapping(file_handle.Get(), - NULL, - PAGE_READONLY, - 0, - 1, // Just one byte. No need to look at the data. - NULL)); - if (!file_map_handle) - return false; - - // Use a view of the file to get the path to the file. - void* file_view = MapViewOfFile(file_map_handle.Get(), - FILE_MAP_READ, 0, 0, 1); - if (!file_view) - return false; - - // The expansion of |path| into a full path may make it longer. - // GetMappedFileName() will fail if the result is longer than MAX_PATH. - // Pad a bit to be safe. If kMaxPathLength is ever changed to be less - // than MAX_PATH, it would be nessisary to test that GetMappedFileName() - // not return kMaxPathLength. This would mean that only part of the - // path fit in |mapped_file_path|. - const int kMaxPathLength = MAX_PATH + 10; - wchar_t mapped_file_path[kMaxPathLength]; - bool success = false; - HANDLE cp = GetCurrentProcess(); - if (::GetMappedFileNameW(cp, file_view, mapped_file_path, kMaxPathLength)) { - *nt_path = FilePath(mapped_file_path); - success = true; - } - ::UnmapViewOfFile(file_view); - return success; -} - -// TODO(rkc): Work out if we want to handle NTFS junctions here or not, handle -// them if we do decide to. -bool IsLink(const FilePath& file_path) { - return false; -} - -bool GetFileInfo(const FilePath& file_path, File::Info* results) { - ThreadRestrictions::AssertIOAllowed(); - - WIN32_FILE_ATTRIBUTE_DATA attr; - if (!GetFileAttributesEx(file_path.value().c_str(), - GetFileExInfoStandard, &attr)) { - return false; - } - - ULARGE_INTEGER size; - size.HighPart = attr.nFileSizeHigh; - size.LowPart = attr.nFileSizeLow; - results->size = size.QuadPart; - - results->is_directory = - (attr.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0; - results->last_modified = Time::FromFileTime(attr.ftLastWriteTime); - results->last_accessed = Time::FromFileTime(attr.ftLastAccessTime); - results->creation_time = Time::FromFileTime(attr.ftCreationTime); - - return true; -} - -FILE* OpenFile(const FilePath& filename, const char* mode) { - ThreadRestrictions::AssertIOAllowed(); - std::wstring w_mode = ASCIIToWide(std::string(mode)); - return _wfsopen(filename.value().c_str(), w_mode.c_str(), _SH_DENYNO); -} - -FILE* FileToFILE(File file, const char* mode) { - if (!file.IsValid()) - return NULL; - int fd = - _open_osfhandle(reinterpret_cast<intptr_t>(file.GetPlatformFile()), 0); - if (fd < 0) - return NULL; - file.TakePlatformFile(); - FILE* stream = _fdopen(fd, mode); - if (!stream) - _close(fd); - return stream; -} - -int ReadFile(const FilePath& filename, char* data, int max_size) { - ThreadRestrictions::AssertIOAllowed(); - base::win::ScopedHandle file(CreateFile(filename.value().c_str(), - GENERIC_READ, - FILE_SHARE_READ | FILE_SHARE_WRITE, - NULL, - OPEN_EXISTING, - FILE_FLAG_SEQUENTIAL_SCAN, - NULL)); - if (!file) - return -1; - - DWORD read; - if (::ReadFile(file, data, max_size, &read, NULL)) - return read; - - return -1; -} - -int WriteFile(const FilePath& filename, const char* data, int size) { - ThreadRestrictions::AssertIOAllowed(); - base::win::ScopedHandle file(CreateFile(filename.value().c_str(), - GENERIC_WRITE, - 0, - NULL, - CREATE_ALWAYS, - 0, - NULL)); - if (!file) { - DPLOG(WARNING) << "CreateFile failed for path " - << UTF16ToUTF8(filename.value()); - return -1; - } - - DWORD written; - BOOL result = ::WriteFile(file, data, size, &written, NULL); - if (result && static_cast<int>(written) == size) - return written; - - if (!result) { - // WriteFile failed. - DPLOG(WARNING) << "writing file " << UTF16ToUTF8(filename.value()) - << " failed"; - } else { - // Didn't write all the bytes. - DLOG(WARNING) << "wrote" << written << " bytes to " - << UTF16ToUTF8(filename.value()) << " expected " << size; - } - return -1; -} - -int AppendToFile(const FilePath& filename, const char* data, int size) { - ThreadRestrictions::AssertIOAllowed(); - base::win::ScopedHandle file(CreateFile(filename.value().c_str(), - FILE_APPEND_DATA, - 0, - NULL, - OPEN_EXISTING, - 0, - NULL)); - if (!file) { - DPLOG(WARNING) << "CreateFile failed for path " - << UTF16ToUTF8(filename.value()); - return -1; - } - - DWORD written; - BOOL result = ::WriteFile(file, data, size, &written, NULL); - if (result && static_cast<int>(written) == size) - return written; - - if (!result) { - // WriteFile failed. - DPLOG(WARNING) << "writing file " << UTF16ToUTF8(filename.value()) - << " failed"; - } else { - // Didn't write all the bytes. - DLOG(WARNING) << "wrote" << written << " bytes to " - << UTF16ToUTF8(filename.value()) << " expected " << size; - } - return -1; -} - -// Gets the current working directory for the process. -bool GetCurrentDirectory(FilePath* dir) { - ThreadRestrictions::AssertIOAllowed(); - - wchar_t system_buffer[MAX_PATH]; - system_buffer[0] = 0; - DWORD len = ::GetCurrentDirectory(MAX_PATH, system_buffer); - if (len == 0 || len > MAX_PATH) - return false; - // TODO(evanm): the old behavior of this function was to always strip the - // trailing slash. We duplicate this here, but it shouldn't be necessary - // when everyone is using the appropriate FilePath APIs. - std::wstring dir_str(system_buffer); - *dir = FilePath(dir_str).StripTrailingSeparators(); - return true; -} - -// Sets the current working directory for the process. -bool SetCurrentDirectory(const FilePath& directory) { - ThreadRestrictions::AssertIOAllowed(); - BOOL ret = ::SetCurrentDirectory(directory.value().c_str()); - return ret != 0; -} - -int GetMaximumPathComponentLength(const FilePath& path) { - ThreadRestrictions::AssertIOAllowed(); - - wchar_t volume_path[MAX_PATH]; - if (!GetVolumePathNameW(path.NormalizePathSeparators().value().c_str(), - volume_path, - arraysize(volume_path))) { - return -1; - } - - DWORD max_length = 0; - if (!GetVolumeInformationW(volume_path, NULL, 0, NULL, &max_length, NULL, - NULL, 0)) { - return -1; - } - - // Length of |path| with path separator appended. - size_t prefix = path.StripTrailingSeparators().value().size() + 1; - // The whole path string must be shorter than MAX_PATH. That is, it must be - // prefix + component_length < MAX_PATH (or equivalently, <= MAX_PATH - 1). - int whole_path_limit = std::max(0, MAX_PATH - 1 - static_cast<int>(prefix)); - return std::min(whole_path_limit, static_cast<int>(max_length)); -} - -// ----------------------------------------------------------------------------- - -namespace internal { - -bool MoveUnsafe(const FilePath& from_path, const FilePath& to_path) { - ThreadRestrictions::AssertIOAllowed(); - - // NOTE: I suspect we could support longer paths, but that would involve - // analyzing all our usage of files. - if (from_path.value().length() >= MAX_PATH || - to_path.value().length() >= MAX_PATH) { - return false; - } - if (MoveFileEx(from_path.value().c_str(), to_path.value().c_str(), - MOVEFILE_COPY_ALLOWED | MOVEFILE_REPLACE_EXISTING) != 0) - return true; - - // Keep the last error value from MoveFileEx around in case the below - // fails. - bool ret = false; - DWORD last_error = ::GetLastError(); - - if (DirectoryExists(from_path)) { - // MoveFileEx fails if moving directory across volumes. We will simulate - // the move by using Copy and Delete. Ideally we could check whether - // from_path and to_path are indeed in different volumes. - ret = internal::CopyAndDeleteDirectory(from_path, to_path); - } - - if (!ret) { - // Leave a clue about what went wrong so that it can be (at least) picked - // up by a PLOG entry. - ::SetLastError(last_error); - } - - return ret; -} - -bool CopyFileUnsafe(const FilePath& from_path, const FilePath& to_path) { - ThreadRestrictions::AssertIOAllowed(); - - // NOTE: I suspect we could support longer paths, but that would involve - // analyzing all our usage of files. - if (from_path.value().length() >= MAX_PATH || - to_path.value().length() >= MAX_PATH) { - return false; - } - - // Unlike the posix implementation that copies the file manually and discards - // the ACL bits, CopyFile() copies the complete SECURITY_DESCRIPTOR and access - // bits, which is usually not what we want. We can't do much about the - // SECURITY_DESCRIPTOR but at least remove the read only bit. - const wchar_t* dest = to_path.value().c_str(); - if (!::CopyFile(from_path.value().c_str(), dest, false)) { - // Copy failed. - return false; - } - DWORD attrs = GetFileAttributes(dest); - if (attrs == INVALID_FILE_ATTRIBUTES) { - return false; - } - if (attrs & FILE_ATTRIBUTE_READONLY) { - SetFileAttributes(dest, attrs & ~FILE_ATTRIBUTE_READONLY); - } - return true; -} - -bool CopyAndDeleteDirectory(const FilePath& from_path, - const FilePath& to_path) { - ThreadRestrictions::AssertIOAllowed(); - if (CopyDirectory(from_path, to_path, true)) { - if (DeleteFile(from_path, true)) - return true; - - // Like Move, this function is not transactional, so we just - // leave the copied bits behind if deleting from_path fails. - // If to_path exists previously then we have already overwritten - // it by now, we don't get better off by deleting the new bits. - } - return false; -} - -} // namespace internal -} // namespace base
--- a/security/sandbox/chromium/base/files/file_path.h +++ b/security/sandbox/chromium/base/files/file_path.h @@ -102,17 +102,16 @@ #ifndef BASE_FILES_FILE_PATH_H_ #define BASE_FILES_FILE_PATH_H_ #include <stddef.h> #include <string> #include <vector> #include "base/base_export.h" -#include "base/compiler_specific.h" #include "base/containers/hash_tables.h" #include "base/strings/string16.h" #include "base/strings/string_piece.h" // For implicit conversions. #include "build/build_config.h" // Windows-style drive letter support and pathname separator characters can be // enabled and disabled independently, to aid testing. These #defines are // here so that the same setting can be used in both the implementation and @@ -448,28 +447,19 @@ BASE_EXPORT extern void PrintTo(const ba #define FILE_PATH_LITERAL(x) L ## x #define PRFilePath "ls" #define PRFilePathLiteral L"%ls" #endif // OS_WIN // Provide a hash function so that hash_sets and maps can contain FilePath // objects. namespace BASE_HASH_NAMESPACE { -#if defined(COMPILER_GCC) template<> struct hash<base::FilePath> { size_t operator()(const base::FilePath& f) const { return hash<base::FilePath::StringType>()(f.value()); } }; -#elif defined(COMPILER_MSVC) - -inline size_t hash_value(const base::FilePath& f) { - return hash_value(f.value()); -} - -#endif // COMPILER - } // namespace BASE_HASH_NAMESPACE #endif // BASE_FILES_FILE_PATH_H_
--- a/security/sandbox/chromium/base/guid.h +++ b/security/sandbox/chromium/base/guid.h @@ -10,17 +10,17 @@ #include "base/base_export.h" #include "base/basictypes.h" #include "build/build_config.h" namespace base { // Generate a 128-bit random GUID of the form: "%08X-%04X-%04X-%04X-%012llX". // If GUID generation fails an empty string is returned. -// The POSIX implementation uses psuedo random number generation to create +// The POSIX implementation uses pseudo random number generation to create // the GUID. The Windows implementation uses system services. BASE_EXPORT std::string GenerateGUID(); // Returns true if the input string conforms to the GUID format. BASE_EXPORT bool IsValidGUID(const std::string& guid); #if defined(OS_POSIX) // For unit testing purposes only. Do not use outside of tests.
new file mode 100644 --- /dev/null +++ b/security/sandbox/chromium/base/hash.cc @@ -0,0 +1,18 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "base/hash.h" + +// Definition in base/third_party/superfasthash/superfasthash.c. (Third-party +// code did not come with its own header file, so declaring the function here.) +// Note: This algorithm is also in Blink under Source/wtf/StringHasher.h. +extern "C" uint32_t SuperFastHash(const char* data, int len); + +namespace base { + +uint32 SuperFastHash(const char* data, int len) { + return ::SuperFastHash(data, len); +} + +} // namespace base
new file mode 100644 --- /dev/null +++ b/security/sandbox/chromium/base/hash.h @@ -0,0 +1,38 @@ +// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef BASE_HASH_H_ +#define BASE_HASH_H_ + +#include <limits> +#include <string> + +#include "base/base_export.h" +#include "base/basictypes.h" +#include "base/logging.h" + +namespace base { + +// WARNING: This hash function should not be used for any cryptographic purpose. +BASE_EXPORT uint32 SuperFastHash(const char* data, int len); + +// Computes a hash of a memory buffer |data| of a given |length|. +// WARNING: This hash function should not be used for any cryptographic purpose. +inline uint32 Hash(const char* data, size_t length) { + if (length > static_cast<size_t>(std::numeric_limits<int>::max())) { + NOTREACHED(); + return 0; + } + return SuperFastHash(data, static_cast<int>(length)); +} + +// Computes a hash of a string |str|. +// WARNING: This hash function should not be used for any cryptographic purpose. +inline uint32 Hash(const std::string& str) { + return Hash(str.data(), str.size()); +} + +} // namespace base + +#endif // BASE_HASH_H_
--- a/security/sandbox/chromium/base/lazy_instance.cc +++ b/security/sandbox/chromium/base/lazy_instance.cc @@ -3,17 +3,16 @@ // found in the LICENSE file. #include "base/lazy_instance.h" #include "base/at_exit.h" #include "base/atomicops.h" #include "base/basictypes.h" #include "base/threading/platform_thread.h" -#include "base/third_party/dynamic_annotations/dynamic_annotations.h" namespace base { namespace internal { // TODO(joth): This function could be shared with Singleton, in place of its // WaitForInstance() call. bool NeedsLazyInstance(subtle::AtomicWord* state) { // Try to create the instance, if we're the first, will go from 0 to @@ -37,19 +36,16 @@ bool NeedsLazyInstance(subtle::AtomicWor // Someone else created the instance. return false; } void CompleteLazyInstance(subtle::AtomicWord* state, subtle::AtomicWord new_instance, void* lazy_instance, void (*dtor)(void*)) { - // See the comment to the corresponding HAPPENS_AFTER in Pointer(). - ANNOTATE_HAPPENS_BEFORE(state); - // Instance is created, go from CREATING to CREATED. // Releases visibility over private_buf_ to readers. Pairing Acquire_Load's // are in NeedsInstance() and Pointer(). subtle::Release_Store(state, new_instance); // Make sure that the lazily instantiated object will get destroyed at exit. if (dtor) AtExitManager::RegisterCallback(dtor, lazy_instance);
--- a/security/sandbox/chromium/base/lazy_instance.h +++ b/security/sandbox/chromium/base/lazy_instance.h @@ -38,17 +38,16 @@ #include <new> // For placement new. #include "base/atomicops.h" #include "base/base_export.h" #include "base/basictypes.h" #include "base/debug/leak_annotations.h" #include "base/logging.h" #include "base/memory/aligned_memory.h" -#include "base/third_party/dynamic_annotations/dynamic_annotations.h" #include "base/threading/thread_restrictions.h" // LazyInstance uses its own struct initializer-list style static // initialization, as base's LINKER_INITIALIZED requires a constructor and on // some compilers (notably gcc 4.4) this still ends up needing runtime // initialization. #define LAZY_INSTANCE_INITIALIZER {0} @@ -161,23 +160,16 @@ class LazyInstance { if (!(value & kLazyInstanceCreatedMask) && internal::NeedsLazyInstance(&private_instance_)) { // Create the instance in the space provided by |private_buf_|. value = reinterpret_cast<subtle::AtomicWord>( Traits::New(private_buf_.void_data())); internal::CompleteLazyInstance(&private_instance_, value, this, Traits::kRegisterOnExit ? OnExit : NULL); } - - // This annotation helps race detectors recognize correct lock-less - // synchronization between different threads calling Pointer(). - // We suggest dynamic race detection tool that "Traits::New" above - // and CompleteLazyInstance(...) happens before "return instance()" below. - // See the corresponding HAPPENS_BEFORE in CompleteLazyInstance(...). - ANNOTATE_HAPPENS_AFTER(&private_instance_); return instance(); } bool operator==(Type* p) { switch (subtle::NoBarrier_Load(&private_instance_)) { case 0: return p == NULL; case internal::kLazyInstanceStateCreating:
--- a/security/sandbox/chromium/base/location.cc +++ b/security/sandbox/chromium/base/location.cc @@ -1,19 +1,16 @@ // Copyright (c) 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "build/build_config.h" #if defined(COMPILER_MSVC) -// MSDN says to #include <intrin.h>, but that breaks the VS2005 build. -extern "C" { - void* _ReturnAddress(); -} +#include <intrin.h> #endif #include "base/location.h" #include "base/strings/string_number_conversions.h" #include "base/strings/stringprintf.h" namespace tracked_objects {
--- a/security/sandbox/chromium/base/logging.h +++ b/security/sandbox/chromium/base/logging.h @@ -445,24 +445,46 @@ const LogSeverity LOG_0 = LOG_ERROR; !(condition) ? ::base::debug::BreakDebugger() : EAT_STREAM_PARAMETERS #define PCHECK(condition) CHECK(condition) #define CHECK_OP(name, op, val1, val2) CHECK((val1) op (val2)) #else +#if defined(_PREFAST_) && defined(OS_WIN) +// Use __analysis_assume to tell the VC++ static analysis engine that +// assert conditions are true, to suppress warnings. The LAZY_STREAM +// parameter doesn't reference 'condition' in /analyze builds because +// this evaluation confuses /analyze. The !! before condition is because +// __analysis_assume gets confused on some conditions: +// http://randomascii.wordpress.com/2011/09/13/analyze-for-visual-studio-the-ugly-part-5/ + +#define CHECK(condition) \ + __analysis_assume(!!(condition)), \ + LAZY_STREAM(LOG_STREAM(FATAL), false) \ + << "Check failed: " #condition ". " + +#define PCHECK(condition) \ + __analysis_assume(!!(condition)), \ + LAZY_STREAM(PLOG_STREAM(FATAL), false) \ + << "Check failed: " #condition ". " + +#else // _PREFAST_ + #define CHECK(condition) \ LAZY_STREAM(LOG_STREAM(FATAL), !(condition)) \ << "Check failed: " #condition ". " -#define PCHECK(condition) \ +#define PCHECK(condition) \ LAZY_STREAM(PLOG_STREAM(FATAL), !(condition)) \ << "Check failed: " #condition ". " +#endif // _PREFAST_ + // Helper macro for binary operators. // Don't use this macro directly in your code, use CHECK_EQ et al below. // // TODO(akalin): Rewrite this so that constructs like if (...) // CHECK_EQ(...) else { ... } work properly. #define CHECK_OP(name, op, val1, val2) \ if (std::string* _result = \ logging::Check##name##Impl((val1), (val2), \ @@ -478,35 +500,32 @@ const LogSeverity LOG_0 = LOG_ERROR; template<class t1, class t2> std::string* MakeCheckOpString(const t1& v1, const t2& v2, const char* names) { std::ostringstream ss; ss << names << " (" << v1 << " vs. " << v2 << ")"; std::string* msg = new std::string(ss.str()); return msg; } -// MSVC doesn't like complex extern templates and DLLs. -#if !defined(COMPILER_MSVC) // Commonly used instantiations of MakeCheckOpString<>. Explicitly instantiated // in logging.cc. extern template BASE_EXPORT std::string* MakeCheckOpString<int, int>( const int&, const int&, const char* names); extern template BASE_EXPORT std::string* MakeCheckOpString<unsigned long, unsigned long>( const unsigned long&, const unsigned long&, const char* names); extern template BASE_EXPORT std::string* MakeCheckOpString<unsigned long, unsigned int>( const unsigned long&, const unsigned int&, const char* names); extern template BASE_EXPORT std::string* MakeCheckOpString<unsigned int, unsigned long>( const unsigned int&, const unsigned long&, const char* names); extern template BASE_EXPORT std::string* MakeCheckOpString<std::string, std::string>( const std::string&, const std::string&, const char* name); -#endif // Helper functions for CHECK_OP macro. // The (int, int) specialization works around the issue that the compiler // will not instantiate the template version of the function on values of // unnamed enum type - see comment below. #define DEFINE_CHECK_OP_IMPL(name, op) \ template <class t1, class t2> \ inline std::string* Check##name##Impl(const t1& v1, const t2& v2, \ @@ -527,16 +546,17 @@ DEFINE_CHECK_OP_IMPL(GT, > ) #undef DEFINE_CHECK_OP_IMPL #define CHECK_EQ(val1, val2) CHECK_OP(EQ, ==, val1, val2) #define CHECK_NE(val1, val2) CHECK_OP(NE, !=, val1, val2) #define CHECK_LE(val1, val2) CHECK_OP(LE, <=, val1, val2) #define CHECK_LT(val1, val2) CHECK_OP(LT, < , val1, val2) #define CHECK_GE(val1, val2) CHECK_OP(GE, >=, val1, val2) #define CHECK_GT(val1, val2) CHECK_OP(GT, > , val1, val2) +#define CHECK_IMPLIES(val1, val2) CHECK(!(val1) || (val2)) #if defined(NDEBUG) #define ENABLE_DLOG 0 #else #define ENABLE_DLOG 1 #endif #if defined(NDEBUG) && !defined(DCHECK_ALWAYS_ON) @@ -613,24 +633,41 @@ const LogSeverity LOG_DCHECK = LOG_INFO; #endif // DCHECK_IS_ON // DCHECK et al. make sure to reference |condition| regardless of // whether DCHECKs are enabled; this is so that we don't get unused // variable warnings if the only use of a variable is in a DCHECK. // This behavior is different from DLOG_IF et al. -#define DCHECK(condition) \ - LAZY_STREAM(LOG_STREAM(DCHECK), DCHECK_IS_ON && !(condition)) \ +#if defined(_PREFAST_) && defined(OS_WIN) +// See comments on the previous use of __analysis_assume. + +#define DCHECK(condition) \ + __analysis_assume(!!(condition)), \ + LAZY_STREAM(LOG_STREAM(DCHECK), false) \ << "Check failed: " #condition ". " -#define DPCHECK(condition) \ - LAZY_STREAM(PLOG_STREAM(DCHECK), DCHECK_IS_ON && !(condition)) \ +#define DPCHECK(condition) \ + __analysis_assume(!!(condition)), \ + LAZY_STREAM(PLOG_STREAM(DCHECK), false) \ << "Check failed: " #condition ". " +#else // _PREFAST_ + +#define DCHECK(condition) \ + LAZY_STREAM(LOG_STREAM(DCHECK), DCHECK_IS_ON ? !(condition) : false) \ + << "Check failed: " #condition ". " + +#define DPCHECK(condition) \ + LAZY_STREAM(PLOG_STREAM(DCHECK), DCHECK_IS_ON ? !(condition) : false) \ + << "Check failed: " #condition ". " + +#endif // _PREFAST_ + // Helper macro for binary operators. // Don't use this macro directly in your code, use DCHECK_EQ et al below. #define DCHECK_OP(name, op, val1, val2) \ if (DCHECK_IS_ON) \ if (std::string* _result = \ logging::Check##name##Impl((val1), (val2), \ #val1 " " #op " " #val2)) \ logging::LogMessage( \ @@ -657,18 +694,19 @@ const LogSeverity LOG_DCHECK = LOG_INFO; // type of the desired pointer. #define DCHECK_EQ(val1, val2) DCHECK_OP(EQ, ==, val1, val2) #define DCHECK_NE(val1, val2) DCHECK_OP(NE, !=, val1, val2) #define DCHECK_LE(val1, val2) DCHECK_OP(LE, <=, val1, val2) #define DCHECK_LT(val1, val2) DCHECK_OP(LT, < , val1, val2) #define DCHECK_GE(val1, val2) DCHECK_OP(GE, >=, val1, val2) #define DCHECK_GT(val1, val2) DCHECK_OP(GT, > , val1, val2) +#define DCHECK_IMPLIES(val1, val2) DCHECK(!(val1) || (val2)) -#if defined(NDEBUG) && defined(OS_CHROMEOS) +#if !DCHECK_IS_ON && defined(OS_CHROMEOS) #define NOTREACHED() LOG(ERROR) << "NOTREACHED() hit in " << \ __FUNCTION__ << ". " #else #define NOTREACHED() DCHECK(false) #endif // Redefine the standard assert to use our nice log files #undef assert
--- a/security/sandbox/chromium/base/macros.h +++ b/security/sandbox/chromium/base/macros.h @@ -45,22 +45,16 @@ #define DISALLOW_IMPLICIT_CONSTRUCTORS(TypeName) \ TypeName(); \ DISALLOW_COPY_AND_ASSIGN(TypeName) // The arraysize(arr) macro returns the # of elements in an array arr. // The expression is a compile-time constant, and therefore can be // used in defining new arrays, for example. If you use arraysize on // a pointer by mistake, you will get a compile-time error. -// -// One caveat is that arraysize() doesn't accept any array of an -// anonymous type or a type defined inside a function. In these rare -// cases, you have to use the unsafe ARRAYSIZE_UNSAFE() macro below. This is -// due to a limitation in C++'s template system. The limitation might -// eventually be removed, but it hasn't happened yet. // This template function declaration is used in defining arraysize. // Note that the function doesn't need an implementation, as we only // use its type. template <typename T, size_t N> char (&ArraySizeHelper(T (&array)[N]))[N]; // That gcc wants both of these prototypes seems mysterious. VC, for @@ -68,57 +62,16 @@ char (&ArraySizeHelper(T (&array)[N]))[N // template overloads: the final frontier. #ifndef _MSC_VER template <typename T, size_t N> char (&ArraySizeHelper(const T (&array)[N]))[N]; #endif #define arraysize(array) (sizeof(ArraySizeHelper(array))) -// ARRAYSIZE_UNSAFE performs essentially the same calculation as arraysize, -// but can be used on anonymous types or types defined inside -// functions. It's less safe than arraysize as it accepts some -// (although not all) pointers. Therefore, you should use arraysize -// whenever possible. -// -// The expression ARRAYSIZE_UNSAFE(a) is a compile-time constant of type -// size_t. -// -// ARRAYSIZE_UNSAFE catches a few type errors. If you see a compiler error -// -// "warning: division by zero in ..." -// -// when using ARRAYSIZE_UNSAFE, you are (wrongfully) giving it a pointer. -// You should only use ARRAYSIZE_UNSAFE on statically allocated arrays. -// -// The following comments are on the implementation details, and can -// be ignored by the users. -// -// ARRAYSIZE_UNSAFE(arr) works by inspecting sizeof(arr) (the # of bytes in -// the array) and sizeof(*(arr)) (the # of bytes in one array -// element). If the former is divisible by the latter, perhaps arr is -// indeed an array, in which case the division result is the # of -// elements in the array. Otherwise, arr cannot possibly be an array, -// and we generate a compiler error to prevent the code from -// compiling. -// -// Since the size of bool is implementation-defined, we need to cast -// !(sizeof(a) & sizeof(*(a))) to size_t in order to ensure the final -// result has type size_t. -// -// This macro is not perfect as it wrongfully accepts certain -// pointers, namely where the pointer size is divisible by the pointee -// size. Since all our code has to go through a 32-bit compiler, -// where a pointer is 4 bytes, this means all pointers to a type whose -// size is 3 or greater than 4 will be (righteously) rejected. - -#define ARRAYSIZE_UNSAFE(a) \ - ((sizeof(a) / sizeof(*(a))) / \ - static_cast<size_t>(!(sizeof(a) % sizeof(*(a))))) - // Use implicit_cast as a safe version of static_cast or const_cast // for upcasting in the type hierarchy (i.e. casting a pointer to Foo // to a pointer to SuperclassOfFoo or casting a pointer to Foo to // a const pointer to Foo). // When you use implicit_cast, the compiler checks that the cast is safe. // Such explicit implicit_casts are necessary in surprisingly many // situations where C++ demands an exact type match instead of an @@ -136,86 +89,30 @@ template<typename To, typename From> inline To implicit_cast(From const &f) { return f; } // The COMPILE_ASSERT macro can be used to verify that a compile time // expression is true. For example, you could use it to verify the // size of a static array: // -// COMPILE_ASSERT(ARRAYSIZE_UNSAFE(content_type_names) == CONTENT_NUM_TYPES, +// COMPILE_ASSERT(arraysize(content_type_names) == CONTENT_NUM_TYPES, // content_type_names_incorrect_size); // // or to make sure a struct is smaller than a certain size: // // COMPILE_ASSERT(sizeof(foo) < 128, foo_too_large); // // The second argument to the macro is the name of the variable. If // the expression is false, most compilers will issue a warning/error // containing the name of the variable. #undef COMPILE_ASSERT - -#if __cplusplus >= 201103L - -// Under C++11, just use static_assert. #define COMPILE_ASSERT(expr, msg) static_assert(expr, #msg) -#else - -template <bool> -struct CompileAssert { -}; - -#define COMPILE_ASSERT(expr, msg) \ - typedef CompileAssert<(bool(expr))> msg[bool(expr) ? 1 : -1] ALLOW_UNUSED - -// Implementation details of COMPILE_ASSERT: -// -// - COMPILE_ASSERT works by defining an array type that has -1 -// elements (and thus is invalid) when the expression is false. -// -// - The simpler definition -// -// #define COMPILE_ASSERT(expr, msg) typedef char msg[(expr) ? 1 : -1] -// -// does not work, as gcc supports variable-length arrays whose sizes -// are determined at run-time (this is gcc's extension and not part -// of the C++ standard). As a result, gcc fails to reject the -// following code with the simple definition: -// -// int foo; -// COMPILE_ASSERT(foo, msg); // not supposed to compile as foo is -// // not a compile-time constant. -// -// - By using the type CompileAssert<(bool(expr))>, we ensures that -// expr is a compile-time constant. (Template arguments must be -// determined at compile-time.) -// -// - The outer parentheses in CompileAssert<(bool(expr))> are necessary -// to work around a bug in gcc 3.4.4 and 4.0.1. If we had written -// -// CompileAssert<bool(expr)> -// -// instead, these compilers will refuse to compile -// -// COMPILE_ASSERT(5 > 0, some_message); -// -// (They seem to think the ">" in "5 > 0" marks the end of the -// template argument list.) -// -// - The array size is (bool(expr) ? 1 : -1), instead of simply -// -// ((expr) ? 1 : -1). -// -// This is to avoid running into a bug in MS VC 7.1, which -// causes ((0.0) ? 1 : -1) to incorrectly evaluate to 1. - -#endif - // bit_cast<Dest,Source> is a template function that implements the // equivalent of "*reinterpret_cast<Dest*>(&source)". We need this in // very low-level functions like the protobuf library and fast math // support. // // float f = 3.14159265358979; // int i = bit_cast<int32>(f); // // i = 0x40490fdb
--- a/security/sandbox/chromium/base/memory/ref_counted.h +++ b/security/sandbox/chromium/base/memory/ref_counted.h @@ -1,24 +1,31 @@ // Copyright (c) 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #ifndef BASE_MEMORY_REF_COUNTED_H_ #define BASE_MEMORY_REF_COUNTED_H_ #include <cassert> +#include <iosfwd> #include "base/atomic_ref_count.h" #include "base/base_export.h" #include "base/compiler_specific.h" #ifndef NDEBUG #include "base/logging.h" #endif #include "base/threading/thread_collision_warner.h" +#include "build/build_config.h" +#include "mozilla/Attributes.h" + +#if defined(OS_LINUX) || defined(OS_MACOSX) || defined(OS_IOS) || defined(OS_ANDROID) +#define DISABLE_SCOPED_REFPTR_CONVERSION_OPERATOR +#endif namespace base { namespace subtle { class BASE_EXPORT RefCountedBase { public: bool HasOneRef() const { return ref_count_ == 1; } @@ -196,17 +203,17 @@ class RefCountedThreadSafe : public subt // A thread-safe wrapper for some piece of data so we can place other // things in scoped_refptrs<>. // template<typename T> class RefCountedData : public base::RefCountedThreadSafe< base::RefCountedData<T> > { public: RefCountedData() : data() {} - RefCountedData(const T& in_value) : data(in_value) {} + MOZ_IMPLICIT RefCountedData(const T& in_value) : data(in_value) {} T data; private: friend class base::RefCountedThreadSafe<base::RefCountedData<T> >; ~RefCountedData() {} }; @@ -263,56 +270,63 @@ class RefCountedData template <class T> class scoped_refptr { public: typedef T element_type; scoped_refptr() : ptr_(NULL) { } - scoped_refptr(T* p) : ptr_(p) { + MOZ_IMPLICIT scoped_refptr(T* p) : ptr_(p) { if (ptr_) - ptr_->AddRef(); + AddRef(ptr_); } scoped_refptr(const scoped_refptr<T>& r) : ptr_(r.ptr_) { if (ptr_) - ptr_->AddRef(); + AddRef(ptr_); } template <typename U> scoped_refptr(const scoped_refptr<U>& r) : ptr_(r.get()) { if (ptr_) - ptr_->AddRef(); + AddRef(ptr_); } ~scoped_refptr() { if (ptr_) - ptr_->Release(); + Release(ptr_); } T* get() const { return ptr_; } +#if !defined(DISABLE_SCOPED_REFPTR_CONVERSION_OPERATOR) // Allow scoped_refptr<C> to be used in boolean expression // and comparison operations. operator T*() const { return ptr_; } +#endif + + T& operator*() const { + assert(ptr_ != NULL); + return *ptr_; + } T* operator->() const { assert(ptr_ != NULL); return ptr_; } scoped_refptr<T>& operator=(T* p) { // AddRef first so that self assignment should work if (p) - p->AddRef(); + AddRef(p); T* old_ptr = ptr_; ptr_ = p; if (old_ptr) - old_ptr->Release(); + Release(old_ptr); return *this; } scoped_refptr<T>& operator=(const scoped_refptr<T>& r) { return *this = r.ptr_; } template <typename U> @@ -325,20 +339,83 @@ class scoped_refptr { ptr_ = *pp; *pp = p; } void swap(scoped_refptr<T>& r) { swap(&r.ptr_); } +#if defined(DISABLE_SCOPED_REFPTR_CONVERSION_OPERATOR) + template <typename U> + bool operator==(const scoped_refptr<U>& rhs) const { + return ptr_ == rhs.get(); + } + + template <typename U> + bool operator!=(const scoped_refptr<U>& rhs) const { + return !operator==(rhs); + } + + template <typename U> + bool operator<(const scoped_refptr<U>& rhs) const { + return ptr_ < rhs.get(); + } +#endif + protected: T* ptr_; + + private: + // Non-inline helpers to allow: + // class Opaque; + // extern template class scoped_refptr<Opaque>; + // Otherwise the compiler will complain that Opaque is an incomplete type. + static void AddRef(T* ptr); + static void Release(T* ptr); }; +template <typename T> +void scoped_refptr<T>::AddRef(T* ptr) { + ptr->AddRef(); +} + +template <typename T> +void scoped_refptr<T>::Release(T* ptr) { + ptr->Release(); +} + // Handy utility for creating a scoped_refptr<T> out of a T* explicitly without // having to retype all the template arguments template <typename T> scoped_refptr<T> make_scoped_refptr(T* t) { return scoped_refptr<T>(t); } +#if defined(DISABLE_SCOPED_REFPTR_CONVERSION_OPERATOR) +// Temporary operator overloads to facilitate the transition... +template <typename T, typename U> +bool operator==(const scoped_refptr<T>& lhs, const U* rhs) { + return lhs.get() == rhs; +} + +template <typename T, typename U> +bool operator==(const T* lhs, const scoped_refptr<U>& rhs) { + return lhs == rhs.get(); +} + +template <typename T, typename U> +bool operator!=(const scoped_refptr<T>& lhs, const U* rhs) { + return !operator==(lhs, rhs); +} + +template <typename T, typename U> +bool operator!=(const T* lhs, const scoped_refptr<U>& rhs) { + return !operator==(lhs, rhs); +} + +template <typename T> +std::ostream& operator<<(std::ostream& out, const scoped_refptr<T>& p) { + return out << p.get(); +} +#endif // defined(DISABLE_SCOPED_REFPTR_CONVERSION_OPERATOR) + #endif // BASE_MEMORY_REF_COUNTED_H_
--- a/security/sandbox/chromium/base/memory/scoped_ptr.h +++ b/security/sandbox/chromium/base/memory/scoped_ptr.h @@ -53,41 +53,31 @@ // return arg.Pass(); // } // // { // scoped_ptr<Foo> ptr(new Foo("yay")); // ptr manages Foo("yay"). // TakesOwnership(ptr.Pass()); // ptr no longer owns Foo("yay"). // scoped_ptr<Foo> ptr2 = CreateFoo(); // ptr2 owns the return Foo. // scoped_ptr<Foo> ptr3 = // ptr3 now owns what was in ptr2. -// PassThru(ptr2.Pass()); // ptr2 is correspondingly NULL. +// PassThru(ptr2.Pass()); // ptr2 is correspondingly nullptr. // } // // Notice that if you do not call Pass() when returning from PassThru(), or // when invoking TakesOwnership(), the code will not compile because scopers // are not copyable; they only implement move semantics which require calling // the Pass() function to signify a destructive transfer of state. CreateFoo() // is different though because we are constructing a temporary on the return // line and thus can avoid needing to call Pass(). // // Pass() properly handles upcast in initialization, i.e. you can use a // scoped_ptr<Child> to initialize a scoped_ptr<Parent>: // // scoped_ptr<Foo> foo(new Foo()); // scoped_ptr<FooParent> parent(foo.Pass()); -// -// PassAs<>() should be used to upcast return value in return statement: -// -// scoped_ptr<Foo> CreateFoo() { -// scoped_ptr<FooChild> result(new FooChild()); -// return result.PassAs<Foo>(); -// } -// -// Note that PassAs<>() is implemented only for scoped_ptr<T>, but not for -// scoped_ptr<T[]>. This is because casting array pointers may not be safe. #ifndef BASE_MEMORY_SCOPED_PTR_H_ #define BASE_MEMORY_SCOPED_PTR_H_ // This is an implementation designed to match the anticipated future TR2 // implementation of the scoped_ptr class. #include <assert.h> @@ -179,22 +169,33 @@ namespace internal { template <typename T> struct IsNotRefCounted { enum { value = !base::is_convertible<T*, base::subtle::RefCountedBase*>::value && !base::is_convertible<T*, base::subtle::RefCountedThreadSafeBase*>:: value }; }; +template <typename T> +struct ShouldAbortOnSelfReset { + template <typename U> + static NoType Test(const typename U::AllowSelfReset*); + + template <typename U> + static YesType Test(...); + + static const bool value = sizeof(Test<T>(0)) == sizeof(YesType); +}; + // Minimal implementation of the core logic of scoped_ptr, suitable for // reuse in both scoped_ptr and its specializations. template <class T, class D> class scoped_ptr_impl { public: - explicit scoped_ptr_impl(T* p) : data_(p) { } + explicit scoped_ptr_impl(T* p) : data_(p) {} // Initializer for deleters that have data parameters. scoped_ptr_impl(T* p, const D& d) : data_(p, d) {} // Templated constructor that destructively takes the value from another // scoped_ptr_impl. template <typename U, typename V> scoped_ptr_impl(scoped_ptr_impl<U, V>* other) @@ -209,45 +210,45 @@ class scoped_ptr_impl { void TakeState(scoped_ptr_impl<U, V>* other) { // See comment in templated constructor above regarding lack of support // for move-only deleters. reset(other->release()); get_deleter() = other->get_deleter(); } ~scoped_ptr_impl() { - if (data_.ptr != NULL) { + if (data_.ptr != nullptr) { // Not using get_deleter() saves one function call in non-optimized // builds. static_cast<D&>(data_)(data_.ptr); } } void reset(T* p) { - // This is a self-reset, which is no longer allowed: http://crbug.com/162971 - if (p != NULL && p == data_.ptr) - abort(); + // This is a self-reset, which is no longer allowed for default deleters: + // https://crbug.com/162971 + assert(!ShouldAbortOnSelfReset<D>::value || p == nullptr || p != data_.ptr); // Note that running data_.ptr = p can lead to undefined behavior if // get_deleter()(get()) deletes this. In order to prevent this, reset() // should update the stored pointer before deleting its old value. // // However, changing reset() to use that behavior may cause current code to // break in unexpected ways. If the destruction of the owned object // dereferences the scoped_ptr when it is destroyed by a call to reset(), // then it will incorrectly dispatch calls to |p| rather than the original // value of |data_.ptr|. // - // During the transition period, set the stored pointer to NULL while + // During the transition period, set the stored pointer to nullptr while // deleting the object. Eventually, this safety check will be removed to // prevent the scenario initially described from occuring and // http://crbug.com/176091 can be closed. T* old = data_.ptr; - data_.ptr = NULL; - if (old != NULL) + data_.ptr = nullptr; + if (old != nullptr) static_cast<D&>(data_)(old); data_.ptr = p; } T* get() const { return data_.ptr; } D& get_deleter() { return data_; } const D& get_deleter() const { return data_; } @@ -258,17 +259,17 @@ class scoped_ptr_impl { // any more-specific overloads can be used, if available. using std::swap; swap(static_cast<D&>(data_), static_cast<D&>(p2.data_)); swap(data_.ptr, p2.data_.ptr); } T* release() { T* old_ptr = data_.ptr; - data_.ptr = NULL; + data_.ptr = nullptr; return old_ptr; } private: // Needed to allow type-converting constructor. template <typename U, typename V> friend class scoped_ptr_impl; // Use the empty base class optimization to allow us to have a D @@ -288,97 +289,105 @@ class scoped_ptr_impl { } // namespace internal } // namespace base // A scoped_ptr<T> is like a T*, except that the destructor of scoped_ptr<T> // automatically deletes the pointer it holds (if any). // That is, scoped_ptr<T> owns the T object that it points to. -// Like a T*, a scoped_ptr<T> may hold either NULL or a pointer to a T object. -// Also like T*, scoped_ptr<T> is thread-compatible, and once you +// Like a T*, a scoped_ptr<T> may hold either nullptr or a pointer to a T +// object. Also like T*, scoped_ptr<T> is thread-compatible, and once you // dereference it, you get the thread safety guarantees of T. // // The size of scoped_ptr is small. On most compilers, when using the // DefaultDeleter, sizeof(scoped_ptr<T>) == sizeof(T*). Custom deleters will // increase the size proportional to whatever state they need to have. See // comments inside scoped_ptr_impl<> for details. // // Current implementation targets having a strict subset of C++11's // unique_ptr<> features. Known deficiencies include not supporting move-only // deleteres, function pointers as deleters, and deleters with reference // types. template <class T, class D = base::DefaultDeleter<T> > class scoped_ptr { - MOVE_ONLY_TYPE_FOR_CPP_03(scoped_ptr, RValue) + MOVE_ONLY_TYPE_WITH_MOVE_CONSTRUCTOR_FOR_CPP_03(scoped_ptr) COMPILE_ASSERT(base::internal::IsNotRefCounted<T>::value, T_is_refcounted_type_and_needs_scoped_refptr); public: // The element and deleter types. typedef T element_type; typedef D deleter_type; - // Constructor. Defaults to initializing with NULL. - scoped_ptr() : impl_(NULL) { } + // Constructor. Defaults to initializing with nullptr. + scoped_ptr() : impl_(nullptr) {} // Constructor. Takes ownership of p. - explicit scoped_ptr(element_type* p) : impl_(p) { } + explicit scoped_ptr(element_type* p) : impl_(p) {} // Constructor. Allows initialization of a stateful deleter. - scoped_ptr(element_type* p, const D& d) : impl_(p, d) { } + scoped_ptr(element_type* p, const D& d) : impl_(p, d) {} + + // Constructor. Allows construction from a nullptr. + scoped_ptr(decltype(nullptr)) : impl_(nullptr) {} // Constructor. Allows construction from a scoped_ptr rvalue for a // convertible type and deleter. // // IMPLEMENTATION NOTE: C++11 unique_ptr<> keeps this constructor distinct // from the normal move constructor. By C++11 20.7.1.2.1.21, this constructor // has different post-conditions if D is a reference type. Since this // implementation does not support deleters with reference type, // we do not need a separate move constructor allowing us to avoid one // use of SFINAE. You only need to care about this if you modify the // implementation of scoped_ptr. template <typename U, typename V> - scoped_ptr(scoped_ptr<U, V> other) : impl_(&other.impl_) { + scoped_ptr(scoped_ptr<U, V>&& other) + : impl_(&other.impl_) { COMPILE_ASSERT(!base::is_array<U>::value, U_cannot_be_an_array); } - // Constructor. Move constructor for C++03 move emulation of this type. - scoped_ptr(RValue rvalue) : impl_(&rvalue.object->impl_) { } - // operator=. Allows assignment from a scoped_ptr rvalue for a convertible // type and deleter. // // IMPLEMENTATION NOTE: C++11 unique_ptr<> keeps this operator= distinct from // the normal move assignment operator. By C++11 20.7.1.2.3.4, this templated // form has different requirements on for move-only Deleters. Since this // implementation does not support move-only Deleters, we do not need a // separate move assignment operator allowing us to avoid one use of SFINAE. // You only need to care about this if you modify the implementation of // scoped_ptr. template <typename U, typename V> - scoped_ptr& operator=(scoped_ptr<U, V> rhs) { + scoped_ptr& operator=(scoped_ptr<U, V>&& rhs) { COMPILE_ASSERT(!base::is_array<U>::value, U_cannot_be_an_array); impl_.TakeState(&rhs.impl_); return *this; } + // operator=. Allows assignment from a nullptr. Deletes the currently owned + // object, if any. + scoped_ptr& operator=(decltype(nullptr)) { + reset(); + return *this; + } + // Reset. Deletes the currently owned object, if any. // Then takes ownership of a new object, if given. - void reset(element_type* p = NULL) { impl_.reset(p); } + void reset(element_type* p = nullptr) { impl_.reset(p); } // Accessors to get the owned object. // operator* and operator-> will assert() if there is no current object. element_type& operator*() const { - assert(impl_.get() != NULL); + assert(impl_.get() != nullptr); return *impl_.get(); } element_type* operator->() const { - assert(impl_.get() != NULL); + assert(impl_.get() != nullptr); return impl_.get(); } element_type* get() const { return impl_.get(); } // Access to the deleter. deleter_type& get_deleter() { return impl_.get_deleter(); } const deleter_type& get_deleter() const { return impl_.get_deleter(); } @@ -389,49 +398,39 @@ class scoped_ptr { // are declared explicitly, as otherwise "scoped_ptr1 == // scoped_ptr2" will compile but do the wrong thing (i.e., convert // to Testable and then do the comparison). private: typedef base::internal::scoped_ptr_impl<element_type, deleter_type> scoped_ptr::*Testable; public: - operator Testable() const { return impl_.get() ? &scoped_ptr::impl_ : NULL; } + operator Testable() const { + return impl_.get() ? &scoped_ptr::impl_ : nullptr; + } // Comparison operators. // These return whether two scoped_ptr refer to the same object, not just to // two different but equal objects. bool operator==(const element_type* p) const { return impl_.get() == p; } bool operator!=(const element_type* p) const { return impl_.get() != p; } // Swap two scoped pointers. void swap(scoped_ptr& p2) { impl_.swap(p2.impl_); } // Release a pointer. - // The return value is the current pointer held by this object. - // If this object holds a NULL pointer, the return value is NULL. - // After this operation, this object will hold a NULL pointer, - // and will not own the object any more. + // The return value is the current pointer held by this object. If this object + // holds a nullptr, the return value is nullptr. After this operation, this + // object will hold a nullptr, and will not own the object any more. element_type* release() WARN_UNUSED_RESULT { return impl_.release(); } - // C++98 doesn't support functions templates with default parameters which - // makes it hard to write a PassAs() that understands converting the deleter - // while preserving simple calling semantics. - // - // Until there is a use case for PassAs() with custom deleters, just ignore - // the custom deleter. - template <typename PassAsType> - scoped_ptr<PassAsType> PassAs() { - return scoped_ptr<PassAsType>(Pass()); - } - private: // Needed to reach into |impl_| in the constructor. template <typename U, typename V> friend class scoped_ptr; base::internal::scoped_ptr_impl<element_type, deleter_type> impl_; // Forbidden for API compatibility with std::unique_ptr. explicit scoped_ptr(int disallow_construction_from_null); @@ -440,93 +439,101 @@ class scoped_ptr { // because you should never have the same object owned by two different // scoped_ptrs. template <class U> bool operator==(scoped_ptr<U> const& p2) const; template <class U> bool operator!=(scoped_ptr<U> const& p2) const; }; template <class T, class D> class scoped_ptr<T[], D> { - MOVE_ONLY_TYPE_FOR_CPP_03(scoped_ptr, RValue) + MOVE_ONLY_TYPE_WITH_MOVE_CONSTRUCTOR_FOR_CPP_03(scoped_ptr) public: // The element and deleter types. typedef T element_type; typedef D deleter_type; - // Constructor. Defaults to initializing with NULL. - scoped_ptr() : impl_(NULL) { } + // Constructor. Defaults to initializing with nullptr. + scoped_ptr() : impl_(nullptr) {} // Constructor. Stores the given array. Note that the argument's type // must exactly match T*. In particular: // - it cannot be a pointer to a type derived from T, because it is // inherently unsafe in the general case to access an array through a // pointer whose dynamic type does not match its static type (eg., if // T and the derived types had different sizes access would be // incorrectly calculated). Deletion is also always undefined // (C++98 [expr.delete]p3). If you're doing this, fix your code. - // - it cannot be NULL, because NULL is an integral expression, not a - // pointer to T. Use the no-argument version instead of explicitly - // passing NULL. // - it cannot be const-qualified differently from T per unique_ptr spec // (http://cplusplus.github.com/LWG/lwg-active.html#2118). Users wanting // to work around this may use implicit_cast<const T*>(). // However, because of the first bullet in this comment, users MUST // NOT use implicit_cast<Base*>() to upcast the static type of the array. - explicit scoped_ptr(element_type* array) : impl_(array) { } + explicit scoped_ptr(element_type* array) : impl_(array) {} + + // Constructor. Allows construction from a nullptr. + scoped_ptr(decltype(nullptr)) : impl_(nullptr) {} + + // Constructor. Allows construction from a scoped_ptr rvalue. + scoped_ptr(scoped_ptr&& other) : impl_(&other.impl_) {} - // Constructor. Move constructor for C++03 move emulation of this type. - scoped_ptr(RValue rvalue) : impl_(&rvalue.object->impl_) { } + // operator=. Allows assignment from a scoped_ptr rvalue. + scoped_ptr& operator=(scoped_ptr&& rhs) { + impl_.TakeState(&rhs.impl_); + return *this; + } - // operator=. Move operator= for C++03 move emulation of this type. - scoped_ptr& operator=(RValue rhs) { - impl_.TakeState(&rhs.object->impl_); + // operator=. Allows assignment from a nullptr. Deletes the currently owned + // array, if any. + scoped_ptr& operator=(decltype(nullptr)) { + reset(); return *this; } // Reset. Deletes the currently owned array, if any. // Then takes ownership of a new object, if given. - void reset(element_type* array = NULL) { impl_.reset(array); } + void reset(element_type* array = nullptr) { impl_.reset(array); } // Accessors to get the owned array. element_type& operator[](size_t i) const { - assert(impl_.get() != NULL); + assert(impl_.get() != nullptr); return impl_.get()[i]; } element_type* get() const { return impl_.get(); } // Access to the deleter. deleter_type& get_deleter() { return impl_.get_deleter(); } const deleter_type& get_deleter() const { return impl_.get_deleter(); } // Allow scoped_ptr<element_type> to be used in boolean expressions, but not // implicitly convertible to a real bool (which is dangerous). private: typedef base::internal::scoped_ptr_impl<element_type, deleter_type> scoped_ptr::*Testable; public: - operator Testable() const { return impl_.get() ? &scoped_ptr::impl_ : NULL; } + operator Testable() const { + return impl_.get() ? &scoped_ptr::impl_ : nullptr; + } // Comparison operators. // These return whether two scoped_ptr refer to the same object, not just to // two different but equal objects. bool operator==(element_type* array) const { return impl_.get() == array; } bool operator!=(element_type* array) const { return impl_.get() != array; } // Swap two scoped pointers. void swap(scoped_ptr& p2) { impl_.swap(p2.impl_); } // Release a pointer. - // The return value is the current pointer held by this object. - // If this object holds a NULL pointer, the return value is NULL. - // After this operation, this object will hold a NULL pointer, - // and will not own the object any more. + // The return value is the current pointer held by this object. If this object + // holds a nullptr, the return value is nullptr. After this operation, this + // object will hold a nullptr, and will not own the object any more. element_type* release() WARN_UNUSED_RESULT { return impl_.release(); } private: // Force element_type to be a complete type. enum { type_must_be_complete = sizeof(element_type) };
--- a/security/sandbox/chromium/base/memory/weak_ptr.h +++ b/security/sandbox/chromium/base/memory/weak_ptr.h @@ -43,27 +43,28 @@ // // With this implementation a caller may use SpawnWorker() to dispatch multiple // Workers and subsequently delete the Controller, without waiting for all // Workers to have completed. // ------------------------- IMPORTANT: Thread-safety ------------------------- // Weak pointers may be passed safely between threads, but must always be -// dereferenced and invalidated on the same thread otherwise checking the -// pointer would be racey. +// dereferenced and invalidated on the same SequencedTaskRunner otherwise +// checking the pointer would be racey. // // To ensure correct use, the first time a WeakPtr issued by a WeakPtrFactory // is dereferenced, the factory and its WeakPtrs become bound to the calling -// thread, and cannot be dereferenced or invalidated on any other thread. Bound -// WeakPtrs can still be handed off to other threads, e.g. to use to post tasks -// back to object on the bound thread. +// thread or current SequencedWorkerPool token, and cannot be dereferenced or +// invalidated on any other task runner. Bound WeakPtrs can still be handed +// off to other task runners, e.g. to use to post tasks back to object on the +// bound sequence. // -// Invalidating the factory's WeakPtrs un-binds it from the thread, allowing it -// to be passed for a different thread to use or delete it. +// Invalidating the factory's WeakPtrs un-binds it from the sequence, allowing +// it to be passed for a different sequence to use or delete it. #ifndef BASE_MEMORY_WEAK_PTR_H_ #define BASE_MEMORY_WEAK_PTR_H_ #include "base/basictypes.h" #include "base/base_export.h" #include "base/logging.h" #include "base/memory/ref_counted.h" @@ -76,18 +77,18 @@ template <typename T> class SupportsWeak template <typename T> class WeakPtr; namespace internal { // These classes are part of the WeakPtr implementation. // DO NOT USE THESE CLASSES DIRECTLY YOURSELF. class BASE_EXPORT WeakReference { public: - // Although Flag is bound to a specific thread, it may be deleted from another - // via base::WeakPtr::~WeakPtr(). + // Although Flag is bound to a specific SequencedTaskRunner, it may be + // deleted from another via base::WeakPtr::~WeakPtr(). class BASE_EXPORT Flag : public RefCountedThreadSafe<Flag> { public: Flag(); void Invalidate(); bool IsValid() const; private:
--- a/security/sandbox/chromium/base/move.h +++ b/security/sandbox/chromium/base/move.h @@ -1,12 +1,14 @@ // Copyright (c) 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include "base/compiler_specific.h" + #ifndef BASE_MOVE_H_ #define BASE_MOVE_H_ // Macro with the boilerplate that makes a type move-only in C++03. // // USAGE // // This macro should be used instead of DISALLOW_COPY_AND_ASSIGN to create @@ -206,13 +208,22 @@ struct rvalue_type { \ explicit rvalue_type(type* object) : object(object) {} \ type* object; \ }; \ type(type&); \ void operator=(type&); \ public: \ operator rvalue_type() { return rvalue_type(this); } \ - type Pass() { return type(rvalue_type(this)); } \ + type Pass() WARN_UNUSED_RESULT { return type(rvalue_type(this)); } \ + typedef void MoveOnlyTypeForCPP03; \ + private: + +#define MOVE_ONLY_TYPE_WITH_MOVE_CONSTRUCTOR_FOR_CPP_03(type) \ + private: \ + type(type&); \ + void operator=(type&); \ + public: \ + type&& Pass() WARN_UNUSED_RESULT { return static_cast<type&&>(*this); } \ typedef void MoveOnlyTypeForCPP03; \ private: #endif // BASE_MOVE_H_
new file mode 100644 --- /dev/null +++ b/security/sandbox/chromium/base/numerics/safe_conversions.h @@ -0,0 +1,64 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef BASE_SAFE_CONVERSIONS_H_ +#define BASE_SAFE_CONVERSIONS_H_ + +#include <limits> + +#include "base/logging.h" +#include "base/numerics/safe_conversions_impl.h" + +namespace base { + +// Convenience function that returns true if the supplied value is in range +// for the destination type. +template <typename Dst, typename Src> +inline bool IsValueInRangeForNumericType(Src value) { + return internal::DstRangeRelationToSrcRange<Dst>(value) == + internal::RANGE_VALID; +} + +// checked_cast<> is analogous to static_cast<> for numeric types, +// except that it CHECKs that the specified numeric conversion will not +// overflow or underflow. NaN source will always trigger a CHECK. +template <typename Dst, typename Src> +inline Dst checked_cast(Src value) { + CHECK(IsValueInRangeForNumericType<Dst>(value)); + return static_cast<Dst>(value); +} + +// saturated_cast<> is analogous to static_cast<> for numeric types, except +// that the specified numeric conversion will saturate rather than overflow or +// underflow. NaN assignment to an integral will trigger a CHECK condition. +template <typename Dst, typename Src> +inline Dst saturated_cast(Src value) { + // Optimization for floating point values, which already saturate. + if (std::numeric_limits<Dst>::is_iec559) + return static_cast<Dst>(value); + + switch (internal::DstRangeRelationToSrcRange<Dst>(value)) { + case internal::RANGE_VALID: + return static_cast<Dst>(value); + + case internal::RANGE_UNDERFLOW: + return std::numeric_limits<Dst>::min(); + + case internal::RANGE_OVERFLOW: + return std::numeric_limits<Dst>::max(); + + // Should fail only on attempting to assign NaN to a saturated integer. + case internal::RANGE_INVALID: + CHECK(false); + return std::numeric_limits<Dst>::max(); + } + + NOTREACHED(); + return static_cast<Dst>(value); +} + +} // namespace base + +#endif // BASE_SAFE_CONVERSIONS_H_ +
new file mode 100644 --- /dev/null +++ b/security/sandbox/chromium/base/numerics/safe_conversions_impl.h @@ -0,0 +1,216 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef BASE_SAFE_CONVERSIONS_IMPL_H_ +#define BASE_SAFE_CONVERSIONS_IMPL_H_ + +#include <limits> + +#include "base/template_util.h" + +namespace base { +namespace internal { + +// The std library doesn't provide a binary max_exponent for integers, however +// we can compute one by adding one to the number of non-sign bits. This allows +// for accurate range comparisons between floating point and integer types. +template <typename NumericType> +struct MaxExponent { + static const int value = std::numeric_limits<NumericType>::is_iec559 + ? std::numeric_limits<NumericType>::max_exponent + : (sizeof(NumericType) * 8 + 1 - + std::numeric_limits<NumericType>::is_signed); +}; + +enum IntegerRepresentation { + INTEGER_REPRESENTATION_UNSIGNED, + INTEGER_REPRESENTATION_SIGNED +}; + +// A range for a given nunmeric Src type is contained for a given numeric Dst +// type if both numeric_limits<Src>::max() <= numeric_limits<Dst>::max() and +// numeric_limits<Src>::min() >= numeric_limits<Dst>::min() are true. +// We implement this as template specializations rather than simple static +// comparisons to ensure type correctness in our comparisons. +enum NumericRangeRepresentation { + NUMERIC_RANGE_NOT_CONTAINED, + NUMERIC_RANGE_CONTAINED +}; + +// Helper templates to statically determine if our destination type can contain +// maximum and minimum values represented by the source type. + +template < + typename Dst, + typename Src, + IntegerRepresentation DstSign = std::numeric_limits<Dst>::is_signed + ? INTEGER_REPRESENTATION_SIGNED + : INTEGER_REPRESENTATION_UNSIGNED, + IntegerRepresentation SrcSign = + std::numeric_limits<Src>::is_signed + ? INTEGER_REPRESENTATION_SIGNED + : INTEGER_REPRESENTATION_UNSIGNED > +struct StaticDstRangeRelationToSrcRange; + +// Same sign: Dst is guaranteed to contain Src only if its range is equal or +// larger. +template <typename Dst, typename Src, IntegerRepresentation Sign> +struct StaticDstRangeRelationToSrcRange<Dst, Src, Sign, Sign> { + static const NumericRangeRepresentation value = + MaxExponent<Dst>::value >= MaxExponent<Src>::value + ? NUMERIC_RANGE_CONTAINED + : NUMERIC_RANGE_NOT_CONTAINED; +}; + +// Unsigned to signed: Dst is guaranteed to contain source only if its range is +// larger. +template <typename Dst, typename Src> +struct StaticDstRangeRelationToSrcRange<Dst, + Src, + INTEGER_REPRESENTATION_SIGNED, + INTEGER_REPRESENTATION_UNSIGNED> { + static const NumericRangeRepresentation value = + MaxExponent<Dst>::value > MaxExponent<Src>::value + ? NUMERIC_RANGE_CONTAINED + : NUMERIC_RANGE_NOT_CONTAINED; +}; + +// Signed to unsigned: Dst cannot be statically determined to contain Src. +template <typename Dst, typename Src> +struct StaticDstRangeRelationToSrcRange<Dst, + Src, + INTEGER_REPRESENTATION_UNSIGNED, + INTEGER_REPRESENTATION_SIGNED> { + static const NumericRangeRepresentation value = NUMERIC_RANGE_NOT_CONTAINED; +}; + +enum RangeConstraint { + RANGE_VALID = 0x0, // Value can be represented by the destination type. + RANGE_UNDERFLOW = 0x1, // Value would overflow. + RANGE_OVERFLOW = 0x2, // Value would underflow. + RANGE_INVALID = RANGE_UNDERFLOW | RANGE_OVERFLOW // Invalid (i.e. NaN). +}; + +// Helper function for coercing an int back to a RangeContraint. +inline RangeConstraint GetRangeConstraint(int integer_range_constraint) { + DCHECK(integer_range_constraint >= RANGE_VALID && + integer_range_constraint <= RANGE_INVALID); + return static_cast<RangeConstraint>(integer_range_constraint); +} + +// This function creates a RangeConstraint from an upper and lower bound +// check by taking advantage of the fact that only NaN can be out of range in +// both directions at once. +inline RangeConstraint GetRangeConstraint(bool is_in_upper_bound, + bool is_in_lower_bound) { + return GetRangeConstraint((is_in_upper_bound ? 0 : RANGE_OVERFLOW) | + (is_in_lower_bound ? 0 : RANGE_UNDERFLOW)); +} + +template < + typename Dst, + typename Src, + IntegerRepresentation DstSign = std::numeric_limits<Dst>::is_signed + ? INTEGER_REPRESENTATION_SIGNED + : INTEGER_REPRESENTATION_UNSIGNED, + IntegerRepresentation SrcSign = std::numeric_limits<Src>::is_signed + ? INTEGER_REPRESENTATION_SIGNED + : INTEGER_REPRESENTATION_UNSIGNED, + NumericRangeRepresentation DstRange = + StaticDstRangeRelationToSrcRange<Dst, Src>::value > +struct DstRangeRelationToSrcRangeImpl; + +// The following templates are for ranges that must be verified at runtime. We +// split it into checks based on signedness to avoid confusing casts and +// compiler warnings on signed an unsigned comparisons. + +// Dst range is statically determined to contain Src: Nothing to check. +template <typename Dst, + typename Src, + IntegerRepresentation DstSign, + IntegerRepresentation SrcSign> +struct DstRangeRelationToSrcRangeImpl<Dst, + Src, + DstSign, + SrcSign, + NUMERIC_RANGE_CONTAINED> { + static RangeConstraint Check(Src value) { return RANGE_VALID; } +}; + +// Signed to signed narrowing: Both the upper and lower boundaries may be +// exceeded. +template <typename Dst, typename Src> +struct DstRangeRelationToSrcRangeImpl<Dst, + Src, + INTEGER_REPRESENTATION_SIGNED, + INTEGER_REPRESENTATION_SIGNED, + NUMERIC_RANGE_NOT_CONTAINED> { + static RangeConstraint Check(Src value) { + return std::numeric_limits<Dst>::is_iec559 + ? GetRangeConstraint(value <= std::numeric_limits<Dst>::max(), + value >= -std::numeric_limits<Dst>::max()) + : GetRangeConstraint(value <= std::numeric_limits<Dst>::max(), + value >= std::numeric_limits<Dst>::min()); + } +}; + +// Unsigned to unsigned narrowing: Only the upper boundary can be exceeded. +template <typename Dst, typename Src> +struct DstRangeRelationToSrcRangeImpl<Dst, + Src, + INTEGER_REPRESENTATION_UNSIGNED, + INTEGER_REPRESENTATION_UNSIGNED, + NUMERIC_RANGE_NOT_CONTAINED> { + static RangeConstraint Check(Src value) { + return GetRangeConstraint(value <= std::numeric_limits<Dst>::max(), true); + } +}; + +// Unsigned to signed: The upper boundary may be exceeded. +template <typename Dst, typename Src> +struct DstRangeRelationToSrcRangeImpl<Dst, + Src, + INTEGER_REPRESENTATION_SIGNED, + INTEGER_REPRESENTATION_UNSIGNED, + NUMERIC_RANGE_NOT_CONTAINED> { + static RangeConstraint Check(Src value) { + return sizeof(Dst) > sizeof(Src) + ? RANGE_VALID + : GetRangeConstraint( + value <= static_cast<Src>(std::numeric_limits<Dst>::max()), + true); + } +}; + +// Signed to unsigned: The upper boundary may be exceeded for a narrower Dst, +// and any negative value exceeds the lower boundary. +template <typename Dst, typename Src> +struct DstRangeRelationToSrcRangeImpl<Dst, + Src, + INTEGER_REPRESENTATION_UNSIGNED, + INTEGER_REPRESENTATION_SIGNED, + NUMERIC_RANGE_NOT_CONTAINED> { + static RangeConstraint Check(Src value) { + return (MaxExponent<Dst>::value >= MaxExponent<Src>::value) + ? GetRangeConstraint(true, value >= static_cast<Src>(0)) + : GetRangeConstraint( + value <= static_cast<Src>(std::numeric_limits<Dst>::max()), + value >= static_cast<Src>(0)); + } +}; + +template <typename Dst, typename Src> +inline RangeConstraint DstRangeRelationToSrcRange(Src value) { + static_assert(std::numeric_limits<Src>::is_specialized, + "Argument must be numeric."); + static_assert(std::numeric_limits<Dst>::is_specialized, + "Result must be numeric."); + return DstRangeRelationToSrcRangeImpl<Dst, Src>::Check(value); +} + +} // namespace internal +} // namespace base + +#endif // BASE_SAFE_CONVERSIONS_IMPL_H_ +
new file mode 100644 --- /dev/null +++ b/security/sandbox/chromium/base/os_compat_android.h @@ -0,0 +1,28 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef BASE_OS_COMPAT_ANDROID_H_ +#define BASE_OS_COMPAT_ANDROID_H_ + +#include <fcntl.h> +#include <sys/types.h> +#include <utime.h> + +// Not implemented in Bionic. +extern "C" int futimes(int fd, const struct timeval tv[2]); + +// Not exposed or implemented in Bionic. +extern "C" char* mkdtemp(char* path); + +// Android has no timegm(). +extern "C" time_t timegm(struct tm* const t); + +// The lockf() function is not available on Android; we translate to flock(). +#define F_LOCK LOCK_EX +#define F_ULOCK LOCK_UN +inline int lockf(int fd, int cmd, off_t ignored_len) { + return flock(fd, cmd); +} + +#endif // BASE_OS_COMPAT_ANDROID_H_
--- a/security/sandbox/chromium/base/posix/eintr_wrapper.h +++ b/security/sandbox/chromium/base/posix/eintr_wrapper.h @@ -20,39 +20,39 @@ #if defined(OS_POSIX) #include <errno.h> #if defined(NDEBUG) #define HANDLE_EINTR(x) ({ \ - typeof(x) eintr_wrapper_result; \ + decltype(x) eintr_wrapper_result; \ do { \ eintr_wrapper_result = (x); \ } while (eintr_wrapper_result == -1 && errno == EINTR); \ eintr_wrapper_result; \ }) #else #define HANDLE_EINTR(x) ({ \ int eintr_wrapper_counter = 0; \ - typeof(x) eintr_wrapper_result; \ + decltype(x) eintr_wrapper_result; \ do { \ eintr_wrapper_result = (x); \ } while (eintr_wrapper_result == -1 && errno == EINTR && \ eintr_wrapper_counter++ < 100); \ eintr_wrapper_result; \ }) #endif // NDEBUG #define IGNORE_EINTR(x) ({ \ - typeof(x) eintr_wrapper_result; \ + decltype(x) eintr_wrapper_result; \ do { \ eintr_wrapper_result = (x); \ if (eintr_wrapper_result == -1 && errno == EINTR) { \ eintr_wrapper_result = 0; \ } \ } while (0); \ eintr_wrapper_result; \ })
new file mode 100644 --- /dev/null +++ b/security/sandbox/chromium/base/safe_strerror_posix.cc @@ -0,0 +1,119 @@ +// Copyright (c) 2006-2009 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#if defined(__ANDROID__) +// Post-L versions of bionic define the GNU-specific strerror_r if _GNU_SOURCE +// is defined, but the symbol is renamed to __gnu_strerror_r which only exists +// on those later versions. To preserve ABI compatibility with older versions, +// undefine _GNU_SOURCE and use the POSIX version. +#undef _GNU_SOURCE +#endif + +#include "build/build_config.h" +#include "base/safe_strerror_posix.h" + +#include <errno.h> +#include <stdio.h> +#include <string.h> + +#define USE_HISTORICAL_STRERRO_R (defined(__GLIBC__) || defined(OS_NACL)) + +#if USE_HISTORICAL_STRERRO_R && defined(__GNUC__) +// GCC will complain about the unused second wrap function unless we tell it +// that we meant for them to be potentially unused, which is exactly what this +// attribute is for. +#define POSSIBLY_UNUSED __attribute__((unused)) +#else +#define POSSIBLY_UNUSED +#endif + +#if USE_HISTORICAL_STRERRO_R +// glibc has two strerror_r functions: a historical GNU-specific one that +// returns type char *, and a POSIX.1-2001 compliant one available since 2.3.4 +// that returns int. This wraps the GNU-specific one. +static void POSSIBLY_UNUSED wrap_posix_strerror_r( + char *(*strerror_r_ptr)(int, char *, size_t), + int err, + char *buf, + size_t len) { + // GNU version. + char *rc = (*strerror_r_ptr)(err, buf, len); + if (rc != buf) { + // glibc did not use buf and returned a static string instead. Copy it + // into buf. + buf[0] = '\0'; + strncat(buf, rc, len - 1); + } + // The GNU version never fails. Unknown errors get an "unknown error" message. + // The result is always null terminated. +} +#endif // USE_HISTORICAL_STRERRO_R + +// Wrapper for strerror_r functions that implement the POSIX interface. POSIX +// does not define the behaviour for some of the edge cases, so we wrap it to +// guarantee that they are handled. This is compiled on all POSIX platforms, but +// it will only be used on Linux if the POSIX strerror_r implementation is +// being used (see below). +static void POSSIBLY_UNUSED wrap_posix_strerror_r( + int (*strerror_r_ptr)(int, char *, size_t), + int err, + char *buf, + size_t len) { + int old_errno = errno; + // Have to cast since otherwise we get an error if this is the GNU version + // (but in such a scenario this function is never called). Sadly we can't use + // C++-style casts because the appropriate one is reinterpret_cast but it's + // considered illegal to reinterpret_cast a type to itself, so we get an + // error in the opposite case. + int result = (*strerror_r_ptr)(err, buf, len); + if (result == 0) { + // POSIX is vague about whether the string will be terminated, although + // it indirectly implies that typically ERANGE will be returned, instead + // of truncating the string. We play it safe by always terminating the + // string explicitly. + buf[len - 1] = '\0'; + } else { + // Error. POSIX is vague about whether the return value is itself a system + // error code or something else. On Linux currently it is -1 and errno is + // set. On BSD-derived systems it is a system error and errno is unchanged. + // We try and detect which case it is so as to put as much useful info as + // we can into our message. + int strerror_error; // The error encountered in strerror + int new_errno = errno; + if (new_errno != old_errno) { + // errno was changed, so probably the return value is just -1 or something + // else that doesn't provide any info, and errno is the error. + strerror_error = new_errno; + } else { + // Either the error from strerror_r was the same as the previous value, or + // errno wasn't used. Assume the latter. + strerror_error = result; + } + // snprintf truncates and always null-terminates. + snprintf(buf, + len, + "Error %d while retrieving error %d", + strerror_error, + err); + } + errno = old_errno; +} + +void safe_strerror_r(int err, char *buf, size_t len) { + if (buf == NULL || len <= 0) { + return; + } + // If using glibc (i.e., Linux), the compiler will automatically select the + // appropriate overloaded function based on the function type of strerror_r. + // The other one will be elided from the translation unit since both are + // static. + wrap_posix_strerror_r(&strerror_r, err, buf, len); +} + +std::string safe_strerror(int err) { + const int buffer_size = 256; + char buf[buffer_size]; + safe_strerror_r(err, buf, sizeof(buf)); + return std::string(buf); +}
new file mode 100644 --- /dev/null +++ b/security/sandbox/chromium/base/safe_strerror_posix.h @@ -0,0 +1,38 @@ +// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef BASE_SAFE_STRERROR_POSIX_H_ +#define BASE_SAFE_STRERROR_POSIX_H_ + +#include <string> + +#include "base/base_export.h" + +// BEFORE using anything from this file, first look at PLOG and friends in +// logging.h and use them instead if applicable. +// +// This file declares safe, portable alternatives to the POSIX strerror() +// function. strerror() is inherently unsafe in multi-threaded apps and should +// never be used. Doing so can cause crashes. Additionally, the thread-safe +// alternative strerror_r varies in semantics across platforms. Use these +// functions instead. + +// Thread-safe strerror function with dependable semantics that never fails. +// It will write the string form of error "err" to buffer buf of length len. +// If there is an error calling the OS's strerror_r() function then a message to +// that effect will be printed into buf, truncating if necessary. The final +// result is always null-terminated. The value of errno is never changed. +// +// Use this instead of strerror_r(). +BASE_EXPORT void safe_strerror_r(int err, char *buf, size_t len); + +// Calls safe_strerror_r with a buffer of suitable size and returns the result +// in a C++ string. +// +// Use this instead of strerror(). Note though that safe_strerror_r will be +// more robust in the case of heap corruption errors, since it doesn't need to +// allocate a string. +BASE_EXPORT std::string safe_strerror(int err); + +#endif // BASE_SAFE_STRERROR_POSIX_H_
--- a/security/sandbox/chromium/base/sequenced_task_runner.h +++ b/security/sandbox/chromium/base/sequenced_task_runner.h @@ -134,17 +134,17 @@ class BASE_EXPORT SequencedTaskRunner : bool ReleaseSoon(const tracked_objects::Location& from_here, T* object) { return subtle::ReleaseHelperInternal<T, bool>::ReleaseViaSequencedTaskRunner( this, from_here, object); } protected: - virtual ~SequencedTaskRunner() {} + ~SequencedTaskRunner() override {} private: template <class T, class R> friend class subtle::DeleteHelperInternal; template <class T, class R> friend class subtle::ReleaseHelperInternal; bool DeleteSoonInternal(const tracked_objects::Location& from_here, void(*deleter)(const void*), const void* object);
--- a/security/sandbox/chromium/base/sequenced_task_runner_helpers.h +++ b/security/sandbox/chromium/base/sequenced_task_runner_helpers.h @@ -1,16 +1,17 @@ // Copyright (c) 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #ifndef BASE_SEQUENCED_TASK_RUNNER_HELPERS_H_ #define BASE_SEQUENCED_TASK_RUNNER_HELPERS_H_ #include "base/basictypes.h" +#include "base/debug/alias.h" // TODO(akalin): Investigate whether it's possible to just have // SequencedTaskRunner use these helpers (instead of MessageLoop). // Then we can just move these to sequenced_task_runner.h. namespace tracked_objects { class Location; }
--- a/security/sandbox/chromium/base/single_thread_task_runner.h +++ b/security/sandbox/chromium/base/single_thread_task_runner.h @@ -24,14 +24,14 @@ namespace base { class BASE_EXPORT SingleThreadTaskRunner : public SequencedTaskRunner { public: // A more explicit alias to RunsTasksOnCurrentThread(). bool BelongsToCurrentThread() const { return RunsTasksOnCurrentThread(); } protected: - virtual ~SingleThreadTaskRunner() {} + ~SingleThreadTaskRunner() override {} }; } // namespace base #endif // BASE_SINGLE_THREAD_TASK_RUNNER_H_
new file mode 100644 --- /dev/null +++ b/security/sandbox/chromium/base/strings/string16.cc @@ -0,0 +1,82 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "base/strings/string16.h" + +#if defined(WCHAR_T_IS_UTF16) + +#error This file should not be used on 2-byte wchar_t systems +// If this winds up being needed on 2-byte wchar_t systems, either the +// definitions below can be used, or the host system's wide character +// functions like wmemcmp can be wrapped. + +#elif defined(WCHAR_T_IS_UTF32) + +#include <ostream> + +#include "base/strings/utf_string_conversions.h" + +namespace base { + +int c16memcmp(const char16* s1, const char16* s2, size_t n) { + // We cannot call memcmp because that changes the semantics. + while (n-- > 0) { + if (*s1 != *s2) { + // We cannot use (*s1 - *s2) because char16 is unsigned. + return ((*s1 < *s2) ? -1 : 1); + } + ++s1; + ++s2; + } + return 0; +} + +size_t c16len(const char16* s) { + const char16 *s_orig = s; + while (*s) { + ++s; + } + return s - s_orig; +} + +const char16* c16memchr(const char16* s, char16 c, size_t n) { + while (n-- > 0) { + if (*s == c) { + return s; + } + ++s; + } + return 0; +} + +char16* c16memmove(char16* s1, const char16* s2, size_t n) { + return static_cast<char16*>(memmove(s1, s2, n * sizeof(char16))); +} + +char16* c16memcpy(char16* s1, const char16* s2, size_t n) { + return static_cast<char16*>(memcpy(s1, s2, n * sizeof(char16))); +} + +char16* c16memset(char16* s, char16 c, size_t n) { + char16 *s_orig = s; + while (n-- > 0) { + *s = c; + ++s; + } + return s_orig; +} + +std::ostream& operator<<(std::ostream& out, const string16& str) { + return out << UTF16ToUTF8(str); +} + +void PrintTo(const string16& str, std::ostream* out) { + *out << str; +} + +} // namespace base + +template class std::basic_string<base::char16, base::string16_char_traits>; + +#endif // WCHAR_T_IS_UTF32
--- a/security/sandbox/chromium/base/strings/string_number_conversions.cc +++ b/security/sandbox/chromium/base/strings/string_number_conversions.cc @@ -98,17 +98,17 @@ struct IntToStringT { template<typename CHAR, int BASE, bool BASE_LTE_10> class BaseCharToDigit { }; // Faster specialization for bases <= 10 template<typename CHAR, int BASE> class BaseCharToDigit<CHAR, BASE, true> { public: static bool Convert(CHAR c, uint8* digit) { if (c >= '0' && c < '0' + BASE) { - *digit = c - '0'; + *digit = static_cast<uint8>(c - '0'); return true; } return false; } }; // Specialization for bases where 10 < base <= 36 template<typename CHAR, int BASE> class BaseCharToDigit<CHAR, BASE, false> {
--- a/security/sandbox/chromium/base/strings/string_piece.h +++ b/security/sandbox/chromium/base/strings/string_piece.h @@ -32,16 +32,17 @@ #include <iosfwd> #include <string> #include "base/base_export.h" #include "base/basictypes.h" #include "base/containers/hash_tables.h" #include "base/strings/string16.h" +#include "mozilla/Attributes.h" namespace base { template <typename STRING_TYPE> class BasicStringPiece; typedef BasicStringPiece<std::string> StringPiece; typedef BasicStringPiece<string16> StringPiece16; // internal -------------------------------------------------------------------- @@ -173,20 +174,20 @@ template <typename STRING_TYPE> class Ba static const size_type npos; public: // We provide non-explicit singleton constructors so users can pass // in a "const char*" or a "string" wherever a "StringPiece" is // expected (likewise for char16, string16, StringPiece16). BasicStringPiece() : ptr_(NULL), length_(0) {} - BasicStringPiece(const value_type* str) + MOZ_IMPLICIT BasicStringPiece(const value_type* str) : ptr_(str), length_((str == NULL) ? 0 : STRING_TYPE::traits_type::length(str)) {} - BasicStringPiece(const STRING_TYPE& str) + MOZ_IMPLICIT BasicStringPiece(const STRING_TYPE& str) : ptr_(str.data()), length_(str.size()) {} BasicStringPiece(const value_type* offset, size_type len) : ptr_(offset), length_(len) {} BasicStringPiece(const typename STRING_TYPE::const_iterator& begin, const typename STRING_TYPE::const_iterator& end) : ptr_((end > begin) ? &(*begin) : NULL), length_((end > begin) ? (size_type)(end - begin) : 0) {} @@ -434,37 +435,25 @@ BASE_EXPORT std::ostream& operator<<(std #define HASH_STRING_PIECE(StringPieceType, string_piece) \ std::size_t result = 0; \ for (StringPieceType::const_iterator i = string_piece.begin(); \ i != string_piece.end(); ++i) \ result = (result * 131) + *i; \ return result; \ namespace BASE_HASH_NAMESPACE { -#if defined(COMPILER_GCC) template<> struct hash<base::StringPiece> { std::size_t operator()(const base::StringPiece& sp) const { HASH_STRING_PIECE(base::StringPiece, sp); } }; template<> struct hash<base::StringPiece16> { std::size_t operator()(const base::StringPiece16& sp16) const { HASH_STRING_PIECE(base::StringPiece16, sp16); } }; -#elif defined(COMPILER_MSVC) - -inline size_t hash_value(const base::StringPiece& sp) { - HASH_STRING_PIECE(base::StringPiece, sp); -} -inline size_t hash_value(const base::StringPiece16& sp16) { - HASH_STRING_PIECE(base::StringPiece16, sp16); -} - -#endif // COMPILER - } // namespace BASE_HASH_NAMESPACE #endif // BASE_STRINGS_STRING_PIECE_H_
--- a/security/sandbox/chromium/base/strings/string_util.cc +++ b/security/sandbox/chromium/base/strings/string_util.cc @@ -59,16 +59,52 @@ struct ReplacementOffset { size_t offset; }; static bool CompareParameter(const ReplacementOffset& elem1, const ReplacementOffset& elem2) { return elem1.parameter < elem2.parameter; } +// Assuming that a pointer is the size of a "machine word", then +// uintptr_t is an integer type that is also a machine word. +typedef uintptr_t MachineWord; +const uintptr_t kMachineWordAlignmentMask = sizeof(MachineWord) - 1; + +inline bool IsAlignedToMachineWord(const void* pointer) { + return !(reinterpret_cast<MachineWord>(pointer) & kMachineWordAlignmentMask); +} + +template<typename T> inline T* AlignToMachineWord(T* pointer) { + return reinterpret_cast<T*>(reinterpret_cast<MachineWord>(pointer) & + ~kMachineWordAlignmentMask); +} + +template<size_t size, typename CharacterType> struct NonASCIIMask; +template<> struct NonASCIIMask<4, base::char16> { + static inline uint32_t value() { return 0xFF80FF80U; } +}; +template<> struct NonASCIIMask<4, char> { + static inline uint32_t value() { return 0x80808080U; } +}; +template<> struct NonASCIIMask<8, base::char16> { + static inline uint64_t value() { return 0xFF80FF80FF80FF80ULL; } +}; +template<> struct NonASCIIMask<8, char> { + static inline uint64_t value() { return 0x8080808080808080ULL; } +}; +#if defined(WCHAR_T_IS_UTF32) +template<> struct NonASCIIMask<4, wchar_t> { + static inline uint32_t value() { return 0xFFFFFF80U; } +}; +template<> struct NonASCIIMask<8, wchar_t> { + static inline uint64_t value() { return 0xFFFFFF80FFFFFF80ULL; } +}; +#endif // WCHAR_T_IS_UTF32 + } // namespace namespace base { bool IsWprintfFormatPortable(const wchar_t* format) { for (const wchar_t* position = format; *position != '\0'; ++position) { if (*position == '%') { bool in_specification = true; @@ -317,34 +353,64 @@ bool ContainsOnlyChars(const StringPiece return input.find_first_not_of(characters) == StringPiece::npos; } bool ContainsOnlyChars(const StringPiece16& input, const StringPiece16& characters) { return input.find_first_not_of(characters) == StringPiece16::npos; } -template<class STR> -static bool DoIsStringASCII(const STR& str) { - for (size_t i = 0; i < str.length(); i++) { - typename ToUnsigned<typename STR::value_type>::Unsigned c = str[i]; - if (c > 0x7F) - return false; +template <class Char> +inline bool DoIsStringASCII(const Char* characters, size_t length) { + MachineWord all_char_bits = 0; + const Char* end = characters + length; + + // Prologue: align the input. + while (!IsAlignedToMachineWord(characters) && characters != end) { + all_char_bits |= *characters; + ++characters; } - return true; + + // Compare the values of CPU word size. + const Char* word_end = AlignToMachineWord(end); + const size_t loop_increment = sizeof(MachineWord) / sizeof(Char); + while (characters < word_end) { + all_char_bits |= *(reinterpret_cast<const MachineWord*>(characters)); + characters += loop_increment; + } + + // Process the remaining bytes. + while (characters != end) { + all_char_bits |= *characters; + ++characters; + } + + MachineWord non_ascii_bit_mask = + NonASCIIMask<sizeof(MachineWord), Char>::value(); + return !(all_char_bits & non_ascii_bit_mask); } bool IsStringASCII(const StringPiece& str) { - return DoIsStringASCII(str); + return DoIsStringASCII(str.data(), str.length()); +} + +bool IsStringASCII(const StringPiece16& str) { + return DoIsStringASCII(str.data(), str.length()); } bool IsStringASCII(const string16& str) { - return DoIsStringASCII(str); + return DoIsStringASCII(str.data(), str.length()); } +#if defined(WCHAR_T_IS_UTF32) +bool IsStringASCII(const std::wstring& str) { + return DoIsStringASCII(str.data(), str.length()); +} +#endif + bool IsStringUTF8(const std::string& str) { const char *src = str.data(); int32 src_len = static_cast<int32>(str.length()); int32 char_index = 0; while (char_index < src_len) { int32 code_point; CBU8_NEXT(src, char_index, src_len, code_point);
--- a/security/sandbox/chromium/base/strings/string_util.h +++ b/security/sandbox/chromium/base/strings/string_util.h @@ -240,46 +240,55 @@ BASE_EXPORT bool ContainsOnlyChars(const // representation looks like a UTF-8 string (the second case). // // Note that IsStringUTF8 checks not only if the input is structurally // valid but also if it doesn't contain any non-character codepoint // (e.g. U+FFFE). It's done on purpose because all the existing callers want // to have the maximum 'discriminating' power from other encodings. If // there's a use case for just checking the structural validity, we have to // add a new function for that. +// +// IsStringASCII assumes the input is likely all ASCII, and does not leave early +// if it is not the case. BASE_EXPORT bool IsStringUTF8(const std::string& str); BASE_EXPORT bool IsStringASCII(const StringPiece& str); +BASE_EXPORT bool IsStringASCII(const StringPiece16& str); +// A convenience adaptor for WebStrings, as they don't convert into +// StringPieces directly. BASE_EXPORT bool IsStringASCII(const string16& str); +#if defined(WCHAR_T_IS_UTF32) +BASE_EXPORT bool IsStringASCII(const std::wstring& str); +#endif + +// Converts the elements of the given string. This version uses a pointer to +// clearly differentiate it from the non-pointer variant. +template <class str> inline void StringToLowerASCII(str* s) { + for (typename str::iterator i = s->begin(); i != s->end(); ++i) + *i = ToLowerASCII(*i); +} + +template <class str> inline str StringToLowerASCII(const str& s) { + // for std::string and std::wstring + str output(s); + StringToLowerASCII(&output); + return output; +} } // namespace base #if defined(OS_WIN) #include "base/strings/string_util_win.h" #elif defined(OS_POSIX) #include "base/strings/string_util_posix.h" #else #error Define string operations appropriately for your platform #endif // Converts the elements of the given string. This version uses a pointer to // clearly differentiate it from the non-pointer variant. -template <class str> inline void StringToLowerASCII(str* s) { - for (typename str::iterator i = s->begin(); i != s->end(); ++i) - *i = base::ToLowerASCII(*i); -} - -template <class str> inline str StringToLowerASCII(const str& s) { - // for std::string and std::wstring - str output(s); - StringToLowerASCII(&output); - return output; -} - -// Converts the elements of the given string. This version uses a pointer to -// clearly differentiate it from the non-pointer variant. template <class str> inline void StringToUpperASCII(str* s) { for (typename str::iterator i = s->begin(); i != s->end(); ++i) *i = base::ToUpperASCII(*i); } template <class str> inline str StringToUpperASCII(const str& s) { // for std::string and std::wstring str output(s); @@ -347,24 +356,24 @@ inline bool IsAsciiDigit(Char c) { template <typename Char> inline bool IsHexDigit(Char c) { return (c >= '0' && c <= '9') || (c >= 'A' && c <= 'F') || (c >= 'a' && c <= 'f'); } template <typename Char> -inline Char HexDigitToInt(Char c) { +inline char HexDigitToInt(Char c) { DCHECK(IsHexDigit(c)); if (c >= '0' && c <= '9') - return c - '0'; + return static_cast<char>(c - '0'); if (c >= 'A' && c <= 'F') - return c - 'A' + 10; + return static_cast<char>(c - 'A' + 10); if (c >= 'a' && c <= 'f') - return c - 'a' + 10; + return static_cast<char>(c - 'a' + 10); return 0; } // Returns true if it's a whitespace character. inline bool IsWhitespace(wchar_t c) { return wcschr(base::kWhitespaceWide, c) != NULL; }
new file mode 100644 --- /dev/null +++ b/security/sandbox/chromium/base/strings/string_util_posix.h @@ -0,0 +1,52 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef BASE_STRINGS_STRING_UTIL_POSIX_H_ +#define BASE_STRINGS_STRING_UTIL_POSIX_H_ + +#include <stdarg.h> +#include <stdio.h> +#include <string.h> +#include <wchar.h> + +#include "base/logging.h" + +namespace base { + +// Chromium code style is to not use malloc'd strings; this is only for use +// for interaction with APIs that require it. +inline char* strdup(const char* str) { + return ::strdup(str); +} + +inline int strcasecmp(const char* string1, const char* string2) { + return ::strcasecmp(string1, string2); +} + +inline int strncasecmp(const char* string1, const char* string2, size_t count) { + return ::strncasecmp(string1, string2, count); +} + +inline int vsnprintf(char* buffer, size_t size, + const char* format, va_list arguments) { + return ::vsnprintf(buffer, size, format, arguments); +} + +inline int strncmp16(const char16* s1, const char16* s2, size_t count) { +#if defined(WCHAR_T_IS_UTF16) + return ::wcsncmp(s1, s2, count); +#elif defined(WCHAR_T_IS_UTF32) + return c16memcmp(s1, s2, count); +#endif +} + +inline int vswprintf(wchar_t* buffer, size_t size, + const wchar_t* format, va_list arguments) { + DCHECK(IsWprintfFormatPortable(format)); + return ::vswprintf(buffer, size, format, arguments); +} + +} // namespace base + +#endif // BASE_STRINGS_STRING_UTIL_POSIX_H_
--- a/security/sandbox/chromium/base/strings/stringprintf.h +++ b/security/sandbox/chromium/base/strings/stringprintf.h @@ -11,26 +11,26 @@ #include "base/base_export.h" #include "base/compiler_specific.h" namespace base { // Return a C++ string given printf-like input. BASE_EXPORT std::string StringPrintf(const char* format, ...) - PRINTF_FORMAT(1, 2); + PRINTF_FORMAT(1, 2) WARN_UNUSED_RESULT; // OS_ANDROID's libc does not support wchar_t, so several overloads are omitted. #if !defined(OS_ANDROID) BASE_EXPORT std::wstring StringPrintf(const wchar_t* format, ...) - WPRINTF_FORMAT(1, 2); + WPRINTF_FORMAT(1, 2) WARN_UNUSED_RESULT; #endif // Return a C++ string given vprintf-like input. BASE_EXPORT std::string StringPrintV(const char* format, va_list ap) - PRINTF_FORMAT(1, 0); + PRINTF_FORMAT(1, 0) WARN_UNUSED_RESULT; // Store result into a supplied string and return it. BASE_EXPORT const std::string& SStringPrintf(std::string* dst, const char* format, ...) PRINTF_FORMAT(2, 3); #if !defined(OS_ANDROID) BASE_EXPORT const std::wstring& SStringPrintf(std::wstring* dst, const wchar_t* format, ...)
--- a/security/sandbox/chromium/base/strings/utf_string_conversion_utils.cc +++ b/security/sandbox/chromium/base/strings/utf_string_conversion_utils.cc @@ -66,17 +66,17 @@ bool ReadUnicodeCharacter(const wchar_t* } #endif // defined(WCHAR_T_IS_UTF32) // WriteUnicodeCharacter ------------------------------------------------------- size_t WriteUnicodeCharacter(uint32 code_point, std::string* output) { if (code_point <= 0x7f) { // Fast path the common case of one byte. - output->push_back(code_point); + output->push_back(static_cast<char>(code_point)); return 1; } // CBU8_APPEND_UNSAFE can append up to 4 bytes. size_t char_offset = output->length(); size_t original_char_offset = char_offset; output->resize(char_offset + CBU8_MAX_LENGTH);
--- a/security/sandbox/chromium/base/strings/utf_string_conversions.cc +++ b/security/sandbox/chromium/base/strings/utf_string_conversions.cc @@ -38,36 +38,54 @@ bool ConvertUnicode(const SRC_CHAR* src, return success; } } // namespace // UTF-8 <-> Wide -------------------------------------------------------------- bool WideToUTF8(const wchar_t* src, size_t src_len, std::string* output) { - PrepareForUTF8Output(src, src_len, output); - return ConvertUnicode(src, src_len, output); + if (IsStringASCII(std::wstring(src, src_len))) { + output->assign(src, src + src_len); + return true; + } else { + PrepareForUTF8Output(src, src_len, output); + return ConvertUnicode(src, src_len, output); + } } std::string WideToUTF8(const std::wstring& wide) { + if (IsStringASCII(wide)) { + return std::string(wide.data(), wide.data() + wide.length()); + } + std::string ret; - // Ignore the success flag of this call, it will do the best it can for - // invalid input, which is what we want here. - WideToUTF8(wide.data(), wide.length(), &ret); + PrepareForUTF8Output(wide.data(), wide.length(), &ret); + ConvertUnicode(wide.data(), wide.length(), &ret); return ret; } bool UTF8ToWide(const char* src, size_t src_len, std::wstring* output) { - PrepareForUTF16Or32Output(src, src_len, output); - return ConvertUnicode(src, src_len, output); + if (IsStringASCII(StringPiece(src, src_len))) { + output->assign(src, src + src_len); + return true; + } else { + PrepareForUTF16Or32Output(src, src_len, output); + return ConvertUnicode(src, src_len, output); + } } std::wstring UTF8ToWide(const StringPiece& utf8) { + if (IsStringASCII(utf8)) { + return std::wstring(utf8.begin(), utf8.end()); + } + std::wstring ret; - UTF8ToWide(utf8.data(), utf8.length(), &ret); + PrepareForUTF16Or32Output(utf8.data(), utf8.length(), &ret); + ConvertUnicode(utf8.data(), utf8.length(), &ret); return ret; } // UTF-16 <-> Wide ------------------------------------------------------------- #if defined(WCHAR_T_IS_UTF16) // When wide == UTF-16, then conversions are a NOP. @@ -121,34 +139,53 @@ std::wstring UTF16ToWide(const string16& #endif // defined(WCHAR_T_IS_UTF32) // UTF16 <-> UTF8 -------------------------------------------------------------- #if defined(WCHAR_T_IS_UTF32) bool UTF8ToUTF16(const char* src, size_t src_len, string16* output) { - PrepareForUTF16Or32Output(src, src_len, output); - return ConvertUnicode(src, src_len, output); + if (IsStringASCII(StringPiece(src, src_len))) { + output->assign(src, src + src_len); + return true; + } else { + PrepareForUTF16Or32Output(src, src_len, output); + return ConvertUnicode(src, src_len, output); + } } string16 UTF8ToUTF16(const StringPiece& utf8) { + if (IsStringASCII(utf8)) { + return string16(utf8.begin(), utf8.end()); + } + string16 ret; + PrepareForUTF16Or32Output(utf8.data(), utf8.length(), &ret); // Ignore the success flag of this call, it will do the best it can for // invalid input, which is what we want here. - UTF8ToUTF16(utf8.data(), utf8.length(), &ret); + ConvertUnicode(utf8.data(), utf8.length(), &ret); return ret; } bool UTF16ToUTF8(const char16* src, size_t src_len, std::string* output) { - PrepareForUTF8Output(src, src_len, output); - return ConvertUnicode(src, src_len, output); + if (IsStringASCII(StringPiece16(src, src_len))) { + output->assign(src, src + src_len); + return true; + } else { + PrepareForUTF8Output(src, src_len, output); + return ConvertUnicode(src, src_len, output); + } } std::string UTF16ToUTF8(const string16& utf16) { + if (IsStringASCII(utf16)) { + return std::string(utf16.begin(), utf16.end()); + } + std::string ret; // Ignore the success flag of this call, it will do the best it can for // invalid input, which is what we want here. UTF16ToUTF8(utf16.data(), utf16.length(), &ret); return ret; } #elif defined(WCHAR_T_IS_UTF16)
new file mode 100644 --- /dev/null +++ b/security/sandbox/chromium/base/synchronization/condition_variable.h @@ -0,0 +1,118 @@ +// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// ConditionVariable wraps pthreads condition variable synchronization or, on +// Windows, simulates it. This functionality is very helpful for having +// several threads wait for an event, as is common with a thread pool managed +// by a master. The meaning of such an event in the (worker) thread pool +// scenario is that additional tasks are now available for processing. It is +// used in Chrome in the DNS prefetching system to notify worker threads that +// a queue now has items (tasks) which need to be tended to. A related use +// would have a pool manager waiting on a ConditionVariable, waiting for a +// thread in the pool to announce (signal) that there is now more room in a +// (bounded size) communications queue for the manager to deposit tasks, or, +// as a second example, that the queue of tasks is completely empty and all +// workers are waiting. +// +// USAGE NOTE 1: spurious signal events are possible with this and +// most implementations of condition variables. As a result, be +// *sure* to retest your condition before proceeding. The following +// is a good example of doing this correctly: +// +// while (!work_to_be_done()) Wait(...); +// +// In contrast do NOT do the following: +// +// if (!work_to_be_done()) Wait(...); // Don't do this. +// +// Especially avoid the above if you are relying on some other thread only +// issuing a signal up *if* there is work-to-do. There can/will +// be spurious signals. Recheck state on waiting thread before +// assuming the signal was intentional. Caveat caller ;-). +// +// USAGE NOTE 2: Broadcast() frees up all waiting threads at once, +// which leads to contention for the locks they all held when they +// called Wait(). This results in POOR performance. A much better +// approach to getting a lot of threads out of Wait() is to have each +// thread (upon exiting Wait()) call Signal() to free up another +// Wait'ing thread. Look at condition_variable_unittest.cc for +// both examples. +// +// Broadcast() can be used nicely during teardown, as it gets the job +// done, and leaves no sleeping threads... and performance is less +// critical at that point. +// +// The semantics of Broadcast() are carefully crafted so that *all* +// threads that were waiting when the request was made will indeed +// get signaled. Some implementations mess up, and don't signal them +// all, while others allow the wait to be effectively turned off (for +// a while while waiting threads come around). This implementation +// appears correct, as it will not "lose" any signals, and will guarantee +// that all threads get signaled by Broadcast(). +// +// This implementation offers support for "performance" in its selection of +// which thread to revive. Performance, in direct contrast with "fairness," +// assures that the thread that most recently began to Wait() is selected by +// Signal to revive. Fairness would (if publicly supported) assure that the +// thread that has Wait()ed the longest is selected. The default policy +// may improve performance, as the selected thread may have a greater chance of +// having some of its stack data in various CPU caches. +// +// For a discussion of the many very subtle implementation details, see the FAQ +// at the end of condition_variable_win.cc. + +#ifndef BASE_SYNCHRONIZATION_CONDITION_VARIABLE_H_ +#define BASE_SYNCHRONIZATION_CONDITION_VARIABLE_H_ + +#include "build/build_config.h" + +#if defined(OS_POSIX) +#include <pthread.h> +#endif + +#include "base/base_export.h" +#include "base/basictypes.h" +#include "base/synchronization/lock.h" + +namespace base { + +class ConditionVarImpl; +class TimeDelta; + +class BASE_EXPORT ConditionVariable { + public: + // Construct a cv for use with ONLY one user lock. + explicit ConditionVariable(Lock* user_lock); + + ~ConditionVariable(); + + // Wait() releases the caller's critical section atomically as it starts to + // sleep, and the reacquires it when it is signaled. + void Wait(); + void TimedWait(const TimeDelta& max_time); + + // Broadcast() revives all waiting threads. + void Broadcast(); + // Signal() revives one waiting thread. + void Signal(); + + private: + +#if defined(OS_WIN) + ConditionVarImpl* impl_; +#elif defined(OS_POSIX) + pthread_cond_t condition_; + pthread_mutex_t* user_mutex_; +#if !defined(NDEBUG) || defined(DCHECK_ALWAYS_ON) + base::Lock* user_lock_; // Needed to adjust shadow lock state on wait. +#endif + +#endif + + DISALLOW_COPY_AND_ASSIGN(ConditionVariable); +}; + +} // namespace base + +#endif // BASE_SYNCHRONIZATION_CONDITION_VARIABLE_H_
new file mode 100644 --- /dev/null +++ b/security/sandbox/chromium/base/synchronization/condition_variable_posix.cc @@ -0,0 +1,122 @@ +// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "base/synchronization/condition_variable.h" + +#include <errno.h> +#include <sys/time.h> + +#include "base/logging.h" +#include "base/synchronization/lock.h" +#include "base/threading/thread_restrictions.h" +#include "base/time/time.h" + +namespace base { + +ConditionVariable::ConditionVariable(Lock* user_lock) + : user_mutex_(user_lock->lock_.native_handle()) +#if !defined(NDEBUG) || defined(DCHECK_ALWAYS_ON) + , user_lock_(user_lock) +#endif +{ + int rv = 0; + // http://crbug.com/293736 + // NaCl doesn't support monotonic clock based absolute deadlines. + // On older Android platform versions, it's supported through the + // non-standard pthread_cond_timedwait_monotonic_np. Newer platform + // versions have pthread_condattr_setclock. + // Mac can use relative time deadlines. +#if !defined(OS_MACOSX) && !defined(OS_NACL) && \ + !(defined(OS_ANDROID) && defined(HAVE_PTHREAD_COND_TIMEDWAIT_MONOTONIC)) + pthread_condattr_t attrs; + rv = pthread_condattr_init(&attrs); + DCHECK_EQ(0, rv); + pthread_condattr_setclock(&attrs, CLOCK_MONOTONIC); + rv = pthread_cond_init(&condition_, &attrs); + pthread_condattr_destroy(&attrs); +#else + rv = pthread_cond_init(&condition_, NULL); +#endif + DCHECK_EQ(0, rv); +} + +ConditionVariable::~ConditionVariable() { + int rv = pthread_cond_destroy(&condition_); + DCHECK_EQ(0, rv); +} + +void ConditionVariable::Wait() { + base::ThreadRestrictions::AssertWaitAllowed(); +#if !defined(NDEBUG) || defined(DCHECK_ALWAYS_ON) + user_lock_->CheckHeldAndUnmark(); +#endif + int rv = pthread_cond_wait(&condition_, user_mutex_); + DCHECK_EQ(0, rv); +#if !defined(NDEBUG) || defined(DCHECK_ALWAYS_ON) + user_lock_->CheckUnheldAndMark(); +#endif +} + +void ConditionVariable::TimedWait(const TimeDelta& max_time) { + base::ThreadRestrictions::AssertWaitAllowed(); + int64 usecs = max_time.InMicroseconds(); + struct timespec relative_time; + relative_time.tv_sec = usecs / Time::kMicrosecondsPerSecond; + relative_time.tv_nsec = + (usecs % Time::kMicrosecondsPerSecond) * Time::kNanosecondsPerMicrosecond; + +#if !defined(NDEBUG) || defined(DCHECK_ALWAYS_ON) + user_lock_->CheckHeldAndUnmark(); +#endif + +#if defined(OS_MACOSX) + int rv = pthread_cond_timedwait_relative_np( + &condition_, user_mutex_, &relative_time); +#else + // The timeout argument to pthread_cond_timedwait is in absolute time. + struct timespec absolute_time; +#if defined(OS_NACL) + // See comment in constructor for why this is different in NaCl. + struct timeval now; + gettimeofday(&now, NULL); + absolute_time.tv_sec = now.tv_sec; + absolute_time.tv_nsec = now.tv_usec * Time::kNanosecondsPerMicrosecond; +#else + struct timespec now; + clock_gettime(CLOCK_MONOTONIC, &now); + absolute_time.tv_sec = now.tv_sec; + absolute_time.tv_nsec = now.tv_nsec; +#endif + + absolute_time.tv_sec += relative_time.tv_sec; + absolute_time.tv_nsec += relative_time.tv_nsec; + absolute_time.tv_sec += absolute_time.tv_nsec / Time::kNanosecondsPerSecond; + absolute_time.tv_nsec %= Time::kNanosecondsPerSecond; + DCHECK_GE(absolute_time.tv_sec, now.tv_sec); // Overflow paranoia + +#if defined(OS_ANDROID) && defined(HAVE_PTHREAD_COND_TIMEDWAIT_MONOTONIC) + int rv = pthread_cond_timedwait_monotonic_np( + &condition_, user_mutex_, &absolute_time); +#else + int rv = pthread_cond_timedwait(&condition_, user_mutex_, &absolute_time); +#endif // OS_ANDROID && HAVE_PTHREAD_COND_TIMEDWAIT_MONOTONIC +#endif // OS_MACOSX + + DCHECK(rv == 0 || rv == ETIMEDOUT); +#if !defined(NDEBUG) || defined(DCHECK_ALWAYS_ON) + user_lock_->CheckUnheldAndMark(); +#endif +} + +void ConditionVariable::Broadcast() { + int rv = pthread_cond_broadcast(&condition_); + DCHECK_EQ(0, rv); +} + +void ConditionVariable::Signal() { + int rv = pthread_cond_signal(&condition_); + DCHECK_EQ(0, rv); +} + +} // namespace base
new file mode 100644 --- /dev/null +++ b/security/sandbox/chromium/base/synchronization/lock_impl_posix.cc @@ -0,0 +1,55 @@ +// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "base/synchronization/lock_impl.h" + +#include <errno.h> +#include <string.h> + +#include "base/logging.h" + +namespace base { +namespace internal { + +LockImpl::LockImpl() { +#ifndef NDEBUG + // In debug, setup attributes for lock error checking. + pthread_mutexattr_t mta; + int rv = pthread_mutexattr_init(&mta); + DCHECK_EQ(rv, 0) << ". " << strerror(rv); + rv = pthread_mutexattr_settype(&mta, PTHREAD_MUTEX_ERRORCHECK); + DCHECK_EQ(rv, 0) << ". " << strerror(rv); + rv = pthread_mutex_init(&native_handle_, &mta); + DCHECK_EQ(rv, 0) << ". " << strerror(rv); + rv = pthread_mutexattr_destroy(&mta); + DCHECK_EQ(rv, 0) << ". " << strerror(rv); +#else + // In release, go with the default lock attributes. + pthread_mutex_init(&native_handle_, NULL); +#endif +} + +LockImpl::~LockImpl() { + int rv = pthread_mutex_destroy(&native_handle_); + DCHECK_EQ(rv, 0) << ". " << strerror(rv); +} + +bool LockImpl::Try() { + int rv = pthread_mutex_trylock(&native_handle_); + DCHECK(rv == 0 || rv == EBUSY) << ". " << strerror(rv); + return rv == 0; +} + +void LockImpl::Lock() { + int rv = pthread_mutex_lock(&native_handle_); + DCHECK_EQ(rv, 0) << ". " << strerror(rv); +} + +void LockImpl::Unlock() { + int rv = pthread_mutex_unlock(&native_handle_); + DCHECK_EQ(rv, 0) << ". " << strerror(rv); +} + +} // namespace internal +} // namespace base
new file mode 100644 --- /dev/null +++ b/security/sandbox/chromium/base/synchronization/waitable_event.h @@ -0,0 +1,193 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef BASE_SYNCHRONIZATION_WAITABLE_EVENT_H_ +#define BASE_SYNCHRONIZATION_WAITABLE_EVENT_H_ + +#include "base/base_export.h" +#include "base/basictypes.h" + +#if defined(OS_WIN) +#include "base/win/scoped_handle.h" +#endif + +#if defined(OS_POSIX) +#include <list> +#include <utility> +#include "base/memory/ref_counted.h" +#include "base/synchronization/lock.h" +#endif + +namespace base { + +// This replaces INFINITE from Win32 +static const int kNoTimeout = -1; + +class TimeDelta; + +// A WaitableEvent can be a useful thread synchronization tool when you want to +// allow one thread to wait for another thread to finish some work. For +// non-Windows systems, this can only be used from within a single address +// space. +// +// Use a WaitableEvent when you would otherwise use a Lock+ConditionVariable to +// protect a simple boolean value. However, if you find yourself using a +// WaitableEvent in conjunction with a Lock to wait for a more complex state +// change (e.g., for an item to be added to a queue), then you should probably +// be using a ConditionVariable instead of a WaitableEvent. +// +// NOTE: On Windows, this class provides a subset of the functionality afforded +// by a Windows event object. This is intentional. If you are writing Windows +// specific code and you need other features of a Windows event, then you might +// be better off just using an Windows event directly. +class BASE_EXPORT WaitableEvent { + public: + // If manual_reset is true, then to set the event state to non-signaled, a + // consumer must call the Reset method. If this parameter is false, then the + // system automatically resets the event state to non-signaled after a single + // waiting thread has been released. + WaitableEvent(bool manual_reset, bool initially_signaled); + +#if defined(OS_WIN) + // Create a WaitableEvent from an Event HANDLE which has already been + // created. This objects takes ownership of the HANDLE and will close it when + // deleted. + // TODO(rvargas): Pass ScopedHandle instead (and on Release). + explicit WaitableEvent(HANDLE event_handle); + + // Releases ownership of the handle from this object. + HANDLE Release(); +#endif + + ~WaitableEvent(); + + // Put the event in the un-signaled state. + void Reset(); + + // Put the event in the signaled state. Causing any thread blocked on Wait + // to be woken up. + void Signal(); + + // Returns true if the event is in the signaled state, else false. If this + // is not a manual reset event, then this test will cause a reset. + bool IsSignaled(); + + // Wait indefinitely for the event to be signaled. Wait's return "happens + // after" |Signal| has completed. This means that it's safe for a + // WaitableEvent to synchronise its own destruction, like this: + // + // WaitableEvent *e = new WaitableEvent; + // SendToOtherThread(e); + // e->Wait(); + // delete e; + void Wait(); + + // Wait up until max_time has passed for the event to be signaled. Returns + // true if the event was signaled. If this method returns false, then it + // does not necessarily mean that max_time was exceeded. + // + // TimedWait can synchronise its own destruction like |Wait|. + bool TimedWait(const TimeDelta& max_time); + +#if defined(OS_WIN) + HANDLE handle() const { return handle_.Get(); } +#endif + + // Wait, synchronously, on multiple events. + // waitables: an array of WaitableEvent pointers + // count: the number of elements in @waitables + // + // returns: the index of a WaitableEvent which has been signaled. + // + // You MUST NOT delete any of the WaitableEvent objects while this wait is + // happening, however WaitMany's return "happens after" the |Signal| call + // that caused it has completed, like |Wait|. + static size_t WaitMany(WaitableEvent** waitables, size_t count); + + // For asynchronous waiting, see WaitableEventWatcher + + // This is a private helper class. It's here because it's used by friends of + // this class (such as WaitableEventWatcher) to be able to enqueue elements + // of the wait-list + class Waiter { + public: + // Signal the waiter to wake up. + // + // Consider the case of a Waiter which is in multiple WaitableEvent's + // wait-lists. Each WaitableEvent is automatic-reset and two of them are + // signaled at the same time. Now, each will wake only the first waiter in + // the wake-list before resetting. However, if those two waiters happen to + // be the same object (as can happen if another thread didn't have a chance + // to dequeue the waiter from the other wait-list in time), two auto-resets + // will have happened, but only one waiter has been signaled! + // + // Because of this, a Waiter may "reject" a wake by returning false. In + // this case, the auto-reset WaitableEvent shouldn't act as if anything has + // been notified. + virtual bool Fire(WaitableEvent* signaling_event) = 0; + + // Waiters may implement this in order to provide an extra condition for + // two Waiters to be considered equal. In WaitableEvent::Dequeue, if the + // pointers match then this function is called as a final check. See the + // comments in ~Handle for why. + virtual bool Compare(void* tag) = 0; + + protected: + virtual ~Waiter() {} + }; + + private: + friend class WaitableEventWatcher; + +#if defined(OS_WIN) + win::ScopedHandle handle_; +#else + // On Windows, one can close a HANDLE which is currently being waited on. The + // MSDN documentation says that the resulting behaviour is 'undefined', but + // it doesn't crash. However, if we were to include the following members + // directly then, on POSIX, one couldn't use WaitableEventWatcher to watch an + // event which gets deleted. This mismatch has bitten us several times now, + // so we have a kernel of the WaitableEvent, which is reference counted. + // WaitableEventWatchers may then take a reference and thus match the Windows + // behaviour. + struct WaitableEventKernel : + public RefCountedThreadSafe<WaitableEventKernel> { + public: + WaitableEventKernel(bool manual_reset, bool initially_signaled); + + bool Dequeue(Waiter* waiter, void* tag); + + base::Lock lock_; + const bool manual_reset_; + bool signaled_; + std::list<Waiter*> waiters_; + + private: + friend class RefCountedThreadSafe<WaitableEventKernel>; + ~WaitableEventKernel(); + }; + + typedef std::pair<WaitableEvent*, size_t> WaiterAndIndex; + + // When dealing with arrays of WaitableEvent*, we want to sort by the address + // of the WaitableEvent in order to have a globally consistent locking order. + // In that case we keep them, in sorted order, in an array of pairs where the + // second element is the index of the WaitableEvent in the original, + // unsorted, array. + static size_t EnqueueMany(WaiterAndIndex* waitables, + size_t count, Waiter* waiter); + + bool SignalAll(); + bool SignalOne(); + void Enqueue(Waiter* waiter); + + scoped_refptr<WaitableEventKernel> kernel_; +#endif + + DISALLOW_COPY_AND_ASSIGN(WaitableEvent); +}; + +} // namespace base + +#endif // BASE_SYNCHRONIZATION_WAITABLE_EVENT_H_
new file mode 100644 --- /dev/null +++ b/security/sandbox/chromium/base/synchronization/waitable_event_posix.cc @@ -0,0 +1,415 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include <algorithm> +#include <vector> + +#include "base/logging.h" +#include "base/synchronization/waitable_event.h" +#include "base/synchronization/condition_variable.h" +#include "base/synchronization/lock.h" +#include "base/threading/thread_restrictions.h" + +// ----------------------------------------------------------------------------- +// A WaitableEvent on POSIX is implemented as a wait-list. Currently we don't +// support cross-process events (where one process can signal an event which +// others are waiting on). Because of this, we can avoid having one thread per +// listener in several cases. +// +// The WaitableEvent maintains a list of waiters, protected by a lock. Each +// waiter is either an async wait, in which case we have a Task and the +// MessageLoop to run it on, or a blocking wait, in which case we have the +// condition variable to signal. +// +// Waiting involves grabbing the lock and adding oneself to the wait list. Async +// waits can be canceled, which means grabbing the lock and removing oneself +// from the list. +// +// Waiting on multiple events is handled by adding a single, synchronous wait to +// the wait-list of many events. An event passes a pointer to itself when +// firing a waiter and so we can store that pointer to find out which event +// triggered. +// ----------------------------------------------------------------------------- + +namespace base { + +// ----------------------------------------------------------------------------- +// This is just an abstract base class for waking the two types of waiters +// ----------------------------------------------------------------------------- +WaitableEvent::WaitableEvent(bool manual_reset, bool initially_signaled) + : kernel_(new WaitableEventKernel(manual_reset, initially_signaled)) { +} + +WaitableEvent::~WaitableEvent() { +} + +void WaitableEvent::Reset() { + base::AutoLock locked(kernel_->lock_); + kernel_->signaled_ = false; +} + +void WaitableEvent::Signal() { + base::AutoLock locked(kernel_->lock_); + + if (kernel_->signaled_) + return; + + if (kernel_->manual_reset_) { + SignalAll(); + kernel_->signaled_ = true; + } else { + // In the case of auto reset, if no waiters were woken, we remain + // signaled. + if (!SignalOne()) + kernel_->signaled_ = true; + } +} + +bool WaitableEvent::IsSignaled() { + base::AutoLock locked(kernel_->lock_); + + const bool result = kernel_->signaled_; + if (result && !kernel_->manual_reset_) + kernel_->signaled_ = false; + return result; +} + +// ----------------------------------------------------------------------------- +// Synchronous waits + +// ----------------------------------------------------------------------------- +// This is a synchronous waiter. The thread is waiting on the given condition +// variable and the fired flag in this object. +// ----------------------------------------------------------------------------- +class SyncWaiter : public WaitableEvent::Waiter { + public: + SyncWaiter() + : fired_(false), + signaling_event_(NULL), + lock_(), + cv_(&lock_) { + } + + bool Fire(WaitableEvent* signaling_event) override { + base::AutoLock locked(lock_); + + if (fired_) + return false; + + fired_ = true; + signaling_event_ = signaling_event; + + cv_.Broadcast(); + + // Unlike AsyncWaiter objects, SyncWaiter objects are stack-allocated on + // the blocking thread's stack. There is no |delete this;| in Fire. The + // SyncWaiter object is destroyed when it goes out of scope. + + return true; + } + + WaitableEvent* signaling_event() const { + return signaling_event_; + } + + // --------------------------------------------------------------------------- + // These waiters are always stack allocated and don't delete themselves. Thus + // there's no problem and the ABA tag is the same as the object pointer. + // --------------------------------------------------------------------------- + bool Compare(void* tag) override { return this == tag; } + + // --------------------------------------------------------------------------- + // Called with lock held. + // --------------------------------------------------------------------------- + bool fired() const { + return fired_; + } + + // --------------------------------------------------------------------------- + // During a TimedWait, we need a way to make sure that an auto-reset + // WaitableEvent doesn't think that this event has been signaled between + // unlocking it and removing it from the wait-list. Called with lock held. + // --------------------------------------------------------------------------- + void Disable() { + fired_ = true; + } + + base::Lock* lock() { + return &lock_; + } + + base::ConditionVariable* cv() { + return &cv_; + } + + private: + bool fired_; + WaitableEvent* signaling_event_; // The WaitableEvent which woke us + base::Lock lock_; + base::ConditionVariable cv_; +}; + +void WaitableEvent::Wait() { + bool result = TimedWait(TimeDelta::FromSeconds(-1)); + DCHECK(result) << "TimedWait() should never fail with infinite timeout"; +} + +bool WaitableEvent::TimedWait(const TimeDelta& max_time) { + base::ThreadRestrictions::AssertWaitAllowed(); + const TimeTicks end_time(TimeTicks::Now() + max_time); + const bool finite_time = max_time.ToInternalValue() >= 0; + + kernel_->lock_.Acquire(); + if (kernel_->signaled_) { + if (!kernel_->manual_reset_) { + // In this case we were signaled when we had no waiters. Now that + // someone has waited upon us, we can automatically reset. + kernel_->signaled_ = false; + } + + kernel_->lock_.Release(); + return true; + } + + SyncWaiter sw; + sw.lock()->Acquire(); + + Enqueue(&sw); + kernel_->lock_.Release(); + // We are violating locking order here by holding the SyncWaiter lock but not + // the WaitableEvent lock. However, this is safe because we don't lock @lock_ + // again before unlocking it. + + for (;;) { + const TimeTicks current_time(TimeTicks::Now()); + + if (sw.fired() || (finite_time && current_time >= end_time)) { + const bool return_value = sw.fired(); + + // We can't acquire @lock_ before releasing the SyncWaiter lock (because + // of locking order), however, in between the two a signal could be fired + // and @sw would accept it, however we will still return false, so the + // signal would be lost on an auto-reset WaitableEvent. Thus we call + // Disable which makes sw::Fire return false. + sw.Disable(); + sw.lock()->Release(); + + // This is a bug that has been enshrined in the interface of + // WaitableEvent now: |Dequeue| is called even when |sw.fired()| is true, + // even though it'll always return false in that case. However, taking + // the lock ensures that |Signal| has completed before we return and + // means that a WaitableEvent can synchronise its own destruction. + kernel_->lock_.Acquire(); + kernel_->Dequeue(&sw, &sw); + kernel_->lock_.Release(); + + return return_value; + } + + if (finite_time) { + const TimeDelta max_wait(end_time - current_time); + sw.cv()->TimedWait(max_wait); + } else { + sw.cv()->Wait(); + } + } +} + +// ----------------------------------------------------------------------------- +// Synchronous waiting on multiple objects. + +static bool // StrictWeakOrdering +cmp_fst_addr(const std::pair<WaitableEvent*, unsigned> &a, + const std::pair<WaitableEvent*, unsigned> &b) { + return a.first < b.first; +} + +// static +size_t WaitableEvent::WaitMany(WaitableEvent** raw_waitables, + size_t count) { + base::ThreadRestrictions::AssertWaitAllowed(); + DCHECK(count) << "Cannot wait on no events"; + + // We need to acquire the locks in a globally consistent order. Thus we sort + // the array of waitables by address. We actually sort a pairs so that we can + // map back to the original index values later. + std::vector<std::pair<WaitableEvent*, size_t> > waitables; + waitables.reserve(count); + for (size_t i = 0; i < count; ++i) + waitables.push_back(std::make_pair(raw_waitables[i], i)); + + DCHECK_EQ(count, waitables.size()); + + sort(waitables.begin(), waitables.end(), cmp_fst_addr); + + // The set of waitables must be distinct. Since we have just sorted by + // address, we can check this cheaply by comparing pairs of consecutive + // elements. + for (size_t i = 0; i < waitables.size() - 1; ++i) { + DCHECK(waitables[i].first != waitables[i+1].first); + } + + SyncWaiter sw; + + const size_t r = EnqueueMany(&waitables[0], count, &sw); + if (r) { + // One of the events is already signaled. The SyncWaiter has not been + // enqueued anywhere. EnqueueMany returns the count of remaining waitables + // when the signaled one was seen, so the index of the signaled event is + // @count - @r. + return waitables[count - r].second; + } + + // At this point, we hold the locks on all the WaitableEvents and we have + // enqueued our waiter in them all. + sw.lock()->Acquire(); + // Release the WaitableEvent locks in the reverse order + for (size_t i = 0; i < count; ++i) { + waitables[count - (1 + i)].first->kernel_->lock_.Release(); + } + + for (;;) { + if (sw.fired()) + break; + + sw.cv()->Wait(); + } + sw.lock()->Release(); + + // The address of the WaitableEvent which fired is stored in the SyncWaiter. + WaitableEvent *const signaled_event = sw.signaling_event(); + // This will store the index of the raw_waitables which fired. + size_t signaled_index = 0; + + // Take the locks of each WaitableEvent in turn (except the signaled one) and + // remove our SyncWaiter from the wait-list + for (size_t i = 0; i < count; ++i) { + if (raw_waitables[i] != signaled_event) { + raw_waitables[i]->kernel_->lock_.Acquire(); + // There's no possible ABA issue with the address of the SyncWaiter here + // because it lives on the stack. Thus the tag value is just the pointer + // value again. + raw_waitables[i]->kernel_->Dequeue(&sw, &sw); + raw_waitables[i]->kernel_->lock_.Release(); + } else { + // By taking this lock here we ensure that |Signal| has completed by the + // time we return, because |Signal| holds this lock. This matches the + // behaviour of |Wait| and |TimedWait|. + raw_waitables[i]->kernel_->lock_.Acquire(); + raw_waitables[i]->kernel_->lock_.Release(); + signaled_index = i; + } + } + + return signaled_index; +} + +// ----------------------------------------------------------------------------- +// If return value == 0: +// The locks of the WaitableEvents have been taken in order and the Waiter has +// been enqueued in the wait-list of each. None of the WaitableEvents are +// currently signaled +// else: +// None of the WaitableEvent locks are held. The Waiter has not been enqueued +// in any of them and the return value is the index of the first WaitableEvent +// which was signaled, from the end of the array. +// ----------------------------------------------------------------------------- +// static +size_t WaitableEvent::EnqueueMany + (std::pair<WaitableEvent*, size_t>* waitables, + size_t count, Waiter* waiter) { + if (!count) + return 0; + + waitables[0].first->kernel_->lock_.Acquire(); + if (waitables[0].first->kernel_->signaled_) { + if (!waitables[0].first->kernel_->manual_reset_) + waitables[0].first->kernel_->signaled_ = false; + waitables[0].first->kernel_->lock_.Release(); + return count; + } + + const size_t r = EnqueueMany(waitables + 1, count - 1, waiter); + if (r) { + waitables[0].first->kernel_->lock_.Release(); + } else { + waitables[0].first->Enqueue(waiter); + } + + return r; +} + +// ----------------------------------------------------------------------------- + + +// ----------------------------------------------------------------------------- +// Private functions... + +WaitableEvent::WaitableEventKernel::WaitableEventKernel(bool manual_reset, + bool initially_signaled) + : manual_reset_(manual_reset), + signaled_(initially_signaled) { +} + +WaitableEvent::WaitableEventKernel::~WaitableEventKernel() { +} + +// ----------------------------------------------------------------------------- +// Wake all waiting waiters. Called with lock held. +// ----------------------------------------------------------------------------- +bool WaitableEvent::SignalAll() { + bool signaled_at_least_one = false; + + for (std::list<Waiter*>::iterator + i = kernel_->waiters_.begin(); i != kernel_->waiters_.end(); ++i) { + if ((*i)->Fire(this)) + signaled_at_least_one = true; + } + + kernel_->waiters_.clear(); + return signaled_at_least_one; +} + +// --------------------------------------------------------------------------- +// Try to wake a single waiter. Return true if one was woken. Called with lock +// held. +// --------------------------------------------------------------------------- +bool WaitableEvent::SignalOne() { + for (;;) { + if (kernel_->waiters_.empty()) + return false; + + const bool r = (*kernel_->waiters_.begin())->Fire(this); + kernel_->waiters_.pop_front(); + if (r) + return true; + } +} + +// ----------------------------------------------------------------------------- +// Add a waiter to the list of those waiting. Called with lock held. +// ----------------------------------------------------------------------------- +void WaitableEvent::Enqueue(Waiter* waiter) { + kernel_->waiters_.push_back(waiter); +} + +// ----------------------------------------------------------------------------- +// Remove a waiter from the list of those waiting. Return true if the waiter was +// actually removed. Called with lock held. +// ----------------------------------------------------------------------------- +bool WaitableEvent::WaitableEventKernel::Dequeue(Waiter* waiter, void* tag) { + for (std::list<Waiter*>::iterator + i = waiters_.begin(); i != waiters_.end(); ++i) { + if (*i == waiter && (*i)->Compare(tag)) { + waiters_.erase(i); + return true; + } + } + + return false; +} + +// ----------------------------------------------------------------------------- + +} // namespace base
--- a/security/sandbox/chromium/base/template_util.h +++ b/security/sandbox/chromium/base/template_util.h @@ -23,47 +23,25 @@ struct integral_constant { template <class T, T v> const T integral_constant<T, v>::value; typedef integral_constant<bool, true> true_type; typedef integral_constant<bool, false> false_type; template <class T> struct is_pointer : false_type {}; template <class T> struct is_pointer<T*> : true_type {}; -// Member function pointer detection up to four params. Add more as needed -// below. This is built-in to C++ 11, and we can remove this when we switch. +// Member function pointer detection. This is built-in to C++ 11's stdlib, and +// we can remove this when we switch to it. template<typename T> struct is_member_function_pointer : false_type {}; -template <typename R, typename Z> -struct is_member_function_pointer<R(Z::*)()> : true_type {}; -template <typename R, typename Z> -struct is_member_function_pointer<R(Z::*)() const> : true_type {}; - -template <typename R, typename Z, typename A> -struct is_member_function_pointer<R(Z::*)(A)> : true_type {}; -template <typename R, typename Z, typename A> -struct is_member_function_pointer<R(Z::*)(A) const> : true_type {}; - -template <typename R, typename Z, typename A, typename B> -struct is_member_function_pointer<R(Z::*)(A, B)> : true_type {}; -template <typename R, typename Z, typename A, typename B> -struct is_member_function_pointer<R(Z::*)(A, B) const> : true_type {}; - -template <typename R, typename Z, typename A, typename B, typename C> -struct is_member_function_pointer<R(Z::*)(A, B, C)> : true_type {}; -template <typename R, typename Z, typename A, typename B, typename C> -struct is_member_function_pointer<R(Z::*)(A, B, C) const> : true_type {}; - -template <typename R, typename Z, typename A, typename B, typename C, - typename D> -struct is_member_function_pointer<R(Z::*)(A, B, C, D)> : true_type {}; -template <typename R, typename Z, typename A, typename B, typename C, - typename D> -struct is_member_function_pointer<R(Z::*)(A, B, C, D) const> : true_type {}; +template <typename R, typename Z, typename... A> +struct is_member_function_pointer<R(Z::*)(A...)> : true_type {}; +template <typename R, typename Z, typename... A> +struct is_member_function_pointer<R(Z::*)(A...) const> : true_type {}; template <class T, class U> struct is_same : public false_type {}; template <class T> struct is_same<T,T> : true_type {}; template<class> struct is_array : public false_type {}; template<class T, size_t n> struct is_array<T[n]> : public true_type {}; template<class T> struct is_array<T[]> : public true_type {};
--- a/security/sandbox/chromium/base/third_party/dmg_fp/dtoa.cc +++ b/security/sandbox/chromium/base/third_party/dmg_fp/dtoa.cc @@ -647,17 +647,17 @@ multadd while(++i < wds); if (carry) { if (wds >= b->maxwds) { b1 = Balloc(b->k+1); Bcopy(b1, b); Bfree(b); b = b1; } - b->x[wds++] = carry; + b->x[wds++] = (ULong)carry; b->wds = wds; } return b; } static Bigint * s2b #ifdef KR_headers @@ -842,17 +842,17 @@ mult xc = xc0; carry = 0; do { z = *x++ * (ULLong)y + *xc + carry; carry = z >> 32; *xc++ = z & FFFFFFFF; } while(x < xae); - *xc = carry; + *xc = (ULong)carry; } } #else #ifdef Pack_32 for(; xb < xbe; xb++, xc0++) { if (y = *xb & 0xffff) { x = xa; xc = xc0; @@ -1506,17 +1506,17 @@ static unsigned char hexdig[256]; #ifdef KR_headers htinit(h, s, inc) unsigned char *h; unsigned char *s; int inc; #else htinit(unsigned char *h, unsigned char *s, int inc) #endif { int i, j; for(i = 0; (j = s[i]) !=0; i++) - h[j] = i + inc; + h[j] = (unsigned char)(i + inc); } static void #ifdef KR_headers hexdig_init() #else hexdig_init(void) #endif @@ -3298,17 +3298,17 @@ strtod } else word0(&rv) += P*Exp_msk1; } else { #ifdef Avoid_Underflow if (bc.scale && y <= 2*P*Exp_msk1) { if (aadj <= 0x7fffffff) { - if ((z = aadj) <= 0) + if ((z = (ULong)aadj) <= 0) z = 1; aadj = z; aadj1 = bc.dsign ? aadj : -aadj; } dval(&aadj2) = aadj1; word0(&aadj2) += (2*P+1)*Exp_msk1 - y; aadj1 = dval(&aadj2); } @@ -3854,19 +3854,19 @@ dtoa } #ifndef No_leftright if (leftright) { /* Use Steele & White method of only * generating digits needed. */ dval(&eps) = 0.5/tens[ilim-1] - dval(&eps); for(i = 0;;) { - L = dval(&u); + L = (long)dval(&u); dval(&u) -= L; - *s++ = '0' + (int)L; + *s++ = '0' + (char)L; if (dval(&u) < dval(&eps)) goto ret1; if (1. - dval(&u) < dval(&eps)) goto bump_up; if (++i >= ilim) break; dval(&eps) *= 10.; dval(&u) *= 10.; @@ -3875,17 +3875,17 @@ dtoa else { #endif /* Generate ilim digits, then fix them up. */ dval(&eps) *= tens[ilim-1]; for(i = 1;; i++, dval(&u) *= 10.) { L = (Long)(dval(&u)); if (!(dval(&u) -= L)) ilim = i; - *s++ = '0' + (int)L; + *s++ = '0' + (char)L; if (i == ilim) { if (dval(&u) > 0.5 + dval(&eps)) goto bump_up; else if (dval(&u) < 0.5 - dval(&eps)) { while(*--s == '0') {} s++; goto ret1; } @@ -3918,17 +3918,17 @@ dtoa dval(&u) -= L*ds; #ifdef Check_FLT_ROUNDS /* If FLT_ROUNDS == 2, L will usually be high by 1 */ if (dval(&u) < 0) { L--; dval(&u) += ds; } #endif - *s++ = '0' + (int)L; + *s++ = '0' + (char)L; if (!dval(&u)) { #ifdef SET_INEXACT inexact = 0; #endif break; } if (i == ilim) { #ifdef Honor_FLT_ROUNDS @@ -4096,17 +4096,17 @@ dtoa if (dig == '9') goto round_9_up; if (j > 0) dig++; #ifdef SET_INEXACT else if (!b->x[0] && b->wds <= 1) inexact = 0; #endif - *s++ = dig; + *s++ = (char)dig; goto ret; } #endif if (j < 0 || (j == 0 && mode != 1 #ifndef ROUND_BIASED && !(word1(&u) & 1) #endif )) { @@ -4126,50 +4126,51 @@ dtoa if (j1 > 0) { b = lshift(b, 1); j1 = cmp(b, S); if ((j1 > 0 || (j1 == 0 && dig & 1)) && dig++ == '9') goto round_9_up; } accept_dig: - *s++ = dig; + *s++ = (char)dig; goto ret; } if (j1 > 0) { #ifdef Honor_FLT_ROUNDS if (!Rounding) goto accept_dig; #endif if (dig == '9') { /* possible if i == 1 */ round_9_up: *s++ = '9'; goto roundoff; } - *s++ = dig + 1; + *s++ = (char)dig + 1; goto ret; } #ifdef Honor_FLT_ROUNDS keep_dig: #endif - *s++ = dig; + *s++ = (char)dig; if (i == ilim) break; b = multadd(b, 10, 0); if (mlo == mhi) mlo = mhi = multadd(mhi, 10, 0); else { mlo = multadd(mlo, 10, 0); mhi = multadd(mhi, 10, 0); } } } else for(i = 1;; i++) { - *s++ = dig = quorem(b,S) + '0'; + dig = quorem(b,S) + '0'; + *s++ = (char)dig; if (!b->x[0] && b->wds <= 1) { #ifdef SET_INEXACT inexact = 0; #endif goto ret; } if (i >= ilim) break;
--- a/security/sandbox/chromium/base/third_party/dmg_fp/g_fmt.cc +++ b/security/sandbox/chromium/base/third_party/dmg_fp/g_fmt.cc @@ -62,17 +62,17 @@ g_fmt(register char *b, double x) *b++ = '-'; decpt = -decpt; } else *b++ = '+'; for(j = 2, k = 10; 10*k <= decpt; j++, k *= 10) {} for(;;) { i = decpt / k; - *b++ = i + '0'; + *b++ = (char)i + '0'; if (--j <= 0) break; decpt -= i*k; decpt *= 10; } *b = 0; } else if (decpt <= 0) {
new file mode 100644 --- /dev/null +++ b/security/sandbox/chromium/base/third_party/superfasthash/LICENSE @@ -0,0 +1,27 @@ +Paul Hsieh OLD BSD license + +Copyright (c) 2010, Paul Hsieh +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. +* Redistributions in binary form must reproduce the above copyright notice, this + list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. +* Neither my name, Paul Hsieh, nor the names of any other contributors to the + code use may not be used to endorse or promote products derived from this + software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
new file mode 100644 --- /dev/null +++ b/security/sandbox/chromium/base/third_party/superfasthash/README.chromium @@ -0,0 +1,29 @@ +Name: Paul Hsieh's SuperFastHash +Short Name: SuperFastHash +URL: http://www.azillionmonkeys.com/qed/hash.html +Version: 0 +Date: 2012-02-21 +License: BSD +License File: LICENSE +Security Critical: yes + +Description: +A fast string hashing algorithm. + +Local Modifications: +- Added LICENSE. +- Added license text as a comment to the top of superfasthash.c. +- #include <stdint.h> instead of "pstdint.h". +- #include <stdlib.h>. + +The license is a standard 3-clause BSD license with the following minor changes: + +"nor the names of its contributors may be used" +is replaced with: +"nor the names of any other contributors to the code use may not be used" + +and + +"IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE" +is replaced with: +"IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE"
new file mode 100644 --- /dev/null +++ b/security/sandbox/chromium/base/third_party/superfasthash/superfasthash.c @@ -0,0 +1,84 @@ +// Copyright (c) 2010, Paul Hsieh +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither my name, Paul Hsieh, nor the names of any other contributors to the +// code use may not be used to endorse or promote products derived from this +// software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. + +#include <stdint.h> +#include <stdlib.h> +#undef get16bits +#if (defined(__GNUC__) && defined(__i386__)) || defined(__WATCOMC__) \ + || defined(_MSC_VER) || defined (__BORLANDC__) || defined (__TURBOC__) +#define get16bits(d) (*((const uint16_t *) (d))) +#endif + +#if !defined (get16bits) +#define get16bits(d) ((((uint32_t)(((const uint8_t *)(d))[1])) << 8)\ + +(uint32_t)(((const uint8_t *)(d))[0]) ) +#endif + +uint32_t SuperFastHash (const char * data, int len) { +uint32_t hash = len, tmp; +int rem; + + if (len <= 0 || data == NULL) return 0; + + rem = len & 3; + len >>= 2; + + /* Main loop */ + for (;len > 0; len--) { + hash += get16bits (data); + tmp = (get16bits (data+2) << 11) ^ hash; + hash = (hash << 16) ^ tmp; + data += 2*sizeof (uint16_t); + hash += hash >> 11; + } + + /* Handle end cases */ + switch (rem) { + case 3: hash += get16bits (data); + hash ^= hash << 16; + hash ^= ((signed char)data[sizeof (uint16_t)]) << 18; + hash += hash >> 11; + break; + case 2: hash += get16bits (data); + hash ^= hash << 11; + hash += hash >> 17; + break; + case 1: hash += (signed char)*data; + hash ^= hash << 10; + hash += hash >> 1; + } + + /* Force "avalanching" of final 127 bits */ + hash ^= hash << 3; + hash += hash >> 5; + hash ^= hash << 4; + hash += hash >> 17; + hash ^= hash << 25; + hash += hash >> 6; + + return hash; +}
new file mode 100644 --- /dev/null +++ b/security/sandbox/chromium/base/threading/platform_thread_linux.cc @@ -0,0 +1,119 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "base/threading/platform_thread.h" + +#include <errno.h> +#include <sched.h> + +#include "base/lazy_instance.h" +#include "base/logging.h" +#include "base/memory/scoped_ptr.h" +#include "base/safe_strerror_posix.h" +#include "base/threading/thread_id_name_manager.h" +#include "base/threading/thread_restrictions.h" +#include "base/tracked_objects.h" + +#if !defined(OS_NACL) +#include <sys/prctl.h> +#include <sys/resource.h> +#include <sys/syscall.h> +#include <sys/time.h> +#include <unistd.h> +#endif + +namespace base { + +namespace { + +int ThreadNiceValue(ThreadPriority priority) { + switch (priority) { + case kThreadPriority_RealtimeAudio: + return -10; + case kThreadPriority_Background: + return 10; + case kThreadPriority_Normal: + return 0; + case kThreadPriority_Display: + return -6; + default: + NOTREACHED() << "Unknown priority."; + return 0; + } +} + +} // namespace + +// static +void PlatformThread::SetName(const char* name) { + ThreadIdNameManager::GetInstance()->SetName(CurrentId(), name); + tracked_objects::ThreadData::InitializeThreadContext(name); + +#if !defined(OS_NACL) + // On linux we can get the thread names to show up in the debugger by setting + // the process name for the LWP. We don't want to do this for the main + // thread because that would rename the process, causing tools like killall + // to stop working. + if (PlatformThread::CurrentId() == getpid()) + return; + + // http://0pointer.de/blog/projects/name-your-threads.html + // Set the name for the LWP (which gets truncated to 15 characters). + // Note that glibc also has a 'pthread_setname_np' api, but it may not be + // available everywhere and it's only benefit over using prctl directly is + // that it can set the name of threads other than the current thread. + int err = prctl(PR_SET_NAME, name); + // We expect EPERM failures in sandboxed processes, just ignore those. + if (err < 0 && errno != EPERM) + DPLOG(ERROR) << "prctl(PR_SET_NAME)"; +#endif // !defined(OS_NACL) +} + +// static +void PlatformThread::SetThreadPriority(PlatformThreadHandle handle, + ThreadPriority priority) { +#if !defined(OS_NACL) + if (priority == kThreadPriority_RealtimeAudio) { + const struct sched_param kRealTimePrio = {8}; + if (pthread_setschedparam(pthread_self(), SCHED_RR, &kRealTimePrio) == 0) { + // Got real time priority, no need to set nice level. + return; + } + } + + // setpriority(2) should change the whole thread group's (i.e. process) + // priority. however, on linux it will only change the target thread's + // priority. see the bugs section in + // http://man7.org/linux/man-pages/man2/getpriority.2.html. + // we prefer using 0 rather than the current thread id since they are + // equivalent but it makes sandboxing easier (https://crbug.com/399473). + DCHECK_NE(handle.id_, kInvalidThreadId); + const int kNiceSetting = ThreadNiceValue(priority); + const PlatformThreadId current_id = PlatformThread::CurrentId(); + if (setpriority(PRIO_PROCESS, + handle.id_ == current_id ? 0 : handle.id_, + kNiceSetting)) { + DVPLOG(1) << "Failed to set nice value of thread (" << handle.id_ << ") to " + << kNiceSetting; + } +#endif // !defined(OS_NACL) +} + +void InitThreading() {} + +void InitOnThread() {} + +void TerminateOnThread() {} + +size_t GetDefaultThreadStackSize(const pthread_attr_t& attributes) { +#if !defined(THREAD_SANITIZER) + return 0; +#else + // ThreadSanitizer bloats the stack heavily. Evidence has been that the + // default stack size isn't enough for some browser tests. + return 2 * (1 << 23); // 2 times 8192K (the default stack size on Linux). +#endif +} + +} // namespace base
new file mode 100644 --- /dev/null +++ b/security/sandbox/chromium/base/threading/platform_thread_posix.cc @@ -0,0 +1,238 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "base/threading/platform_thread.h" + +#include <errno.h> +#include <sched.h> + +#include "base/lazy_instance.h" +#include "base/logging.h" +#include "base/memory/scoped_ptr.h" +#include "base/safe_strerror_posix.h" +#include "base/synchronization/waitable_event.h" +#include "base/threading/thread_id_name_manager.h" +#include "base/threading/thread_restrictions.h" +#include "base/tracked_objects.h" + +#if defined(OS_MACOSX) +#include <sys/resource.h> +#include <algorithm> +#endif + +#if defined(OS_LINUX) +#include <sys/prctl.h> +#include <sys/resource.h> +#include <sys/syscall.h> +#include <sys/time.h> +#include <unistd.h> +#endif + +namespace base { + +void InitThreading(); +void InitOnThread(); +void TerminateOnThread(); +size_t GetDefaultThreadStackSize(const pthread_attr_t& attributes); + +namespace { + +struct ThreadParams { + ThreadParams() + : delegate(NULL), + joinable(false), + priority(kThreadPriority_Normal), + handle(NULL), + handle_set(false, false) { + } + + PlatformThread::Delegate* delegate; + bool joinable; + ThreadPriority priority; + PlatformThreadHandle* handle; + WaitableEvent handle_set; +}; + +void* ThreadFunc(void* params) { + base::InitOnThread(); + ThreadParams* thread_params = static_cast<ThreadParams*>(params); + + PlatformThread::Delegate* delegate = thread_params->delegate; + if (!thread_params->joinable) + base::ThreadRestrictions::SetSingletonAllowed(false); + + if (thread_params->priority != kThreadPriority_Normal) { + PlatformThread::SetThreadPriority(PlatformThread::CurrentHandle(), + thread_params->priority); + } + + // Stash the id in the handle so the calling thread has a complete + // handle, and unblock the parent thread. + *(thread_params->handle) = PlatformThreadHandle(pthread_self(), + PlatformThread::CurrentId()); + thread_params->handle_set.Signal(); + + ThreadIdNameManager::GetInstance()->RegisterThread( + PlatformThread::CurrentHandle().platform_handle(), + PlatformThread::CurrentId()); + + delegate->ThreadMain(); + + ThreadIdNameManager::GetInstance()->RemoveName( + PlatformThread::CurrentHandle().platform_handle(), + PlatformThread::CurrentId()); + + base::TerminateOnThread(); + return NULL; +} + +bool CreateThread(size_t stack_size, bool joinable, + PlatformThread::Delegate* delegate, + PlatformThreadHandle* thread_handle, + ThreadPriority priority) { + base::InitThreading(); + + bool success = false; + pthread_attr_t attributes; + pthread_attr_init(&attributes); + + // Pthreads are joinable by default, so only specify the detached + // attribute if the thread should be non-joinable. + if (!joinable) { + pthread_attr_setdetachstate(&attributes, PTHREAD_CREATE_DETACHED); + } + + // Get a better default if available. + if (stack_size == 0) + stack_size = base::GetDefaultThreadStackSize(attributes); + + if (stack_size > 0) + pthread_attr_setstacksize(&attributes, stack_size); + + ThreadParams params; + params.delegate = delegate; + params.joinable = joinable; + params.priority = priority; + params.handle = thread_handle; + + pthread_t handle; + int err = pthread_create(&handle, + &attributes, + ThreadFunc, + ¶ms); + success = !err; + if (!success) { + // Value of |handle| is undefined if pthread_create fails. + handle = 0; + errno = err; + PLOG(ERROR) << "pthread_create"; + } + + pthread_attr_destroy(&attributes); + + // Don't let this call complete until the thread id + // is set in the handle. + if (success) + params.handle_set.Wait(); + CHECK_EQ(handle, thread_handle->platform_handle()); + + return success; +} + +} // namespace + +// static +PlatformThreadId PlatformThread::CurrentId() { + // Pthreads doesn't have the concept of a thread ID, so we have to reach down + // into the kernel. +#if defined(OS_MACOSX) + return pthread_mach_thread_np(pthread_self()); +#elif defined(OS_LINUX) + return syscall(__NR_gettid); +#elif defined(OS_ANDROID) + return gettid(); +#elif defined(OS_SOLARIS) || defined(OS_QNX) + return pthread_self(); +#elif defined(OS_NACL) && defined(__GLIBC__) + return pthread_self(); +#elif defined(OS_NACL) && !defined(__GLIBC__) + // Pointers are 32-bits in NaCl. + return reinterpret_cast<int32>(pthread_self()); +#elif defined(OS_POSIX) + return reinterpret_cast<int64>(pthread_self()); +#endif +} + +// static +PlatformThreadRef PlatformThread::CurrentRef() { + return PlatformThreadRef(pthread_self()); +} + +// static +PlatformThreadHandle PlatformThread::CurrentHandle() { + return PlatformThreadHandle(pthread_self(), CurrentId()); +} + +// static +void PlatformThread::YieldCurrentThread() { + sched_yield(); +} + +// static +void PlatformThread::Sleep(TimeDelta duration) { + struct timespec sleep_time, remaining; + + // Break the duration into seconds and nanoseconds. + // NOTE: TimeDelta's microseconds are int64s while timespec's + // nanoseconds are longs, so this unpacking must prevent overflow. + sleep_time.tv_sec = duration.InSeconds(); + duration -= TimeDelta::FromSeconds(sleep_time.tv_sec); + sleep_time.tv_nsec = duration.InMicroseconds() * 1000; // nanoseconds + + while (nanosleep(&sleep_time, &remaining) == -1 && errno == EINTR) + sleep_time = remaining; +} + +// static +const char* PlatformThread::GetName() { + return ThreadIdNameManager::GetInstance()->GetName(CurrentId()); +} + +// static +bool PlatformThread::Create(size_t stack_size, Delegate* delegate, + PlatformThreadHandle* thread_handle) { + base::ThreadRestrictions::ScopedAllowWait allow_wait; + return CreateThread(stack_size, true /* joinable thread */, + delegate, thread_handle, kThreadPriority_Normal); +} + +// static +bool PlatformThread::CreateWithPriority(size_t stack_size, Delegate* delegate, + PlatformThreadHandle* thread_handle, + ThreadPriority priority) { + base::ThreadRestrictions::ScopedAllowWait allow_wait; + return CreateThread(stack_size, true, // joinable thread + delegate, thread_handle, priority); +} + +// static +bool PlatformThread::CreateNonJoinable(size_t stack_size, Delegate* delegate) { + PlatformThreadHandle unused; + + base::ThreadRestrictions::ScopedAllowWait allow_wait; + bool result = CreateThread(stack_size, false /* non-joinable thread */, + delegate, &unused, kThreadPriority_Normal); + return result; +} + +// static +void PlatformThread::Join(PlatformThreadHandle thread_handle) { + // Joining another thread may block the current thread for a long time, since + // the thread referred to by |thread_handle| may still be running long-lived / + // blocking tasks. + base::ThreadRestrictions::AssertIOAllowed(); + CHECK_EQ(0, pthread_join(thread_handle.handle_, NULL)); +} + +} // namespace base
--- a/security/sandbox/chromium/base/threading/platform_thread_win.cc +++ b/security/sandbox/chromium/base/threading/platform_thread_win.cc @@ -145,19 +145,18 @@ void PlatformThread::YieldCurrentThread( ::Sleep(0); } // static void PlatformThread::Sleep(TimeDelta duration) { // When measured with a high resolution clock, Sleep() sometimes returns much // too early. We may need to call it repeatedly to get the desired duration. TimeTicks end = TimeTicks::Now() + duration; - TimeTicks now; - while ((now = TimeTicks::Now()) < end) - ::Sleep((end - now).InMillisecondsRoundedUp()); + for (TimeTicks now = TimeTicks::Now(); now < end; now = TimeTicks::Now()) + ::Sleep(static_cast<DWORD>((end - now).InMillisecondsRoundedUp())); } // static void PlatformThread::SetName(const char* name) { ThreadIdNameManager::GetInstance()->SetName(CurrentId(), name); // On Windows only, we don't need to tell the profiler about the "BrokerEvent" // thread, as it exists only in the chrome.exe image, and never spawns or runs
--- a/security/sandbox/chromium/base/threading/sequenced_worker_pool.h +++ b/security/sandbox/chromium/base/threading/sequenced_worker_pool.h @@ -285,20 +285,20 @@ class BASE_EXPORT SequencedWorkerPool : // behavior. bool PostSequencedWorkerTaskWithShutdownBehavior( SequenceToken sequence_token, const tracked_objects::Location& from_here, const Closure& task, WorkerShutdown shutdown_behavior); // TaskRunner implementation. Forwards to PostDelayedWorkerTask(). - virtual bool PostDelayedTask(const tracked_objects::Location& from_here, - const Closure& task, - TimeDelta delay) OVERRIDE; - virtual bool RunsTasksOnCurrentThread() const OVERRIDE; + bool PostDelayedTask(const tracked_objects::Location& from_here, + const Closure& task, + TimeDelta delay) override; + bool RunsTasksOnCurrentThread() const override; // Returns true if the current thread is processing a task with the given // sequence_token. bool IsRunningSequenceOnCurrentThread(SequenceToken sequence_token) const; // Blocks until all pending tasks are complete. This should only be called in // unit tests when you want to validate something that should have happened. // This will not flush delayed tasks; delayed tasks get deleted. @@ -331,19 +331,19 @@ class BASE_EXPORT SequencedWorkerPool : // Check if Shutdown was called for given threading pool. This method is used // for aborting time consuming operation to avoid blocking shutdown. // // Can be called from any thread. bool IsShutdownInProgress(); protected: - virtual ~SequencedWorkerPool(); + ~SequencedWorkerPool() override; - virtual void OnDestruct() const OVERRIDE; + void OnDestruct() const override; private: friend class RefCountedThreadSafe<SequencedWorkerPool>; friend class DeleteHelper<SequencedWorkerPool>; class Inner; class Worker;
--- a/security/sandbox/chromium/base/threading/thread_collision_warner.h +++ b/security/sandbox/chromium/base/threading/thread_collision_warner.h @@ -133,18 +133,18 @@ namespace base { // used. During the unit tests is used another class that doesn't "DCHECK" // in case of collision (check thread_collision_warner_unittests.cc) struct BASE_EXPORT AsserterBase { virtual ~AsserterBase() {} virtual void warn() = 0; }; struct BASE_EXPORT DCheckAsserter : public AsserterBase { - virtual ~DCheckAsserter() {} - virtual void warn() OVERRIDE; + ~DCheckAsserter() override {} + void warn() override; }; class BASE_EXPORT ThreadCollisionWarner { public: // The parameter asserter is there only for test purpose explicit ThreadCollisionWarner(AsserterBase* asserter = new DCheckAsserter()) : valid_thread_id_(0), counter_(0),
new file mode 100644 --- /dev/null +++ b/security/sandbox/chromium/base/threading/thread_local_posix.cc @@ -0,0 +1,42 @@ +// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "base/threading/thread_local.h" + +#include <pthread.h> + +#include "base/logging.h" + +#if !defined(OS_ANDROID) + +namespace base { +namespace internal { + +// static +void ThreadLocalPlatform::AllocateSlot(SlotType* slot) { + int error = pthread_key_create(slot, NULL); + CHECK_EQ(error, 0); +} + +// static +void ThreadLocalPlatform::FreeSlot(SlotType slot) { + int error = pthread_key_delete(slot); + DCHECK_EQ(0, error); +} + +// static +void* ThreadLocalPlatform::GetValueFromSlot(SlotType slot) { + return pthread_getspecific(slot); +} + +// static +void ThreadLocalPlatform::SetValueInSlot(SlotType slot, void* value) { + int error = pthread_setspecific(slot, value); + DCHECK_EQ(error, 0); +} + +} // namespace internal +} // namespace base + +#endif // !defined(OS_ANDROID)
new file mode 100644 --- /dev/null +++ b/security/sandbox/chromium/base/threading/thread_local_storage.h @@ -0,0 +1,144 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef BASE_THREADING_THREAD_LOCAL_STORAGE_H_ +#define BASE_THREADING_THREAD_LOCAL_STORAGE_H_ + +#include "base/base_export.h" +#include "base/basictypes.h" + +#if defined(OS_WIN) +#include <windows.h> +#elif defined(OS_POSIX) +#include <pthread.h> +#endif + +namespace base { + +namespace internal { + +// WARNING: You should *NOT* be using this class directly. +// PlatformThreadLocalStorage is low-level abstraction to the OS's TLS +// interface, you should instead be using ThreadLocalStorage::StaticSlot/Slot. +class BASE_EXPORT PlatformThreadLocalStorage { + public: + +#if defined(OS_WIN) + typedef unsigned long TLSKey; + enum { TLS_KEY_OUT_OF_INDEXES = TLS_OUT_OF_INDEXES }; +#elif defined(OS_POSIX) + typedef pthread_key_t TLSKey; + // The following is a "reserved key" which is used in our generic Chromium + // ThreadLocalStorage implementation. We expect that an OS will not return + // such a key, but if it is returned (i.e., the OS tries to allocate it) we + // will just request another key. + enum { TLS_KEY_OUT_OF_INDEXES = 0x7FFFFFFF }; +#endif + + // The following methods need to be supported on each OS platform, so that + // the Chromium ThreadLocalStore functionality can be constructed. + // Chromium will use these methods to acquire a single OS slot, and then use + // that to support a much larger number of Chromium slots (independent of the + // OS restrictions). + // The following returns true if it successfully is able to return an OS + // key in |key|. + static bool AllocTLS(TLSKey* key); + // Note: FreeTLS() doesn't have to be called, it is fine with this leak, OS + // might not reuse released slot, you might just reset the TLS value with + // SetTLSValue(). + static void FreeTLS(TLSKey key); + static void SetTLSValue(TLSKey key, void* value); + static void* GetTLSValue(TLSKey key); + + // Each platform (OS implementation) is required to call this method on each + // terminating thread when the thread is about to terminate. This method + // will then call all registered destructors for slots in Chromium + // ThreadLocalStorage, until there are no slot values remaining as having + // been set on this thread. + // Destructors may end up being called multiple times on a terminating + // thread, as other destructors may re-set slots that were previously + // destroyed. +#if defined(OS_WIN) + // Since Windows which doesn't support TLS destructor, the implementation + // should use GetTLSValue() to retrieve the value of TLS slot. + static void OnThreadExit(); +#elif defined(OS_POSIX) + // |Value| is the data stored in TLS slot, The implementation can't use + // GetTLSValue() to retrieve the value of slot as it has already been reset + // in Posix. + static void OnThreadExit(void* value); +#endif +}; + +} // namespace internal + +// Wrapper for thread local storage. This class doesn't do much except provide +// an API for portability. +class BASE_EXPORT ThreadLocalStorage { + public: + + // Prototype for the TLS destructor function, which can be optionally used to + // cleanup thread local storage on thread exit. 'value' is the data that is + // stored in thread local storage. + typedef void (*TLSDestructorFunc)(void* value); + + // StaticSlot uses its own struct initializer-list style static + // initialization, as base's LINKER_INITIALIZED requires a constructor and on + // some compilers (notably gcc 4.4) this still ends up needing runtime + // initialization. + #define TLS_INITIALIZER {0} + + // A key representing one value stored in TLS. + // Initialize like + // ThreadLocalStorage::StaticSlot my_slot = TLS_INITIALIZER; + // If you're not using a static variable, use the convenience class + // ThreadLocalStorage::Slot (below) instead. + struct BASE_EXPORT StaticSlot { + // Set up the TLS slot. Called by the constructor. + // 'destructor' is a pointer to a function to perform per-thread cleanup of + // this object. If set to NULL, no cleanup is done for this TLS slot. + // Returns false on error. + bool Initialize(TLSDestructorFunc destructor); + + // Free a previously allocated TLS 'slot'. + // If a destructor was set for this slot, removes + // the destructor so that remaining threads exiting + // will not free data. + void Free(); + + // Get the thread-local value stored in slot 'slot'. + // Values are guaranteed to initially be zero. + void* Get() const; + + // Set the thread-local value stored in slot 'slot' to + // value 'value'. + void Set(void* value); + + bool initialized() const { return initialized_; } + + // The internals of this struct should be considered private. + bool initialized_; + int slot_; + }; + + // A convenience wrapper around StaticSlot with a constructor. Can be used + // as a member variable. + class BASE_EXPORT Slot : public StaticSlot { + public: + // Calls StaticSlot::Initialize(). + explicit Slot(TLSDestructorFunc destructor = NULL); + + private: + using StaticSlot::initialized_; + using StaticSlot::slot_; + + DISALLOW_COPY_AND_ASSIGN(Slot); + }; + + DISALLOW_COPY_AND_ASSIGN(ThreadLocalStorage); +}; + +} // namespace base + +#endif // BASE_THREADING_THREAD_LOCAL_STORAGE_H_
--- a/security/sandbox/chromium/base/threading/thread_restrictions.h +++ b/security/sandbox/chromium/base/threading/thread_restrictions.h @@ -10,70 +10,57 @@ // See comment at top of thread_checker.h #if (!defined(NDEBUG) || defined(DCHECK_ALWAYS_ON)) #define ENABLE_THREAD_RESTRICTIONS 1 #else #define ENABLE_THREAD_RESTRICTIONS 0 #endif -class AcceleratedPresenter; class BrowserProcessImpl; class HistogramSynchronizer; -class MetricsService; class NativeBackendKWallet; class ScopedAllowWaitForLegacyWebViewApi; -class TestingAutomationProvider; -namespace browser_sync { -class NonFrontendDataTypeController; -class UIModelWorker; -} namespace cc { class CompletionEvent; } namespace chromeos { -class AudioMixerAlsa; class BlockingMethodCaller; namespace system { class StatisticsProviderImpl; } } namespace chrome_browser_net { class Predictor; } namespace content { class BrowserGpuChannelHostFactory; +class BrowserGpuMemoryBufferManager; class BrowserShutdownProfileDumper; class BrowserTestBase; -class GLHelper; class GpuChannelHost; class NestedMessagePumpAndroid; class RenderWidgetResizeHelper; class ScopedAllowWaitForAndroidLayoutTests; class TextInputClientMac; } namespace dbus { class Bus; } namespace disk_cache { class BackendImpl; class InFlightIO; } -namespace media { -class AudioOutputController; -} namespace mojo { namespace common { class WatcherThreadManager; } } namespace net { -class FileStreamPosix; -class FileStreamWin; namespace internal { class AddressTrackerLinux; } } namespace remoting { class AutoThread; } @@ -184,51 +171,43 @@ class BASE_EXPORT ThreadRestrictions { // BEGIN ALLOWED USAGE. friend class content::BrowserShutdownProfileDumper; friend class content::BrowserTestBase; friend class content::NestedMessagePumpAndroid; friend class content::RenderWidgetResizeHelper; friend class content::ScopedAllowWaitForAndroidLayoutTests; friend class ::HistogramSynchronizer; friend class ::ScopedAllowWaitForLegacyWebViewApi; - friend class ::TestingAutomationProvider; friend class cc::CompletionEvent; friend class mojo::common::WatcherThreadManager; friend class remoting::AutoThread; friend class MessagePumpDefault; friend class SequencedWorkerPool; friend class SimpleThread; friend class Thread; friend class ThreadTestHelper; friend class PlatformThread; friend class android::JavaHandlerThread; // END ALLOWED USAGE. // BEGIN USAGE THAT NEEDS TO BE FIXED. - friend class ::chromeos::AudioMixerAlsa; // http://crbug.com/125206 friend class ::chromeos::BlockingMethodCaller; // http://crbug.com/125360 friend class ::chromeos::system::StatisticsProviderImpl; // http://crbug.com/125385 - friend class browser_sync::NonFrontendDataTypeController; // http://crbug.com/19757 - friend class browser_sync::UIModelWorker; // http://crbug.com/19757 friend class chrome_browser_net::Predictor; // http://crbug.com/78451 friend class content::BrowserGpuChannelHostFactory; // http://crbug.com/125248 - friend class content::GLHelper; // http://crbug.com/125415 + friend class + content::BrowserGpuMemoryBufferManager; // http://crbug.com/420368 friend class content::GpuChannelHost; // http://crbug.com/125264 friend class content::TextInputClientMac; // http://crbug.com/121917 friend class dbus::Bus; // http://crbug.com/125222 friend class disk_cache::BackendImpl; // http://crbug.com/74623 friend class disk_cache::InFlightIO; // http://crbug.com/74623 - friend class media::AudioOutputController; // http://crbug.com/120973 - friend class net::FileStreamPosix; // http://crbug.com/115067 - friend class net::FileStreamWin; // http://crbug.com/115067 friend class net::internal::AddressTrackerLinux; // http://crbug.com/125097 - friend class ::AcceleratedPresenter; // http://crbug.com/125391 friend class ::BrowserProcessImpl; // http://crbug.com/125207 - friend class ::MetricsService; // http://crbug.com/124954 friend class ::NativeBackendKWallet; // http://crbug.com/125331 // END USAGE THAT NEEDS TO BE FIXED. #if ENABLE_THREAD_RESTRICTIONS static bool SetWaitAllowed(bool allowed); #else static bool SetWaitAllowed(bool allowed) { return true; } #endif
--- a/security/sandbox/chromium/base/time/time.cc +++ b/security/sandbox/chromium/base/time/time.cc @@ -1,20 +1,23 @@ // Copyright (c) 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "base/time/time.h" +#include <ios> #include <limits> #include <ostream> +#include <sstream> #include "base/float_util.h" #include "base/lazy_instance.h" #include "base/logging.h" +#include "base/strings/stringprintf.h" #include "base/third_party/nspr/prtime.h" namespace base { // TimeDelta ------------------------------------------------------------------ // static TimeDelta TimeDelta::Max() { @@ -89,16 +92,20 @@ int64 TimeDelta::InMillisecondsRoundedUp int64 TimeDelta::InMicroseconds() const { if (is_max()) { // Preserve max to prevent overflow. return std::numeric_limits<int64>::max(); } return delta_; } +std::ostream& operator<<(std::ostream& os, TimeDelta time_delta) { + return os << time_delta.InSecondsF() << "s"; +}