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

Side by Side Diff: third_party/WebKit/Source/wtf/ArrayBufferBuilder.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) 2013 Google Inc. All rights reserved. 2 * Copyright (C) 2013 Google Inc. All rights reserved.
3 * 3 *
4 * Redistribution and use in source and binary forms, with or without 4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are 5 * modification, are permitted provided that the following conditions are
6 * met: 6 * met:
7 * 7 *
8 * * Redistributions of source code must retain the above copyright 8 * * 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 * * Redistributions in binary form must reproduce the above 10 * * Redistributions in binary form must reproduce the above
(...skipping 24 matching lines...) Expand all
35 #include <limits> 35 #include <limits>
36 36
37 namespace WTF { 37 namespace WTF {
38 38
39 static const int defaultBufferCapacity = 32768; 39 static const int defaultBufferCapacity = 32768;
40 40
41 ArrayBufferBuilder::ArrayBufferBuilder() 41 ArrayBufferBuilder::ArrayBufferBuilder()
42 : m_bytesUsed(0) 42 : m_bytesUsed(0)
43 , m_variableCapacity(true) 43 , m_variableCapacity(true)
44 { 44 {
45 m_buffer = ArrayBuffer::create(defaultBufferCapacity, 1); 45 m_buffer = ArrayBuffer::createOrNull(defaultBufferCapacity, 1);
46 } 46 }
47 47
48 bool ArrayBufferBuilder::expandCapacity(unsigned sizeToIncrease) 48 bool ArrayBufferBuilder::expandCapacity(unsigned sizeToIncrease)
49 { 49 {
50 ASSERT(isValid());
50 unsigned currentBufferSize = m_buffer->byteLength(); 51 unsigned currentBufferSize = m_buffer->byteLength();
51 52
52 // If the size of the buffer exceeds max of unsigned, it can't be grown any 53 // If the size of the buffer exceeds max of unsigned, it can't be grown any
53 // more. 54 // more.
54 if (sizeToIncrease > std::numeric_limits<unsigned>::max() - m_bytesUsed) 55 if (sizeToIncrease > std::numeric_limits<unsigned>::max() - m_bytesUsed)
55 return false; 56 return false;
56 57
57 unsigned newBufferSize = m_bytesUsed + sizeToIncrease; 58 unsigned newBufferSize = m_bytesUsed + sizeToIncrease;
58 59
59 // Grow exponentially if possible. 60 // Grow exponentially if possible.
60 unsigned exponentialGrowthNewBufferSize = std::numeric_limits<unsigned>::max (); 61 unsigned exponentialGrowthNewBufferSize = std::numeric_limits<unsigned>::max ();
61 if (currentBufferSize <= std::numeric_limits<unsigned>::max() / 2) 62 if (currentBufferSize <= std::numeric_limits<unsigned>::max() / 2)
62 exponentialGrowthNewBufferSize = currentBufferSize * 2; 63 exponentialGrowthNewBufferSize = currentBufferSize * 2;
63 if (exponentialGrowthNewBufferSize > newBufferSize) 64 if (exponentialGrowthNewBufferSize > newBufferSize)
64 newBufferSize = exponentialGrowthNewBufferSize; 65 newBufferSize = exponentialGrowthNewBufferSize;
65 66
66 // Copy existing data in current buffer to new buffer. 67 // Copy existing data in current buffer to new buffer.
67 RefPtr<ArrayBuffer> newBuffer = ArrayBuffer::create(newBufferSize, 1); 68 RefPtr<ArrayBuffer> newBuffer = ArrayBuffer::createOrNull(newBufferSize, 1);
68 if (!newBuffer) 69 if (!newBuffer)
69 return false; 70 return false;
70 71
71 memcpy(newBuffer->data(), m_buffer->data(), m_bytesUsed); 72 memcpy(newBuffer->data(), m_buffer->data(), m_bytesUsed);
72 m_buffer = newBuffer; 73 m_buffer = newBuffer;
73 return true; 74 return true;
74 } 75 }
75 76
76 unsigned ArrayBufferBuilder::append(const char* data, unsigned length) 77 unsigned ArrayBufferBuilder::append(const char* data, unsigned length)
77 { 78 {
79 ASSERT(isValid());
78 ASSERT(length > 0); 80 ASSERT(length > 0);
79 81
80 unsigned currentBufferSize = m_buffer->byteLength(); 82 unsigned currentBufferSize = m_buffer->byteLength();
81 83
82 ASSERT(m_bytesUsed <= currentBufferSize); 84 ASSERT(m_bytesUsed <= currentBufferSize);
83 85
84 unsigned remainingBufferSpace = currentBufferSize - m_bytesUsed; 86 unsigned remainingBufferSpace = currentBufferSize - m_bytesUsed;
85 87
86 unsigned bytesToSave = length; 88 unsigned bytesToSave = length;
87 89
88 if (length > remainingBufferSpace) { 90 if (length > remainingBufferSpace) {
89 if (m_variableCapacity) { 91 if (m_variableCapacity) {
90 if (!expandCapacity(length)) 92 if (!expandCapacity(length))
91 return 0; 93 return 0;
92 } else { 94 } else {
93 bytesToSave = remainingBufferSpace; 95 bytesToSave = remainingBufferSpace;
94 } 96 }
95 } 97 }
96 98
97 memcpy(static_cast<char*>(m_buffer->data()) + m_bytesUsed, data, bytesToSave ); 99 memcpy(static_cast<char*>(m_buffer->data()) + m_bytesUsed, data, bytesToSave );
98 m_bytesUsed += bytesToSave; 100 m_bytesUsed += bytesToSave;
99 101
100 return bytesToSave; 102 return bytesToSave;
101 } 103 }
102 104
103 PassRefPtr<ArrayBuffer> ArrayBufferBuilder::toArrayBuffer() 105 PassRefPtr<ArrayBuffer> ArrayBufferBuilder::toArrayBuffer()
104 { 106 {
107 ASSERT(isValid());
105 // Fully used. Return m_buffer as-is. 108 // Fully used. Return m_buffer as-is.
106 if (m_buffer->byteLength() == m_bytesUsed) 109 if (m_buffer->byteLength() == m_bytesUsed)
107 return m_buffer; 110 return m_buffer;
108 111
109 return m_buffer->slice(0, m_bytesUsed); 112 RefPtr<ArrayBuffer> tmp = m_buffer->sliceOrNull(0, m_bytesUsed);
113 if (tmp)
114 return tmp;
115 return m_buffer;
110 } 116 }
111 117
112 String ArrayBufferBuilder::toString() 118 String ArrayBufferBuilder::toString()
113 { 119 {
120 ASSERT(isValid());
114 return String(static_cast<const char*>(m_buffer->data()), m_bytesUsed); 121 return String(static_cast<const char*>(m_buffer->data()), m_bytesUsed);
115 } 122 }
116 123
117 void ArrayBufferBuilder::shrinkToFit() 124 void ArrayBufferBuilder::shrinkToFit()
118 { 125 {
126 ASSERT(isValid());
119 ASSERT(m_bytesUsed <= m_buffer->byteLength()); 127 ASSERT(m_bytesUsed <= m_buffer->byteLength());
120 128
121 if (m_buffer->byteLength() > m_bytesUsed) 129 if (m_buffer->byteLength() > m_bytesUsed) {
122 m_buffer = m_buffer->slice(0, m_bytesUsed); 130 RefPtr<ArrayBuffer> tmp = m_buffer->sliceOrNull(0, m_bytesUsed);
131 if (tmp)
132 m_buffer = tmp;
133 }
123 } 134 }
124 135
125 } // namespace WTF 136 } // namespace WTF
OLDNEW
« no previous file with comments | « third_party/WebKit/Source/wtf/ArrayBufferBuilder.h ('k') | third_party/WebKit/Source/wtf/ArrayBufferContents.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698