Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(76)

Side by Side Diff: third_party/WebKit/Source/wtf/ArrayBufferContents.cpp

Issue 1414553002: Fix out-of-memory crashes related to ArrayBuffer allocation Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: rebase+more tweaks Created 5 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 /* 1 /*
2 * Copyright (C) 2009 Apple Inc. All rights reserved. 2 * Copyright (C) 2009 Apple Inc. All rights reserved.
3 * Copyright (C) 2013 Google Inc. All rights reserved. 3 * Copyright (C) 2013 Google Inc. All rights reserved.
4 * 4 *
5 * Redistribution and use in source and binary forms, with or without 5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions 6 * modification, are permitted provided that the following conditions
7 * are met: 7 * are met:
8 * 1. Redistributions of source code must retain the above copyright 8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer. 9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright 10 * 2. Redistributions in binary form must reproduce the above copyright
(...skipping 16 matching lines...) Expand all
27 #include "config.h" 27 #include "config.h"
28 #include "wtf/ArrayBufferContents.h" 28 #include "wtf/ArrayBufferContents.h"
29 29
30 #include "wtf/Assertions.h" 30 #include "wtf/Assertions.h"
31 #include "wtf/PartitionAlloc.h" 31 #include "wtf/PartitionAlloc.h"
32 #include "wtf/Partitions.h" 32 #include "wtf/Partitions.h"
33 #include <string.h> 33 #include <string.h>
34 34
35 namespace WTF { 35 namespace WTF {
36 36
37 bool ArrayBufferContents::s_fakeAllocationFailureForTestingOneTime = false;
37 AdjustAmountOfExternalAllocatedMemoryFunction ArrayBufferContents::s_adjustAmoun tOfExternalAllocatedMemoryFunction; 38 AdjustAmountOfExternalAllocatedMemoryFunction ArrayBufferContents::s_adjustAmoun tOfExternalAllocatedMemoryFunction;
38 39
39 ArrayBufferContents::ArrayBufferContents() 40 ArrayBufferContents::ArrayBufferContents()
40 : m_holder(adoptRef(new DataHolder())) { } 41 : m_holder(adoptRef(new DataHolder())) { }
41 42
42 ArrayBufferContents::ArrayBufferContents(unsigned numElements, unsigned elementB yteSize, SharingType isShared, ArrayBufferContents::InitializationPolicy policy) 43 ArrayBufferContents::ArrayBufferContents(unsigned numElements, unsigned elementB yteSize, SharingType isShared, InitializationPolicy initPolicy, OutOfMemoryPolic y oomPolicy)
43 : m_holder(adoptRef(new DataHolder())) 44 : m_holder(adoptRef(new DataHolder()))
44 { 45 {
45 // Do not allow 32-bit overflow of the total size. 46 // Do not allow 32-bit overflow of the total size.
46 unsigned totalSize = numElements * elementByteSize; 47 unsigned totalSize = numElements * elementByteSize;
47 if (numElements) { 48 if (numElements) {
48 if (totalSize / numElements != elementByteSize) { 49 if (totalSize / numElements != elementByteSize) {
49 return; 50 return;
50 } 51 }
51 } 52 }
52 53 m_holder->allocateNew(totalSize, isShared, initPolicy, oomPolicy);
53 m_holder->allocateNew(totalSize, isShared, policy);
54 } 54 }
55 55
56 ArrayBufferContents::ArrayBufferContents( 56 ArrayBufferContents::ArrayBufferContents(
57 void* data, unsigned sizeInBytes, SharingType isShared) 57 void* data, unsigned sizeInBytes, SharingType isShared, OutOfMemoryPolicy oo mPolicy)
58 : m_holder(adoptRef(new DataHolder())) 58 : m_holder(adoptRef(new DataHolder()))
59 { 59 {
60 if (data) { 60 if (data) {
61 m_holder->adopt(data, sizeInBytes, isShared); 61 m_holder->adopt(data, sizeInBytes, isShared);
62 } else { 62 } else {
63 ASSERT(!sizeInBytes); 63 ASSERT(!sizeInBytes);
64 sizeInBytes = 0; 64 sizeInBytes = 0;
65 // Allow null data if size is 0 bytes, make sure data is valid pointer. 65 // Allow null data if size is 0 bytes, make sure data is valid pointer.
66 // (PartitionAlloc guarantees valid pointer for size 0) 66 // (PartitionAlloc guarantees valid pointer for size 0)
67 m_holder->allocateNew(sizeInBytes, isShared, ZeroInitialize); 67 m_holder->allocateNew(sizeInBytes, isShared, ZeroInitialize, oomPolicy);
68 } 68 }
69 } 69 }
70 70
71 ArrayBufferContents::~ArrayBufferContents() 71 ArrayBufferContents::~ArrayBufferContents()
72 { 72 {
73 } 73 }
74 74
75 void ArrayBufferContents::neuter() 75 void ArrayBufferContents::neuter()
76 { 76 {
77 m_holder.clear(); 77 m_holder.clear();
78 } 78 }
79 79
80 void ArrayBufferContents::transfer(ArrayBufferContents& other) 80 void ArrayBufferContents::transfer(ArrayBufferContents& other)
81 { 81 {
82 ASSERT(!isShared()); 82 ASSERT(!isShared());
83 ASSERT(!other.m_holder->data()); 83 ASSERT(!other.m_holder->data());
84 other.m_holder = m_holder; 84 other.m_holder = m_holder;
85 neuter(); 85 neuter();
86 } 86 }
87 87
88 void ArrayBufferContents::shareWith(ArrayBufferContents& other) 88 void ArrayBufferContents::shareWith(ArrayBufferContents& other)
89 { 89 {
90 ASSERT(isShared()); 90 ASSERT(isShared());
91 ASSERT(!other.m_holder->data()); 91 ASSERT(!other.m_holder->data());
92 other.m_holder = m_holder; 92 other.m_holder = m_holder;
93 } 93 }
94 94
95 void ArrayBufferContents::copyTo(ArrayBufferContents& other) 95 void ArrayBufferContents::copyTo(ArrayBufferContents& other, OutOfMemoryPolicy o omPolicy)
96 { 96 {
97 ASSERT(!m_holder->isShared() && !other.m_holder->isShared()); 97 ASSERT(!m_holder->isShared() && !other.m_holder->isShared());
98 m_holder->copyMemoryTo(*other.m_holder); 98 m_holder->copyMemoryTo(*other.m_holder, oomPolicy);
99 } 99 }
100 100
101 void ArrayBufferContents::allocateMemory(size_t size, InitializationPolicy polic y, void*& data) 101 void ArrayBufferContents::deprecatedAllocateMemoryOrCrash(size_t size, Initializ ationPolicy policy, void*& data)
102 { 102 {
103 if (s_adjustAmountOfExternalAllocatedMemoryFunction) 103 if (s_adjustAmountOfExternalAllocatedMemoryFunction)
104 s_adjustAmountOfExternalAllocatedMemoryFunction(static_cast<int>(size)); 104 s_adjustAmountOfExternalAllocatedMemoryFunction(static_cast<int>(size));
105 if (s_fakeAllocationFailureForTestingOneTime)
106 IMMEDIATE_CRASH();
105 data = partitionAllocGeneric(WTF::Partitions::bufferPartition(), size); 107 data = partitionAllocGeneric(WTF::Partitions::bufferPartition(), size);
106 if (policy == ZeroInitialize && data) 108 ASSERT(data); // Supposed to have crashed on alloc failure
109 if (policy == ZeroInitialize)
107 memset(data, '\0', size); 110 memset(data, '\0', size);
108 } 111 }
109 112
113 void ArrayBufferContents::allocateMemoryOrNull(size_t size, InitializationPolicy policy, void*& data)
114 {
115 if (s_fakeAllocationFailureForTestingOneTime) {
116 data = nullptr;
117 s_fakeAllocationFailureForTestingOneTime = false;
118 } else {
119 data = partitionAllocGenericFlags(WTF::Partitions::bufferPartition(), WT F::PartitionAllocReturnNull, size);
120 }
121
122 if (data) {
123 if (s_adjustAmountOfExternalAllocatedMemoryFunction)
124 s_adjustAmountOfExternalAllocatedMemoryFunction(static_cast<int>(siz e));
125 if (policy == ZeroInitialize)
126 memset(data, '\0', size);
127 }
128 }
129
110 void ArrayBufferContents::freeMemory(void* data, size_t size) 130 void ArrayBufferContents::freeMemory(void* data, size_t size)
111 { 131 {
112 Partitions::bufferFree(data); 132 Partitions::bufferFree(data);
113 if (s_adjustAmountOfExternalAllocatedMemoryFunction) 133 if (s_adjustAmountOfExternalAllocatedMemoryFunction)
114 s_adjustAmountOfExternalAllocatedMemoryFunction(-static_cast<int>(size)) ; 134 s_adjustAmountOfExternalAllocatedMemoryFunction(-static_cast<int>(size)) ;
115 } 135 }
116 136
117 ArrayBufferContents::DataHolder::DataHolder() 137 ArrayBufferContents::DataHolder::DataHolder()
118 : m_data(nullptr) 138 : m_data(nullptr)
119 , m_sizeInBytes(0) 139 , m_sizeInBytes(0)
120 , m_isShared(NotShared) { } 140 , m_isShared(NotShared) { }
121 141
122 ArrayBufferContents::DataHolder::~DataHolder() 142 ArrayBufferContents::DataHolder::~DataHolder()
123 { 143 {
124 ArrayBufferContents::freeMemory(m_data, m_sizeInBytes); 144 ArrayBufferContents::freeMemory(m_data, m_sizeInBytes);
125 145
126 m_data = nullptr; 146 m_data = nullptr;
127 m_sizeInBytes = 0; 147 m_sizeInBytes = 0;
128 m_isShared = NotShared; 148 m_isShared = NotShared;
129 } 149 }
130 150
131 void ArrayBufferContents::DataHolder::allocateNew(unsigned sizeInBytes, SharingT ype isShared, InitializationPolicy policy) 151 void ArrayBufferContents::DataHolder::allocateNew(unsigned sizeInBytes, SharingT ype isShared, InitializationPolicy initPolicy, OutOfMemoryPolicy oomPolicy)
132 { 152 {
133 ASSERT(!m_data); 153 ASSERT(!m_data);
134 void* data = nullptr; 154 void* data = nullptr;
135 allocateMemory(sizeInBytes, policy, data); 155 if (oomPolicy == CrashIfOutOfMemory_DEPRECATED) {
156 deprecatedAllocateMemoryOrCrash(sizeInBytes, initPolicy, data);
157 } else {
158 ASSERT(oomPolicy == NullDataIfOutOfMemory);
159 allocateMemoryOrNull(sizeInBytes, initPolicy, data);
160 }
136 m_data = data; 161 m_data = data;
137 m_sizeInBytes = data ? sizeInBytes : 0; 162 m_sizeInBytes = data ? sizeInBytes : 0;
138 m_isShared = isShared; 163 m_isShared = isShared;
139 } 164 }
140 165
141 void ArrayBufferContents::DataHolder::adopt(void* data, unsigned sizeInBytes, Sh aringType isShared) 166 void ArrayBufferContents::DataHolder::adopt(void* data, unsigned sizeInBytes, Sh aringType isShared)
142 { 167 {
143 ASSERT(!m_data); 168 ASSERT(!m_data);
144 m_data = data; 169 m_data = data;
145 m_sizeInBytes = sizeInBytes; 170 m_sizeInBytes = sizeInBytes;
146 m_isShared = isShared; 171 m_isShared = isShared;
147 } 172 }
148 173
149 void ArrayBufferContents::DataHolder::copyMemoryTo(DataHolder& other) 174 void ArrayBufferContents::DataHolder::copyMemoryTo(DataHolder& other, OutOfMemor yPolicy oomPolicy)
150 { 175 {
151 ASSERT(!other.m_sizeInBytes); 176 ASSERT(!other.m_sizeInBytes);
152 ArrayBufferContents::freeMemory(other.m_data, other.m_sizeInBytes); 177 ArrayBufferContents::freeMemory(other.m_data, other.m_sizeInBytes);
153 ArrayBufferContents::allocateMemory(m_sizeInBytes, DontInitialize, other.m_d ata); 178 if (oomPolicy == CrashIfOutOfMemory_DEPRECATED)
154 if (!other.m_data) 179 ArrayBufferContents::deprecatedAllocateMemoryOrCrash(m_sizeInBytes, Dont Initialize, other.m_data);
180 else
181 ArrayBufferContents::allocateMemoryOrNull(m_sizeInBytes, DontInitialize, other.m_data);
182
183 if (!other.m_data) {
184 other.m_sizeInBytes = 0;
155 return; 185 return;
186 }
156 memcpy(other.m_data, m_data, m_sizeInBytes); 187 memcpy(other.m_data, m_data, m_sizeInBytes);
157 other.m_sizeInBytes = m_sizeInBytes; 188 other.m_sizeInBytes = m_sizeInBytes;
158 } 189 }
159 190
160 } // namespace WTF 191 } // namespace WTF
OLDNEW
« no previous file with comments | « third_party/WebKit/Source/wtf/ArrayBufferContents.h ('k') | third_party/WebKit/Source/wtf/Float32Array.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698