author | Bob Owen <bobowencode@gmail.com> |
Tue, 18 Nov 2014 13:48:21 +0000 | |
changeset 217593 | a52ce2ed0c280b9a3a4970b471b79ca46af4e43d |
parent 217592 | d37a1340fa0bc3dec06c5040d0d65bf418c0454f |
child 217594 | 90ddcaa449595f506821e5988a735a23a41d0721 |
push id | 27886 |
push user | ryanvm@gmail.com |
push date | Thu, 27 Nov 2014 01:34:27 +0000 |
treeherder | mozilla-central@159a0ec99a6d [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | jld, aklotz, glandium |
bugs | 1041775 |
milestone | 36.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/build/build_config.h +++ b/security/sandbox/build/build_config.h @@ -1,60 +1,58 @@ // 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 adds defines about the platform we're currently building on. // Operating System: -// OS_WIN / OS_MACOSX / OS_LINUX / OS_POSIX (MACOSX or LINUX) +// OS_WIN / OS_MACOSX / OS_LINUX / OS_POSIX (MACOSX or LINUX) / OS_NACL // Compiler: // COMPILER_MSVC / COMPILER_GCC // Processor: // ARCH_CPU_X86 / ARCH_CPU_X86_64 / ARCH_CPU_X86_FAMILY (X86 or X86_64) // ARCH_CPU_32_BITS / ARCH_CPU_64_BITS #ifndef BUILD_BUILD_CONFIG_H_ #define BUILD_BUILD_CONFIG_H_ #if defined(__APPLE__) #include <TargetConditionals.h> #endif // A set of macros to use for platform detection. -#if defined(ANDROID) +#if defined(__native_client__) +// __native_client__ must be first, so that other OS_ defines are not set. +#define OS_NACL 1 +#elif defined(ANDROID) #define OS_ANDROID 1 #elif defined(__APPLE__) #define OS_MACOSX 1 #if defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE #define OS_IOS 1 #endif // defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE -#elif defined(__native_client__) -#define OS_NACL 1 #elif defined(__linux__) #define OS_LINUX 1 -// Use TOOLKIT_GTK on linux if TOOLKIT_VIEWS isn't defined. -#if !defined(TOOLKIT_VIEWS) && defined(USE_X11) -#define TOOLKIT_GTK -#endif +// include a system header to pull in features.h for glibc/uclibc macros. +#include <unistd.h> #if defined(__GLIBC__) && !defined(__UCLIBC__) // we really are using glibc, not uClibc pretending to be glibc -#define LIBC_GLIBC +#define LIBC_GLIBC 1 #endif #elif defined(_WIN32) #define OS_WIN 1 #define TOOLKIT_VIEWS 1 #elif defined(__FreeBSD__) #define OS_FREEBSD 1 -#define TOOLKIT_GTK #elif defined(__OpenBSD__) #define OS_OPENBSD 1 -#define TOOLKIT_GTK #elif defined(__sun) #define OS_SOLARIS 1 -#define TOOLKIT_GTK +#elif defined(__QNXNTO__) +#define OS_QNX 1 #else #error Please add support for your platform in build/build_config.h #endif #if defined(USE_OPENSSL) && defined(USE_NSS) #error Cannot use both OpenSSL and NSS #endif @@ -63,17 +61,17 @@ #if defined(OS_FREEBSD) || defined(OS_OPENBSD) #define OS_BSD 1 #endif // For access to standard POSIXish features, use OS_POSIX instead of a // more specific macro. #if defined(OS_MACOSX) || defined(OS_LINUX) || defined(OS_FREEBSD) || \ defined(OS_OPENBSD) || defined(OS_SOLARIS) || defined(OS_ANDROID) || \ - defined(OS_NACL) + defined(OS_NACL) || defined(OS_QNX) #define OS_POSIX 1 #endif // Use tcmalloc #if (defined(OS_WIN) || defined(OS_LINUX) || defined(OS_ANDROID)) && \ !defined(NO_TCMALLOC) #define USE_TCMALLOC 1 #endif @@ -101,18 +99,24 @@ #define ARCH_CPU_X86 1 #define ARCH_CPU_32_BITS 1 #define ARCH_CPU_LITTLE_ENDIAN 1 #elif defined(__ARMEL__) #define ARCH_CPU_ARM_FAMILY 1 #define ARCH_CPU_ARMEL 1 #define ARCH_CPU_32_BITS 1 #define ARCH_CPU_LITTLE_ENDIAN 1 +#elif defined(__aarch64__) +#define ARCH_CPU_ARM_FAMILY 1 +#define ARCH_CPU_ARM64 1 +#define ARCH_CPU_64_BITS 1 +#define ARCH_CPU_LITTLE_ENDIAN 1 #elif defined(__pnacl__) #define ARCH_CPU_32_BITS 1 +#define ARCH_CPU_LITTLE_ENDIAN 1 #elif defined(__MIPSEL__) #define ARCH_CPU_MIPS_FAMILY 1 #define ARCH_CPU_MIPSEL 1 #define ARCH_CPU_32_BITS 1 #define ARCH_CPU_LITTLE_ENDIAN 1 #else #error Please add support for your architecture in build/build_config.h #endif @@ -131,22 +135,16 @@ // compile in this mode (in particular, Chrome doesn't). This is intended for // other projects using base who manage their own dependencies and make sure // short wchar works for them. #define WCHAR_T_IS_UTF16 #else #error Please add support for your compiler in build/build_config.h #endif -#if defined(__ARMEL__) && !defined(OS_IOS) -#define WCHAR_T_IS_UNSIGNED 1 -#elif defined(__MIPSEL__) -#define WCHAR_T_IS_UNSIGNED 0 -#endif - #if defined(OS_ANDROID) // The compiler thinks std::string::const_iterator and "const char*" are // equivalent types. #define STD_STRING_ITERATOR_IS_CHAR_POINTER // The compiler thinks base::string16::const_iterator and "char16*" are // equivalent types. #define BASE_STRING16_ITERATOR_IS_CHAR16_POINTER #endif
new file mode 100644 --- /dev/null +++ b/security/sandbox/chromium-commit-status.txt @@ -0,0 +1,7 @@ +Chromium Commit Directory / File (relative to security/sandbox/) +---------------------------------------- ------------------------------------------------ +9522fad406dd161400daa518075828e47bd47f60 build +9522fad406dd161400daa518075828e47bd47f60 chromium +8e2be8d727b46e1f6f1694786dc2161b11146bd4 chromium/base/compiler_specific.h + (Note: above is to keep MSVC2010 support.) +9522fad406dd161400daa518075828e47bd47f60 win
--- a/security/sandbox/chromium/base/atomicops.h +++ b/security/sandbox/chromium/base/atomicops.h @@ -23,32 +23,33 @@ // NoBarrier_Load() // Although there are currently no compiler enforcement, you are encouraged // to use these. // #ifndef BASE_ATOMICOPS_H_ #define BASE_ATOMICOPS_H_ -#include "base/basictypes.h" +#include <stdint.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. #undef MemoryBarrier #endif namespace base { namespace subtle { -typedef int32 Atomic32; +typedef int32_t Atomic32; #ifdef ARCH_CPU_64_BITS // We need to be able to go between Atomic64 and AtomicWord implicitly. This // means Atomic64 and AtomicWord should be the same type on 64-bit. #if defined(__ILP32__) || defined(OS_NACL) // NaCl's intptr_t is not actually 64-bits on 64-bit! // http://code.google.com/p/nativeclient/issues/detail?id=1162 typedef int64_t Atomic64; #else @@ -128,30 +129,32 @@ Atomic64 Release_CompareAndSwap(volatile void NoBarrier_Store(volatile Atomic64* ptr, Atomic64 value); void Acquire_Store(volatile Atomic64* ptr, Atomic64 value); void Release_Store(volatile Atomic64* ptr, Atomic64 value); 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 base::subtle +} // 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_ARM_FAMILY) +#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" #endif
--- a/security/sandbox/chromium/base/atomicops_internals_tsan.h +++ b/security/sandbox/chromium/base/atomicops_internals_tsan.h @@ -3,376 +3,184 @@ // 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 "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. - bool has_sse2; // Processor has SSE2. -}; -BASE_EXPORT extern struct AtomicOps_x86CPUFeatureStruct - AtomicOps_Internalx86CPUFeatures; - -#define ATOMICOPS_COMPILER_BARRIER() __asm__ __volatile__("" : : : "memory") +#include <sanitizer/tsan_interface_atomic.h> namespace base { namespace subtle { -#ifndef TSAN_INTERFACE_ATOMIC_H -#define TSAN_INTERFACE_ATOMIC_H - -#ifdef __cplusplus -extern "C" { -#endif - -typedef char __tsan_atomic8; -typedef short __tsan_atomic16; // NOLINT -typedef int __tsan_atomic32; -typedef long __tsan_atomic64; // NOLINT - -#if defined(__SIZEOF_INT128__) \ - || (__clang_major__ * 100 + __clang_minor__ >= 302) -typedef __int128 __tsan_atomic128; -#define __TSAN_HAS_INT128 1 -#else -typedef char __tsan_atomic128; -#define __TSAN_HAS_INT128 0 -#endif - -typedef enum { - __tsan_memory_order_relaxed, - __tsan_memory_order_consume, - __tsan_memory_order_acquire, - __tsan_memory_order_release, - __tsan_memory_order_acq_rel, - __tsan_memory_order_seq_cst, -} __tsan_memory_order; - -__tsan_atomic8 __tsan_atomic8_load(const volatile __tsan_atomic8 *a, - __tsan_memory_order mo); -__tsan_atomic16 __tsan_atomic16_load(const volatile __tsan_atomic16 *a, - __tsan_memory_order mo); -__tsan_atomic32 __tsan_atomic32_load(const volatile __tsan_atomic32 *a, - __tsan_memory_order mo); -__tsan_atomic64 __tsan_atomic64_load(const volatile __tsan_atomic64 *a, - __tsan_memory_order mo); -__tsan_atomic128 __tsan_atomic128_load(const volatile __tsan_atomic128 *a, - __tsan_memory_order mo); - -void __tsan_atomic8_store(volatile __tsan_atomic8 *a, __tsan_atomic8 v, - __tsan_memory_order mo); -void __tsan_atomic16_store(volatile __tsan_atomic16 *a, __tsan_atomic16 v, - __tsan_memory_order mo); -void __tsan_atomic32_store(volatile __tsan_atomic32 *a, __tsan_atomic32 v, - __tsan_memory_order mo); -void __tsan_atomic64_store(volatile __tsan_atomic64 *a, __tsan_atomic64 v, - __tsan_memory_order mo); -void __tsan_atomic128_store(volatile __tsan_atomic128 *a, __tsan_atomic128 v, - __tsan_memory_order mo); - -__tsan_atomic8 __tsan_atomic8_exchange(volatile __tsan_atomic8 *a, - __tsan_atomic8 v, __tsan_memory_order mo); -__tsan_atomic16 __tsan_atomic16_exchange(volatile __tsan_atomic16 *a, - __tsan_atomic16 v, __tsan_memory_order mo); -__tsan_atomic32 __tsan_atomic32_exchange(volatile __tsan_atomic32 *a, - __tsan_atomic32 v, __tsan_memory_order mo); -__tsan_atomic64 __tsan_atomic64_exchange(volatile __tsan_atomic64 *a, - __tsan_atomic64 v, __tsan_memory_order mo); -__tsan_atomic128 __tsan_atomic128_exchange(volatile __tsan_atomic128 *a, - __tsan_atomic128 v, __tsan_memory_order mo); - -__tsan_atomic8 __tsan_atomic8_fetch_add(volatile __tsan_atomic8 *a, - __tsan_atomic8 v, __tsan_memory_order mo); -__tsan_atomic16 __tsan_atomic16_fetch_add(volatile __tsan_atomic16 *a, - __tsan_atomic16 v, __tsan_memory_order mo); -__tsan_atomic32 __tsan_atomic32_fetch_add(volatile __tsan_atomic32 *a, - __tsan_atomic32 v, __tsan_memory_order mo); -__tsan_atomic64 __tsan_atomic64_fetch_add(volatile __tsan_atomic64 *a, - __tsan_atomic64 v, __tsan_memory_order mo); -__tsan_atomic128 __tsan_atomic128_fetch_add(volatile __tsan_atomic128 *a, - __tsan_atomic128 v, __tsan_memory_order mo); - -__tsan_atomic8 __tsan_atomic8_fetch_and(volatile __tsan_atomic8 *a, - __tsan_atomic8 v, __tsan_memory_order mo); -__tsan_atomic16 __tsan_atomic16_fetch_and(volatile __tsan_atomic16 *a, - __tsan_atomic16 v, __tsan_memory_order mo); -__tsan_atomic32 __tsan_atomic32_fetch_and(volatile __tsan_atomic32 *a, - __tsan_atomic32 v, __tsan_memory_order mo); -__tsan_atomic64 __tsan_atomic64_fetch_and(volatile __tsan_atomic64 *a, - __tsan_atomic64 v, __tsan_memory_order mo); -__tsan_atomic128 __tsan_atomic128_fetch_and(volatile __tsan_atomic128 *a, - __tsan_atomic128 v, __tsan_memory_order mo); - -__tsan_atomic8 __tsan_atomic8_fetch_or(volatile __tsan_atomic8 *a, - __tsan_atomic8 v, __tsan_memory_order mo); -__tsan_atomic16 __tsan_atomic16_fetch_or(volatile __tsan_atomic16 *a, - __tsan_atomic16 v, __tsan_memory_order mo); -__tsan_atomic32 __tsan_atomic32_fetch_or(volatile __tsan_atomic32 *a, - __tsan_atomic32 v, __tsan_memory_order mo); -__tsan_atomic64 __tsan_atomic64_fetch_or(volatile __tsan_atomic64 *a, - __tsan_atomic64 v, __tsan_memory_order mo); -__tsan_atomic128 __tsan_atomic128_fetch_or(volatile __tsan_atomic128 *a, - __tsan_atomic128 v, __tsan_memory_order mo); - -__tsan_atomic8 __tsan_atomic8_fetch_xor(volatile __tsan_atomic8 *a, - __tsan_atomic8 v, __tsan_memory_order mo); -__tsan_atomic16 __tsan_atomic16_fetch_xor(volatile __tsan_atomic16 *a, - __tsan_atomic16 v, __tsan_memory_order mo); -__tsan_atomic32 __tsan_atomic32_fetch_xor(volatile __tsan_atomic32 *a, - __tsan_atomic32 v, __tsan_memory_order mo); -__tsan_atomic64 __tsan_atomic64_fetch_xor(volatile __tsan_atomic64 *a, - __tsan_atomic64 v, __tsan_memory_order mo); -__tsan_atomic128 __tsan_atomic128_fetch_xor(volatile __tsan_atomic128 *a, - __tsan_atomic128 v, __tsan_memory_order mo); - -__tsan_atomic8 __tsan_atomic8_fetch_nand(volatile __tsan_atomic8 *a, - __tsan_atomic8 v, __tsan_memory_order mo); -__tsan_atomic16 __tsan_atomic16_fetch_nand(volatile __tsan_atomic16 *a, - __tsan_atomic16 v, __tsan_memory_order mo); -__tsan_atomic32 __tsan_atomic32_fetch_nand(volatile __tsan_atomic32 *a, - __tsan_atomic32 v, __tsan_memory_order mo); -__tsan_atomic64 __tsan_atomic64_fetch_nand(volatile __tsan_atomic64 *a, - __tsan_atomic64 v, __tsan_memory_order mo); -__tsan_atomic128 __tsan_atomic128_fetch_nand(volatile __tsan_atomic128 *a, - __tsan_atomic128 v, __tsan_memory_order mo); - -int __tsan_atomic8_compare_exchange_weak(volatile __tsan_atomic8 *a, - __tsan_atomic8 *c, __tsan_atomic8 v, __tsan_memory_order mo, - __tsan_memory_order fail_mo); -int __tsan_atomic16_compare_exchange_weak(volatile __tsan_atomic16 *a, - __tsan_atomic16 *c, __tsan_atomic16 v, __tsan_memory_order mo, - __tsan_memory_order fail_mo); -int __tsan_atomic32_compare_exchange_weak(volatile __tsan_atomic32 *a, - __tsan_atomic32 *c, __tsan_atomic32 v, __tsan_memory_order mo, - __tsan_memory_order fail_mo); -int __tsan_atomic64_compare_exchange_weak(volatile __tsan_atomic64 *a, - __tsan_atomic64 *c, __tsan_atomic64 v, __tsan_memory_order mo, - __tsan_memory_order fail_mo); -int __tsan_atomic128_compare_exchange_weak(volatile __tsan_atomic128 *a, - __tsan_atomic128 *c, __tsan_atomic128 v, __tsan_memory_order mo, - __tsan_memory_order fail_mo); - -int __tsan_atomic8_compare_exchange_strong(volatile __tsan_atomic8 *a, - __tsan_atomic8 *c, __tsan_atomic8 v, __tsan_memory_order mo, - __tsan_memory_order fail_mo); -int __tsan_atomic16_compare_exchange_strong(volatile __tsan_atomic16 *a, - __tsan_atomic16 *c, __tsan_atomic16 v, __tsan_memory_order mo, - __tsan_memory_order fail_mo); -int __tsan_atomic32_compare_exchange_strong(volatile __tsan_atomic32 *a, - __tsan_atomic32 *c, __tsan_atomic32 v, __tsan_memory_order mo, - __tsan_memory_order fail_mo); -int __tsan_atomic64_compare_exchange_strong(volatile __tsan_atomic64 *a, - __tsan_atomic64 *c, __tsan_atomic64 v, __tsan_memory_order mo, - __tsan_memory_order fail_mo); -int __tsan_atomic128_compare_exchange_strong(volatile __tsan_atomic128 *a, - __tsan_atomic128 *c, __tsan_atomic128 v, __tsan_memory_order mo, - __tsan_memory_order fail_mo); - -__tsan_atomic8 __tsan_atomic8_compare_exchange_val( - volatile __tsan_atomic8 *a, __tsan_atomic8 c, __tsan_atomic8 v, - __tsan_memory_order mo, __tsan_memory_order fail_mo); -__tsan_atomic16 __tsan_atomic16_compare_exchange_val( - volatile __tsan_atomic16 *a, __tsan_atomic16 c, __tsan_atomic16 v, - __tsan_memory_order mo, __tsan_memory_order fail_mo); -__tsan_atomic32 __tsan_atomic32_compare_exchange_val( - volatile __tsan_atomic32 *a, __tsan_atomic32 c, __tsan_atomic32 v, - __tsan_memory_order mo, __tsan_memory_order fail_mo); -__tsan_atomic64 __tsan_atomic64_compare_exchange_val( - volatile __tsan_atomic64 *a, __tsan_atomic64 c, __tsan_atomic64 v, - __tsan_memory_order mo, __tsan_memory_order fail_mo); -__tsan_atomic128 __tsan_atomic128_compare_exchange_val( - volatile __tsan_atomic128 *a, __tsan_atomic128 c, __tsan_atomic128 v, - __tsan_memory_order mo, __tsan_memory_order fail_mo); - -void __tsan_atomic_thread_fence(__tsan_memory_order mo); -void __tsan_atomic_signal_fence(__tsan_memory_order mo); - -#ifdef __cplusplus -} // extern "C" -#endif - -#endif // #ifndef TSAN_INTERFACE_ATOMIC_H - -inline Atomic32 NoBarrier_CompareAndSwap(volatile Atomic32 *ptr, - Atomic32 old_value, - Atomic32 new_value) { +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) { +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) { +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) { +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) { +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) { +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) { +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) { +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) { +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) { +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) { +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) { +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) { +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) { +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) { +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) { +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) { +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) { +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) { +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) { +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) { +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) { +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) { +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) { +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) { +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) { +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) { +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) { +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 -#undef ATOMICOPS_COMPILER_BARRIER - #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 @@ -12,17 +12,16 @@ // 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. - bool has_sse2; // Processor has SSE2. }; BASE_EXPORT extern struct AtomicOps_x86CPUFeatureStruct AtomicOps_Internalx86CPUFeatures; #define ATOMICOPS_COMPILER_BARRIER() __asm__ __volatile__("" : : : "memory") namespace base { namespace subtle { @@ -87,51 +86,25 @@ inline Atomic32 Release_CompareAndSwap(v Atomic32 new_value) { return NoBarrier_CompareAndSwap(ptr, old_value, new_value); } inline void NoBarrier_Store(volatile Atomic32* ptr, Atomic32 value) { *ptr = value; } -#if defined(__x86_64__) - -// 64-bit implementations of memory barrier can be simpler, because it -// "mfence" is guaranteed to exist. inline void MemoryBarrier() { __asm__ __volatile__("mfence" : : : "memory"); } inline void Acquire_Store(volatile Atomic32* ptr, Atomic32 value) { *ptr = value; MemoryBarrier(); } -#else - -inline void MemoryBarrier() { - if (AtomicOps_Internalx86CPUFeatures.has_sse2) { - __asm__ __volatile__("mfence" : : : "memory"); - } else { // mfence is faster but not present on PIII - Atomic32 x = 0; - NoBarrier_AtomicExchange(&x, 0); // acts as a barrier on PIII - } -} - -inline void Acquire_Store(volatile Atomic32* ptr, Atomic32 value) { - if (AtomicOps_Internalx86CPUFeatures.has_sse2) { - *ptr = value; - __asm__ __volatile__("mfence" : : : "memory"); - } else { - NoBarrier_AtomicExchange(ptr, value); - // acts as a barrier on PIII - } -} -#endif - inline void Release_Store(volatile Atomic32* ptr, Atomic32 value) { ATOMICOPS_COMPILER_BARRIER(); *ptr = value; // An x86 store acts as a release barrier. // See comments in Atomic64 version of Release_Store(), below. } inline Atomic32 NoBarrier_Load(volatile const Atomic32* ptr) { return *ptr;
--- a/security/sandbox/chromium/base/atomicops_internals_x86_msvc.h +++ b/security/sandbox/chromium/base/atomicops_internals_x86_msvc.h @@ -4,49 +4,53 @@ // This file is an internal atomic implementation, use base/atomicops.h instead. #ifndef BASE_ATOMICOPS_INTERNALS_X86_MSVC_H_ #define BASE_ATOMICOPS_INTERNALS_X86_MSVC_H_ #include <windows.h> +#include <intrin.h> + +#include "base/macros.h" + #if 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. #undef MemoryBarrier #endif namespace base { namespace subtle { inline Atomic32 NoBarrier_CompareAndSwap(volatile Atomic32* ptr, Atomic32 old_value, Atomic32 new_value) { - LONG result = InterlockedCompareExchange( + LONG result = _InterlockedCompareExchange( reinterpret_cast<volatile LONG*>(ptr), static_cast<LONG>(new_value), static_cast<LONG>(old_value)); return static_cast<Atomic32>(result); } inline Atomic32 NoBarrier_AtomicExchange(volatile Atomic32* ptr, Atomic32 new_value) { - LONG result = InterlockedExchange( + LONG result = _InterlockedExchange( reinterpret_cast<volatile LONG*>(ptr), static_cast<LONG>(new_value)); return static_cast<Atomic32>(result); } inline Atomic32 Barrier_AtomicIncrement(volatile Atomic32* ptr, Atomic32 increment) { - return InterlockedExchangeAdd( + return _InterlockedExchangeAdd( reinterpret_cast<volatile LONG*>(ptr), static_cast<LONG>(increment)) + increment; } inline Atomic32 NoBarrier_AtomicIncrement(volatile Atomic32* ptr, Atomic32 increment) { return Barrier_AtomicIncrement(ptr, increment); }
--- a/security/sandbox/chromium/base/base_paths.h +++ b/security/sandbox/chromium/base/base_paths.h @@ -26,16 +26,20 @@ namespace base { enum BasePathKey { PATH_START = 0, DIR_CURRENT, // Current directory. DIR_EXE, // Directory containing FILE_EXE. DIR_MODULE, // Directory containing FILE_MODULE. DIR_TEMP, // Temporary directory. + DIR_HOME, // User's root home directory. On Windows this will look + // like "C:\Users\you" (or on XP + // "C:\Document and Settings\you") which isn't necessarily + // a great place to put files. FILE_EXE, // Path and filename of the current executable. FILE_MODULE, // Path and filename of the module containing the code for // the PathService (which could differ from FILE_EXE if the // PathService were compiled into a shared object, for // example). DIR_SOURCE_ROOT, // Returns the root of the source tree. This key is useful // for tests that need to locate various resources. It // should not be used outside of test code.
--- a/security/sandbox/chromium/base/base_paths_win.h +++ b/security/sandbox/chromium/base/base_paths_win.h @@ -20,32 +20,32 @@ 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_PROFILE, // Usually "C:\Documents and settings\<user>. 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 #endif // BASE_BASE_PATHS_WIN_H__
--- a/security/sandbox/chromium/base/base_switches.cc +++ b/security/sandbox/chromium/base/base_switches.cc @@ -1,31 +1,32 @@ // 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/base_switches.h" namespace switches { -// If the program includes base/debug/debug_on_start_win.h, the process will -// (on Windows only) start the JIT system-registered debugger on itself and -// will wait for 60 seconds for the debugger to attach to itself. Then a break -// point will be hit. -const char kDebugOnStart[] = "debug-on-start"; - // Disables the crash reporting. const char kDisableBreakpad[] = "disable-breakpad"; -// Enable DCHECKs in release mode. -const char kEnableDCHECK[] = "enable-dcheck"; +// Indicates that crash reporting should be enabled. On platforms where helper +// processes cannot access to files needed to make this decision, this flag is +// generated internally. +const char kEnableCrashReporter[] = "enable-crash-reporter"; // Generates full memory crash dump. const char kFullMemoryCrashReport[] = "full-memory-crash-report"; +// Force low-end device when set to 1; +// Auto-detect low-end device when set to 2; +// Force non-low-end device when set to other values or empty; +const char kLowEndDeviceMode[] = "low-end-device-mode"; + // Suppresses all error dialogs when present. const char kNoErrorDialogs[] = "noerrdialogs"; // When running certain tests that spawn child processes, this switch indicates // to the test framework that the current process is a child process. const char kTestChildProcess[] = "test-child-process"; // Gives the default maximal active V-logging level; 0 is the default. @@ -44,17 +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"; +// 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"; + #if defined(OS_POSIX) -// A flag, generated internally for renderer and other helper process command -// lines on Linux and Mac. It tells the helper process to enable crash dumping -// and reporting, because helpers cannot access the files needed to make this -// decision. -const char kEnableCrashReporter[] = "enable-crash-reporter"; +// Used for turning on Breakpad crash reporting in a debug environment where +// crash reporting is typically compiled but disabled. +const char kEnableCrashReporterForTesting[] = + "enable-crash-reporter-for-testing"; #endif } // namespace switches
--- a/security/sandbox/chromium/base/base_switches.h +++ b/security/sandbox/chromium/base/base_switches.h @@ -6,26 +6,28 @@ #ifndef BASE_BASE_SWITCHES_H_ #define BASE_BASE_SWITCHES_H_ #include "build/build_config.h" namespace switches { -extern const char kDebugOnStart[]; extern const char kDisableBreakpad[]; -extern const char kEnableDCHECK[]; +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 kV[]; extern const char kVModule[]; extern const char kWaitForDebugger[]; -extern const char kTraceToConsole[]; #if defined(OS_POSIX) -extern const char kEnableCrashReporter[]; +extern const char kEnableCrashReporterForTesting[]; #endif } // namespace switches #endif // BASE_BASE_SWITCHES_H_
--- a/security/sandbox/chromium/base/basictypes.h +++ b/security/sandbox/chromium/base/basictypes.h @@ -37,22 +37,22 @@ typedef uint32_t uint32; typedef long int64; typedef unsigned long uint64; #else typedef long long int64; typedef unsigned long long uint64; #endif // DEPRECATED: Please use std::numeric_limits (from <limits>) instead. -const uint8 kuint8max = (( uint8) 0xFF); -const uint16 kuint16max = ((uint16) 0xFFFF); -const uint32 kuint32max = ((uint32) 0xFFFFFFFF); -const uint64 kuint64max = ((uint64) GG_LONGLONG(0xFFFFFFFFFFFFFFFF)); -const int8 kint8min = (( int8) 0x80); -const int8 kint8max = (( int8) 0x7F); -const int16 kint16min = (( int16) 0x8000); -const int16 kint16max = (( int16) 0x7FFF); -const int32 kint32min = (( int32) 0x80000000); -const int32 kint32max = (( int32) 0x7FFFFFFF); -const int64 kint64min = (( int64) GG_LONGLONG(0x8000000000000000)); -const int64 kint64max = (( int64) GG_LONGLONG(0x7FFFFFFFFFFFFFFF)); +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; +const int16 kint16min = -0x7FFF - 1; +const int16 kint16max = 0x7FFF; +const int32 kint32min = -0x7FFFFFFF - 1; +const int32 kint32max = 0x7FFFFFFF; +const int64 kint64min = -0x7FFFFFFFFFFFFFFFLL - 1; +const int64 kint64max = 0x7FFFFFFFFFFFFFFFLL; #endif // BASE_BASICTYPES_H_
--- a/security/sandbox/chromium/base/bind.h +++ b/security/sandbox/chromium/base/bind.h @@ -60,22 +60,16 @@ base::Callback< typename internal::FunctorTraits<Functor>::RunType, void()> ::UnboundRunType> Bind(Functor functor) { // Typedefs for how to store and run the functor. typedef typename internal::FunctorTraits<Functor>::RunnableType RunnableType; typedef typename internal::FunctorTraits<Functor>::RunType RunType; - // Use RunnableType::RunType instead of RunType above because our - // checks should below for bound references need to know what the actual - // functor is going to interpret the argument as. - typedef internal::FunctionTraits<typename RunnableType::RunType> - BoundFunctorTraits; - typedef internal::BindState<RunnableType, RunType, void()> BindState; return Callback<typename BindState::UnboundRunType>( new BindState(internal::MakeRunnable(functor))); } template <typename Functor, typename P1>
--- a/security/sandbox/chromium/base/bind_helpers.h +++ b/security/sandbox/chromium/base/bind_helpers.h @@ -7,17 +7,17 @@ // that are bound by the Bind() function in base/bind.h. // // It also defines a set of simple functions and utilities that people want // when using Callback<> and Bind(). // // // ARGUMENT BINDING WRAPPERS // -// The wrapper functions are base::Unretained(), base::Owned(), bass::Passed(), +// The wrapper functions are base::Unretained(), base::Owned(), base::Passed(), // base::ConstRef(), and base::IgnoreResult(). // // Unretained() allows Bind() to bind a non-refcounted class, and to disable // refcounting on arguments that are refcounted objects. // // Owned() transfers ownership of an object to the Callback resulting from // bind; the object will be deleted when the Callback is deleted. //
--- a/security/sandbox/chromium/base/callback.h +++ b/security/sandbox/chromium/base/callback.h @@ -138,18 +138,18 @@ // ----------------------------------------------------------------------------- // Quick reference for advanced binding // ----------------------------------------------------------------------------- // // BINDING A CLASS METHOD WITH WEAK POINTERS // // base::Bind(&MyClass::Foo, GetWeakPtr()); // -// The callback will not be issued if the object is destroyed at the time -// it's issued. DANGER: weak pointers are not threadsafe, so don't use this +// The callback will not be run if the object has already been destroyed. +// DANGER: weak pointers are not threadsafe, so don't use this // when passing between threads! // // BINDING A CLASS METHOD WITH MANUAL LIFETIME MANAGEMENT // // base::Bind(&MyClass::Foo, base::Unretained(this)); // // This disables all lifetime management on the object. You're responsible // for making sure the object is alive at the time of the call. You break it, @@ -209,21 +209,26 @@ // scoped_refptr<Foo> f(new Foo) // base::Closure cb = base::Bind(&TakesOneRef, f); // // This should "just work." The closure will take a reference as long as it // is alive, and another reference will be taken for the called function. // // PASSING PARAMETERS BY REFERENCE // -// void foo(int arg) { cout << arg << endl } +// Const references are *copied* unless ConstRef is used. Example: +// +// void foo(const int& arg) { printf("%d %p\n", arg, &arg); } // int n = 1; +// base::Closure has_copy = base::Bind(&foo, n); // base::Closure has_ref = base::Bind(&foo, base::ConstRef(n)); // n = 2; -// has_ref.Run(); // Prints "2" +// foo(n); // Prints "2 0xaaaaaaaaaaaa" +// has_copy.Run(); // Prints "1 0xbbbbbbbbbbbb" +// has_ref.Run(); // Prints "2 0xaaaaaaaaaaaa" // // Normally parameters are copied in the closure. DANGER: ConstRef stores a // const reference instead, referencing the original parameter. This means // that you must ensure the object outlives the callback! // // // ----------------------------------------------------------------------------- // Implementation notes @@ -751,15 +756,15 @@ class Callback<R(A1, A2, A3, A4, A5, A6, typename internal::CallbackParamTraits<A4>::ForwardType, typename internal::CallbackParamTraits<A5>::ForwardType, typename internal::CallbackParamTraits<A6>::ForwardType, typename internal::CallbackParamTraits<A7>::ForwardType); }; -// Syntactic sugar to make Callbacks<void(void)> easier to declare since it +// Syntactic sugar to make Callback<void(void)> easier to declare since it // will be used in a lot of APIs with delayed execution. typedef Callback<void(void)> Closure; } // namespace base #endif // BASE_CALLBACK_H
--- a/security/sandbox/chromium/base/callback_internal.h +++ b/security/sandbox/chromium/base/callback_internal.h @@ -62,58 +62,72 @@ class BASE_EXPORT CallbackBase { // that our subclasses will not get inlined versions. Avoids more template // bloat. ~CallbackBase(); scoped_refptr<BindStateBase> bind_state_; InvokeFuncStorage polymorphic_invoke_; }; +// A helper template to determine if given type is non-const move-only-type, +// i.e. if a value of the given type should be passed via .Pass() in a +// 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) && + !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 // "reference of a reference" if the argument is a reference type. // // This array type becomes an issue for storage because we are passing bound // parameters by const reference. In this case, we end up passing an actual // array type in the initializer list which C++ does not allow. This will // break passing of C-string literals. -template <typename T> +template <typename T, bool is_move_only = IsMoveOnlyType<T>::value> struct CallbackParamTraits { typedef const T& ForwardType; typedef T StorageType; }; // The Storage should almost be impossible to trigger unless someone manually // specifies type of the bind parameters. However, in case they do, // this will guard against us accidentally storing a reference parameter. // // The ForwardType should only be used for unbound arguments. template <typename T> -struct CallbackParamTraits<T&> { +struct CallbackParamTraits<T&, false> { typedef T& ForwardType; typedef T StorageType; }; // Note that for array types, we implicitly add a const in the conversion. This // means that it is not possible to bind array arguments to functions that take // a non-const pointer. Trying to specialize the template based on a "const // T[n]" does not seem to match correctly, so we are stuck with this // restriction. template <typename T, size_t n> -struct CallbackParamTraits<T[n]> { +struct CallbackParamTraits<T[n], false> { typedef const T* ForwardType; typedef const T* StorageType; }; // See comment for CallbackParamTraits<T[n]>. template <typename T> -struct CallbackParamTraits<T[]> { +struct CallbackParamTraits<T[], false> { typedef const T* ForwardType; typedef const T* StorageType; }; // Parameter traits for movable-but-not-copyable scopers. // // Callback<>/Bind() understands movable-but-not-copyable semantics where // the type cannot be copied but can still have its state destructively @@ -121,36 +135,20 @@ struct CallbackParamTraits<T[]> { // helper function. When used with Bind(), this signifies transferal of the // object's state to the target function. // // For these types, the ForwardType must not be a const reference, or a // reference. A const reference is inappropriate, and would break const // correctness, because we are implementing a destructive move. A non-const // reference cannot be used with temporaries which means the result of a // function or a cast would not be usable with Callback<> or Bind(). -// -// TODO(ajwong): We might be able to use SFINAE to search for the existence of -// a Pass() function in the type and avoid the whitelist in CallbackParamTraits -// and CallbackForward. -template <typename T, typename D> -struct CallbackParamTraits<scoped_ptr<T, D> > { - typedef scoped_ptr<T, D> ForwardType; - typedef scoped_ptr<T, D> StorageType; -}; - -template <typename T, typename R> -struct CallbackParamTraits<scoped_ptr_malloc<T, R> > { - typedef scoped_ptr_malloc<T, R> ForwardType; - typedef scoped_ptr_malloc<T, R> StorageType; -}; - template <typename T> -struct CallbackParamTraits<ScopedVector<T> > { - typedef ScopedVector<T> ForwardType; - typedef ScopedVector<T> StorageType; +struct CallbackParamTraits<T, true> { + typedef T ForwardType; + typedef T StorageType; }; // CallbackForward() is a very limited simulation of C++11's std::forward() // used by the Callback/Bind system for a set of movable-but-not-copyable // types. It is needed because forwarding a movable-but-not-copyable // argument to another function requires us to invoke the proper move // operator to create a rvalue version of the type. The supported types are // whitelisted below as overloads of the CallbackForward() function. The @@ -160,25 +158,21 @@ struct CallbackParamTraits<ScopedVector< // is impossible to implement a general std::forward with C++11 due to a lack // of rvalue references. // // In addition to Callback/Bind, this is used by PostTaskAndReplyWithResult to // simulate std::forward() and forward the result of one Callback as a // parameter to another callback. This is to support Callbacks that return // the movable-but-not-copyable types whitelisted above. template <typename T> -T& CallbackForward(T& t) { return t; } - -template <typename T, typename D> -scoped_ptr<T, D> CallbackForward(scoped_ptr<T, D>& p) { return p.Pass(); } - -template <typename T, typename R> -scoped_ptr_malloc<T, R> CallbackForward(scoped_ptr_malloc<T, R>& p) { - return p.Pass(); +typename enable_if<!IsMoveOnlyType<T>::value, T>::type& CallbackForward(T& t) { + return t; } template <typename T> -ScopedVector<T> CallbackForward(ScopedVector<T>& p) { return p.Pass(); } +typename enable_if<IsMoveOnlyType<T>::value, T>::type CallbackForward(T& t) { + return t.Pass(); +} } // namespace internal } // namespace base #endif // BASE_CALLBACK_INTERNAL_H_
--- a/security/sandbox/chromium/base/compiler_specific.h +++ b/security/sandbox/chromium/base/compiler_specific.h @@ -63,16 +63,38 @@ #define MSVC_POP_WARNING() #define MSVC_DISABLE_OPTIMIZE() #define MSVC_ENABLE_OPTIMIZE() #define NON_EXPORTED_BASE(code) code #endif // COMPILER_MSVC +// The C++ standard requires that static const members have an out-of-class +// definition (in a single compilation unit), but MSVC chokes on this (when +// language extensions, which are required, are enabled). (You're only likely to +// notice the need for a definition if you take the address of the member or, +// more commonly, pass it to a function that takes it as a reference argument -- +// probably an STL function.) This macro makes MSVC do the right thing. See +// http://msdn.microsoft.com/en-us/library/34h23df8(v=vs.100).aspx for more +// information. Use like: +// +// In .h file: +// struct Foo { +// static const int kBar = 5; +// }; +// +// In .cc file: +// STATIC_CONST_MEMBER_DEFINITION const int Foo::kBar; +#if defined(COMPILER_MSVC) +#define STATIC_CONST_MEMBER_DEFINITION __declspec(selectany) +#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 = ...; #if defined(COMPILER_GCC) #define ALLOW_UNUSED __attribute__((unused)) #else @@ -114,29 +136,37 @@ // 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(COMPILER_MSVC) +#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(__clang__) +#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; @@ -161,24 +191,39 @@ // WPRINTF_FORMAT is the same, but for wide format strings. // This doesn't appear to yet be implemented in any compiler. // See http://gcc.gnu.org/bugzilla/show_bug.cgi?id=38308 . #define WPRINTF_FORMAT(format_param, dots_param) // If available, it would look like: // __attribute__((format(wprintf, format_param, dots_param))) - // MemorySanitizer annotations. -#ifdef MEMORY_SANITIZER -extern "C" { -void __msan_unpoison(const void *p, unsigned long s); -} // extern "C" +#if defined(MEMORY_SANITIZER) && !defined(OS_NACL) +#include <sanitizer/msan_interface.h> // Mark a memory region fully initialized. // Use this to annotate code that deliberately reads uninitialized data, for // example a GC scavenging root set pointers from the stack. #define MSAN_UNPOISON(p, s) __msan_unpoison(p, s) #else // MEMORY_SANITIZER #define MSAN_UNPOISON(p, s) #endif // MEMORY_SANITIZER +// Macro useful for writing cross-platform function pointers. +#if !defined(CDECL) +#if defined(OS_WIN) +#define CDECL __cdecl +#else // defined(OS_WIN) +#define CDECL +#endif // defined(OS_WIN) +#endif // !defined(CDECL) + +// Macro for hinting that an expression is likely to be false. +#if !defined(UNLIKELY) +#if defined(COMPILER_GCC) +#define UNLIKELY(x) __builtin_expect(!!(x), 0) +#else +#define UNLIKELY(x) (x) +#endif // defined(COMPILER_GCC) +#endif // !defined(UNLIKELY) + #endif // BASE_COMPILER_SPECIFIC_H_
--- a/security/sandbox/chromium/base/containers/hash_tables.h +++ b/security/sandbox/chromium/base/containers/hash_tables.h @@ -98,17 +98,17 @@ DEFINE_TRIVIAL_HASH(unsigned long long); std::size_t result = 0; \ for (string_type::const_iterator i = s.begin(); i != s.end(); ++i) \ result = (result * 131) + *i; \ return result; \ } \ } DEFINE_STRING_HASH(std::string); -DEFINE_STRING_HASH(string16); +DEFINE_STRING_HASH(base::string16); #undef DEFINE_STRING_HASH } // namespace BASE_HASH_NAMESPACE #else // COMPILER #error define BASE_HASH_NAMESPACE for your compiler #endif // COMPILER @@ -135,17 +135,17 @@ inline std::size_t HashInts32(uint32 val if (sizeof(std::size_t) >= sizeof(uint64)) return static_cast<std::size_t>(hash64); uint64 odd_random = 481046412LL << 32 | 1025306955LL; uint32 shift_random = 10121U << 16; hash64 = hash64 * odd_random + shift_random; std::size_t high_bits = static_cast<std::size_t>( - hash64 >> (sizeof(uint64) - sizeof(std::size_t))); + hash64 >> (8 * (sizeof(uint64) - sizeof(std::size_t)))); return high_bits; } // Implement hashing for pairs of up-to 64-bit integer values. // We use the compound integer hash method to produce a 64-bit hash code, by // breaking the two 64-bit inputs into 4 32-bit values: // http://opendatastructures.org/versions/edition-0.1d/ods-java/node33.html#SECTION00832000000000000000 // Then we reduce our result to 32 bits if required, similar to above. @@ -170,17 +170,17 @@ inline std::size_t HashInts64(uint64 val if (sizeof(std::size_t) >= sizeof(uint64)) return static_cast<std::size_t>(hash64); uint64 odd_random = 1578233944LL << 32 | 194370989LL; uint32 shift_random = 20591U << 16; hash64 = hash64 * odd_random + shift_random; std::size_t high_bits = static_cast<std::size_t>( - hash64 >> (sizeof(uint64) - sizeof(std::size_t))); + hash64 >> (8 * (sizeof(uint64) - sizeof(std::size_t)))); return high_bits; } #define DEFINE_32BIT_PAIR_HASH(Type1, Type2) \ inline std::size_t HashPair(Type1 value1, Type2 value2) { \ return HashInts32(value1, value2); \ }
--- a/security/sandbox/chromium/base/cpu.cc +++ b/security/sandbox/chromium/base/cpu.cc @@ -3,21 +3,28 @@ // found in the LICENSE file. #include "base/cpu.h" #include <string.h> #include <algorithm> +#include "base/basictypes.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/lazy_instance.h" +#endif + #if defined(ARCH_CPU_X86_FAMILY) #if defined(_MSC_VER) #include <intrin.h> +#include <immintrin.h> // For _xgetbv() #endif #endif namespace base { CPU::CPU() : signature_(0), type_(0), @@ -28,68 +35,117 @@ CPU::CPU() ext_family_(0), has_mmx_(false), has_sse_(false), has_sse2_(false), 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), cpu_vendor_("unknown") { Initialize(); } +namespace { + #if defined(ARCH_CPU_X86_FAMILY) #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" "xchg %%edi, %%ebx\n" : "=a"(cpu_info[0]), "=D"(cpu_info[1]), "=c"(cpu_info[2]), "=d"(cpu_info[3]) : "a"(info_type) ); } -void __cpuidex(int cpu_info[4], int info_type, int info_index) { - __asm__ volatile ( - "mov %%ebx, %%edi\n" - "cpuid\n" - "xchg %%edi, %%ebx\n" - : "=a"(cpu_info[0]), "=D"(cpu_info[1]), "=c"(cpu_info[2]), "=d"(cpu_info[3]) - : "a"(info_type), "c"(info_index) - ); -} - #else void __cpuid(int cpu_info[4], int info_type) { __asm__ volatile ( "cpuid \n\t" : "=a"(cpu_info[0]), "=b"(cpu_info[1]), "=c"(cpu_info[2]), "=d"(cpu_info[3]) : "a"(info_type) ); } -void __cpuidex(int cpu_info[4], int info_type, int info_index) { - __asm__ volatile ( - "cpuid \n\t" - : "=a"(cpu_info[0]), "=b"(cpu_info[1]), "=c"(cpu_info[2]), "=d"(cpu_info[3]) - : "a"(info_type), "c"(info_index) - ); +#endif + +// _xgetbv returns the value of an Intel Extended Control Register (XCR). +// Currently only XCR0 is defined by Intel so |xcr| should always be zero. +uint64 _xgetbv(uint32 xcr) { + uint32 eax, edx; + + __asm__ volatile ("xgetbv" : "=a" (eax), "=d" (edx) : "c" (xcr)); + return (static_cast<uint64>(edx) << 32) | eax; } -#endif -#endif // _MSC_VER +#endif // !_MSC_VER #endif // ARCH_CPU_X86_FAMILY +#if defined(ARCH_CPU_ARM_FAMILY) && (defined(OS_ANDROID) || defined(OS_LINUX)) + +// 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()) { + 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 (line.compare(0, strlen(kProcessorPrefix), kProcessorPrefix) == 0) { + cpu_brand.assign(line.substr(strlen(kProcessorPrefix))); + break; + } + } + } + return cpu_brand; +} + +class LazyCpuInfoValue { + public: + LazyCpuInfoValue() : value_(ParseCpuInfo()) {} + const std::string& value() { return value_; } + + private: + const std::string value_; + DISALLOW_COPY_AND_ASSIGN(LazyCpuInfoValue); +}; + +base::LazyInstance<LazyCpuInfoValue> g_lazy_cpu_brand = + 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}; char cpu_string[48]; // __cpuid with an InfoType argument of 0 returns the number of // valid Ids in CPUInfo[0] and the CPU identification string in // the other three array elements. The CPU identification string is @@ -108,24 +164,41 @@ void CPU::Initialize() { __cpuid(cpu_info, 1); signature_ = cpu_info[0]; stepping_ = cpu_info[0] & 0xf; model_ = ((cpu_info[0] >> 4) & 0xf) + ((cpu_info[0] >> 12) & 0xf0); family_ = (cpu_info[0] >> 8) & 0xf; type_ = (cpu_info[0] >> 12) & 0x3; ext_model_ = (cpu_info[0] >> 16) & 0xf; ext_family_ = (cpu_info[0] >> 20) & 0xff; - has_mmx_ = (cpu_info[3] & 0x00800000) != 0; - has_sse_ = (cpu_info[3] & 0x02000000) != 0; - has_sse2_ = (cpu_info[3] & 0x04000000) != 0; - has_sse3_ = (cpu_info[2] & 0x00000001) != 0; + has_mmx_ = (cpu_info[3] & 0x00800000) != 0; + has_sse_ = (cpu_info[3] & 0x02000000) != 0; + has_sse2_ = (cpu_info[3] & 0x04000000) != 0; + has_sse3_ = (cpu_info[2] & 0x00000001) != 0; has_ssse3_ = (cpu_info[2] & 0x00000200) != 0; has_sse41_ = (cpu_info[2] & 0x00080000) != 0; has_sse42_ = (cpu_info[2] & 0x00100000) != 0; - has_avx_ = (cpu_info[2] & 0x10000000) != 0; + has_avx_hardware_ = + (cpu_info[2] & 0x10000000) != 0; + // AVX instructions will generate an illegal instruction exception unless + // a) they are supported by the CPU, + // b) XSAVE is supported by the CPU and + // c) XSAVE is enabled by the kernel. + // See http://software.intel.com/en-us/blogs/2011/04/14/is-avx-enabled + // + // In addition, we have observed some crashes with the xgetbv instruction + // even after following Intel's example code. (See crbug.com/375968.) + // Because of that, we also test the XSAVE bit because its description in + // the CPUID documentation suggests that it signals xgetbv support. + has_avx_ = + has_avx_hardware_ && + (cpu_info[2] & 0x04000000) != 0 /* XSAVE */ && + (cpu_info[2] & 0x08000000) != 0 /* OSXSAVE */ && + (_xgetbv(0) & 6) == 6 /* XSAVE enabled by kernel */; + has_aesni_ = (cpu_info[2] & 0x02000000) != 0; } // Get the brand string of the cpu. __cpuid(cpu_info, 0x80000000); const int parameter_end = 0x80000004; int max_parameter = cpu_info[0]; if (cpu_info[0] >= parameter_end) { @@ -140,16 +213,18 @@ void CPU::Initialize() { cpu_brand_.assign(cpu_string, cpu_string_ptr - cpu_string); } 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()); #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 @@ -41,16 +41,23 @@ class BASE_EXPORT CPU { bool has_mmx() const { return has_mmx_; } bool has_sse() const { return has_sse_; } bool has_sse2() const { return has_sse2_; } bool has_sse3() const { return has_sse3_; } bool has_ssse3() const { return has_ssse3_; } bool has_sse41() const { return has_sse41_; } bool has_sse42() const { return has_sse42_; } bool has_avx() const { return has_avx_; } + // has_avx_hardware returns true when AVX is present in the CPU. This might + // differ from the value of |has_avx()| because |has_avx()| also tests for + // 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_; } IntelMicroArchitecture GetIntelMicroArchitecture() const; const std::string& cpu_brand() const { return cpu_brand_; } private: // Query the processor for CPUID information. @@ -66,16 +73,18 @@ class BASE_EXPORT CPU { bool has_mmx_; bool has_sse_; bool has_sse2_; 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_; std::string cpu_vendor_; std::string cpu_brand_; }; } // namespace base #endif // BASE_CPU_H_
--- a/security/sandbox/chromium/base/debug/debugger.h +++ b/security/sandbox/chromium/base/debug/debugger.h @@ -9,20 +9,16 @@ #ifndef BASE_DEBUG_DEBUGGER_H #define BASE_DEBUG_DEBUGGER_H #include "base/base_export.h" namespace base { namespace debug { -// Starts the registered system-wide JIT debugger to attach it to specified -// process. -BASE_EXPORT bool SpawnDebuggerOnProcess(unsigned process_id); - // Waits wait_seconds seconds for a debugger to attach to the current process. // When silent is false, an exception is thrown when a debugger is detected. BASE_EXPORT bool WaitForDebugger(int wait_seconds, bool silent); // Returns true if the given process is being run under a debugger. // // On OS X, the underlying mechanism doesn't work when the sandbox is enabled. // To get around this, this function caches its value.
--- a/security/sandbox/chromium/base/debug/leak_annotations.h +++ b/security/sandbox/chromium/base/debug/leak_annotations.h @@ -1,49 +1,39 @@ // 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_DEBUG_LEAK_ANNOTATIONS_H_ #define BASE_DEBUG_LEAK_ANNOTATIONS_H_ +#include "base/basictypes.h" #include "build/build_config.h" // This file defines macros which can be used to annotate intentional memory -// leaks. Support for annotations is implemented in HeapChecker and -// LeakSanitizer. Annotated objects will be treated as a source of live -// pointers, i.e. any heap objects reachable by following pointers from an -// annotated object will not be reported as leaks. +// leaks. Support for annotations is implemented in LeakSanitizer. Annotated +// objects will be treated as a source of live pointers, i.e. any heap objects +// reachable by following pointers from an annotated object will not be +// reported as leaks. // // ANNOTATE_SCOPED_MEMORY_LEAK: all allocations made in the current scope // will be annotated as leaks. // ANNOTATE_LEAKING_OBJECT_PTR(X): the heap object referenced by pointer X will // be annotated as a leak. -// -// Note that HeapChecker will report a fatal error if an object which has been -// annotated with ANNOTATE_LEAKING_OBJECT_PTR is later deleted (but -// LeakSanitizer won't). - -#if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_NACL) && \ - defined(USE_HEAPCHECKER) -#include "third_party/tcmalloc/chromium/src/gperftools/heap-checker.h" - -#define ANNOTATE_SCOPED_MEMORY_LEAK \ - HeapLeakChecker::Disabler heap_leak_checker_disabler; static_cast<void>(0) +#if defined(LEAK_SANITIZER) && !defined(OS_NACL) -#define ANNOTATE_LEAKING_OBJECT_PTR(X) \ - HeapLeakChecker::IgnoreObject(X) - -#elif defined(LEAK_SANITIZER) && !defined(OS_NACL) - +// Public LSan API from <sanitizer/lsan_interface.h>. extern "C" { void __lsan_disable(); void __lsan_enable(); void __lsan_ignore_object(const void *p); + +// Invoke leak detection immediately. If leaks are found, the process will exit. +void __lsan_do_leak_check(); } // extern "C" class ScopedLeakSanitizerDisabler { public: ScopedLeakSanitizerDisabler() { __lsan_disable(); } ~ScopedLeakSanitizerDisabler() { __lsan_enable(); } private: DISALLOW_COPY_AND_ASSIGN(ScopedLeakSanitizerDisabler);
--- a/security/sandbox/chromium/base/debug/profiler.cc +++ b/security/sandbox/chromium/base/debug/profiler.cc @@ -9,24 +9,26 @@ #include "base/process/process_handle.h" #include "base/strings/string_util.h" #include "base/strings/stringprintf.h" #if defined(OS_WIN) #include "base/win/pe_image.h" #endif // defined(OS_WIN) -#if defined(ENABLE_PROFILING) && !defined(NO_TCMALLOC) +// TODO(peria): Enable profiling on Windows. +#if defined(ENABLE_PROFILING) && !defined(NO_TCMALLOC) && !defined(OS_WIN) #include "third_party/tcmalloc/chromium/src/gperftools/profiler.h" #endif namespace base { namespace debug { -#if defined(ENABLE_PROFILING) && !defined(NO_TCMALLOC) +// TODO(peria): Enable profiling on Windows. +#if defined(ENABLE_PROFILING) && !defined(NO_TCMALLOC) && !defined(OS_WIN) static int profile_count = 0; void StartProfiling(const std::string& name) { ++profile_count; std::string full_name(name); std::string pid = StringPrintf("%d", GetCurrentProcId()); std::string count = StringPrintf("%d", profile_count);
--- a/security/sandbox/chromium/base/file_descriptor_posix.h +++ b/security/sandbox/chromium/base/file_descriptor_posix.h @@ -1,38 +1,43 @@ // 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" + 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 // these objects over IPC. See comments in ipc/ipc_message_utils.h // above the template specialisation for this structure. // ----------------------------------------------------------------------------- struct FileDescriptor { - FileDescriptor() - : fd(-1), - auto_close(false) { } + FileDescriptor() : fd(-1), auto_close(false) {} - FileDescriptor(int ifd, bool iauto_close) - : fd(ifd), - auto_close(iauto_close) { } + FileDescriptor(int ifd, bool iauto_close) : fd(ifd), auto_close(iauto_close) { + } + + FileDescriptor(File file) : fd(file.TakePlatformFile()), 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); + } + // A comparison operator so that we can use these as keys in a std::map. bool operator<(const FileDescriptor& other) const { return other.fd < fd; } int fd; // If true, this file descriptor should be closed after it has been used. For // example an IPC system might interpret this flag as indicating that the
--- a/security/sandbox/chromium/base/file_util.h +++ b/security/sandbox/chromium/base/file_util.h @@ -20,33 +20,31 @@ #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/platform_file.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; -extern bool g_bug108724_debug; - //----------------------------------------------------------------------------- // 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); @@ -90,28 +88,34 @@ BASE_EXPORT bool Move(const FilePath& fr // 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, - PlatformFileError* error); + 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); @@ -127,46 +131,55 @@ BASE_EXPORT bool DirectoryExists(const F 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); -// Read the file at |path| into |contents|, returning true on success. -// This function fails if the |path| contains path traversal components ('..'). -// |contents| may be NULL, in which case this function is useful for its -// side effect of priming the disk cache. -// Useful for unit tests. +// 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); -} // namespace base - -// ----------------------------------------------------------------------------- - -namespace file_util { +// 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 base::FilePath& target, - const base::FilePath& symlink); +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 base::FilePath& symlink, - base::FilePath* target); +BASE_EXPORT bool ReadSymbolicLink(const FilePath& symlink, FilePath* target); -// Bits ans masks of the file permission. +// 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, @@ -177,183 +190,168 @@ enum FilePermissionBits { 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 base::FilePath& path, - int* mode); +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 base::FilePath& path, - int mode); -#endif // defined(OS_POSIX) +BASE_EXPORT bool SetPosixFilePermissions(const FilePath& path, int mode); -// Return true if the given directory is empty -BASE_EXPORT bool IsDirectoryEmpty(const base::FilePath& dir_path); +#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: DON'T USE THIS. If you want to create a temporary file, use one of -// the functions below. -BASE_EXPORT bool GetTempDir(base::FilePath* path); -// Get a temporary directory for shared memory files. -// Only useful on POSIX; redirects to GetTempDir() on Windows. -BASE_EXPORT bool GetShmemTempDir(base::FilePath* path, bool executable); +// +// 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") +// Get the home directory. This is more complicated than just getenv("HOME") // as it knows to fall back on getpwent() etc. -BASE_EXPORT base::FilePath GetHomeDir(); +// +// 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(base::FilePath* path); +BASE_EXPORT bool CreateTemporaryFile(FilePath* path); // Same as CreateTemporaryFile but the file is created in |dir|. -BASE_EXPORT bool CreateTemporaryFileInDir(const base::FilePath& dir, - base::FilePath* temp_file); +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(base::FilePath* path); -// Like above but for shmem files. Only useful for POSIX. -// The executable flag says the file needs to support using -// mprotect with PROT_EXEC after mapping. -BASE_EXPORT FILE* CreateAndOpenTemporaryShmemFile(base::FilePath* path, - bool executable); +BASE_EXPORT FILE* CreateAndOpenTemporaryFile(FilePath* path); + // Similar to CreateAndOpenTemporaryFile, but the file is created in |dir|. -BASE_EXPORT FILE* CreateAndOpenTemporaryFileInDir(const base::FilePath& dir, - base::FilePath* path); +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 base::FilePath::StringType& prefix, - base::FilePath* new_temp_path); +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 base::FilePath& base_dir, - const base::FilePath::StringType& prefix, - base::FilePath* new_dir); +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 base::FilePath& full_path, - base::PlatformFileError* error); +BASE_EXPORT bool CreateDirectoryAndGetError(const FilePath& full_path, + File::Error* error); // Backward-compatible convenience method for the above. -BASE_EXPORT bool CreateDirectory(const base::FilePath& full_path); +BASE_EXPORT bool CreateDirectory(const FilePath& full_path); // Returns the file size. Returns true on success. -BASE_EXPORT bool GetFileSize(const base::FilePath& file_path, int64* file_size); +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 base::FilePath& path, - base::FilePath* real_path); +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 base::FilePath& device_path, - base::FilePath* drive_letter_path); +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 base::FilePath& path, - base::FilePath* nt_path); +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 base::FilePath& file_path); +BASE_EXPORT bool IsLink(const FilePath& file_path); // Returns information about the given file path. -BASE_EXPORT bool GetFileInfo(const base::FilePath& file_path, - base::PlatformFileInfo* info); +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 base::FilePath& path, - const base::Time& last_accessed, - const base::Time& last_modified); - -// Set the time of the last modification. Useful for unit tests. -BASE_EXPORT bool SetLastModifiedTime(const base::FilePath& path, - const base::Time& last_modified); - -#if defined(OS_POSIX) -// Store inode number of |path| in |inode|. Return true on success. -BASE_EXPORT bool GetInode(const base::FilePath& path, ino_t* inode); -#endif +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 base::FilePath& filename, const char* mode); +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 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 base::FilePath& filename, char* data, int size); +// 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 base::FilePath& filename, const char* data, +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 base::FilePath& filename, +BASE_EXPORT int AppendToFile(const FilePath& filename, const char* data, int size); // Gets the current working directory for the process. -BASE_EXPORT bool GetCurrentDirectory(base::FilePath* path); +BASE_EXPORT bool GetCurrentDirectory(FilePath* path); // Sets the current working directory for the process. -BASE_EXPORT bool SetCurrentDirectory(const base::FilePath& path); +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 base::FilePath& path, - const base::FilePath::StringType& suffix); - -#if defined(OS_POSIX) -// Creates a directory with a guaranteed unique name based on |path|, returning -// the pathname if successful, or an empty path if there was an error creating -// the directory. Does not create parent directories. -BASE_EXPORT base::FilePath MakeUniqueDirectory(const base::FilePath& path); -#endif +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. @@ -378,43 +376,16 @@ BASE_EXPORT bool VerifyPathControlledByU // 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); -// A class to handle auto-closing of FILE*'s. -class ScopedFILEClose { - public: - inline void operator()(FILE* x) const { - if (x) { - fclose(x); - } - } -}; - -typedef scoped_ptr_malloc<FILE, ScopedFILEClose> ScopedFILE; - -#if defined(OS_POSIX) -// A class to handle auto-closing of FDs. -class ScopedFDClose { - public: - inline void operator()(int* x) const { - if (x && *x >= 0) { - if (HANDLE_EINTR(close(*x)) < 0) - DPLOG(ERROR) << "close"; - } - } -}; - -typedef scoped_ptr_malloc<int, ScopedFDClose> ScopedFD; -#endif // OS_POSIX - #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, @@ -422,20 +393,45 @@ enum FileSystemType { 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 base::FilePath& path, - FileSystemType* type); +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.
--- a/security/sandbox/chromium/base/file_util_win.cc +++ b/security/sandbox/chromium/base/file_util_win.cc @@ -1,24 +1,26 @@ // 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" @@ -29,173 +31,202 @@ namespace base { namespace { const DWORD kFileShareAll = FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE; -bool ShellCopy(const FilePath& from_path, - const FilePath& to_path, - bool recursive) { - // WinXP SHFileOperation doesn't like trailing separators. - FilePath stripped_from = from_path.StripTrailingSeparators(); - FilePath stripped_to = to_path.StripTrailingSeparators(); - - ThreadRestrictions::AssertIOAllowed(); - - // NOTE: I suspect we could support longer paths, but that would involve - // analyzing all our usage of files. - if (stripped_from.value().length() >= MAX_PATH || - stripped_to.value().length() >= MAX_PATH) { - return false; - } - - // 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_from[MAX_PATH + 1] = {0}; - wchar_t double_terminated_path_to[MAX_PATH + 1] = {0}; -#pragma warning(suppress:4996) // don't complain about wcscpy deprecation - wcscpy(double_terminated_path_from, stripped_from.value().c_str()); -#pragma warning(suppress:4996) // don't complain about wcscpy deprecation - wcscpy(double_terminated_path_to, stripped_to.value().c_str()); - - SHFILEOPSTRUCT file_operation = {0}; - file_operation.wFunc = FO_COPY; - file_operation.pFrom = double_terminated_path_from; - file_operation.pTo = double_terminated_path_to; - file_operation.fFlags = FOF_NOERRORUI | FOF_SILENT | FOF_NOCONFIRMATION | - FOF_NOCONFIRMMKDIR; - if (!recursive) - file_operation.fFlags |= FOF_NORECURSION | FOF_FILESONLY; - - return (SHFileOperation(&file_operation) == 0); -} - } // 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. - PlatformFileInfo file_info; - if (file_util::GetFileInfo(path, &file_info) && file_info.is_directory) + 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 - if (g_bug108724_debug) - LOG(WARNING) << "copying "; 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; - if (g_bug108724_debug) - LOG(WARNING) << "Performing shell operation"; int err = SHFileOperation(&file_operation); - if (g_bug108724_debug) - LOG(WARNING) << "Done: " << err; // 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. - return (err == 0 || err == ERROR_FILE_NOT_FOUND || err == 0x402); + // 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, - PlatformFileError* error) { + 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 = LastErrorToPlatformFileError(GetLastError()); + *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(); - if (recursive) - return ShellCopy(from_path, to_path, true); - - // The following code assumes that from path is a directory. - DCHECK(DirectoryExists(from_path)); + // 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; + } - // Instead of creating a new directory, we copy the old one to include the - // security information of the folder as part of the copy. - if (!PathExists(to_path)) { - // Except that Vista fails to do that, and instead do a recursive copy if - // the target directory doesn't exist. - if (base::win::GetVersion() >= base::win::VERSION_VISTA) - file_util::CreateDirectory(to_path); - else - ShellCopy(from_path, to_path, 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; } - FilePath directory = from_path.Append(L"*.*"); - return ShellCopy(directory, to_path, 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) { @@ -214,88 +245,84 @@ bool PathIsWritable(const FilePath& path 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; } -} // namespace base - -// ----------------------------------------------------------------------------- - -namespace file_util { - -using base::DirectoryExists; -using base::FilePath; -using base::kFileShareAll; - bool GetTempDir(FilePath* path) { - base::ThreadRestrictions::AssertIOAllowed(); - 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; } -bool GetShmemTempDir(FilePath* path, bool executable) { - return GetTempDir(path); +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) { - base::ThreadRestrictions::AssertIOAllowed(); + ThreadRestrictions::AssertIOAllowed(); FilePath temp_file; if (!GetTempDir(path)) return false; if (CreateTemporaryFileInDir(*path, &temp_file)) { *path = temp_file; return true; } return false; } -FILE* CreateAndOpenTemporaryShmemFile(FilePath* path, bool executable) { - base::ThreadRestrictions::AssertIOAllowed(); - return CreateAndOpenTemporaryFile(path); -} - // 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) { - base::ThreadRestrictions::AssertIOAllowed(); + 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) { - base::ThreadRestrictions::AssertIOAllowed(); +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 " << dir.value(); + 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); @@ -306,273 +333,126 @@ bool CreateTemporaryFileInDir(const File 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) { - base::ThreadRestrictions::AssertIOAllowed(); + 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(base::IntToString16(::base::GetCurrentProcId())); + new_dir_name.append(IntToString16(GetCurrentProcId())); new_dir_name.push_back('_'); - new_dir_name.append(base::IntToString16(base::RandInt(0, kint16max))); + 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) { - base::ThreadRestrictions::AssertIOAllowed(); + 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, - base::PlatformFileError* error) { - base::ThreadRestrictions::AssertIOAllowed(); + 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 = base::PLATFORM_FILE_ERROR_NOT_A_DIRECTORY; + *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 = base::PLATFORM_FILE_ERROR_NOT_FOUND; + *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 != base::PLATFORM_FILE_OK); + 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 = base::LastErrorToPlatformFileError(error_code); + *error = File::OSErrorToFileError(error_code); DLOG(WARNING) << "Failed to create directory " << full_path_str << ", last error is " << error_code << "."; return false; } } else { return true; } } -// 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, base::PlatformFileInfo* results) { - base::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 = base::Time::FromFileTime(attr.ftLastWriteTime); - results->last_accessed = base::Time::FromFileTime(attr.ftLastAccessTime); - results->creation_time = base::Time::FromFileTime(attr.ftCreationTime); - - return true; -} - -FILE* OpenFile(const FilePath& filename, const char* mode) { - base::ThreadRestrictions::AssertIOAllowed(); - std::wstring w_mode = ASCIIToWide(std::string(mode)); - return _wfsopen(filename.value().c_str(), w_mode.c_str(), _SH_DENYNO); -} - -FILE* OpenFile(const std::string& filename, const char* mode) { - base::ThreadRestrictions::AssertIOAllowed(); - return _fsopen(filename.c_str(), mode, _SH_DENYNO); -} - -int ReadFile(const FilePath& filename, char* data, int size) { - base::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, size, &read, NULL) && - static_cast<int>(read) == size) - return read; - return -1; -} - -int WriteFile(const FilePath& filename, const char* data, int size) { - base::ThreadRestrictions::AssertIOAllowed(); - base::win::ScopedHandle file(CreateFile(filename.value().c_str(), - GENERIC_WRITE, - 0, - NULL, - CREATE_ALWAYS, - 0, - NULL)); - if (!file) { - DLOG_GETLASTERROR(WARNING) << "CreateFile failed for path " - << 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. - DLOG_GETLASTERROR(WARNING) << "writing file " << filename.value() - << " failed"; - } else { - // Didn't write all the bytes. - DLOG(WARNING) << "wrote" << written << " bytes to " - << filename.value() << " expected " << size; - } - return -1; -} - -int AppendToFile(const FilePath& filename, const char* data, int size) { - base::ThreadRestrictions::AssertIOAllowed(); - base::win::ScopedHandle file(CreateFile(filename.value().c_str(), - FILE_APPEND_DATA, - 0, - NULL, - OPEN_EXISTING, - 0, - NULL)); - if (!file) { - DLOG_GETLASTERROR(WARNING) << "CreateFile failed for path " - << 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. - DLOG_GETLASTERROR(WARNING) << "writing file " << filename.value() - << " failed"; - } else { - // Didn't write all the bytes. - DLOG(WARNING) << "wrote" << written << " bytes to " - << filename.value() << " expected " << size; - } - return -1; -} - -// Gets the current working directory for the process. -bool GetCurrentDirectory(FilePath* dir) { - base::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) { - base::ThreadRestrictions::AssertIOAllowed(); - BOOL ret = ::SetCurrentDirectory(directory.value().c_str()); - return ret != 0; -} - bool NormalizeFilePath(const FilePath& path, FilePath* real_path) { - base::ThreadRestrictions::AssertIOAllowed(); + 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) { - base::ThreadRestrictions::AssertIOAllowed(); + 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; } @@ -605,17 +485,17 @@ bool DevicePathToDriveLetterPath(const F // 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) { - base::ThreadRestrictions::AssertIOAllowed(); + 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, @@ -659,18 +539,174 @@ bool NormalizeToNativeFilePath(const Fil 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) { - base::ThreadRestrictions::AssertIOAllowed(); + ThreadRestrictions::AssertIOAllowed(); wchar_t volume_path[MAX_PATH]; if (!GetVolumePathNameW(path.NormalizePathSeparators().value().c_str(), volume_path, arraysize(volume_path))) { return -1; } @@ -683,19 +719,18 @@ int GetMaximumPathComponentLength(const // 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 file_util +// ----------------------------------------------------------------------------- -namespace base { 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 || @@ -731,18 +766,34 @@ bool CopyFileUnsafe(const FilePath& from 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; } - return (::CopyFile(from_path.value().c_str(), to_path.value().c_str(), - false) != 0); + + // 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;
--- a/security/sandbox/chromium/base/files/file_path.h +++ b/security/sandbox/chromium/base/files/file_path.h @@ -184,16 +184,23 @@ class BASE_EXPORT FilePath { void clear() { path_.clear(); } // Returns true if |character| is in kSeparators. static bool IsSeparator(CharType character); // Returns a vector of all of the components of the provided path. It is // equivalent to calling DirName().value() on the path's root component, // and BaseName().value() on each child component. + // + // To make sure this is lossless so we can differentiate absolute and + // relative paths, the root slash will be included even though no other + // slashes will be. The precise behavior is: + // + // Posix: "/foo/bar" -> [ "/", "foo", "bar" ] + // Windows: "C:\foo\bar" -> [ "C:", "\\", "foo", "bar" ] void GetComponents(std::vector<FilePath::StringType>* components) const; // Returns true if this FilePath is a strict parent of the |child|. Absolute // and relative paths are accepted i.e. is /foo parent to /foo/bar and // is foo parent to foo/bar. Does not convert paths to absolute, follow // symlinks or directory navigation (e.g. ".."). A path is *NOT* its own // parent. bool IsParent(const FilePath& child) const; @@ -219,28 +226,43 @@ class BASE_EXPORT FilePath { // object, either a file or a directory. If this object already refers to // the root directory, returns a FilePath identifying the root directory; // this is the only situation in which BaseName will return an absolute path. FilePath BaseName() const WARN_UNUSED_RESULT; // Returns ".jpg" for path "C:\pics\jojo.jpg", or an empty string if // the file has no extension. If non-empty, Extension() will always start // with precisely one ".". The following code should always work regardless - // of the value of path. + // of the value of path. For common double-extensions like .tar.gz and + // .user.js, this method returns the combined extension. For a single + // component, use FinalExtension(). // new_path = path.RemoveExtension().value().append(path.Extension()); // ASSERT(new_path == path.value()); // NOTE: this is different from the original file_util implementation which // returned the extension without a leading "." ("jpg" instead of ".jpg") StringType Extension() const; + // Returns the path's file extension, as in Extension(), but will + // never return a double extension. + // + // TODO(davidben): Check all our extension-sensitive code to see if + // we can rename this to Extension() and the other to something like + // LongExtension(), defaulting to short extensions and leaving the + // long "extensions" to logic like base::GetUniquePathNumber(). + StringType FinalExtension() const; + // Returns "C:\pics\jojo" for path "C:\pics\jojo.jpg" // NOTE: this is slightly different from the similar file_util implementation // which returned simply 'jojo'. FilePath RemoveExtension() const WARN_UNUSED_RESULT; + // Removes the path's file extension, as in RemoveExtension(), but + // ignores double extensions. + FilePath RemoveFinalExtension() const WARN_UNUSED_RESULT; + // Inserts |suffix| after the file name portion of |path| but before the // extension. Returns "" if BaseName() == "." or "..". // Examples: // path == "C:\pics\jojo.jpg" suffix == " (1)", returns "C:\pics\jojo (1).jpg" // path == "jojo.jpg" suffix == " (1)", returns "jojo (1).jpg" // path == "C:\pics\jojo" suffix == " (1)", returns "C:\pics\jojo (1)" // path == "C:\pics.old\jojo" suffix == " (1)", returns "C:\pics.old\jojo (1)" FilePath InsertBeforeExtension( @@ -294,18 +316,18 @@ class BASE_EXPORT FilePath { // Returns a copy of this FilePath that ends with a trailing separator. If // the input path is empty, an empty FilePath will be returned. FilePath AsEndingWithSeparator() const WARN_UNUSED_RESULT; // Returns a copy of this FilePath that does not end with a trailing // separator. FilePath StripTrailingSeparators() const WARN_UNUSED_RESULT; - // Returns true if this FilePath contains any attempt to reference a parent - // directory (i.e. has a path component that is ".." + // Returns true if this FilePath contains an attempt to reference a parent + // directory (e.g. has a path component that is ".."). bool ReferencesParent() const; // Return a Unicode human-readable version of this path. // Warning: you can *not*, in general, go from a display name back to a real // path. Only use this when displaying paths to users, not just when you // want to stuff a string16 into some other API. string16 LossyDisplayName() const; @@ -327,34 +349,16 @@ class BASE_EXPORT FilePath { // Once it becomes safe to to stop caring about non-UTF-8 file names, // the SysNativeMBToWide() hack will be removed from the code, along // with "Unsafe" in the function name. std::string AsUTF8Unsafe() const; // Similar to AsUTF8Unsafe, but returns UTF-16 instead. string16 AsUTF16Unsafe() const; - // Older Chromium code assumes that paths are always wstrings. - // This function converts wstrings to FilePaths, and is - // useful to smooth porting that old code to the FilePath API. - // It has "Hack" its name so people feel bad about using it. - // http://code.google.com/p/chromium/issues/detail?id=24672 - // - // If you are trying to be a good citizen and remove these, ask yourself: - // - Am I interacting with other Chrome code that deals with files? Then - // try to convert the API into using FilePath. - // - Am I interacting with OS-native calls? Then use value() to get at an - // OS-native string format. - // - Am I using well-known file names, like "config.ini"? Then use the - // ASCII functions (we require paths to always be supersets of ASCII). - // - Am I displaying a string to the user in some UI? Then use the - // LossyDisplayName() function, but keep in mind that you can't - // ever use the result of that again as a path. - static FilePath FromWStringHack(const std::wstring& wstring); - // Returns a FilePath object from a path name in UTF-8. This function // should only be used for cases where you are sure that the input // string is UTF-8. // // Like AsUTF8Unsafe(), this function is unsafe. This function // internally calls SysWideToNativeMB() on POSIX systems other than Mac // and Chrome OS, to mitigate the encoding issue. See the comment at // AsUTF8Unsafe() for details. @@ -365,16 +369,20 @@ class BASE_EXPORT FilePath { void WriteToPickle(Pickle* pickle) const; bool ReadFromPickle(PickleIterator* iter); // Normalize all path separators to backslash on Windows // (if FILE_PATH_USES_WIN_SEPARATORS is true), or do nothing on POSIX systems. FilePath NormalizePathSeparators() const; + // Normalize all path separattors to given type on Windows + // (if FILE_PATH_USES_WIN_SEPARATORS is true), or do nothing on POSIX systems. + FilePath NormalizePathSeparatorsTo(CharType separator) const; + // Compare two strings in the same way the file system does. // Note that these always ignore case, even on file systems that are case- // sensitive. If case-sensitive comparison is ever needed, add corresponding // methods here. // The methods are written as a static method so that they can also be used // on parts of a file path, e.g., just the extension. // CompareIgnoreCase() returns -1, 0 or 1 for less-than, equal-to and // greater-than respectively. @@ -400,16 +408,25 @@ class BASE_EXPORT FilePath { // Special UTF-8 version of FastUnicodeCompare. Cf: // http://developer.apple.com/mac/library/technotes/tn/tn1150.html#StringComparisonAlgorithm // IMPORTANT: The input strings must be in the special HFS decomposed form! // (cf. above GetHFSDecomposedForm method) static int HFSFastUnicodeCompare(const StringType& string1, const StringType& string2); #endif +#if defined(OS_ANDROID) + // On android, file selection dialog can return a file with content uri + // scheme(starting with content://). Content uri needs to be opened with + // ContentResolver to guarantee that the app has appropriate permissions + // to access it. + // Returns true if the path is a content uri, or false otherwise. + bool IsContentUri() const; +#endif + private: // Remove trailing separators from this object. If the path is absolute, it // will never be stripped any more than to refer to the absolute root // directory, so "////" will become "/", not "". A leading pair of // separators is never stripped, to support alternate roots. This is used to // support UNC paths on Windows. void StripTrailingSeparatorsInternal();
--- a/security/sandbox/chromium/base/guid.h +++ b/security/sandbox/chromium/base/guid.h @@ -22,11 +22,11 @@ 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. BASE_EXPORT std::string RandomDataToGUIDString(const uint64 bytes[2]); #endif -} // namespace guid +} // namespace base #endif // BASE_GUID_H_
--- a/security/sandbox/chromium/base/lazy_instance.h +++ b/security/sandbox/chromium/base/lazy_instance.h @@ -52,17 +52,19 @@ // initialization. #define LAZY_INSTANCE_INITIALIZER {0} namespace base { template <typename Type> struct DefaultLazyInstanceTraits { static const bool kRegisterOnExit = true; +#ifndef NDEBUG static const bool kAllowedToAccessOnNonjoinableThread = false; +#endif static Type* New(void* instance) { DCHECK_EQ(reinterpret_cast<uintptr_t>(instance) & (ALIGNOF(Type) - 1), 0u) << ": Bad boy, the buffer passed to placement new is not aligned!\n" "This may break some stuff like SSE-based optimizations assuming the " "<Type> objects are word aligned."; // Use placement new to initialize our instance in our preallocated space. // The parenthesis is very important here to force POD type initialization. @@ -84,17 +86,19 @@ namespace internal { // base::LazyInstance<T, base::internal::LeakyLazyInstanceTraits<T> > // my_leaky_lazy_instance; // (especially when T is MyLongTypeNameImplClientHolderFactory). // Only use this internal::-qualified verbose form to extend this traits class // (depending on its implementation details). template <typename Type> struct LeakyLazyInstanceTraits { static const bool kRegisterOnExit = false; +#ifndef NDEBUG static const bool kAllowedToAccessOnNonjoinableThread = true; +#endif static Type* New(void* instance) { ANNOTATE_SCOPED_MEMORY_LEAK; return DefaultLazyInstanceTraits<Type>::New(instance); } static void Delete(Type* instance) { } };
--- a/security/sandbox/chromium/base/location.cc +++ b/security/sandbox/chromium/base/location.cc @@ -1,16 +1,19 @@ // 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) -#include <intrin.h> +// MSDN says to #include <intrin.h>, but that breaks the VS2005 build. +extern "C" { + void* _ReturnAddress(); +} #endif #include "base/location.h" #include "base/strings/string_number_conversions.h" #include "base/strings/stringprintf.h" namespace tracked_objects { @@ -84,16 +87,16 @@ LocationSnapshot::~LocationSnapshot() { //------------------------------------------------------------------------------ #if defined(COMPILER_MSVC) __declspec(noinline) #endif BASE_EXPORT const void* GetProgramCounter() { #if defined(COMPILER_MSVC) return _ReturnAddress(); -#elif defined(COMPILER_GCC) +#elif defined(COMPILER_GCC) && !defined(OS_NACL) return __builtin_extract_return_addr(__builtin_return_address(0)); -#endif // COMPILER_GCC - +#else return NULL; +#endif } } // namespace tracked_objects
--- a/security/sandbox/chromium/base/logging.h +++ b/security/sandbox/chromium/base/logging.h @@ -47,20 +47,16 @@ // things to LOG(<a particular severity level>). E.g., // // LOG(INFO) << "Found " << num_cookies << " cookies"; // // You can also do conditional logging: // // LOG_IF(INFO, num_cookies > 10) << "Got lots of cookies"; // -// The above will cause log messages to be output on the 1st, 11th, 21st, ... -// times it is executed. Note that the special COUNTER value is used to -// identify which repetition is happening. -// // The CHECK(condition) macro is active in both debug and release builds and // effectively performs a LOG(FATAL) which terminates the process and // generates a crashdump unless a debugger is attached. // // There are also "debug mode" logging macros like the ones above: // // DLOG(INFO) << "Found cookies"; // @@ -126,28 +122,23 @@ // DPLOG_IF(ERROR, cond) << "Couldn't do foo"; // PCHECK(condition) << "Couldn't do foo"; // DPCHECK(condition) << "Couldn't do foo"; // // which append the last system error to the message in string form (taken from // GetLastError() on Windows and errno on POSIX). // // The supported severity levels for macros that allow you to specify one -// are (in increasing order of severity) INFO, WARNING, ERROR, ERROR_REPORT, -// and FATAL. +// are (in increasing order of severity) INFO, WARNING, ERROR, and FATAL. // // Very important: logging a message at the FATAL severity level causes // the program to terminate (after the message is logged). // -// Note the special severity of ERROR_REPORT only available/relevant in normal -// mode, which displays error dialog without terminating the program. There is -// no error dialog for severity ERROR or below in normal mode. -// -// There is also the special severity of DFATAL, which logs FATAL in -// debug mode, ERROR in normal mode. +// There is the special severity of DFATAL, which logs FATAL in debug mode, +// ERROR in normal mode. namespace logging { // TODO(avi): do we want to do a unification of character types here? #if defined(OS_WIN) typedef wchar_t PathChar; #else typedef char PathChar; @@ -170,50 +161,42 @@ enum LoggingDestination { #elif defined(OS_POSIX) LOG_DEFAULT = LOG_TO_SYSTEM_DEBUG_LOG, #endif }; // Indicates that the log file should be locked when being written to. // Unless there is only one single-threaded process that is logging to // the log file, the file should be locked during writes to make each -// log outut atomic. Other writers will block. +// log output atomic. Other writers will block. // // All processes writing to the log file must have their locking set for it to // work properly. Defaults to LOCK_LOG_FILE. enum LogLockingState { LOCK_LOG_FILE, DONT_LOCK_LOG_FILE }; // On startup, should we delete or append to an existing log file (if any)? // Defaults to APPEND_TO_OLD_LOG_FILE. enum OldFileDeletionState { DELETE_OLD_LOG_FILE, APPEND_TO_OLD_LOG_FILE }; -enum DcheckState { - DISABLE_DCHECK_FOR_NON_OFFICIAL_RELEASE_BUILDS, - ENABLE_DCHECK_FOR_NON_OFFICIAL_RELEASE_BUILDS -}; - struct BASE_EXPORT LoggingSettings { // The defaults values are: // // logging_dest: LOG_DEFAULT // log_file: NULL // lock_log: LOCK_LOG_FILE // delete_old: APPEND_TO_OLD_LOG_FILE - // dcheck_state: DISABLE_DCHECK_FOR_NON_OFFICIAL_RELEASE_BUILDS LoggingSettings(); LoggingDestination logging_dest; // The three settings below have an effect only when LOG_TO_FILE is // set in |logging_dest|. const PathChar* log_file; LogLockingState lock_log; OldFileDeletionState delete_old; - - DcheckState dcheck_state; }; // Define different names for the BaseInitLoggingImpl() function depending on // whether NDEBUG is defined or not so that we'll fail to link if someone tries // to compile logging.cc with NDEBUG but includes logging.h without defining it, // or vice versa. #if NDEBUG #define BaseInitLoggingImpl BaseInitLoggingImpl_built_with_NDEBUG @@ -283,42 +266,34 @@ BASE_EXPORT void SetShowErrorDialogs(boo // Sets the Log Assert Handler that will be used to notify of check failures. // The default handler shows a dialog box and then terminate the process, // however clients can use this function to override with their own handling // (e.g. a silent one for Unit Tests) typedef void (*LogAssertHandlerFunction)(const std::string& str); BASE_EXPORT void SetLogAssertHandler(LogAssertHandlerFunction handler); -// Sets the Log Report Handler that will be used to notify of check failures -// in non-debug mode. The default handler shows a dialog box and continues -// the execution, however clients can use this function to override with their -// own handling. -typedef void (*LogReportHandlerFunction)(const std::string& str); -BASE_EXPORT void SetLogReportHandler(LogReportHandlerFunction handler); - // Sets the Log Message Handler that gets passed every log message before // it's sent to other log destinations (if any). // Returns true to signal that it handled the message and the message // should not be sent to other log destinations. typedef bool (*LogMessageHandlerFunction)(int severity, const char* file, int line, size_t message_start, const std::string& str); BASE_EXPORT void SetLogMessageHandler(LogMessageHandlerFunction handler); BASE_EXPORT LogMessageHandlerFunction GetLogMessageHandler(); typedef int LogSeverity; const LogSeverity LOG_VERBOSE = -1; // This is level 1 verbosity // Note: the log severities are used to index into the array of names, // see log_severity_names. const LogSeverity LOG_INFO = 0; const LogSeverity LOG_WARNING = 1; const LogSeverity LOG_ERROR = 2; -const LogSeverity LOG_ERROR_REPORT = 3; -const LogSeverity LOG_FATAL = 4; -const LogSeverity LOG_NUM_SEVERITIES = 5; +const LogSeverity LOG_FATAL = 3; +const LogSeverity LOG_NUM_SEVERITIES = 4; // LOG_DFATAL is LOG_FATAL in debug mode, ERROR in normal mode #ifdef NDEBUG const LogSeverity LOG_DFATAL = LOG_ERROR; #else const LogSeverity LOG_DFATAL = LOG_FATAL; #endif @@ -326,32 +301,27 @@ const LogSeverity LOG_DFATAL = LOG_FATAL // by LOG() and LOG_IF, etc. Since these are used all over our code, it's // better to have compact code for these operations. #define COMPACT_GOOGLE_LOG_EX_INFO(ClassName, ...) \ logging::ClassName(__FILE__, __LINE__, logging::LOG_INFO , ##__VA_ARGS__) #define COMPACT_GOOGLE_LOG_EX_WARNING(ClassName, ...) \ logging::ClassName(__FILE__, __LINE__, logging::LOG_WARNING , ##__VA_ARGS__) #define COMPACT_GOOGLE_LOG_EX_ERROR(ClassName, ...) \ logging::ClassName(__FILE__, __LINE__, logging::LOG_ERROR , ##__VA_ARGS__) -#define COMPACT_GOOGLE_LOG_EX_ERROR_REPORT(ClassName, ...) \ - logging::ClassName(__FILE__, __LINE__, \ - logging::LOG_ERROR_REPORT , ##__VA_ARGS__) #define COMPACT_GOOGLE_LOG_EX_FATAL(ClassName, ...) \ logging::ClassName(__FILE__, __LINE__, logging::LOG_FATAL , ##__VA_ARGS__) #define COMPACT_GOOGLE_LOG_EX_DFATAL(ClassName, ...) \ logging::ClassName(__FILE__, __LINE__, logging::LOG_DFATAL , ##__VA_ARGS__) #define COMPACT_GOOGLE_LOG_INFO \ COMPACT_GOOGLE_LOG_EX_INFO(LogMessage) #define COMPACT_GOOGLE_LOG_WARNING \ COMPACT_GOOGLE_LOG_EX_WARNING(LogMessage) #define COMPACT_GOOGLE_LOG_ERROR \ COMPACT_GOOGLE_LOG_EX_ERROR(LogMessage) -#define COMPACT_GOOGLE_LOG_ERROR_REPORT \ - COMPACT_GOOGLE_LOG_EX_ERROR_REPORT(LogMessage) #define COMPACT_GOOGLE_LOG_FATAL \ COMPACT_GOOGLE_LOG_EX_FATAL(LogMessage) #define COMPACT_GOOGLE_LOG_DFATAL \ COMPACT_GOOGLE_LOG_EX_DFATAL(LogMessage) #if defined(OS_WIN) // wingdi.h defines ERROR to be 0. When we call LOG(ERROR), it gets // substituted with 0, and it expands to COMPACT_GOOGLE_LOG_0. To allow us @@ -361,20 +331,19 @@ const LogSeverity LOG_DFATAL = LOG_FATAL #define ERROR 0 #define COMPACT_GOOGLE_LOG_EX_0(ClassName, ...) \ COMPACT_GOOGLE_LOG_EX_ERROR(ClassName , ##__VA_ARGS__) #define COMPACT_GOOGLE_LOG_0 COMPACT_GOOGLE_LOG_ERROR // Needed for LOG_IS_ON(ERROR). const LogSeverity LOG_0 = LOG_ERROR; #endif -// As special cases, we can assume that LOG_IS_ON(ERROR_REPORT) and -// LOG_IS_ON(FATAL) always hold. Also, LOG_IS_ON(DFATAL) always holds -// in debug mode. In particular, CHECK()s will always fire if they -// fail. +// As special cases, we can assume that LOG_IS_ON(FATAL) always holds. Also, +// LOG_IS_ON(DFATAL) always holds in debug mode. In particular, CHECK()s will +// always fire if they fail. #define LOG_IS_ON(severity) \ ((::logging::LOG_ ## severity) >= ::logging::GetMinLogLevel()) // We can't do any caching tricks with VLOG_IS_ON() like the // google-glog version since it requires GCC extensions. This means // that using the v-logging functions in conjunction with --vmodule // may be slow. #define VLOG_IS_ON(verboselevel) \ @@ -433,76 +402,46 @@ const LogSeverity LOG_0 = LOG_ERROR; // TODO(akalin): Add more VLOG variants, e.g. VPLOG. #define LOG_ASSERT(condition) \ LOG_IF(FATAL, !(condition)) << "Assert failed: " #condition ". " #define SYSLOG_ASSERT(condition) \ SYSLOG_IF(FATAL, !(condition)) << "Assert failed: " #condition ". " #if defined(OS_WIN) -#define LOG_GETLASTERROR_STREAM(severity) \ +#define PLOG_STREAM(severity) \ COMPACT_GOOGLE_LOG_EX_ ## severity(Win32ErrorLogMessage, \ ::logging::GetLastSystemErrorCode()).stream() -#define LOG_GETLASTERROR(severity) \ - LAZY_STREAM(LOG_GETLASTERROR_STREAM(severity), LOG_IS_ON(severity)) -#define LOG_GETLASTERROR_MODULE_STREAM(severity, module) \ - COMPACT_GOOGLE_LOG_EX_ ## severity(Win32ErrorLogMessage, \ - ::logging::GetLastSystemErrorCode(), module).stream() -#define LOG_GETLASTERROR_MODULE(severity, module) \ - LAZY_STREAM(LOG_GETLASTERROR_STREAM(severity, module), \ - LOG_IS_ON(severity)) -// PLOG_STREAM is used by PLOG, which is the usual error logging macro -// for each platform. -#define PLOG_STREAM(severity) LOG_GETLASTERROR_STREAM(severity) #elif defined(OS_POSIX) -#define LOG_ERRNO_STREAM(severity) \ +#define PLOG_STREAM(severity) \ COMPACT_GOOGLE_LOG_EX_ ## severity(ErrnoLogMessage, \ ::logging::GetLastSystemErrorCode()).stream() -#define LOG_ERRNO(severity) \ - LAZY_STREAM(LOG_ERRNO_STREAM(severity), LOG_IS_ON(severity)) -// PLOG_STREAM is used by PLOG, which is the usual error logging macro -// for each platform. -#define PLOG_STREAM(severity) LOG_ERRNO_STREAM(severity) #endif #define PLOG(severity) \ LAZY_STREAM(PLOG_STREAM(severity), LOG_IS_ON(severity)) #define PLOG_IF(severity, condition) \ LAZY_STREAM(PLOG_STREAM(severity), LOG_IS_ON(severity) && (condition)) -#if !defined(NDEBUG) -// Debug builds always include DCHECK and DLOG. -#undef LOGGING_IS_OFFICIAL_BUILD -#define LOGGING_IS_OFFICIAL_BUILD 0 -#elif defined(OFFICIAL_BUILD) -// Official release builds always disable and remove DCHECK and DLOG. -#undef LOGGING_IS_OFFICIAL_BUILD -#define LOGGING_IS_OFFICIAL_BUILD 1 -#elif !defined(LOGGING_IS_OFFICIAL_BUILD) -// Unless otherwise specified, unofficial release builds include -// DCHECK and DLOG. -#define LOGGING_IS_OFFICIAL_BUILD 0 -#endif - // The actual stream used isn't important. #define EAT_STREAM_PARAMETERS \ true ? (void) 0 : ::logging::LogMessageVoidify() & LOG_STREAM(FATAL) // CHECK dies with a fatal error if condition is not true. It is *not* // controlled by NDEBUG, so the check will be executed regardless of // compilation mode. // // We make sure CHECK et al. always evaluates their arguments, as // doing CHECK(FunctionWithSideEffect()) is a common idiom. -#if LOGGING_IS_OFFICIAL_BUILD +#if defined(OFFICIAL_BUILD) && defined(NDEBUG) && !defined(OS_ANDROID) // Make all CHECK functions discard their log strings to reduce code -// bloat for official builds. +// bloat for official release builds. // TODO(akalin): This would be more valuable if there were some way to // remove BreakDebugger() from the backtrace, perhaps by turning it // into a macro (like __debugbreak() on Windows). #define CHECK(condition) \ !(condition) ? ::base::debug::BreakDebugger() : EAT_STREAM_PARAMETERS #define PCHECK(condition) CHECK(condition) @@ -589,32 +528,26 @@ DEFINE_CHECK_OP_IMPL(GT, > ) #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) -#if LOGGING_IS_OFFICIAL_BUILD -// In order to have optimized code for official builds, remove DLOGs and -// DCHECKs. +#if defined(NDEBUG) #define ENABLE_DLOG 0 -#define ENABLE_DCHECK 0 +#else +#define ENABLE_DLOG 1 +#endif -#elif defined(NDEBUG) -// Otherwise, if we're a release build, remove DLOGs but not DCHECKs -// (since those can still be turned on via a command-line flag). -#define ENABLE_DLOG 0 -#define ENABLE_DCHECK 1 - +#if defined(NDEBUG) && !defined(DCHECK_ALWAYS_ON) +#define DCHECK_IS_ON 0 #else -// Otherwise, we're a debug build so enable DLOGs and DCHECKs. -#define ENABLE_DLOG 1 -#define ENABLE_DCHECK 1 +#define DCHECK_IS_ON 1 #endif // Definitions for DLOG et al. #if ENABLE_DLOG #define DLOG_IS_ON(severity) LOG_IS_ON(severity) #define DLOG_IF(severity, condition) LOG_IF(severity, condition) @@ -649,105 +582,59 @@ DEFINE_CHECK_OP_IMPL(GT, > ) // We tie its state to ENABLE_DLOG. enum { DEBUG_MODE = ENABLE_DLOG }; #undef ENABLE_DLOG #define DLOG(severity) \ LAZY_STREAM(LOG_STREAM(severity), DLOG_IS_ON(severity)) -#if defined(OS_WIN) -#define DLOG_GETLASTERROR(severity) \ - LAZY_STREAM(LOG_GETLASTERROR_STREAM(severity), DLOG_IS_ON(severity)) -#define DLOG_GETLASTERROR_MODULE(severity, module) \ - LAZY_STREAM(LOG_GETLASTERROR_STREAM(severity, module), \ - DLOG_IS_ON(severity)) -#elif defined(OS_POSIX) -#define DLOG_ERRNO(severity) \ - LAZY_STREAM(LOG_ERRNO_STREAM(severity), DLOG_IS_ON(severity)) -#endif - #define DPLOG(severity) \ LAZY_STREAM(PLOG_STREAM(severity), DLOG_IS_ON(severity)) #define DVLOG(verboselevel) DVLOG_IF(verboselevel, VLOG_IS_ON(verboselevel)) #define DVPLOG(verboselevel) DVPLOG_IF(verboselevel, VLOG_IS_ON(verboselevel)) // Definitions for DCHECK et al. -#if ENABLE_DCHECK - -#if defined(NDEBUG) +#if DCHECK_IS_ON -BASE_EXPORT DcheckState get_dcheck_state(); -BASE_EXPORT void set_dcheck_state(DcheckState state); - -#if defined(DCHECK_ALWAYS_ON) - -#define DCHECK_IS_ON() true #define COMPACT_GOOGLE_LOG_EX_DCHECK(ClassName, ...) \ COMPACT_GOOGLE_LOG_EX_FATAL(ClassName , ##__VA_ARGS__) #define COMPACT_GOOGLE_LOG_DCHECK COMPACT_GOOGLE_LOG_FATAL const LogSeverity LOG_DCHECK = LOG_FATAL; -#else - -#define COMPACT_GOOGLE_LOG_EX_DCHECK(ClassName, ...) \ - COMPACT_GOOGLE_LOG_EX_ERROR_REPORT(ClassName , ##__VA_ARGS__) -#define COMPACT_GOOGLE_LOG_DCHECK COMPACT_GOOGLE_LOG_ERROR_REPORT -const LogSeverity LOG_DCHECK = LOG_ERROR_REPORT; -#define DCHECK_IS_ON() \ - ((::logging::get_dcheck_state() == \ - ::logging::ENABLE_DCHECK_FOR_NON_OFFICIAL_RELEASE_BUILDS) && \ - LOG_IS_ON(DCHECK)) - -#endif // defined(DCHECK_ALWAYS_ON) +#else // DCHECK_IS_ON -#else // defined(NDEBUG) - -// On a regular debug build, we want to have DCHECKs enabled. -#define COMPACT_GOOGLE_LOG_EX_DCHECK(ClassName, ...) \ - COMPACT_GOOGLE_LOG_EX_FATAL(ClassName , ##__VA_ARGS__) -#define COMPACT_GOOGLE_LOG_DCHECK COMPACT_GOOGLE_LOG_FATAL -const LogSeverity LOG_DCHECK = LOG_FATAL; -#define DCHECK_IS_ON() true - -#endif // defined(NDEBUG) - -#else // ENABLE_DCHECK - -// These are just dummy values since DCHECK_IS_ON() is always false in -// this case. +// These are just dummy values. #define COMPACT_GOOGLE_LOG_EX_DCHECK(ClassName, ...) \ COMPACT_GOOGLE_LOG_EX_INFO(ClassName , ##__VA_ARGS__) #define COMPACT_GOOGLE_LOG_DCHECK COMPACT_GOOGLE_LOG_INFO const LogSeverity LOG_DCHECK = LOG_INFO; -#define DCHECK_IS_ON() false -#endif // ENABLE_DCHECK -#undef ENABLE_DCHECK +#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)) \ +#define DCHECK(condition) \ + LAZY_STREAM(LOG_STREAM(DCHECK), DCHECK_IS_ON && !(condition)) \ << "Check failed: " #condition ". " -#define DPCHECK(condition) \ - LAZY_STREAM(PLOG_STREAM(DCHECK), DCHECK_IS_ON() && !(condition)) \ +#define DPCHECK(condition) \ + LAZY_STREAM(PLOG_STREAM(DCHECK), DCHECK_IS_ON && !(condition)) \ << "Check failed: " #condition ". " // 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 (DCHECK_IS_ON) \ if (std::string* _result = \ logging::Check##name##Impl((val1), (val2), \ #val1 " " #op " " #val2)) \ logging::LogMessage( \ __FILE__, __LINE__, ::logging::LOG_DCHECK, \ _result).stream() // Equality/Inequality checks - compare two values, and log a @@ -771,58 +658,45 @@ const LogSeverity LOG_DCHECK = LOG_INFO; #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) +#if defined(NDEBUG) && 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 #define assert(x) DLOG_ASSERT(x) // This class more or less represents a particular log message. You // create an instance of LogMessage and then stream stuff to it. // When you finish streaming to it, ~LogMessage is called and the // full message gets streamed to the appropriate destination. // // You shouldn't actually use LogMessage's constructor to log things, // though. You should use the LOG() macro (and variants thereof) // above. class BASE_EXPORT LogMessage { public: - LogMessage(const char* file, int line, LogSeverity severity, int ctr); - - // Two special constructors that generate reduced amounts of code at - // LOG call sites for common cases. - // - // Used for LOG(INFO): Implied are: - // severity = LOG_INFO, ctr = 0 - // - // Using this constructor instead of the more complex constructor above - // saves a couple of bytes per call site. - LogMessage(const char* file, int line); - - // Used for LOG(severity) where severity != INFO. Implied - // are: ctr = 0 - // - // Using this constructor instead of the more complex constructor above - // saves a couple of bytes per call site. + // Used for LOG(severity). LogMessage(const char* file, int line, LogSeverity severity); - // A special constructor used for check failures. Takes ownership - // of the given string. - // Implied severity = LOG_FATAL + // Used for CHECK_EQ(), etc. Takes ownership of the given string. + // Implied severity = LOG_FATAL. LogMessage(const char* file, int line, std::string* result); - // A special constructor used for check failures, with the option to - // specify severity. Takes ownership of the given string. + // Used for DCHECK_EQ(), etc. Takes ownership of the given string. LogMessage(const char* file, int line, LogSeverity severity, std::string* result); ~LogMessage(); std::ostream& stream() { return stream_; } private: @@ -880,41 +754,34 @@ class LogMessageVoidify { typedef unsigned long SystemErrorCode; #elif defined(OS_POSIX) typedef int SystemErrorCode; #endif // Alias for ::GetLastError() on Windows and errno on POSIX. Avoids having to // pull in windows.h just for GetLastError() and DWORD. BASE_EXPORT SystemErrorCode GetLastSystemErrorCode(); +BASE_EXPORT std::string SystemErrorCodeToString(SystemErrorCode error_code); #if defined(OS_WIN) // Appends a formatted system message of the GetLastError() type. class BASE_EXPORT Win32ErrorLogMessage { public: Win32ErrorLogMessage(const char* file, int line, LogSeverity severity, - SystemErrorCode err, - const char* module); - - Win32ErrorLogMessage(const char* file, - int line, - LogSeverity severity, SystemErrorCode err); // Appends the error message before destructing the encapsulated class. ~Win32ErrorLogMessage(); std::ostream& stream() { return log_message_.stream(); } private: SystemErrorCode err_; - // Optional name of the module defining the error. - const char* module_; LogMessage log_message_; DISALLOW_COPY_AND_ASSIGN(Win32ErrorLogMessage); }; #elif defined(OS_POSIX) // Appends a formatted system message of the errno type class BASE_EXPORT ErrnoLogMessage { public: @@ -955,26 +822,36 @@ BASE_EXPORT void RawLog(int level, const #if defined(OS_WIN) // Returns the default log file path. BASE_EXPORT std::wstring GetLogFileFullPath(); #endif } // namespace logging +// Note that "The behavior of a C++ program is undefined if it adds declarations +// or definitions to namespace std or to a namespace within namespace std unless +// otherwise specified." --C++11[namespace.std] +// +// We've checked that this particular definition has the intended behavior on +// our implementations, but it's prone to breaking in the future, and please +// don't imitate this in your own definitions without checking with some +// standard library experts. +namespace std { // These functions are provided as a convenience for logging, which is where we // use streams (it is against Google style to use streams in other places). It // is designed to allow you to emit non-ASCII Unicode strings to the log file, // which is normally ASCII. It is relatively slow, so try not to use it for // common cases. Non-ASCII characters will be converted to UTF-8 by these // operators. BASE_EXPORT std::ostream& operator<<(std::ostream& out, const wchar_t* wstr); inline std::ostream& operator<<(std::ostream& out, const std::wstring& wstr) { return out << wstr.c_str(); } +} // namespace std // The NOTIMPLEMENTED() macro annotates codepaths which have // not been implemented yet. // // The implementation of this macro is controlled by NOTIMPLEMENTED_POLICY: // 0 -- Do nothing (stripped by compiler) // 1 -- Warn at compile time // 2 -- Fail at compile time
--- a/security/sandbox/chromium/base/memory/aligned_memory.h +++ b/security/sandbox/chromium/base/memory/aligned_memory.h @@ -21,19 +21,19 @@ // // Alternatively, a runtime sized aligned allocation can be created: // // float* my_array = static_cast<float*>(AlignedAlloc(size, alignment)); // // // ... later, to release the memory: // AlignedFree(my_array); // -// Or using scoped_ptr_malloc: +// Or using scoped_ptr: // -// scoped_ptr_malloc<float, ScopedPtrAlignedFree> my_array( +// scoped_ptr<float, AlignedFreeDeleter> my_array( // static_cast<float*>(AlignedAlloc(size, alignment))); #ifndef BASE_MEMORY_ALIGNED_MEMORY_H_ #define BASE_MEMORY_ALIGNED_MEMORY_H_ #include "base/base_export.h" #include "base/basictypes.h" #include "base/compiler_specific.h" @@ -96,19 +96,19 @@ BASE_EXPORT void* AlignedAlloc(size_t si inline void AlignedFree(void* ptr) { #if defined(COMPILER_MSVC) _aligned_free(ptr); #else free(ptr); #endif } -// Helper class for use with scoped_ptr_malloc. -class BASE_EXPORT ScopedPtrAlignedFree { - public: +// Deleter for use with scoped_ptr. E.g., use as +// scoped_ptr<Foo, base::AlignedFreeDeleter> foo; +struct AlignedFreeDeleter { inline void operator()(void* ptr) const { AlignedFree(ptr); } }; } // namespace base #endif // BASE_MEMORY_ALIGNED_MEMORY_H_
--- a/security/sandbox/chromium/base/memory/ref_counted.cc +++ b/security/sandbox/chromium/base/memory/ref_counted.cc @@ -1,61 +1,19 @@ // 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/memory/ref_counted.h" - -#include "base/logging.h" #include "base/threading/thread_collision_warner.h" namespace base { namespace subtle { -RefCountedBase::RefCountedBase() - : ref_count_(0) -#ifndef NDEBUG - , in_dtor_(false) -#endif - { -} - -RefCountedBase::~RefCountedBase() { -#ifndef NDEBUG - DCHECK(in_dtor_) << "RefCounted object deleted without calling Release()"; -#endif -} - -void RefCountedBase::AddRef() const { - // TODO(maruel): Add back once it doesn't assert 500 times/sec. - // Current thread books the critical section "AddRelease" without release it. - // DFAKE_SCOPED_LOCK_THREAD_LOCKED(add_release_); -#ifndef NDEBUG - DCHECK(!in_dtor_); -#endif - ++ref_count_; -} - -bool RefCountedBase::Release() const { - // TODO(maruel): Add back once it doesn't assert 500 times/sec. - // Current thread books the critical section "AddRelease" without release it. - // DFAKE_SCOPED_LOCK_THREAD_LOCKED(add_release_); -#ifndef NDEBUG - DCHECK(!in_dtor_); -#endif - if (--ref_count_ == 0) { -#ifndef NDEBUG - in_dtor_ = true; -#endif - return true; - } - return false; -} - bool RefCountedThreadSafeBase::HasOneRef() const { return AtomicRefCountIsOne( &const_cast<RefCountedThreadSafeBase*>(this)->ref_count_); } RefCountedThreadSafeBase::RefCountedThreadSafeBase() : ref_count_(0) { #ifndef NDEBUG in_dtor_ = false;
--- a/security/sandbox/chromium/base/memory/ref_counted.h +++ b/security/sandbox/chromium/base/memory/ref_counted.h @@ -5,34 +5,73 @@ #ifndef BASE_MEMORY_REF_COUNTED_H_ #define BASE_MEMORY_REF_COUNTED_H_ #include <cassert> #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" namespace base { namespace subtle { class BASE_EXPORT RefCountedBase { public: bool HasOneRef() const { return ref_count_ == 1; } protected: - RefCountedBase(); - ~RefCountedBase(); + RefCountedBase() + : ref_count_(0) + #ifndef NDEBUG + , in_dtor_(false) + #endif + { + } - void AddRef() const; + ~RefCountedBase() { + #ifndef NDEBUG + DCHECK(in_dtor_) << "RefCounted object deleted without calling Release()"; + #endif + } + + + void AddRef() const { + // TODO(maruel): Add back once it doesn't assert 500 times/sec. + // Current thread books the critical section "AddRelease" + // without release it. + // DFAKE_SCOPED_LOCK_THREAD_LOCKED(add_release_); + #ifndef NDEBUG + DCHECK(!in_dtor_); + #endif + ++ref_count_; + } // Returns true if the object should self-delete. - bool Release() const; + bool Release() const { + // TODO(maruel): Add back once it doesn't assert 500 times/sec. + // Current thread books the critical section "AddRelease" + // without release it. + // DFAKE_SCOPED_LOCK_THREAD_LOCKED(add_release_); + #ifndef NDEBUG + DCHECK(!in_dtor_); + #endif + if (--ref_count_ == 0) { + #ifndef NDEBUG + in_dtor_ = true; + #endif + return true; + } + return false; + } private: mutable int ref_count_; #ifndef NDEBUG mutable bool in_dtor_; #endif DFAKE_MUTEX(add_release_); @@ -246,17 +285,21 @@ class scoped_refptr { } ~scoped_refptr() { if (ptr_) ptr_->Release(); } T* get() const { return ptr_; } + + // Allow scoped_refptr<C> to be used in boolean expression + // and comparison operations. operator T*() const { 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)
--- a/security/sandbox/chromium/base/memory/scoped_ptr.h +++ b/security/sandbox/chromium/base/memory/scoped_ptr.h @@ -1,16 +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. -// Scopers help you manage ownership of a pointer, helping you easily manage the -// a pointer within a scope, and automatically destroying the pointer at the -// end of a scope. There are two main classes you will use, which correspond -// to the operators new/delete and new[]/delete[]. +// Scopers help you manage ownership of a pointer, helping you easily manage a +// pointer within a scope, and automatically destroying the pointer at the end +// of a scope. There are two main classes you will use, which correspond to the +// operators new/delete and new[]/delete[]. // // Example usage (scoped_ptr<T>): // { // scoped_ptr<Foo> foo(new Foo("wee")); // } // foo goes out of scope, releasing the pointer with it. // // { // scoped_ptr<Foo> foo; // No pointer managed. @@ -63,37 +63,37 @@ // // 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 assignment, i.e. you can assign -// scoped_ptr<Child> to scoped_ptr<Parent>: +// 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(); +// 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 and scoped_ptr_malloc (deprecated). +// implementation of the scoped_ptr class. #include <assert.h> #include <stddef.h> #include <stdlib.h> #include <algorithm> // For std::swap(). #include "base/basictypes.h" @@ -222,17 +222,17 @@ class scoped_ptr_impl { } 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(); // Note that running data_.ptr = p can lead to undefined behavior if - // get_deleter()(get()) deletes this. In order to pevent this, reset() + // 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|. // @@ -565,144 +565,16 @@ bool operator==(T* p1, const scoped_ptr< return p1 == p2.get(); } template <class T, class D> bool operator!=(T* p1, const scoped_ptr<T, D>& p2) { return p1 != p2.get(); } -// DEPRECATED: Use scoped_ptr<C, base::FreeDeleter> instead. -// -// scoped_ptr_malloc<> is similar to scoped_ptr<>, but it accepts a -// second template argument, the functor used to free the object. - -template<class C, class FreeProc = base::FreeDeleter> -class scoped_ptr_malloc { - MOVE_ONLY_TYPE_FOR_CPP_03(scoped_ptr_malloc, RValue) - - public: - - // The element type - typedef C element_type; - - // Constructor. Defaults to initializing with NULL. - // There is no way to create an uninitialized scoped_ptr. - // The input parameter must be allocated with an allocator that matches the - // Free functor. For the default Free functor, this is malloc, calloc, or - // realloc. - explicit scoped_ptr_malloc(C* p = NULL): ptr_(p) {} - - // Constructor. Move constructor for C++03 move emulation of this type. - scoped_ptr_malloc(RValue rvalue) - : ptr_(rvalue.object->release()) { - } - - // Destructor. If there is a C object, call the Free functor. - ~scoped_ptr_malloc() { - reset(); - } - - // operator=. Move operator= for C++03 move emulation of this type. - scoped_ptr_malloc& operator=(RValue rhs) { - reset(rhs.object->release()); - return *this; - } - - // Reset. Calls the Free functor on the current owned object, if any. - // Then takes ownership of a new object, if given. - // this->reset(this->get()) works. - void reset(C* p = NULL) { - if (ptr_ != p) { - if (ptr_ != NULL) { - FreeProc free_proc; - free_proc(ptr_); - } - ptr_ = p; - } - } - - // Get the current object. - // operator* and operator-> will cause an assert() failure if there is - // no current object. - C& operator*() const { - assert(ptr_ != NULL); - return *ptr_; - } - - C* operator->() const { - assert(ptr_ != NULL); - return ptr_; - } - - C* get() const { - return ptr_; - } - - // Allow scoped_ptr_malloc<C> to be used in boolean expressions, but not - // implicitly convertible to a real bool (which is dangerous). - typedef C* scoped_ptr_malloc::*Testable; - operator Testable() const { return ptr_ ? &scoped_ptr_malloc::ptr_ : NULL; } - - // Comparison operators. - // These return whether a scoped_ptr_malloc and a plain pointer refer - // to the same object, not just to two different but equal objects. - // For compatibility with the boost-derived implementation, these - // take non-const arguments. - bool operator==(C* p) const { - return ptr_ == p; - } - - bool operator!=(C* p) const { - return ptr_ != p; - } - - // Swap two scoped pointers. - void swap(scoped_ptr_malloc & b) { - C* tmp = b.ptr_; - b.ptr_ = ptr_; - ptr_ = tmp; - } - - // 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. - C* release() WARN_UNUSED_RESULT { - C* tmp = ptr_; - ptr_ = NULL; - return tmp; - } - - private: - C* ptr_; - - // no reason to use these: each scoped_ptr_malloc should have its own object - template <class C2, class GP> - bool operator==(scoped_ptr_malloc<C2, GP> const& p) const; - template <class C2, class GP> - bool operator!=(scoped_ptr_malloc<C2, GP> const& p) const; -}; - -template<class C, class FP> inline -void swap(scoped_ptr_malloc<C, FP>& a, scoped_ptr_malloc<C, FP>& b) { - a.swap(b); -} - -template<class C, class FP> inline -bool operator==(C* p, const scoped_ptr_malloc<C, FP>& b) { - return p == b.get(); -} - -template<class C, class FP> inline -bool operator!=(C* p, const scoped_ptr_malloc<C, FP>& b) { - return p != b.get(); -} - // A function to convert T* into scoped_ptr<T> // Doing e.g. make_scoped_ptr(new FooBarBaz<type>(arg)) is a shorter notation // for scoped_ptr<FooBarBaz<type> >(new FooBarBaz<type>(arg)) template <typename T> scoped_ptr<T> make_scoped_ptr(T* ptr) { return scoped_ptr<T>(ptr); }
--- a/security/sandbox/chromium/base/memory/singleton.cc +++ b/security/sandbox/chromium/base/memory/singleton.cc @@ -13,17 +13,20 @@ subtle::AtomicWord WaitForInstance(subtl // - Has the object in BeingCreated state // - Already has the object created... // We know value != NULL. It could be kBeingCreatedMarker, or a valid ptr. // Unless your constructor can be very time consuming, it is very unlikely // to hit this race. When it does, we just spin and yield the thread until // the object has been created. subtle::AtomicWord value; while (true) { - value = subtle::NoBarrier_Load(instance); + // The load has acquire memory ordering as the thread which reads the + // instance pointer must acquire visibility over the associated data. + // The pairing Release_Store operation is in Singleton::get(). + value = subtle::Acquire_Load(instance); if (value != kBeingCreatedMarker) break; PlatformThread::YieldCurrentThread(); } return value; } } // namespace internal
--- a/security/sandbox/chromium/base/memory/singleton.h +++ b/security/sandbox/chromium/base/memory/singleton.h @@ -58,30 +58,34 @@ struct DefaultSingletonTraits { static void Delete(Type* x) { delete x; } // Set to true to automatically register deletion of the object on process // exit. See below for the required call that makes this happen. static const bool kRegisterAtExit = true; +#ifndef NDEBUG // Set to false to disallow access on a non-joinable thread. This is // different from kRegisterAtExit because StaticMemorySingletonTraits allows // access on non-joinable threads, and gracefully handles this. static const bool kAllowedToAccessOnNonjoinableThread = false; +#endif }; // Alternate traits for use with the Singleton<Type>. Identical to // DefaultSingletonTraits except that the Singleton will not be cleaned up // at exit. template<typename Type> struct LeakySingletonTraits : public DefaultSingletonTraits<Type> { static const bool kRegisterAtExit = false; +#ifndef NDEBUG static const bool kAllowedToAccessOnNonjoinableThread = true; +#endif }; // Alternate traits for use with the Singleton<Type>. Allocates memory // for the singleton instance from a static buffer. The singleton will // be cleaned up at exit, but can't be revived after destruction unless // the Resurrect() method is called. // @@ -224,17 +228,19 @@ class Singleton { // Return a pointer to the one true instance of the class. static Type* get() { #ifndef NDEBUG // Avoid making TLS lookup on release builds. if (!Traits::kAllowedToAccessOnNonjoinableThread) base::ThreadRestrictions::AssertSingletonAllowed(); #endif - base::subtle::AtomicWord value = base::subtle::NoBarrier_Load(&instance_); + // The load has acquire memory ordering as the thread which reads the + // instance_ pointer must acquire visibility over the singleton data. + base::subtle::AtomicWord value = base::subtle::Acquire_Load(&instance_); if (value != 0 && value != base::internal::kBeingCreatedMarker) { // See the corresponding HAPPENS_BEFORE below. ANNOTATE_HAPPENS_AFTER(&instance_); return reinterpret_cast<Type*>(value); } // Object isn't created yet, maybe we will get to create it, let's try... if (base::subtle::Acquire_CompareAndSwap( @@ -243,16 +249,17 @@ class Singleton { // will ever get here. Threads might be spinning on us, and they will // stop right after we do this store. Type* newval = Traits::New(); // This annotation helps race detectors recognize correct lock-less // synchronization between different threads calling get(). // See the corresponding HAPPENS_AFTER below and above. ANNOTATE_HAPPENS_BEFORE(&instance_); + // Releases the visibility over instance_ to the readers. base::subtle::Release_Store( &instance_, reinterpret_cast<base::subtle::AtomicWord>(newval)); if (newval != NULL && Traits::kRegisterAtExit) base::AtExitManager::RegisterCallback(OnExit, NULL); return newval; }
--- a/security/sandbox/chromium/base/memory/weak_ptr.h +++ b/security/sandbox/chromium/base/memory/weak_ptr.h @@ -78,17 +78,17 @@ 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(). - class Flag : public RefCountedThreadSafe<Flag> { + class BASE_EXPORT Flag : public RefCountedThreadSafe<Flag> { public: Flag(); void Invalidate(); bool IsValid() const; private: friend class base::RefCountedThreadSafe<Flag>;
--- a/security/sandbox/chromium/base/move.h +++ b/security/sandbox/chromium/base/move.h @@ -131,16 +131,26 @@ // using the result of this reinterpret_cast<> is actually undefined behavior // due to C++98 5.2.10.7. In certain compilers (e.g., NaCl) the optimizer // will generate non-working code. // // In optimized builds, both implementations generate the same assembly so we // choose the one that adheres to the standard. // // +// WHY HAVE typedef void MoveOnlyTypeForCPP03 +// +// Callback<>/Bind() needs to understand movable-but-not-copyable semantics +// to call .Pass() appropriately when it is expected to transfer the value. +// The cryptic typedef MoveOnlyTypeForCPP03 is added to make this check +// easy and automatic in helper templates for Callback<>/Bind(). +// See IsMoveOnlyType template and its usage in base/callback_internal.h +// for more details. +// +// // COMPARED TO C++11 // // In C++11, you would implement this functionality using an r-value reference // and our .Pass() method would be replaced with a call to std::move(). // // This emulation also has a deficiency where it uses up the single // user-defined conversion allowed by C++ during initialization. This can // cause problems in some API edge cases. For instance, in scoped_ptr, it is @@ -197,11 +207,12 @@ 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)); } \ + typedef void MoveOnlyTypeForCPP03; \ private: #endif // BASE_MOVE_H_
--- a/security/sandbox/chromium/base/path_service.h +++ b/security/sandbox/chromium/base/path_service.h @@ -36,23 +36,33 @@ class BASE_EXPORT PathService { // path specifies a directory that does not exist, the directory will be // created by this method. This method returns true if successful. // // If the given path is relative, then it will be resolved against // DIR_CURRENT. // // WARNING: Consumers of PathService::Get may expect paths to be constant // over the lifetime of the app, so this method should be used with caution. + // + // Unit tests generally should use ScopedPathOverride instead. Overrides from + // one test should not carry over to another. static bool Override(int key, const base::FilePath& path); - // This function does the same as PathService::Override but it takes an extra - // parameter |create| which guides whether the directory to be overriden must + // This function does the same as PathService::Override but it takes extra + // parameters: + // - |is_absolute| indicates that |path| has already been expanded into an + // absolute path, otherwise MakeAbsoluteFilePath() will be used. This is + // useful to override paths that may not exist yet, since MakeAbsoluteFilePath + // fails for those. Note that MakeAbsoluteFilePath also expands symbolic + // links, even if path.IsAbsolute() is already true. + // - |create| guides whether the directory to be overriden must // be created in case it doesn't exist already. static bool OverrideAndCreateIfNeeded(int key, const base::FilePath& path, + bool is_absolute, bool create); // To extend the set of supported keys, you can register a path provider, // which is just a function mirroring PathService::Get. The ProviderFunc // returns false if it cannot provide a non-empty path for the given key. // Otherwise, true is returned. // // WARNING: This function could be called on any thread from which the
deleted file mode 100644 --- a/security/sandbox/chromium/base/platform_file.h +++ /dev/null @@ -1,254 +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. - -#ifndef BASE_PLATFORM_FILE_H_ -#define BASE_PLATFORM_FILE_H_ - -#include "build/build_config.h" -#if defined(OS_WIN) -#include <windows.h> -#endif - -#include <string> - -#include "base/base_export.h" -#include "base/basictypes.h" -#include "base/files/file_path.h" -#include "base/time/time.h" - -namespace base { - -// PLATFORM_FILE_(OPEN|CREATE).* are mutually exclusive. You should specify -// exactly one of the five (possibly combining with other flags) when opening -// or creating a file. -// PLATFORM_FILE_(WRITE|APPEND) are mutually exclusive. This is so that APPEND -// behavior will be consistent with O_APPEND on POSIX. -enum PlatformFileFlags { - PLATFORM_FILE_OPEN = 1 << 0, // Opens a file, only if it exists. - PLATFORM_FILE_CREATE = 1 << 1, // Creates a new file, only if it - // does not already exist. - PLATFORM_FILE_OPEN_ALWAYS = 1 << 2, // May create a new file. - PLATFORM_FILE_CREATE_ALWAYS = 1 << 3, // May overwrite an old file. - PLATFORM_FILE_OPEN_TRUNCATED = 1 << 4, // Opens a file and truncates it, - // only if it exists. - PLATFORM_FILE_READ = 1 << 5, - PLATFORM_FILE_WRITE = 1 << 6, - PLATFORM_FILE_APPEND = 1 << 7, - PLATFORM_FILE_EXCLUSIVE_READ = 1 << 8, // EXCLUSIVE is opposite of Windows - // SHARE - PLATFORM_FILE_EXCLUSIVE_WRITE = 1 << 9, - PLATFORM_FILE_ASYNC = 1 << 10, - PLATFORM_FILE_TEMPORARY = 1 << 11, // Used on Windows only - PLATFORM_FILE_HIDDEN = 1 << 12, // Used on Windows only - PLATFORM_FILE_DELETE_ON_CLOSE = 1 << 13, - - PLATFORM_FILE_WRITE_ATTRIBUTES = 1 << 14, // Used on Windows only - PLATFORM_FILE_ENUMERATE = 1 << 15, // May enumerate directory - - PLATFORM_FILE_SHARE_DELETE = 1 << 16, // Used on Windows only - - PLATFORM_FILE_TERMINAL_DEVICE = 1 << 17, // Serial port flags - PLATFORM_FILE_BACKUP_SEMANTICS = 1 << 18, // Used on Windows only - - PLATFORM_FILE_EXECUTE = 1 << 19, // Used on Windows only -}; - -// PLATFORM_FILE_ERROR_ACCESS_DENIED is returned when a call fails because of -// a filesystem restriction. PLATFORM_FILE_ERROR_SECURITY is returned when a -// browser policy doesn't allow the operation to be executed. -enum PlatformFileError { - PLATFORM_FILE_OK = 0, - PLATFORM_FILE_ERROR_FAILED = -1, - PLATFORM_FILE_ERROR_IN_USE = -2, - PLATFORM_FILE_ERROR_EXISTS = -3, - PLATFORM_FILE_ERROR_NOT_FOUND = -4, - PLATFORM_FILE_ERROR_ACCESS_DENIED = -5, - PLATFORM_FILE_ERROR_TOO_MANY_OPENED = -6, - PLATFORM_FILE_ERROR_NO_MEMORY = -7, - PLATFORM_FILE_ERROR_NO_SPACE = -8, - PLATFORM_FILE_ERROR_NOT_A_DIRECTORY = -9, - PLATFORM_FILE_ERROR_INVALID_OPERATION = -10, - PLATFORM_FILE_ERROR_SECURITY = -11, - PLATFORM_FILE_ERROR_ABORT = -12, - PLATFORM_FILE_ERROR_NOT_A_FILE = -13, - PLATFORM_FILE_ERROR_NOT_EMPTY = -14, - PLATFORM_FILE_ERROR_INVALID_URL = -15, - PLATFORM_FILE_ERROR_IO = -16, - // Put new entries here and increment PLATFORM_FILE_ERROR_MAX. - PLATFORM_FILE_ERROR_MAX = -17 -}; - -// This explicit mapping matches both FILE_ on Windows and SEEK_ on Linux. -enum PlatformFileWhence { - PLATFORM_FILE_FROM_BEGIN = 0, - PLATFORM_FILE_FROM_CURRENT = 1, - PLATFORM_FILE_FROM_END = 2 -}; - -// Used to hold information about a given file. -// If you add more fields to this structure (platform-specific fields are OK), -// make sure to update all functions that use it in file_util_{win|posix}.cc -// too, and the ParamTraits<base::PlatformFileInfo> implementation in -// chrome/common/common_param_traits.cc. -struct BASE_EXPORT PlatformFileInfo { - PlatformFileInfo(); - ~PlatformFileInfo(); - - // The size of the file in bytes. Undefined when is_directory is true. - int64 size; - - // True if the file corresponds to a directory. - bool is_directory; - - // True if the file corresponds to a symbolic link. - bool is_symbolic_link; - - // The last modified time of a file. - base::Time last_modified; - - // The last accessed time of a file. - base::Time last_accessed; - - // The creation time of a file. - base::Time creation_time; -}; - -#if defined(OS_WIN) -typedef HANDLE PlatformFile; -const PlatformFile kInvalidPlatformFileValue = INVALID_HANDLE_VALUE; -PlatformFileError LastErrorToPlatformFileError(DWORD saved_errno); -#elif defined(OS_POSIX) -typedef int PlatformFile; -const PlatformFile kInvalidPlatformFileValue = -1; -PlatformFileError ErrnoToPlatformFileError(int saved_errno); -#endif - -// Creates or opens the given file. If |created| is provided, it will be set to -// true if a new file was created [or an old one truncated to zero length to -// simulate a new file, which can happen with PLATFORM_FILE_CREATE_ALWAYS], and -// false otherwise. |error| can be NULL. -// -// This function fails with 'access denied' if the |name| contains path -// traversal ('..') components. -BASE_EXPORT PlatformFile CreatePlatformFile(const FilePath& name, - int flags, - bool* created, - PlatformFileError* error); - -// Same as CreatePlatformFile but allows paths with traversal (like \..\) -// components. Use only with extreme care. -BASE_EXPORT PlatformFile CreatePlatformFileUnsafe(const FilePath& name, - int flags, - bool* created, - PlatformFileError* error); - -BASE_EXPORT FILE* FdopenPlatformFile(PlatformFile file, const char* mode); - -// Closes a file handle. Returns |true| on success and |false| otherwise. -BASE_EXPORT bool ClosePlatformFile(PlatformFile file); - -// Changes current position in the file to an |offset| relative to an origin -// defined by |whence|. Returns the resultant current position in the file -// (relative to the start) or -1 in case of error. -BASE_EXPORT int64 SeekPlatformFile(PlatformFile file, - PlatformFileWhence whence, - int64 offset); - -// Reads the given number of bytes (or until EOF is reached) starting with the -// given offset. Returns the number of bytes read, or -1 on error. Note that -// this function makes a best effort to read all data on all platforms, so it is -// not intended for stream oriented files but instead for cases when the normal -// expectation is that actually |size| bytes are read unless there is an error. -BASE_EXPORT int ReadPlatformFile(PlatformFile file, int64 offset, - char* data, int size); - -// Same as above but without seek. -BASE_EXPORT int ReadPlatformFileAtCurrentPos(PlatformFile file, - char* data, int size); - -// Reads the given number of bytes (or until EOF is reached) starting with the -// given offset, but does not make any effort to read all data on all platforms. -// Returns the number of bytes read, or -1 on error. -BASE_EXPORT int ReadPlatformFileNoBestEffort(PlatformFile file, int64 offset, - char* data, int size); - -// Same as above but without seek. -BASE_EXPORT int ReadPlatformFileCurPosNoBestEffort(PlatformFile file, - char* data, int size); - -// Writes the given buffer into the file at the given offset, overwritting any -// data that was previously there. Returns the number of bytes written, or -1 -// on error. Note that this function makes a best effort to write all data on -// all platforms. -// Ignores the offset and writes to the end of the file if the file was opened -// with PLATFORM_FILE_APPEND. -BASE_EXPORT int WritePlatformFile(PlatformFile file, int64 offset, - const char* data, int size); - -// Save as above but without seek. -BASE_EXPORT int WritePlatformFileAtCurrentPos(PlatformFile file, - const char* data, int size); - -// Save as above but does not make any effort to write all data on all -// platforms. Returns the number of bytes written, or -1 on error. -BASE_EXPORT int WritePlatformFileCurPosNoBestEffort(PlatformFile file, - const char* data, int size); - -// Truncates the given file to the given length. If |length| is greater than -// the current size of the file, the file is extended with zeros. If the file -// doesn't exist, |false| is returned. -BASE_EXPORT bool TruncatePlatformFile(PlatformFile file, int64 length); - -// Flushes the buffers of the given file. -BASE_EXPORT bool FlushPlatformFile(PlatformFile file); - -// Touches the given file. -BASE_EXPORT bool TouchPlatformFile(PlatformFile file, - const Time& last_access_time, - const Time& last_modified_time); - -// Returns some information for the given file. -BASE_EXPORT bool GetPlatformFileInfo(PlatformFile file, PlatformFileInfo* info); - -// Use this class to pass ownership of a PlatformFile to a receiver that may or -// may not want to accept it. This class does not own the storage for the -// PlatformFile. -// -// EXAMPLE: -// -// void MaybeProcessFile(PassPlatformFile pass_file) { -// if (...) { -// PlatformFile file = pass_file.ReleaseValue(); -// // Now, we are responsible for closing |file|. -// } -// } -// -// void OpenAndMaybeProcessFile(const FilePath& path) { -// PlatformFile file = CreatePlatformFile(path, ...); -// MaybeProcessFile(PassPlatformFile(&file)); -// if (file != kInvalidPlatformFileValue) -// ClosePlatformFile(file); -// } -// -class BASE_EXPORT PassPlatformFile { - public: - explicit PassPlatformFile(PlatformFile* value) : value_(value) { - } - - // Called to retrieve the PlatformFile stored in this object. The caller - // gains ownership of the PlatformFile and is now responsible for closing it. - // Any subsequent calls to this method will return an invalid PlatformFile. - PlatformFile ReleaseValue() { - PlatformFile temp = *value_; - *value_ = kInvalidPlatformFileValue; - return temp; - } - - private: - PlatformFile* value_; -}; - -} // namespace base - -#endif // BASE_PLATFORM_FILE_H_
--- a/security/sandbox/chromium/base/port.h +++ b/security/sandbox/chromium/base/port.h @@ -3,38 +3,32 @@ // found in the LICENSE file. #ifndef BASE_PORT_H_ #define BASE_PORT_H_ #include <stdarg.h> #include "build/build_config.h" +// DEPRECATED: Use ...LL and ...ULL suffixes. +// TODO(viettrungluu): Delete these. These are only here until |GG_(U)INT64_C| +// are deleted (some other header files (re)define |GG_(U)INT64_C|, so our +// definitions of them must exactly match theirs). #ifdef COMPILER_MSVC #define GG_LONGLONG(x) x##I64 #define GG_ULONGLONG(x) x##UI64 #else #define GG_LONGLONG(x) x##LL #define GG_ULONGLONG(x) x##ULL #endif -// Per C99 7.8.14, define __STDC_CONSTANT_MACROS before including <stdint.h> -// to get the INTn_C and UINTn_C macros for integer constants. It's difficult -// to guarantee any specific ordering of header includes, so it's difficult to -// guarantee that the INTn_C macros can be defined by including <stdint.h> at -// any specific point. Provide GG_INTn_C macros instead. - -#define GG_INT8_C(x) (x) -#define GG_INT16_C(x) (x) -#define GG_INT32_C(x) (x) +// DEPRECATED: In Chromium, we force-define __STDC_CONSTANT_MACROS, so you can +// just use the regular (U)INTn_C macros from <stdint.h>. +// TODO(viettrungluu): Remove the remaining GG_(U)INTn_C macros. #define GG_INT64_C(x) GG_LONGLONG(x) - -#define GG_UINT8_C(x) (x ## U) -#define GG_UINT16_C(x) (x ## U) -#define GG_UINT32_C(x) (x ## U) #define GG_UINT64_C(x) GG_ULONGLONG(x) // It's possible for functions that use a va_list, such as StringPrintf, to // invalidate the data in it upon use. The fix is to make a copy of the // structure before using it and use that copy instead. va_copy is provided // for this purpose. MSVC does not provide va_copy, so define an // implementation here. It is not guaranteed that assignment is a copy, so the // StringUtil.VariableArgsFunc unit test tests this capability.
--- a/security/sandbox/chromium/base/process/process_handle.h +++ b/security/sandbox/chromium/base/process/process_handle.h @@ -76,21 +76,19 @@ enum IntegrityLevel { }; // Determine the integrity level of the specified process. Returns false // if the system does not support integrity levels (pre-Vista) or in the case // of an underlying system failure. BASE_EXPORT bool GetProcessIntegrityLevel(ProcessHandle process, IntegrityLevel* level); #endif -#if defined(OS_LINUX) || defined(OS_ANDROID) || defined(OS_BSD) +#if defined(OS_POSIX) // Returns the path to the executable of the given process. BASE_EXPORT FilePath GetProcessExecutablePath(ProcessHandle process); -#endif -#if defined(OS_POSIX) // Returns the ID for the parent of the given process. BASE_EXPORT ProcessId GetParentProcessId(ProcessHandle process); #endif } // namespace base #endif // BASE_PROCESS_PROCESS_HANDLE_H_
--- a/security/sandbox/chromium/base/rand_util.h +++ b/security/sandbox/chromium/base/rand_util.h @@ -34,20 +34,21 @@ BASE_EXPORT double BitsToOpenEndedUnitIn // Fills |output_length| bytes of |output| with random data. // // WARNING: // Do not use for security-sensitive purposes. // See crypto/ for cryptographically secure random number generation APIs. BASE_EXPORT void RandBytes(void* output, size_t output_length); -// Fills a string of length |length| with with random data and returns it. +// Fills a string of length |length| with random data and returns it. // |length| should be nonzero. // // Note that this is a variation of |RandBytes| with a different return type. +// The returned string is likely not ASCII/UTF-8. Use with care. // // WARNING: // Do not use for security-sensitive purposes. // See crypto/ for cryptographically secure random number generation APIs. BASE_EXPORT std::string RandBytesAsString(size_t length); #if defined(OS_POSIX) BASE_EXPORT int GetUrandomFD();
--- a/security/sandbox/chromium/base/sequence_checker.h +++ b/security/sandbox/chromium/base/sequence_checker.h @@ -1,32 +1,26 @@ // 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_SEQUENCE_CHECKER_H_ #define BASE_SEQUENCE_CHECKER_H_ -#include "base/memory/ref_counted.h" - // See comments for the similar block in thread_checker.h. #if (!defined(NDEBUG) || defined(DCHECK_ALWAYS_ON)) #define ENABLE_SEQUENCE_CHECKER 1 #else #define ENABLE_SEQUENCE_CHECKER 0 #endif -#if ENABLE_SEQUENCE_CHECKER #include "base/sequence_checker_impl.h" -#endif namespace base { -class SequencedTaskRunner; - // Do nothing implementation, for use in release mode. // // Note: You should almost always use the SequenceChecker class to get // the right version for your build configuration. class SequenceCheckerDoNothing { public: bool CalledOnValidSequencedThread() const { return true; @@ -39,25 +33,25 @@ class SequenceCheckerDoNothing { // methods of a class are called in sequence -- that is, called from // the same SequencedTaskRunner. It is a generalization of // ThreadChecker; see comments in sequence_checker_impl.h for details. // // Example: // class MyClass { // public: // void Foo() { -// DCHECK(sequence_checker_.CalledOnValidSequence()); +// DCHECK(sequence_checker_.CalledOnValidSequencedThread()); // ... (do stuff) ... // } // // private: // SequenceChecker sequence_checker_; // } // -// In Release mode, CalledOnValidSequence will always return true. +// In Release mode, CalledOnValidSequencedThread() will always return true. #if ENABLE_SEQUENCE_CHECKER class SequenceChecker : public SequenceCheckerImpl { }; #else class SequenceChecker : public SequenceCheckerDoNothing { }; #endif // ENABLE_SEQUENCE_CHECKER
--- a/security/sandbox/chromium/base/shim/base/logging.cpp +++ b/security/sandbox/chromium/base/shim/base/logging.cpp @@ -1,109 +1,119 @@ /* -*- 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/. */ +// This is a stripped down version of the Chromium source file base/logging.cc +// This prevents dependency on the Chromium logging and dependency creep in +// general. +// At some point we should find a way to hook this into our own logging see +// bug 1013988. +// The formatting in this file matches the original Chromium file to aid future +// merging. + #include "base/logging.h" -#ifdef OS_WIN + +#if defined(OS_WIN) #include <windows.h> #endif -namespace { -int min_log_level = 0; -} - -namespace logging -{ - -DcheckState g_dcheck_state = DISABLE_DCHECK_FOR_NON_OFFICIAL_RELEASE_BUILDS; +#if defined(OS_POSIX) +#include <errno.h> +#endif -DcheckState get_dcheck_state() { - return g_dcheck_state; -} - -LogMessage::LogMessage(const char* file, int line, LogSeverity severity, - int ctr) : - line_(line) -{ -} +#if defined(OS_WIN) +#include "base/strings/utf_string_conversions.h" +#endif -LogMessage::LogMessage(const char* file, int line, int ctr) : line_(line) -{ -} +namespace logging { -LogMessage::LogMessage(const char* file, int line, std::string* result) : - severity_(LOG_FATAL), - file_(file), - line_(line) -{ -} +namespace { -LogMessage::LogMessage(const char* file, int line, LogSeverity severity, - std::string* result) : - severity_(severity), - file_(file), - line_(line) -{ -} +int min_log_level = 0; -LogMessage::~LogMessage() -{ -} +} // namespace -int GetMinLogLevel() -{ +int GetMinLogLevel() { return min_log_level; } -int GetVlogLevelHelper(const char* file, size_t N) -{ +int GetVlogLevelHelper(const char* file, size_t N) { return 0; } -void RawLog(int level, const char* message) -{ -} +// 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 -#ifdef OS_WIN -LogMessage::SaveLastError::SaveLastError() : - last_error_(::GetLastError()) -{ -} - -LogMessage::SaveLastError::~SaveLastError() -{ - ::SetLastError(last_error_); +#if defined(OS_WIN) +LogMessage::SaveLastError::SaveLastError() : last_error_(::GetLastError()) { } -SystemErrorCode GetLastSystemErrorCode() -{ - return ::GetLastError(); +LogMessage::SaveLastError::~SaveLastError() { + ::SetLastError(last_error_); +} +#endif // defined(OS_WIN) + +LogMessage::LogMessage(const char* file, int line, LogSeverity severity) + : severity_(severity), file_(file), line_(line) { +} + +LogMessage::LogMessage(const char* file, int line, std::string* result) + : severity_(LOG_FATAL), file_(file), line_(line) { + delete result; } -Win32ErrorLogMessage::Win32ErrorLogMessage(const char* file, int line, - LogSeverity severity, - SystemErrorCode err, - const char* module) : - err_(err), - module_(module), - log_message_(file, line, severity) -{ +LogMessage::LogMessage(const char* file, int line, LogSeverity severity, + std::string* result) + : severity_(severity), file_(file), line_(line) { + delete result; +} + +LogMessage::~LogMessage() { } +SystemErrorCode GetLastSystemErrorCode() { +#if defined(OS_WIN) + return ::GetLastError(); +#elif defined(OS_POSIX) + return errno; +#else +#error Not implemented +#endif +} + +#if defined(OS_WIN) Win32ErrorLogMessage::Win32ErrorLogMessage(const char* file, int line, LogSeverity severity, - SystemErrorCode err) : - err_(err), - module_(NULL), - log_message_(file, line, severity) -{ + SystemErrorCode err) + : err_(err), + log_message_(file, line, severity) { } -Win32ErrorLogMessage::~Win32ErrorLogMessage() -{ +Win32ErrorLogMessage::~Win32ErrorLogMessage() { } -#endif // OS_WIN +#endif // OS_WIN + +void RawLog(int level, const char* message) { +} } // namespace logging + +#if defined(OS_WIN) +std::ostream& std::operator<<(std::ostream& out, const wchar_t* wstr) { + return out << base::WideToUTF8(std::wstring(wstr)); +} +#endif
new file mode 100644 --- /dev/null +++ b/security/sandbox/chromium/base/shim/base/threading/thread_local_storage.h @@ -0,0 +1,10 @@ +/* -*- 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
new file mode 100644 --- /dev/null +++ b/security/sandbox/chromium/base/shim/base/win/registry.h @@ -0,0 +1,34 @@ +/* -*- 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/. */ + +// This is a stripped down version of Chromium source file base/win/registry.h +// Within our copy of Chromium files this is only used in base/win/windows_version.cc +// in OSInfo::processor_model_name, which we don't use. + +#ifndef BASE_WIN_REGISTRY_H_ +#define BASE_WIN_REGISTRY_H_ + +namespace base { +namespace win { + +class BASE_EXPORT RegKey { + public: + RegKey(HKEY rootkey, const wchar_t* subkey, REGSAM access) {} + ~RegKey() {} + + LONG ReadValue(const wchar_t* name, std::wstring* out_value) const + { + return 0; + } + + private: + DISALLOW_COPY_AND_ASSIGN(RegKey); +}; + +} // namespace win +} // namespace base + +#endif // BASE_WIN_REGISTRY_H_
--- a/security/sandbox/chromium/base/stl_util.h +++ b/security/sandbox/chromium/base/stl_util.h @@ -196,28 +196,65 @@ bool ContainsKey(const Collection& colle return collection.find(key) != collection.end(); } namespace base { // Returns true if the container is sorted. template <typename Container> bool STLIsSorted(const Container& cont) { - return std::adjacent_find(cont.begin(), cont.end(), - std::greater<typename Container::value_type>()) - == cont.end(); + // Note: Use reverse iterator on container to ensure we only require + // value_type to implement operator<. + return std::adjacent_find(cont.rbegin(), cont.rend(), + std::less<typename Container::value_type>()) + == cont.rend(); } // Returns a new ResultType containing the difference of two sorted containers. template <typename ResultType, typename Arg1, typename Arg2> ResultType STLSetDifference(const Arg1& a1, const Arg2& a2) { DCHECK(STLIsSorted(a1)); DCHECK(STLIsSorted(a2)); ResultType difference; std::set_difference(a1.begin(), a1.end(), a2.begin(), a2.end(), std::inserter(difference, difference.end())); return difference; } +// Returns a new ResultType containing the union of two sorted containers. +template <typename ResultType, typename Arg1, typename Arg2> +ResultType STLSetUnion(const Arg1& a1, const Arg2& a2) { + DCHECK(STLIsSorted(a1)); + DCHECK(STLIsSorted(a2)); + ResultType result; + std::set_union(a1.begin(), a1.end(), + a2.begin(), a2.end(), + std::inserter(result, result.end())); + return result; +} + +// Returns a new ResultType containing the intersection of two sorted +// containers. +template <typename ResultType, typename Arg1, typename Arg2> +ResultType STLSetIntersection(const Arg1& a1, const Arg2& a2) { + DCHECK(STLIsSorted(a1)); + DCHECK(STLIsSorted(a2)); + ResultType result; + std::set_intersection(a1.begin(), a1.end(), + a2.begin(), a2.end(), + std::inserter(result, result.end())); + return result; +} + +// Returns true if the sorted container |a1| contains all elements of the sorted +// container |a2|. +template <typename Arg1, typename Arg2> +bool STLIncludes(const Arg1& a1, const Arg2& a2) { + DCHECK(STLIsSorted(a1)); + DCHECK(STLIsSorted(a2)); + return std::includes(a1.begin(), a1.end(), + a2.begin(), a2.end()); +} + } // namespace base #endif // BASE_STL_UTIL_H_
--- a/security/sandbox/chromium/base/strings/string16.h +++ b/security/sandbox/chromium/base/strings/string16.h @@ -176,14 +176,9 @@ BASE_EXPORT extern void PrintTo(const st // // TODO(mark): File this bug with Apple and update this note with a bug number. extern template class BASE_EXPORT std::basic_string<base::char16, base::string16_char_traits>; #endif // WCHAR_T_IS_UTF32 -// TODO(brettw) update users of string16 to use the namespace and remove -// this "using". -using base::char16; -using base::string16; - #endif // BASE_STRINGS_STRING16_H_
--- a/security/sandbox/chromium/base/strings/string_number_conversions.cc +++ b/security/sandbox/chromium/base/strings/string_number_conversions.cc @@ -73,34 +73,29 @@ struct IntToStringT { // then return the substr of what we ended up using. STR outbuf(kOutputBufSize, 0); bool is_neg = TestNegT<INT, NEG>::TestNeg(value); // Even though is_neg will never be true when INT is parameterized as // unsigned, even the presence of the unary operation causes a warning. UINT res = ToUnsignedT<INT, UINT, NEG>::ToUnsigned(value); - for (typename STR::iterator it = outbuf.end();;) { + typename STR::iterator it(outbuf.end()); + do { --it; DCHECK(it != outbuf.begin()); *it = static_cast<typename STR::value_type>((res % 10) + '0'); res /= 10; - - // We're done.. - if (res == 0) { - if (is_neg) { - --it; - DCHECK(it != outbuf.begin()); - *it = static_cast<typename STR::value_type>('-'); - } - return STR(it, outbuf.end()); - } + } while (res != 0); + if (is_neg) { + --it; + DCHECK(it != outbuf.begin()); + *it = static_cast<typename STR::value_type>('-'); } - NOTREACHED(); - return STR(); + return STR(it, outbuf.end()); } }; // Utility to convert a character to a digit in a given base template<typename CHAR, int BASE, bool BASE_LTE_10> class BaseCharToDigit { }; // Faster specialization for bases <= 10 @@ -296,28 +291,36 @@ class BaseIteratorRangeToNumberTraits { }; template<typename ITERATOR> class BaseHexIteratorRangeToIntTraits : public BaseIteratorRangeToNumberTraits<ITERATOR, int, 16> { }; template<typename ITERATOR> +class BaseHexIteratorRangeToUIntTraits + : public BaseIteratorRangeToNumberTraits<ITERATOR, uint32, 16> { +}; + +template<typename ITERATOR> class BaseHexIteratorRangeToInt64Traits : public BaseIteratorRangeToNumberTraits<ITERATOR, int64, 16> { }; template<typename ITERATOR> class BaseHexIteratorRangeToUInt64Traits : public BaseIteratorRangeToNumberTraits<ITERATOR, uint64, 16> { }; typedef BaseHexIteratorRangeToIntTraits<StringPiece::const_iterator> HexIteratorRangeToIntTraits; +typedef BaseHexIteratorRangeToUIntTraits<StringPiece::const_iterator> + HexIteratorRangeToUIntTraits; + typedef BaseHexIteratorRangeToInt64Traits<StringPiece::const_iterator> HexIteratorRangeToInt64Traits; typedef BaseHexIteratorRangeToUInt64Traits<StringPiece::const_iterator> HexIteratorRangeToUInt64Traits; template<typename STR> bool HexStringToBytesT(const STR& input, std::vector<uint8>* output) { @@ -380,32 +383,37 @@ std::string UintToString(unsigned int va } string16 UintToString16(unsigned int value) { return IntToStringT<string16, unsigned int, unsigned int, false>:: IntToString(value); } std::string Int64ToString(int64 value) { - return IntToStringT<std::string, int64, uint64, true>:: - IntToString(value); + return IntToStringT<std::string, int64, uint64, true>::IntToString(value); } string16 Int64ToString16(int64 value) { return IntToStringT<string16, int64, uint64, true>::IntToString(value); } std::string Uint64ToString(uint64 value) { - return IntToStringT<std::string, uint64, uint64, false>:: - IntToString(value); + return IntToStringT<std::string, uint64, uint64, false>::IntToString(value); } string16 Uint64ToString16(uint64 value) { - return IntToStringT<string16, uint64, uint64, false>:: - IntToString(value); + return IntToStringT<string16, uint64, uint64, false>::IntToString(value); +} + +std::string SizeTToString(size_t value) { + return IntToStringT<std::string, size_t, size_t, false>::IntToString(value); +} + +string16 SizeTToString16(size_t value) { + return IntToStringT<string16, size_t, size_t, false>::IntToString(value); } std::string DoubleToString(double value) { // According to g_fmt.cc, it is sufficient to declare a buffer of size 32. char buffer[32]; dmg_fp::g_fmt(buffer, value); return std::string(buffer); } @@ -494,16 +502,21 @@ std::string HexEncode(const void* bytes, return ret; } bool HexStringToInt(const StringPiece& input, int* output) { return IteratorRangeToNumber<HexIteratorRangeToIntTraits>::Invoke( input.begin(), input.end(), output); } +bool HexStringToUInt(const StringPiece& input, uint32* output) { + return IteratorRangeToNumber<HexIteratorRangeToUIntTraits>::Invoke( + input.begin(), input.end(), output); +} + bool HexStringToInt64(const StringPiece& input, int64* output) { return IteratorRangeToNumber<HexIteratorRangeToInt64Traits>::Invoke( input.begin(), input.end(), output); } bool HexStringToUInt64(const StringPiece& input, uint64* output) { return IteratorRangeToNumber<HexIteratorRangeToUInt64Traits>::Invoke( input.begin(), input.end(), output);
--- a/security/sandbox/chromium/base/strings/string_number_conversions.h +++ b/security/sandbox/chromium/base/strings/string_number_conversions.h @@ -36,16 +36,19 @@ BASE_EXPORT std::string UintToString(uns BASE_EXPORT string16 UintToString16(unsigned value); BASE_EXPORT std::string Int64ToString(int64 value); BASE_EXPORT string16 Int64ToString16(int64 value); BASE_EXPORT std::string Uint64ToString(uint64 value); BASE_EXPORT string16 Uint64ToString16(uint64 value); +BASE_EXPORT std::string SizeTToString(size_t value); +BASE_EXPORT string16 SizeTToString16(size_t value); + // DoubleToString converts the double to a string format that ignores the // locale. If you want to use locale specific formatting, use ICU. BASE_EXPORT std::string DoubleToString(double value); // String -> number conversions ------------------------------------------------ // Perform a best-effort conversion of the input string to a numeric type, // setting |*output| to the result of the conversion. Returns true for @@ -96,16 +99,22 @@ BASE_EXPORT std::string HexEncode(const // Best effort conversion, see StringToInt above for restrictions. // Will only successful parse hex values that will fit into |output|, i.e. // -0x80000000 < |input| < 0x7FFFFFFF. BASE_EXPORT bool HexStringToInt(const StringPiece& input, int* output); // Best effort conversion, see StringToInt above for restrictions. // Will only successful parse hex values that will fit into |output|, i.e. +// 0x00000000 < |input| < 0xFFFFFFFF. +// The string is not required to start with 0x. +BASE_EXPORT bool HexStringToUInt(const StringPiece& input, uint32* output); + +// Best effort conversion, see StringToInt above for restrictions. +// Will only successful parse hex values that will fit into |output|, i.e. // -0x8000000000000000 < |input| < 0x7FFFFFFFFFFFFFFF. BASE_EXPORT bool HexStringToInt64(const StringPiece& input, int64* output); // Best effort conversion, see StringToInt above for restrictions. // Will only successful parse hex values that will fit into |output|, i.e. // 0x0000000000000000 < |input| < 0xFFFFFFFFFFFFFFFF. // The string is not required to start with 0x. BASE_EXPORT bool HexStringToUInt64(const StringPiece& input, uint64* output);
--- a/security/sandbox/chromium/base/strings/string_piece.cc +++ b/security/sandbox/chromium/base/strings/string_piece.cc @@ -4,217 +4,350 @@ // Copied from strings/stringpiece.cc with modifications #include "base/strings/string_piece.h" #include <algorithm> #include <ostream> namespace base { +namespace { + +// For each character in characters_wanted, sets the index corresponding +// to the ASCII code of that character to 1 in table. This is used by +// the find_.*_of methods below to tell whether or not a character is in +// the lookup table in constant time. +// The argument `table' must be an array that is large enough to hold all +// the possible values of an unsigned char. Thus it should be be declared +// as follows: +// bool table[UCHAR_MAX + 1] +inline void BuildLookupTable(const StringPiece& characters_wanted, + bool* table) { + const size_t length = characters_wanted.length(); + const char* const data = characters_wanted.data(); + for (size_t i = 0; i < length; ++i) { + table[static_cast<unsigned char>(data[i])] = true; + } +} + +} // namespace // MSVC doesn't like complex extern templates and DLLs. #if !defined(COMPILER_MSVC) -namespace internal { -template class StringPieceDetail<std::string>; -template class StringPieceDetail<string16>; -} // namespace internal - +template class BasicStringPiece<std::string>; template class BasicStringPiece<string16>; #endif bool operator==(const StringPiece& x, const StringPiece& y) { if (x.size() != y.size()) return false; return StringPiece::wordmemcmp(x.data(), y.data(), x.size()) == 0; } std::ostream& operator<<(std::ostream& o, const StringPiece& piece) { o.write(piece.data(), static_cast<std::streamsize>(piece.size())); return o; } namespace internal { -void CopyToString(const StringPiece& self, std::string* target) { - target->assign(!self.empty() ? self.data() : "", self.size()); + +template<typename STR> +void CopyToStringT(const BasicStringPiece<STR>& self, STR* target) { + if (self.empty()) + target->clear(); + else + target->assign(self.data(), self.size()); } -void AppendToString(const StringPiece& self, std::string* target) { +void CopyToString(const StringPiece& self, std::string* target) { + CopyToStringT(self, target); +} + +void CopyToString(const StringPiece16& self, string16* target) { + CopyToStringT(self, target); +} + +template<typename STR> +void AppendToStringT(const BasicStringPiece<STR>& self, STR* target) { if (!self.empty()) target->append(self.data(), self.size()); } -StringPiece::size_type copy(const StringPiece& self, - char* buf, - StringPiece::size_type n, - StringPiece::size_type pos) { - StringPiece::size_type ret = std::min(self.size() - pos, n); - memcpy(buf, self.data() + pos, ret); +void AppendToString(const StringPiece& self, std::string* target) { + AppendToStringT(self, target); +} + +void AppendToString(const StringPiece16& self, string16* target) { + AppendToStringT(self, target); +} + +template<typename STR> +size_t copyT(const BasicStringPiece<STR>& self, + typename STR::value_type* buf, + size_t n, + size_t pos) { + size_t ret = std::min(self.size() - pos, n); + memcpy(buf, self.data() + pos, ret * sizeof(typename STR::value_type)); return ret; } -StringPiece::size_type find(const StringPiece& self, - const StringPiece& s, - StringPiece::size_type pos) { - if (pos > self.size()) - return StringPiece::npos; +size_t copy(const StringPiece& self, char* buf, size_t n, size_t pos) { + return copyT(self, buf, n, pos); +} + +size_t copy(const StringPiece16& self, char16* buf, size_t n, size_t pos) { + return copyT(self, buf, n, pos); +} - StringPiece::const_iterator result = +template<typename STR> +size_t findT(const BasicStringPiece<STR>& self, + const BasicStringPiece<STR>& s, + size_t pos) { + if (pos > self.size()) + return BasicStringPiece<STR>::npos; + + typename BasicStringPiece<STR>::const_iterator result = std::search(self.begin() + pos, self.end(), s.begin(), s.end()); - const StringPiece::size_type xpos = + const size_t xpos = static_cast<size_t>(result - self.begin()); - return xpos + s.size() <= self.size() ? xpos : StringPiece::npos; + return xpos + s.size() <= self.size() ? xpos : BasicStringPiece<STR>::npos; +} + +size_t find(const StringPiece& self, const StringPiece& s, size_t pos) { + return findT(self, s, pos); } -StringPiece::size_type find(const StringPiece& self, - char c, - StringPiece::size_type pos) { +size_t find(const StringPiece16& self, const StringPiece16& s, size_t pos) { + return findT(self, s, pos); +} + +template<typename STR> +size_t findT(const BasicStringPiece<STR>& self, + typename STR::value_type c, + size_t pos) { if (pos >= self.size()) - return StringPiece::npos; + return BasicStringPiece<STR>::npos; - StringPiece::const_iterator result = + typename BasicStringPiece<STR>::const_iterator result = std::find(self.begin() + pos, self.end(), c); return result != self.end() ? - static_cast<size_t>(result - self.begin()) : StringPiece::npos; + static_cast<size_t>(result - self.begin()) : BasicStringPiece<STR>::npos; +} + +size_t find(const StringPiece& self, char c, size_t pos) { + return findT(self, c, pos); } -StringPiece::size_type rfind(const StringPiece& self, - const StringPiece& s, - StringPiece::size_type pos) { +size_t find(const StringPiece16& self, char16 c, size_t pos) { + return findT(self, c, pos); +} + +template<typename STR> +size_t rfindT(const BasicStringPiece<STR>& self, + const BasicStringPiece<STR>& s, + size_t pos) { if (self.size() < s.size()) - return StringPiece::npos; + return BasicStringPiece<STR>::npos; if (s.empty()) return std::min(self.size(), pos); - StringPiece::const_iterator last = + typename BasicStringPiece<STR>::const_iterator last = self.begin() + std::min(self.size() - s.size(), pos) + s.size(); - StringPiece::const_iterator result = + typename BasicStringPiece<STR>::const_iterator result = std::find_end(self.begin(), last, s.begin(), s.end()); return result != last ? - static_cast<size_t>(result - self.begin()) : StringPiece::npos; + static_cast<size_t>(result - self.begin()) : BasicStringPiece<STR>::npos; +} + +size_t rfind(const StringPiece& self, const StringPiece& s, size_t pos) { + return rfindT(self, s, pos); } -StringPiece::size_type rfind(const StringPiece& self, - char c, - StringPiece::size_type pos) { +size_t rfind(const StringPiece16& self, const StringPiece16& s, size_t pos) { + return rfindT(self, s, pos); +} + +template<typename STR> +size_t rfindT(const BasicStringPiece<STR>& self, + typename STR::value_type c, + size_t pos) { if (self.size() == 0) - return StringPiece::npos; + return BasicStringPiece<STR>::npos; - for (StringPiece::size_type i = std::min(pos, self.size() - 1); ; --i) { + for (size_t i = std::min(pos, self.size() - 1); ; + --i) { if (self.data()[i] == c) return i; if (i == 0) break; } - return StringPiece::npos; + return BasicStringPiece<STR>::npos; +} + +size_t rfind(const StringPiece& self, char c, size_t pos) { + return rfindT(self, c, pos); } -// For each character in characters_wanted, sets the index corresponding -// to the ASCII code of that character to 1 in table. This is used by -// the find_.*_of methods below to tell whether or not a character is in -// the lookup table in constant time. -// The argument `table' must be an array that is large enough to hold all -// the possible values of an unsigned char. Thus it should be be declared -// as follows: -// bool table[UCHAR_MAX + 1] -static inline void BuildLookupTable(const StringPiece& characters_wanted, - bool* table) { - const StringPiece::size_type length = characters_wanted.length(); - const char* const data = characters_wanted.data(); - for (StringPiece::size_type i = 0; i < length; ++i) { - table[static_cast<unsigned char>(data[i])] = true; - } +size_t rfind(const StringPiece16& self, char16 c, size_t pos) { + return rfindT(self, c, pos); } -StringPiece::size_type find_first_of(const StringPiece& self, - const StringPiece& s, - StringPiece::size_type pos) { +// 8-bit version using lookup table. +size_t find_first_of(const StringPiece& self, + const StringPiece& s, + size_t pos) { if (self.size() == 0 || s.size() == 0) return StringPiece::npos; // Avoid the cost of BuildLookupTable() for a single-character search. if (s.size() == 1) return find(self, s.data()[0], pos); bool lookup[UCHAR_MAX + 1] = { false }; BuildLookupTable(s, lookup); - for (StringPiece::size_type i = pos; i < self.size(); ++i) { + for (size_t i = pos; i < self.size(); ++i) { if (lookup[static_cast<unsigned char>(self.data()[i])]) { return i; } } return StringPiece::npos; } -StringPiece::size_type find_first_not_of(const StringPiece& self, - const StringPiece& s, - StringPiece::size_type pos) { +// 16-bit brute force version. +size_t find_first_of(const StringPiece16& self, + const StringPiece16& s, + size_t pos) { + StringPiece16::const_iterator found = + std::find_first_of(self.begin() + pos, self.end(), s.begin(), s.end()); + if (found == self.end()) + return StringPiece16::npos; + return found - self.begin(); +} + +// 8-bit version using lookup table. +size_t find_first_not_of(const StringPiece& self, + const StringPiece& s, + size_t pos) { if (self.size() == 0) return StringPiece::npos; if (s.size() == 0) return 0; // Avoid the cost of BuildLookupTable() for a single-character search. if (s.size() == 1) return find_first_not_of(self, s.data()[0], pos); bool lookup[UCHAR_MAX + 1] = { false }; BuildLookupTable(s, lookup); - for (StringPiece::size_type i = pos; i < self.size(); ++i) { + for (size_t i = pos; i < self.size(); ++i) { if (!lookup[static_cast<unsigned char>(self.data()[i])]) { return i; } } return StringPiece::npos; } -StringPiece::size_type find_first_not_of(const StringPiece& self, - char c, - StringPiece::size_type pos) { +// 16-bit brute-force version. +BASE_EXPORT size_t find_first_not_of(const StringPiece16& self, + const StringPiece16& s, + size_t pos) { if (self.size() == 0) - return StringPiece::npos; + return StringPiece16::npos; + + for (size_t self_i = pos; self_i < self.size(); ++self_i) { + bool found = false; + for (size_t s_i = 0; s_i < s.size(); ++s_i) { + if (self[self_i] == s[s_i]) { + found = true; + break; + } + } + if (!found) + return self_i; + } + return StringPiece16::npos; +} + +template<typename STR> +size_t find_first_not_ofT(const BasicStringPiece<STR>& self, + typename STR::value_type c, + size_t pos) { + if (self.size() == 0) + return BasicStringPiece<STR>::npos; for (; pos < self.size(); ++pos) { if (self.data()[pos] != c) { return pos; } } - return StringPiece::npos; + return BasicStringPiece<STR>::npos; +} + +size_t find_first_not_of(const StringPiece& self, + char c, + size_t pos) { + return find_first_not_ofT(self, c, pos); } -StringPiece::size_type find_last_of(const StringPiece& self, - const StringPiece& s, - StringPiece::size_type pos) { +size_t find_first_not_of(const StringPiece16& self, + char16 c, + size_t pos) { + return find_first_not_ofT(self, c, pos); +} + +// 8-bit version using lookup table. +size_t find_last_of(const StringPiece& self, const StringPiece& s, size_t pos) { if (self.size() == 0 || s.size() == 0) return StringPiece::npos; // Avoid the cost of BuildLookupTable() for a single-character search. if (s.size() == 1) return rfind(self, s.data()[0], pos); bool lookup[UCHAR_MAX + 1] = { false }; BuildLookupTable(s, lookup); - for (StringPiece::size_type i = std::min(pos, self.size() - 1); ; --i) { + for (size_t i = std::min(pos, self.size() - 1); ; --i) { if (lookup[static_cast<unsigned char>(self.data()[i])]) return i; if (i == 0) break; } return StringPiece::npos; } -StringPiece::size_type find_last_not_of(const StringPiece& self, - const StringPiece& s, - StringPiece::size_type pos) { +// 16-bit brute-force version. +size_t find_last_of(const StringPiece16& self, + const StringPiece16& s, + size_t pos) { + if (self.size() == 0) + return StringPiece16::npos; + + for (size_t self_i = std::min(pos, self.size() - 1); ; + --self_i) { + for (size_t s_i = 0; s_i < s.size(); s_i++) { + if (self.data()[self_i] == s[s_i]) + return self_i; + } + if (self_i == 0) + break; + } + return StringPiece16::npos; +} + +// 8-bit version using lookup table. +size_t find_last_not_of(const StringPiece& self, + const StringPiece& s, + size_t pos) { if (self.size() == 0) return StringPiece::npos; - StringPiece::size_type i = std::min(pos, self.size() - 1); + size_t i = std::min(pos, self.size() - 1); if (s.size() == 0) return i; // Avoid the cost of BuildLookupTable() for a single-character search. if (s.size() == 1) return find_last_not_of(self, s.data()[0], pos); bool lookup[UCHAR_MAX + 1] = { false }; @@ -223,33 +356,82 @@ StringPiece::size_type find_last_not_of( if (!lookup[static_cast<unsigned char>(self.data()[i])]) return i; if (i == 0) break; } return StringPiece::npos; } -StringPiece::size_type find_last_not_of(const StringPiece& self, - char c, - StringPiece::size_type pos) { +// 16-bit brute-force version. +size_t find_last_not_of(const StringPiece16& self, + const StringPiece16& s, + size_t pos) { if (self.size() == 0) return StringPiece::npos; - for (StringPiece::size_type i = std::min(pos, self.size() - 1); ; --i) { + for (size_t self_i = std::min(pos, self.size() - 1); ; --self_i) { + bool found = false; + for (size_t s_i = 0; s_i < s.size(); s_i++) { + if (self.data()[self_i] == s[s_i]) { + found = true; + break; + } + } + if (!found) + return self_i; + if (self_i == 0) + break; + } + return StringPiece16::npos; +} + +template<typename STR> +size_t find_last_not_ofT(const BasicStringPiece<STR>& self, + typename STR::value_type c, + size_t pos) { + if (self.size() == 0) + return BasicStringPiece<STR>::npos; + + for (size_t i = std::min(pos, self.size() - 1); ; --i) { if (self.data()[i] != c) return i; if (i == 0) break; } - return StringPiece::npos; + return BasicStringPiece<STR>::npos; +} + +size_t find_last_not_of(const StringPiece& self, + char c, + size_t pos) { + return find_last_not_ofT(self, c, pos); +} + +size_t find_last_not_of(const StringPiece16& self, + char16 c, + size_t pos) { + return find_last_not_ofT(self, c, pos); +} + +template<typename STR> +BasicStringPiece<STR> substrT(const BasicStringPiece<STR>& self, + size_t pos, + size_t n) { + if (pos > self.size()) pos = self.size(); + if (n > self.size() - pos) n = self.size() - pos; + return BasicStringPiece<STR>(self.data() + pos, n); } StringPiece substr(const StringPiece& self, - StringPiece::size_type pos, - StringPiece::size_type n) { - if (pos > self.size()) pos = self.size(); - if (n > self.size() - pos) n = self.size() - pos; - return StringPiece(self.data() + pos, n); + size_t pos, + size_t n) { + return substrT(self, pos, n); +} + +StringPiece16 substr(const StringPiece16& self, + size_t pos, + size_t n) { + return substrT(self, pos, n); } } // namespace internal } // namespace base
--- a/security/sandbox/chromium/base/strings/string_piece.h +++ b/security/sandbox/chromium/base/strings/string_piece.h @@ -1,23 +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. // Copied from strings/stringpiece.h with modifications // // A string-like object that points to a sized piece of memory. // -// Functions or methods may use const StringPiece& parameters to accept either -// a "const char*" or a "string" value that will be implicitly converted to -// a StringPiece. The implicit conversion means that it is often appropriate -// to include this .h file in other files rather than forward-declaring -// StringPiece as would be appropriate for most other Google classes. +// You can use StringPiece as a function or method parameter. A StringPiece +// parameter can receive a double-quoted string literal argument, a "const +// char*" argument, a string argument, or a StringPiece argument with no data +// copying. Systematic use of StringPiece for arguments reduces data +// copies and strlen() calls. // -// Systematic usage of StringPiece is encouraged as it will reduce unnecessary -// conversions from "const char*" to "string" and back again. +// Prefer passing StringPieces by value: +// void MyFunction(StringPiece arg); +// If circumstances require, you may also pass by const reference: +// void MyFunction(const StringPiece& arg); // not preferred +// Both of these have the same lifetime semantics. Passing by value +// generates slightly smaller code. For more discussion, Googlers can see +// the thread go/stringpiecebyvalue on c-users. // // StringPiece16 is similar to StringPiece but for base::string16 instead of // std::string. We do not define as large of a subset of the STL functions // from basic_string as in StringPiece, but this can be changed if these // functions (find, find_first_of, etc.) are found to be useful in this context. // #ifndef BASE_STRINGS_STRING_PIECE_H_ @@ -34,48 +39,158 @@ #include "base/strings/string16.h" namespace base { template <typename STRING_TYPE> class BasicStringPiece; typedef BasicStringPiece<std::string> StringPiece; typedef BasicStringPiece<string16> StringPiece16; +// internal -------------------------------------------------------------------- + +// Many of the StringPiece functions use different implementations for the +// 8-bit and 16-bit versions, and we don't want lots of template expansions in +// this (very common) header that will slow down compilation. +// +// So here we define overloaded functions called by the StringPiece template. +// For those that share an implementation, the two versions will expand to a +// template internal to the .cc file. namespace internal { +BASE_EXPORT void CopyToString(const StringPiece& self, std::string* target); +BASE_EXPORT void CopyToString(const StringPiece16& self, string16* target); + +BASE_EXPORT void AppendToString(const StringPiece& self, std::string* target); +BASE_EXPORT void AppendToString(const StringPiece16& self, string16* target); + +BASE_EXPORT size_t copy(const StringPiece& self, + char* buf, + size_t n, + size_t pos); +BASE_EXPORT size_t copy(const StringPiece16& self, + char16* buf, + size_t n, + size_t pos); + +BASE_EXPORT size_t find(const StringPiece& self, + const StringPiece& s, + size_t pos); +BASE_EXPORT size_t find(const StringPiece16& self, + const StringPiece16& s, + size_t pos); +BASE_EXPORT size_t find(const StringPiece& self, + char c, + size_t pos); +BASE_EXPORT size_t find(const StringPiece16& self, + char16 c, + size_t pos); + +BASE_EXPORT size_t rfind(const StringPiece& self, + const StringPiece& s, + size_t pos); +BASE_EXPORT size_t rfind(const StringPiece16& self, + const StringPiece16& s, + size_t pos); +BASE_EXPORT size_t rfind(const StringPiece& self, + char c, + size_t pos); +BASE_EXPORT size_t rfind(const StringPiece16& self, + char16 c, + size_t pos); + +BASE_EXPORT size_t find_first_of(const StringPiece& self, + const StringPiece& s, + size_t pos); +BASE_EXPORT size_t find_first_of(const StringPiece16& self, + const StringPiece16& s, + size_t pos); + +BASE_EXPORT size_t find_first_not_of(const StringPiece& self, + const StringPiece& s, + size_t pos); +BASE_EXPORT size_t find_first_not_of(const StringPiece16& self, + const StringPiece16& s, + size_t pos); +BASE_EXPORT size_t find_first_not_of(const StringPiece& self, + char c, + size_t pos); +BASE_EXPORT size_t find_first_not_of(const StringPiece16& self, + char16 c, + size_t pos); + +BASE_EXPORT size_t find_last_of(const StringPiece& self, + const StringPiece& s, + size_t pos); +BASE_EXPORT size_t find_last_of(const StringPiece16& self, + const StringPiece16& s, + size_t pos); +BASE_EXPORT size_t find_last_of(const StringPiece& self, + char c, + size_t pos); +BASE_EXPORT size_t find_last_of(const StringPiece16& self, + char16 c, + size_t pos); + +BASE_EXPORT size_t find_last_not_of(const StringPiece& self, + const StringPiece& s, + size_t pos); +BASE_EXPORT size_t find_last_not_of(const StringPiece16& self, + const StringPiece16& s, + size_t pos); +BASE_EXPORT size_t find_last_not_of(const StringPiece16& self, + char16 c, + size_t pos); +BASE_EXPORT size_t find_last_not_of(const StringPiece& self, + char c, + size_t pos); + +BASE_EXPORT StringPiece substr(const StringPiece& self, + size_t pos, + size_t n); +BASE_EXPORT StringPiece16 substr(const StringPiece16& self, + size_t pos, + size_t n); + +} // namespace internal + +// BasicStringPiece ------------------------------------------------------------ + // Defines the types, methods, operators, and data members common to both // StringPiece and StringPiece16. Do not refer to this class directly, but // rather to BasicStringPiece, StringPiece, or StringPiece16. -template <typename STRING_TYPE> class StringPieceDetail { +// +// This is templatized by string class type rather than character type, so +// BasicStringPiece<std::string> or BasicStringPiece<base::string16>. +template <typename STRING_TYPE> class BasicStringPiece { public: - // standard STL container boilerplate + // Standard STL container boilerplate. typedef size_t size_type; typedef typename STRING_TYPE::value_type value_type; typedef const value_type* pointer; typedef const value_type& reference; typedef const value_type& const_reference; typedef ptrdiff_t difference_type; typedef const value_type* const_iterator; typedef std::reverse_iterator<const_iterator> const_reverse_iterator; 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). - StringPieceDetail() : ptr_(NULL), length_(0) {} - StringPieceDetail(const value_type* str) + BasicStringPiece() : ptr_(NULL), length_(0) {} + BasicStringPiece(const value_type* str) : ptr_(str), length_((str == NULL) ? 0 : STRING_TYPE::traits_type::length(str)) {} - StringPieceDetail(const STRING_TYPE& str) + BasicStringPiece(const STRING_TYPE& str) : ptr_(str.data()), length_(str.size()) {} - StringPieceDetail(const value_type* offset, size_type len) + BasicStringPiece(const value_type* offset, size_type len) : ptr_(offset), length_(len) {} - StringPieceDetail(const typename STRING_TYPE::const_iterator& begin, + 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) {} // data() may return a pointer to a buffer with embedded NULs, and the // returned buffer may or may not be null terminated. Therefore it is // typically a mistake to pass data() to a routine that expects a NUL // terminated string. @@ -136,222 +251,122 @@ template <typename STRING_TYPE> class St size_type capacity() const { return length_; } static int wordmemcmp(const value_type* p, const value_type* p2, size_type N) { return STRING_TYPE::traits_type::compare(p, p2, N); } + // Sets the value of the given string target type to be the current string. + // This saves a temporary over doing |a = b.as_string()| + void CopyToString(STRING_TYPE* target) const { + internal::CopyToString(*this, target); + } + + void AppendToString(STRING_TYPE* target) const { + internal::AppendToString(*this, target); + } + + size_type copy(value_type* buf, size_type n, size_type pos = 0) const { + return internal::copy(*this, buf, n, pos); + } + + // Does "this" start with "x" + bool starts_with(const BasicStringPiece& x) const { + return ((this->length_ >= x.length_) && + (wordmemcmp(this->ptr_, x.ptr_, x.length_) == 0)); + } + + // Does "this" end with "x" + bool ends_with(const BasicStringPiece& x) const { + return ((this->length_ >= x.length_) && + (wordmemcmp(this->ptr_ + (this->length_-x.length_), + x.ptr_, x.length_) == 0)); + } + + // find: Search for a character or substring at a given offset. + size_type find(const BasicStringPiece<STRING_TYPE>& s, + size_type pos = 0) const { + return internal::find(*this, s, pos); + } + size_type find(value_type c, size_type pos = 0) const { + return internal::find(*this, c, pos); + } + + // rfind: Reverse find. + size_type rfind(const BasicStringPiece& s, + size_type pos = BasicStringPiece::npos) const { + return internal::rfind(*this, s, pos); + } + size_type rfind(value_type c, size_type pos = BasicStringPiece::npos) const { + return internal::rfind(*this, c, pos); + } + + // find_first_of: Find the first occurence of one of a set of characters. + size_type find_first_of(const BasicStringPiece& s, + size_type pos = 0) const { + return internal::find_first_of(*this, s, pos); + } + size_type find_first_of(value_type c, size_type pos = 0) const { + return find(c, pos); + } + + // find_first_not_of: Find the first occurence not of a set of characters. + size_type find_first_not_of(const BasicStringPiece& s, + size_type pos = 0) const { + return internal::find_first_not_of(*this, s, pos); + } + size_type find_first_not_of(value_type c, size_type pos = 0) const { + return internal::find_first_not_of(*this, c, pos); + } + + // find_last_of: Find the last occurence of one of a set of characters. + size_type find_last_of(const BasicStringPiece& s, + size_type pos = BasicStringPiece::npos) const { + return internal::find_last_of(*this, s, pos); + } + size_type find_last_of(value_type c, + size_type pos = BasicStringPiece::npos) const { + return rfind(c, pos); + } + + // find_last_not_of: Find the last occurence not of a set of characters. + size_type find_last_not_of(const BasicStringPiece& s, + size_type pos = BasicStringPiece::npos) const { + return internal::find_last_not_of(*this, s, pos); + } + size_type find_last_not_of(value_type c, + size_type pos = BasicStringPiece::npos) const { + return internal::find_last_not_of(*this, c, pos); + } + + // substr. + BasicStringPiece substr(size_type pos, + size_type n = BasicStringPiece::npos) const { + return internal::substr(*this, pos, n); + } + protected: const value_type* ptr_; size_type length_; }; template <typename STRING_TYPE> -const typename StringPieceDetail<STRING_TYPE>::size_type -StringPieceDetail<STRING_TYPE>::npos = - typename StringPieceDetail<STRING_TYPE>::size_type(-1); +const typename BasicStringPiece<STRING_TYPE>::size_type +BasicStringPiece<STRING_TYPE>::npos = + typename BasicStringPiece<STRING_TYPE>::size_type(-1); // MSVC doesn't like complex extern templates and DLLs. #if !defined(COMPILER_MSVC) -extern template class BASE_EXPORT StringPieceDetail<std::string>; -extern template class BASE_EXPORT StringPieceDetail<string16>; +extern template class BASE_EXPORT BasicStringPiece<std::string>; +extern template class BASE_EXPORT BasicStringPiece<string16>; #endif -BASE_EXPORT void CopyToString(const StringPiece& self, std::string* target); -BASE_EXPORT void AppendToString(const StringPiece& self, std::string* target); -BASE_EXPORT StringPieceDetail<std::string>::size_type copy( - const StringPiece& self, - char* buf, - StringPieceDetail<std::string>::size_type n, - StringPieceDetail<std::string>::size_type pos); -BASE_EXPORT StringPieceDetail<std::string>::size_type find( - const StringPiece& self, - const StringPiece& s, - StringPieceDetail<std::string>::size_type pos); -BASE_EXPORT StringPieceDetail<std::string>::size_type find( - const StringPiece& self, - char c, - StringPieceDetail<std::string>::size_type pos); -BASE_EXPORT StringPieceDetail<std::string>::size_type rfind( - const StringPiece& self, - const StringPiece& s, - StringPieceDetail<std::string>::size_type pos); -BASE_EXPORT StringPieceDetail<std::string>::size_type rfind( - const StringPiece& self, - char c, - StringPieceDetail<std::string>::size_type pos); -BASE_EXPORT StringPieceDetail<std::string>::size_type find_first_of( - const StringPiece& self, - const StringPiece& s, - StringPieceDetail<std::string>::size_type pos); -BASE_EXPORT StringPieceDetail<std::string>::size_type find_first_not_of( - const StringPiece& self, - const StringPiece& s, - StringPieceDetail<std::string>::size_type pos); -BASE_EXPORT StringPieceDetail<std::string>::size_type find_first_not_of( - const StringPiece& self, - char c, - StringPieceDetail<std::string>::size_type pos); -BASE_EXPORT StringPieceDetail<std::string>::size_type find_last_of( - const StringPiece& self, - const StringPiece& s, - StringPieceDetail<std::string>::size_type pos); -BASE_EXPORT StringPieceDetail<std::string>::size_type find_last_of( - const StringPiece& self, - char c, - StringPieceDetail<std::string>::size_type pos); -BASE_EXPORT StringPieceDetail<std::string>::size_type find_last_not_of( - const StringPiece& self, - const StringPiece& s, - StringPieceDetail<std::string>::size_type pos); -BASE_EXPORT StringPieceDetail<std::string>::size_type find_last_not_of( - const StringPiece& self, - char c, - StringPieceDetail<std::string>::size_type pos); -BASE_EXPORT StringPiece substr(const StringPiece& self, - StringPieceDetail<std::string>::size_type pos, - StringPieceDetail<std::string>::size_type n); -} // namespace internal - -// Defines the template type that is instantiated as either StringPiece or -// StringPiece16. -template <typename STRING_TYPE> class BasicStringPiece : - public internal::StringPieceDetail<STRING_TYPE> { - public: - typedef typename internal::StringPieceDetail<STRING_TYPE>::value_type - value_type; - typedef typename internal::StringPieceDetail<STRING_TYPE>::size_type - size_type; - - BasicStringPiece() {} - BasicStringPiece(const value_type*str) - : internal::StringPieceDetail<STRING_TYPE>(str) {} - BasicStringPiece(const STRING_TYPE& str) - : internal::StringPieceDetail<STRING_TYPE>(str) {} - BasicStringPiece(const value_type* offset, size_type len) - : internal::StringPieceDetail<STRING_TYPE>(offset, len) {} - BasicStringPiece(const typename STRING_TYPE::const_iterator& begin, - const typename STRING_TYPE::const_iterator& end) - : internal::StringPieceDetail<STRING_TYPE>(begin, end) {} -}; - -// Specializes BasicStringPiece for std::string to add a few operations that -// are not needed for string16. -template <> class BasicStringPiece<std::string> : - public internal::StringPieceDetail<std::string> { - public: - BasicStringPiece() {} - BasicStringPiece(const char* str) - : internal::StringPieceDetail<std::string>(str) {} - BasicStringPiece(const std::string& str) - : internal::StringPieceDetail<std::string>(str) {} - BasicStringPiece(const char* offset, size_type len) - : internal::StringPieceDetail<std::string>(offset, len) {} - BasicStringPiece(const std::string::const_iterator& begin, - const std::string::const_iterator& end) - : internal::StringPieceDetail<std::string>(begin, end) {} - - // Prevent the following overload of set() from hiding the definitions in the - // base class. - using internal::StringPieceDetail<std::string>::set; - - void set(const void* data, size_type len) { - ptr_ = reinterpret_cast<const value_type*>(data); - length_ = len; - } - - void CopyToString(std::string* target) const { - internal::CopyToString(*this, target); - } - - void AppendToString(std::string* target) const { - internal::AppendToString(*this, target); - } - - // Does "this" start with "x" - bool starts_with(const BasicStringPiece& x) const { - return ((length_ >= x.length_) && - (wordmemcmp(ptr_, x.ptr_, x.length_) == 0)); - } - - // Does "this" end with "x" - bool ends_with(const BasicStringPiece& x) const { - return ((length_ >= x.length_) && - (wordmemcmp(ptr_ + (length_-x.length_), x.ptr_, x.length_) == 0)); - } - - size_type copy(char* buf, size_type n, size_type pos = 0) const { - return internal::copy(*this, buf, n, pos); - } - - size_type find(const BasicStringPiece& s, size_type pos = 0) const { - return internal::find(*this, s, pos); - } - - size_type find(char c, size_type pos = 0) const { - return internal::find(*this, c, pos); - } - - size_type rfind(const BasicStringPiece& s, size_type pos = npos) const { - return internal::rfind(*this, s, pos); - } - - size_type rfind(char c, size_type pos = npos) const { - return internal::rfind(*this, c, pos); - } - - size_type find_first_of(const BasicStringPiece& s, size_type pos = 0) const { - return internal::find_first_of(*this, s, pos); - } - - size_type find_first_of(char c, size_type pos = 0) const { - return find(c, pos); - } - - size_type find_first_not_of(const BasicStringPiece& s, - size_type pos = 0) const { - return internal::find_first_not_of(*this, s, pos); - } - - size_type find_first_not_of(char c, size_type pos = 0) const { - return internal::find_first_not_of(*this, c, pos); - } - - size_type find_last_of(const BasicStringPiece& s, - size_type pos = npos) const { - return internal::find_last_of(*this, s, pos); - } - - size_type find_last_of(char c, size_type pos = npos) const { - return rfind(c, pos); - } - - size_type find_last_not_of(const BasicStringPiece& s, - size_type pos = npos) const { - return internal::find_last_not_of(*this, s, pos); - } - - size_type find_last_not_of(char c, size_type pos = npos) const { - return internal::find_last_not_of(*this, c, pos); - } - - BasicStringPiece substr(size_type pos, size_type n = npos) const { - return internal::substr(*this, pos, n); - } -}; - -// MSVC doesn't like complex extern templates and DLLs. -#if !defined(COMPILER_MSVC) -// We can't explicitly declare the std::string instantiation here because it was -// already instantiated when specialized, above. Not only is it a no-op, but -// currently it also crashes Clang (see http://crbug.com/107412). -extern template class BASE_EXPORT BasicStringPiece<string16>; -#endif +// StingPiece operators -------------------------------------------------------- BASE_EXPORT bool operator==(const StringPiece& x, const StringPiece& y); inline bool operator!=(const StringPiece& x, const StringPiece& y) { return !(x == y); } inline bool operator<(const StringPiece& x, const StringPiece& y) { @@ -367,16 +382,18 @@ inline bool operator>(const StringPiece& inline bool operator<=(const StringPiece& x, const StringPiece& y) { return !(x > y); } inline bool operator>=(const StringPiece& x, const StringPiece& y) { return !(x < y); } +// StringPiece16 operators ----------------------------------------------------- + inline bool operator==(const StringPiece16& x, const StringPiece16& y) { if (x.size() != y.size()) return false; return StringPiece16::wordmemcmp(x.data(), y.data(), x.size()) == 0; } inline bool operator!=(const StringPiece16& x, const StringPiece16& y) { @@ -401,16 +418,18 @@ inline bool operator>=(const StringPiece return !(x < y); } BASE_EXPORT std::ostream& operator<<(std::ostream& o, const StringPiece& piece); } // namespace base +// Hashing --------------------------------------------------------------------- + // We provide appropriate hash functions so StringPiece and StringPiece16 can // be used as keys in hash sets and maps. // This hash function is copied from base/containers/hash_tables.h. We don't // use the ones already defined for string and string16 directly because it // would require the string constructors to be called, which we don't want. #define HASH_STRING_PIECE(StringPieceType, string_piece) \ std::size_t result = 0; \
new file mode 100644 --- /dev/null +++ b/security/sandbox/chromium/base/strings/string_split.cc @@ -0,0 +1,214 @@ +// 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/strings/string_split.h" + +#include "base/logging.h" +#include "base/strings/string_util.h" +#include "base/strings/utf_string_conversions.h" +#include "base/third_party/icu/icu_utf.h" + +namespace base { + +namespace { + +template <typename STR> +void SplitStringT(const STR& str, + const typename STR::value_type s, + bool trim_whitespace, + std::vector<STR>* r) { + r->clear(); + size_t last = 0; + size_t c = str.size(); + for (size_t i = 0; i <= c; ++i) { + if (i == c || str[i] == s) { + STR tmp(str, last, i - last); + if (trim_whitespace) + TrimWhitespace(tmp, TRIM_ALL, &tmp); + // Avoid converting an empty or all-whitespace source string into a vector + // of one empty string. + if (i != c || !r->empty() || !tmp.empty()) + r->push_back(tmp); + last = i + 1; + } + } +} + +bool SplitStringIntoKeyValue(const std::string& line, + char key_value_delimiter, + std::string* key, + std::string* value) { + key->clear(); + value->clear(); + + // Find the delimiter. + size_t end_key_pos = line.find_first_of(key_value_delimiter); + if (end_key_pos == std::string::npos) { + DVLOG(1) << "cannot find delimiter in: " << line; + return false; // no delimiter + } + key->assign(line, 0, end_key_pos); + + // Find the value string. + std::string remains(line, end_key_pos, line.size() - end_key_pos); + size_t begin_value_pos = remains.find_first_not_of(key_value_delimiter); + if (begin_value_pos == std::string::npos) { + DVLOG(1) << "cannot parse value from line: " << line; + return false; // no value + } + value->assign(remains, begin_value_pos, remains.size() - begin_value_pos); + return true; +} + +template <typename STR> +void SplitStringUsingSubstrT(const STR& str, + const STR& s, + std::vector<STR>* r) { + r->clear(); + typename STR::size_type begin_index = 0; + while (true) { + const typename STR::size_type end_index = str.find(s, begin_index); + if (end_index == STR::npos) { + const STR term = str.substr(begin_index); + STR tmp; + TrimWhitespace(term, TRIM_ALL, &tmp); + r->push_back(tmp); + return; + } + const STR term = str.substr(begin_index, end_index - begin_index); + STR tmp; + TrimWhitespace(term, TRIM_ALL, &tmp); + r->push_back(tmp); + begin_index = end_index + s.size(); + } +} + +template<typename STR> +void SplitStringAlongWhitespaceT(const STR& str, std::vector<STR>* result) { + result->clear(); + const size_t length = str.length(); + if (!length) + return; + + bool last_was_ws = false; + size_t last_non_ws_start = 0; + for (size_t i = 0; i < length; ++i) { + switch (str[i]) { + // HTML 5 defines whitespace as: space, tab, LF, line tab, FF, or CR. + case L' ': + case L'\t': + case L'\xA': + case L'\xB': + case L'\xC': + case L'\xD': + if (!last_was_ws) { + if (i > 0) { + result->push_back( + str.substr(last_non_ws_start, i - last_non_ws_start)); + } + last_was_ws = true; + } + break; + + default: // Not a space character. + if (last_was_ws) { + last_was_ws = false; + last_non_ws_start = i; + } + break; + } + } + if (!last_was_ws) { + result->push_back( + str.substr(last_non_ws_start, length - last_non_ws_start)); + } +} + +} // namespace + +void SplitString(const string16& str, + char16 c, + std::vector<string16>* r) { + DCHECK(CBU16_IS_SINGLE(c)); + SplitStringT(str, c, true, r); +} + +void SplitString(const std::string& str, + char c, + std::vector<std::string>* r) { +#if CHAR_MIN < 0 + DCHECK(c >= 0); +#endif + DCHECK(c < 0x7F); + SplitStringT(str, c, true, r); +} + +bool SplitStringIntoKeyValuePairs(const std::string& line, + char key_value_delimiter, + char key_value_pair_delimiter, + StringPairs* key_value_pairs) { + key_value_pairs->clear(); + + std::vector<std::string> pairs; + SplitString(line, key_value_pair_delimiter, &pairs); + + bool success = true; + for (size_t i = 0; i < pairs.size(); ++i) { + // Don't add empty pairs into the result. + if (pairs[i].empty()) + continue; + + std::string key; + std::string value; + if (!SplitStringIntoKeyValue(pairs[i], key_value_delimiter, &key, &value)) { + // Don't return here, to allow for pairs without associated + // value or key; just record that the split failed. + success = false; + } + key_value_pairs->push_back(make_pair(key, value)); + } + return success; +} + +void SplitStringUsingSubstr(const string16& str, + const string16& s, + std::vector<string16>* r) { + SplitStringUsingSubstrT(str, s, r); +} + +void SplitStringUsingSubstr(const std::string& str, + const std::string& s, + std::vector<std::string>* r) { + SplitStringUsingSubstrT(str, s, r); +} + +void SplitStringDontTrim(const string16& str, + char16 c, + std::vector<string16>* r) { + DCHECK(CBU16_IS_SINGLE(c)); + SplitStringT(str, c, false, r); +} + +void SplitStringDontTrim(const std::string& str, + char c, + std::vector<std::string>* r) { + DCHECK(IsStringUTF8(str)); +#if CHAR_MIN < 0 + DCHECK(c >= 0); +#endif + DCHECK(c < 0x7F); + SplitStringT(str, c, false, r); +} + +void SplitStringAlongWhitespace(const string16& str, + std::vector<string16>* result) { + SplitStringAlongWhitespaceT(str, result); +} + +void SplitStringAlongWhitespace(const std::string& str, + std::vector<std::string>* result) { + SplitStringAlongWhitespaceT(str, result); +} + +} // namespace base
new file mode 100644 --- /dev/null +++ b/security/sandbox/chromium/base/strings/string_split.h @@ -0,0 +1,82 @@ +// 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_STRINGS_STRING_SPLIT_H_ +#define BASE_STRINGS_STRING_SPLIT_H_ + +#include <string> +#include <utility> +#include <vector> + +#include "base/base_export.h" +#include "base/strings/string16.h" + +namespace base { + +// Splits |str| into a vector of strings delimited by |c|, placing the results +// in |r|. If several instances of |c| are contiguous, or if |str| begins with +// or ends with |c|, then an empty string is inserted. +// +// Every substring is trimmed of any leading or trailing white space. +// NOTE: |c| must be in BMP (Basic Multilingual Plane) +BASE_EXPORT void SplitString(const string16& str, + char16 c, + std::vector<string16>* r); + +// |str| should not be in a multi-byte encoding like Shift-JIS or GBK in which +// the trailing byte of a multi-byte character can be in the ASCII range. +// UTF-8, and other single/multi-byte ASCII-compatible encodings are OK. +// Note: |c| must be in the ASCII range. +BASE_EXPORT void SplitString(const std::string& str, + char c, + std::vector<std::string>* r); + +typedef std::vector<std::pair<std::string, std::string> > StringPairs; + +// Splits |line| into key value pairs according to the given delimiters and +// removes whitespace leading each key and trailing each value. Returns true +// only if each pair has a non-empty key and value. |key_value_pairs| will +// include ("","") pairs for entries without |key_value_delimiter|. +BASE_EXPORT bool SplitStringIntoKeyValuePairs(const std::string& line, + char key_value_delimiter, + char key_value_pair_delimiter, + StringPairs* key_value_pairs); + +// The same as SplitString, but use a substring delimiter instead of a char. +BASE_EXPORT void SplitStringUsingSubstr(const string16& str, + const string16& s, + std::vector<string16>* r); +BASE_EXPORT void SplitStringUsingSubstr(const std::string& str, + const std::string& s, + std::vector<std::string>* r); + +// The same as SplitString, but don't trim white space. +// NOTE: |c| must be in BMP (Basic Multilingual Plane) +BASE_EXPORT void SplitStringDontTrim(const string16& str, + char16 c, + std::vector<string16>* r); +// |str| should not be in a multi-byte encoding like Shift-JIS or GBK in which +// the trailing byte of a multi-byte character can be in the ASCII range. +// UTF-8, and other single/multi-byte ASCII-compatible encodings are OK. +// Note: |c| must be in the ASCII range. +BASE_EXPORT void SplitStringDontTrim(const std::string& str, + char c, + std::vector<std::string>* r); + +// WARNING: this uses whitespace as defined by the HTML5 spec. If you need +// a function similar to this but want to trim all types of whitespace, then +// factor this out into a function that takes a string containing the characters +// that are treated as whitespace. +// +// Splits the string along whitespace (where whitespace is the five space +// characters defined by HTML 5). Each contiguous block of non-whitespace +// characters is added to result. +BASE_EXPORT void SplitStringAlongWhitespace(const string16& str, + std::vector<string16>* result); +BASE_EXPORT void SplitStringAlongWhitespace(const std::string& str, + std::vector<std::string>* result); + +} // namespace base + +#endif // BASE_STRINGS_STRING_SPLIT_H_
new file mode 100644 --- /dev/null +++ b/security/sandbox/chromium/base/strings/string_util.cc @@ -0,0 +1,892 @@ +// 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/string_util.h" + +#include <ctype.h> +#include <errno.h> +#include <math.h> +#include <stdarg.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <time.h> +#include <wchar.h> +#include <wctype.h> + +#include <algorithm> +#include <vector> + +#include "base/basictypes.h" +#include "base/logging.h" +#include "base/memory/singleton.h" +#include "base/strings/utf_string_conversion_utils.h" +#include "base/strings/utf_string_conversions.h" +#include "base/third_party/icu/icu_utf.h" +#include "build/build_config.h" + +// Remove when this entire file is in the base namespace. +using base::char16; +using base::string16; + +namespace { + +// Force the singleton used by EmptyString[16] to be a unique type. This +// prevents other code that might accidentally use Singleton<string> from +// getting our internal one. +struct EmptyStrings { + EmptyStrings() {} + const std::string s; + const string16 s16; + + static EmptyStrings* GetInstance() { + return Singleton<EmptyStrings>::get(); + } +}; + +// Used by ReplaceStringPlaceholders to track the position in the string of +// replaced parameters. +struct ReplacementOffset { + ReplacementOffset(uintptr_t parameter, size_t offset) + : parameter(parameter), + offset(offset) {} + + // Index of the parameter. + uintptr_t parameter; + + // Starting position in the string. + size_t offset; +}; + +static bool CompareParameter(const ReplacementOffset& elem1, + const ReplacementOffset& elem2) { + return elem1.parameter < elem2.parameter; +} + +} // namespace + +namespace base { + +bool IsWprintfFormatPortable(const wchar_t* format) { + for (const wchar_t* position = format; *position != '\0'; ++position) { + if (*position == '%') { + bool in_specification = true; + bool modifier_l = false; + while (in_specification) { + // Eat up characters until reaching a known specifier. + if (*++position == '\0') { + // The format string ended in the middle of a specification. Call + // it portable because no unportable specifications were found. The + // string is equally broken on all platforms. + return true; + } + + if (*position == 'l') { + // 'l' is the only thing that can save the 's' and 'c' specifiers. + modifier_l = true; + } else if (((*position == 's' || *position == 'c') && !modifier_l) || + *position == 'S' || *position == 'C' || *position == 'F' || + *position == 'D' || *position == 'O' || *position == 'U') { + // Not portable. + return false; + } + + if (wcschr(L"diouxXeEfgGaAcspn%", *position)) { + // Portable, keep scanning the rest of the format string. + in_specification = false; + } + } + } + } + + return true; +} + +const std::string& EmptyString() { + return EmptyStrings::GetInstance()->s; +} + +const string16& EmptyString16() { + return EmptyStrings::GetInstance()->s16; +} + +template<typename STR> +bool ReplaceCharsT(const STR& input, + const STR& replace_chars, + const STR& replace_with, + STR* output) { + bool removed = false; + size_t replace_length = replace_with.length(); + + *output = input; + + size_t found = output->find_first_of(replace_chars); + while (found != STR::npos) { + removed = true; + output->replace(found, 1, replace_with); + found = output->find_first_of(replace_chars, found + replace_length); + } + + return removed; +} + +bool ReplaceChars(const string16& input, + const base::StringPiece16& replace_chars, + const string16& replace_with, + string16* output) { + return ReplaceCharsT(input, replace_chars.as_string(), replace_with, output); +} + +bool ReplaceChars(const std::string& input, + const base::StringPiece& replace_chars, + const std::string& replace_with, + std::string* output) { + return ReplaceCharsT(input, replace_chars.as_string(), replace_with, output); +} + +bool RemoveChars(const string16& input, + const base::StringPiece16& remove_chars, + string16* output) { + return ReplaceChars(input, remove_chars.as_string(), string16(), output); +} + +bool RemoveChars(const std::string& input, + const base::StringPiece& remove_chars, + std::string* output) { + return ReplaceChars(input, remove_chars.as_string(), std::string(), output); +} + +template<typename STR> +TrimPositions TrimStringT(const STR& input, + const STR& trim_chars, + TrimPositions positions, + STR* output) { + // Find the edges of leading/trailing whitespace as desired. + const size_t last_char = input.length() - 1; + const size_t first_good_char = (positions & TRIM_LEADING) ? + input.find_first_not_of(trim_chars) : 0; + const size_t last_good_char = (positions & TRIM_TRAILING) ? + input.find_last_not_of(trim_chars) : last_char; + + // When the string was all whitespace, report that we stripped off whitespace + // from whichever position the caller was interested in. For empty input, we + // stripped no whitespace, but we still need to clear |output|. + if (input.empty() || + (first_good_char == STR::npos) || (last_good_char == STR::npos)) { + bool input_was_empty = input.empty(); // in case output == &input + output->clear(); + return input_was_empty ? TRIM_NONE : positions; + } + + // Trim the whitespace. + *output = + input.substr(first_good_char, last_good_char - first_good_char + 1); + + // Return where we trimmed from. + return static_cast<TrimPositions>( + ((first_good_char == 0) ? TRIM_NONE : TRIM_LEADING) | + ((last_good_char == last_char) ? TRIM_NONE : TRIM_TRAILING)); +} + +bool TrimString(const string16& input, + const base::StringPiece16& trim_chars, + string16* output) { + return TrimStringT(input, trim_chars.as_string(), TRIM_ALL, output) != + TRIM_NONE; +} + +bool TrimString(const std::string& input, + const base::StringPiece& trim_chars, + std::string* output) { + return TrimStringT(input, trim_chars.as_string(), TRIM_ALL, output) != + TRIM_NONE; +} + +void TruncateUTF8ToByteSize(const std::string& input, + const size_t byte_size, + std::string* output) { + DCHECK(output); + if (byte_size > input.length()) { + *output = input; + return; + } + DCHECK_LE(byte_size, static_cast<uint32>(kint32max)); + // Note: This cast is necessary because CBU8_NEXT uses int32s. + int32 truncation_length = static_cast<int32>(byte_size); + int32 char_index = truncation_length - 1; + const char* data = input.data(); + + // Using CBU8, we will move backwards from the truncation point + // to the beginning of the string looking for a valid UTF8 + // character. Once a full UTF8 character is found, we will + // truncate the string to the end of that character. + while (char_index >= 0) { + int32 prev = char_index; + base_icu::UChar32 code_point = 0; + CBU8_NEXT(data, char_index, truncation_length, code_point); + if (!IsValidCharacter(code_point) || + !IsValidCodepoint(code_point)) { + char_index = prev - 1; + } else { + break; + } + } + + if (char_index >= 0 ) + *output = input.substr(0, char_index); + else + output->clear(); +} + +TrimPositions TrimWhitespace(const string16& input, + TrimPositions positions, + string16* output) { + return TrimStringT(input, base::string16(kWhitespaceUTF16), positions, + output); +} + +TrimPositions TrimWhitespaceASCII(const std::string& input, + TrimPositions positions, + std::string* output) { + return TrimStringT(input, std::string(kWhitespaceASCII), positions, output); +} + +// This function is only for backward-compatibility. +// To be removed when all callers are updated. +TrimPositions TrimWhitespace(const std::string& input, + TrimPositions positions, + std::string* output) { + return TrimWhitespaceASCII(input, positions, output); +} + +template<typename STR> +STR CollapseWhitespaceT(const STR& text, + bool trim_sequences_with_line_breaks) { + STR result; + result.resize(text.size()); + + // Set flags to pretend we're already in a trimmed whitespace sequence, so we + // will trim any leading whitespace. + bool in_whitespace = true; + bool already_trimmed = true; + + int chars_written = 0; + for (typename STR::const_iterator i(text.begin()); i != text.end(); ++i) { + if (IsWhitespace(*i)) { + if (!in_whitespace) { + // Reduce all whitespace sequences to a single space. + in_whitespace = true; + result[chars_written++] = L' '; + } + if (trim_sequences_with_line_breaks && !already_trimmed && + ((*i == '\n') || (*i == '\r'))) { + // Whitespace sequences containing CR or LF are eliminated entirely. + already_trimmed = true; + --chars_written; + } + } else { + // Non-whitespace chracters are copied straight across. + in_whitespace = false; + already_trimmed = false; + result[chars_written++] = *i; + } + } + + if (in_whitespace && !already_trimmed) { + // Any trailing whitespace is eliminated. + --chars_written; + } + + result.resize(chars_written); + return result; +} + +string16 CollapseWhitespace(const string16& text, + bool trim_sequences_with_line_breaks) { + return CollapseWhitespaceT(text, trim_sequences_with_line_breaks); +} + +std::string CollapseWhitespaceASCII(const std::string& text, + bool trim_sequences_with_line_breaks) { + return CollapseWhitespaceT(text, trim_sequences_with_line_breaks); +} + +bool ContainsOnlyChars(const StringPiece& input, + const StringPiece& characters) { + 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; + } + return true; +} + +bool IsStringASCII(const StringPiece& str) { + return DoIsStringASCII(str); +} + +bool IsStringASCII(const string16& str) { + return DoIsStringASCII(str); +} + +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); + if (!IsValidCharacter(code_point)) + return false; + } + return true; +} + +} // namespace base + +template<typename Iter> +static inline bool DoLowerCaseEqualsASCII(Iter a_begin, + Iter a_end, + const char* b) { + for (Iter it = a_begin; it != a_end; ++it, ++b) { + if (!*b || base::ToLowerASCII(*it) != *b) + return false; + } + return *b == 0; +} + +// Front-ends for LowerCaseEqualsASCII. +bool LowerCaseEqualsASCII(const std::string& a, const char* b) { + return DoLowerCaseEqualsASCII(a.begin(), a.end(), b); +} + +bool LowerCaseEqualsASCII(const string16& a, const char* b) { + return DoLowerCaseEqualsASCII(a.begin(), a.end(), b); +} + +bool LowerCaseEqualsASCII(std::string::const_iterator a_begin, + std::string::const_iterator a_end, + const char* b) { + return DoLowerCaseEqualsASCII(a_begin, a_end, b); +} + +bool LowerCaseEqualsASCII(string16::const_iterator a_begin, + string16::const_iterator a_end, + const char* b) { + return DoLowerCaseEqualsASCII(a_begin, a_end, b); +} + +// TODO(port): Resolve wchar_t/iterator issues that require OS_ANDROID here. +#if !defined(OS_ANDROID) +bool LowerCaseEqualsASCII(const char* a_begin, + const char* a_end, + const char* b) { + return DoLowerCaseEqualsASCII(a_begin, a_end, b); +} + +bool LowerCaseEqualsASCII(const char16* a_begin, + const char16* a_end, + const char* b) { + return DoLowerCaseEqualsASCII(a_begin, a_end, b); +} + +#endif // !defined(OS_ANDROID) + +bool EqualsASCII(const string16& a, const base::StringPiece& b) { + if (a.length() != b.length()) + return false; + return std::equal(b.begin(), b.end(), a.begin()); +} + +bool StartsWithASCII(const std::string& str, + const std::string& search, + bool case_sensitive) { + if (case_sensitive) + return str.compare(0, search.length(), search) == 0; + else + return base::strncasecmp(str.c_str(), search.c_str(), search.length()) == 0; +} + +template <typename STR> +bool StartsWithT(const STR& str, const STR& search, bool case_sensitive) { + if (case_sensitive) { + return str.compare(0, search.length(), search) == 0; + } else { + if (search.size() > str.size()) + return false; + return std::equal(search.begin(), search.end(), str.begin(), + base::CaseInsensitiveCompare<typename STR::value_type>()); + } +} + +bool StartsWith(const string16& str, const string16& search, + bool case_sensitive) { + return StartsWithT(str, search, case_sensitive); +} + +template <typename STR> +bool EndsWithT(const STR& str, const STR& search, bool case_sensitive) { + size_t str_length = str.length(); + size_t search_length = search.length(); + if (search_length > str_length) + return false; + if (case_sensitive) + return str.compare(str_length - search_length, search_length, search) == 0; + return std::equal(search.begin(), search.end(), + str.begin() + (str_length - search_length), + base::CaseInsensitiveCompare<typename STR::value_type>()); +} + +bool EndsWith(const std::string& str, const std::string& search, + bool case_sensitive) { + return EndsWithT(str, search, case_sensitive); +} + +bool EndsWith(const string16& str, const string16& search, + bool case_sensitive) { + return EndsWithT(str, search, case_sensitive); +} + +static const char* const kByteStringsUnlocalized[] = { + " B", + " kB", + " MB", + " GB", + " TB", + " PB" +}; + +string16 FormatBytesUnlocalized(int64 bytes) { + double unit_amount = static_cast<double>(bytes); + size_t dimension = 0; + const int kKilo = 1024; + while (unit_amount >= kKilo && + dimension < arraysize(kByteStringsUnlocalized) - 1) { + unit_amount /= kKilo; + dimension++; + } + + char buf[64]; + if (bytes != 0 && dimension > 0 && unit_amount < 100) { + base::snprintf(buf, arraysize(buf), "%.1lf%s", unit_amount, + kByteStringsUnlocalized[dimension]); + } else { + base::snprintf(buf, arraysize(buf), "%.0lf%s", unit_amount, + kByteStringsUnlocalized[dimension]); + } + + return base::ASCIIToUTF16(buf); +} + +template<class StringType> +void DoReplaceSubstringsAfterOffset(StringType* str, + size_t start_offset, + const StringType& find_this, + const StringType& replace_with, + bool replace_all) { + if ((start_offset == StringType::npos) || (start_offset >= str->length())) + return; + + DCHECK(!find_this.empty()); + for (size_t offs(str->find(find_this, start_offset)); + offs != StringType::npos; offs = str->find(find_this, offs)) { + str->replace(offs, find_this.length(), replace_with); + offs += replace_with.length(); + + if (!replace_all) + break; + } +} + +void ReplaceFirstSubstringAfterOffset(string16* str, + size_t start_offset, + const string16& find_this, + const string16& replace_with) { + DoReplaceSubstringsAfterOffset(str, start_offset, find_this, replace_with, + false); // replace first instance +} + +void ReplaceFirstSubstringAfterOffset(std::string* str, + size_t start_offset, + const std::string& find_this, + const std::string& replace_with) { + DoReplaceSubstringsAfterOffset(str, start_offset, find_this, replace_with, + false); // replace first instance +} + +void ReplaceSubstringsAfterOffset(string16* str, + size_t start_offset, + const string16& find_this, + const string16& replace_with) { + DoReplaceSubstringsAfterOffset(str, start_offset, find_this, replace_with, + true); // replace all instances +} + +void ReplaceSubstringsAfterOffset(std::string* str, + size_t start_offset, + const std::string& find_this, + const std::string& replace_with) { + DoReplaceSubstringsAfterOffset(str, start_offset, find_this, replace_with, + true); // replace all instances +} + + +template<typename STR> +static size_t TokenizeT(const STR& str, + const STR& delimiters, + std::vector<STR>* tokens) { + tokens->clear(); + + size_t start = str.find_first_not_of(delimiters); + while (start != STR::npos) { + size_t end = str.find_first_of(delimiters, start + 1); + if (end == STR::npos) { + tokens->push_back(str.substr(start)); + break; + } else { + tokens->push_back(str.substr(start, end - start)); + start = str.find_first_not_of(delimiters, end + 1); + } + } + + return tokens->size(); +} + +size_t Tokenize(const string16& str, + const string16& delimiters, + std::vector<string16>* tokens) { + return TokenizeT(str, delimiters, tokens); +} + +size_t Tokenize(const std::string& str, + const std::string& delimiters, + std::vector<std::string>* tokens) { + return TokenizeT(str, delimiters, tokens); +} + +size_t Tokenize(const base::StringPiece& str, + const base::StringPiece& delimiters, + std::vector<base::StringPiece>* tokens) { + return TokenizeT(str, delimiters, tokens); +} + +template<typename STR> +static STR JoinStringT(const std::vector<STR>& parts, const STR& sep) { + if (parts.empty()) + return STR(); + + STR result(parts[0]); + typename std::vector<STR>::const_iterator iter = parts.begin(); + ++iter; + + for (; iter != parts.end(); ++iter) { + result += sep; + result += *iter; + } + + return result; +} + +std::string JoinString(const std::vector<std::string>& parts, char sep) { + return JoinStringT(parts, std::string(1, sep)); +} + +string16 JoinString(const std::vector<string16>& parts, char16 sep) { + return JoinStringT(parts, string16(1, sep)); +} + +std::string JoinString(const std::vector<std::string>& parts, + const std::string& separator) { + return JoinStringT(parts, separator); +} + +string16 JoinString(const std::vector<string16>& parts, + const string16& separator) { + return JoinStringT(parts, separator); +} + +template<class FormatStringType, class OutStringType> +OutStringType DoReplaceStringPlaceholders(const FormatStringType& format_string, + const std::vector<OutStringType>& subst, std::vector<size_t>* offsets) { + size_t substitutions = subst.size(); + + size_t sub_length = 0; + for (typename std::vector<OutStringType>::const_iterator iter = subst.begin(); + iter != subst.end(); ++iter) { + sub_length += iter->length(); + } + + OutStringType formatted; + formatted.reserve(format_string.length() + sub_length); + + std::vector<ReplacementOffset> r_offsets; + for (typename FormatStringType::const_iterator i = format_string.begin(); + i != format_string.end(); ++i) { + if ('$' == *i) { + if (i + 1 != format_string.end()) { + ++i; + DCHECK('$' == *i || '1' <= *i) << "Invalid placeholder: " << *i; + if ('$' == *i) { + while (i != format_string.end() && '$' == *i) { + formatted.push_back('$'); + ++i; + } + --i; + } else { + uintptr_t index = 0; + while (i != format_string.end() && '0' <= *i && *i <= '9') { + index *= 10; + index += *i - '0'; + ++i; + } + --i; + index -= 1; + if (offsets) { + ReplacementOffset r_offset(index, + static_cast<int>(formatted.size())); + r_offsets.insert(std::lower_bound(r_offsets.begin(), + r_offsets.end(), + r_offset, + &CompareParameter), + r_offset); + } + if (index < substitutions) + formatted.append(subst.at(index)); + } + } + } else { + formatted.push_back(*i); + } + } + if (offsets) { + for (std::vector<ReplacementOffset>::const_iterator i = r_offsets.begin(); + i != r_offsets.end(); ++i) { + offsets->push_back(i->offset); + } + } + return formatted; +} + +string16 ReplaceStringPlaceholders(const string16& format_string, + const std::vector<string16>& subst, + std::vector<size_t>* offsets) { + return DoReplaceStringPlaceholders(format_string, subst, offsets); +} + +std::string ReplaceStringPlaceholders(const base::StringPiece& format_string, + const std::vector<std::string>& subst, + std::vector<size_t>* offsets) { + return DoReplaceStringPlaceholders(format_string, subst, offsets); +} + +string16 ReplaceStringPlaceholders(const string16& format_string, + const string16& a, + size_t* offset) { + std::vector<size_t> offsets; + std::vector<string16> subst; + subst.push_back(a); + string16 result = ReplaceStringPlaceholders(format_string, subst, &offsets); + + DCHECK_EQ(1U, offsets.size()); + if (offset) + *offset = offsets[0]; + return result; +} + +static bool IsWildcard(base_icu::UChar32 character) { + return character == '*' || character == '?'; +} + +// Move the strings pointers to the point where they start to differ. +template <typename CHAR, typename NEXT> +static void EatSameChars(const CHAR** pattern, const CHAR* pattern_end, + const CHAR** string, const CHAR* string_end, + NEXT next) { + const CHAR* escape = NULL; + while (*pattern != pattern_end && *string != string_end) { + if (!escape && IsWildcard(**pattern)) { + // We don't want to match wildcard here, except if it's escaped. + return; + } + + // Check if the escapement char is found. If so, skip it and move to the + // next character. + if (!escape && **pattern == '\\') { + escape = *pattern; + next(pattern, pattern_end); + continue; + } + + // Check if the chars match, if so, increment the ptrs. + const CHAR* pattern_next = *pattern; + const CHAR* string_next = *string; + base_icu::UChar32 pattern_char = next(&pattern_next, pattern_end); + if (pattern_char == next(&string_next, string_end) && + pattern_char != CBU_SENTINEL) { + *pattern = pattern_next; + *string = string_next; + } else { + // Uh oh, it did not match, we are done. If the last char was an + // escapement, that means that it was an error to advance the ptr here, + // let's put it back where it was. This also mean that the MatchPattern + // function will return false because if we can't match an escape char + // here, then no one will. + if (escape) { + *pattern = escape; + } + return; + } + + escape = NULL; + } +} + +template <typename CHAR, typename NEXT> +static void EatWildcard(const CHAR** pattern, const CHAR* end, NEXT next) { + while (*pattern != end) { + if (!IsWildcard(**pattern)) + return; + next(pattern, end); + } +} + +template <typename CHAR, typename NEXT> +static bool MatchPatternT(const CHAR* eval, const CHAR* eval_end, + const CHAR* pattern, const CHAR* pattern_end, + int depth, + NEXT next) { + const int kMaxDepth = 16; + if (depth > kMaxDepth) + return false; + + // Eat all the matching chars. + EatSameChars(&pattern, pattern_end, &eval, eval_end, next); + + // If the string is empty, then the pattern must be empty too, or contains + // only wildcards. + if (eval == eval_end) { + EatWildcard(&pattern, pattern_end, next); + return pattern == pattern_end; + } + + // Pattern is empty but not string, this is not a match. + if (pattern == pattern_end) + return false; + + // If this is a question mark, then we need to compare the rest with + // the current string or the string with one character eaten. + const CHAR* next_pattern = pattern; + next(&next_pattern, pattern_end); + if (pattern[0] == '?') { + if (MatchPatternT(eval, eval_end, next_pattern, pattern_end, + depth + 1, next)) + return true; + const CHAR* next_eval = eval; + next(&next_eval, eval_end); + if (MatchPatternT(next_eval, eval_end, next_pattern, pattern_end, + depth + 1, next)) + return true; + } + + // This is a *, try to match all the possible substrings with the remainder + // of the pattern. + if (pattern[0] == '*') { + // Collapse duplicate wild cards (********** into *) so that the + // method does not recurse unnecessarily. http://crbug.com/52839 + EatWildcard(&next_pattern, pattern_end, next); + + while (eval != eval_end) { + if (MatchPatternT(eval, eval_end, next_pattern, pattern_end, + depth + 1, next)) + return true; + eval++; + } + + // We reached the end of the string, let see if the pattern contains only + // wildcards. + if (eval == eval_end) { + EatWildcard(&pattern, pattern_end, next); + if (pattern != pattern_end) + return false; + return true; + } + } + + return false; +} + +struct NextCharUTF8 { + base_icu::UChar32 operator()(const char** p, const char* end) { + base_icu::UChar32 c; + int offset = 0; + CBU8_NEXT(*p, offset, end - *p, c); + *p += offset; + return c; + } +}; + +struct NextCharUTF16 { + base_icu::UChar32 operator()(const char16** p, const char16* end) { + base_icu::UChar32 c; + int offset = 0; + CBU16_NEXT(*p, offset, end - *p, c); + *p += offset; + return c; + } +}; + +bool MatchPattern(const base::StringPiece& eval, + const base::StringPiece& pattern) { + return MatchPatternT(eval.data(), eval.data() + eval.size(), + pattern.data(), pattern.data() + pattern.size(), + 0, NextCharUTF8()); +} + +bool MatchPattern(const string16& eval, const string16& pattern) { + return MatchPatternT(eval.c_str(), eval.c_str() + eval.size(), + pattern.c_str(), pattern.c_str() + pattern.size(), + 0, NextCharUTF16()); +} + +// The following code is compatible with the OpenBSD lcpy interface. See: +// http://www.gratisoft.us/todd/papers/strlcpy.html +// ftp://ftp.openbsd.org/pub/OpenBSD/src/lib/libc/string/{wcs,str}lcpy.c + +namespace { + +template <typename CHAR> +size_t lcpyT(CHAR* dst, const CHAR* src, size_t dst_size) { + for (size_t i = 0; i < dst_size; ++i) { + if ((dst[i] = src[i]) == 0) // We hit and copied the terminating NULL. + return i; + } + + // We were left off at dst_size. We over copied 1 byte. Null terminate. + if (dst_size != 0) + dst[dst_size - 1] = 0; + + // Count the rest of the |src|, and return it's length in characters. + while (src[dst_size]) ++dst_size; + return dst_size; +} + +} // namespace + +size_t base::strlcpy(char* dst, const char* src, size_t dst_size) { + return lcpyT<char>(dst, src, dst_size); +} +size_t base::wcslcpy(wchar_t* dst, const wchar_t* src, size_t dst_size) { + return lcpyT<wchar_t>(dst, src, dst_size); +}
--- a/security/sandbox/chromium/base/strings/string_util.h +++ b/security/sandbox/chromium/base/strings/string_util.h @@ -14,18 +14,16 @@ #include <vector> #include "base/base_export.h" #include "base/basictypes.h" #include "base/compiler_specific.h" #include "base/strings/string16.h" #include "base/strings/string_piece.h" // For implicit conversions. -// Safe standard library wrappers for all platforms. - namespace base { // C standard-library functions like "strncasecmp" and "snprintf" that aren't // cross-platform are provided as "base::strncasecmp", and their prototypes // are listed below. These functions are then implemented as inline calls // to the platform-specific equivalents in the platform-specific headers. // Compares the two strings s1 and s2 without regard to case using @@ -42,50 +40,30 @@ int strncasecmp(const char* s1, const ch int strncmp16(const char16* s1, const char16* s2, size_t count); // Wrapper for vsnprintf that always null-terminates and always returns the // number of characters that would be in an untruncated formatted // string, even when truncation occurs. int vsnprintf(char* buffer, size_t size, const char* format, va_list arguments) PRINTF_FORMAT(3, 0); -// vswprintf always null-terminates, but when truncation occurs, it will either -// return -1 or the number of characters that would be in an untruncated -// formatted string. The actual return value depends on the underlying -// C library's vswprint