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

Side by Side Diff: Source/WebCore/platform/audio/AudioArray.h

Issue 7741034: Merge 93749 - Resolve potential integer overflow in memory allocation, and ensure (Closed) Base URL: http://svn.webkit.org/repository/webkit/branches/chromium/835/
Patch Set: Created 9 years, 4 months 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
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * Copyright (C) 2010 Google Inc. All rights reserved. 2 * Copyright (C) 2010 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 5 * modification, are permitted provided that the following conditions
6 * are met: 6 * are met:
7 * 7 *
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 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
46 46
47 ~AudioArray() 47 ~AudioArray()
48 { 48 {
49 fastFree(m_allocation); 49 fastFree(m_allocation);
50 } 50 }
51 51
52 // It's OK to call allocate() multiple times, but data will *not* be copied from an initial allocation 52 // It's OK to call allocate() multiple times, but data will *not* be copied from an initial allocation
53 // if re-allocated. Allocations are zero-initialized. 53 // if re-allocated. Allocations are zero-initialized.
54 void allocate(size_t n) 54 void allocate(size_t n)
55 { 55 {
56 // Although n is a size_t, its true limit is max unsigned because we use unsigned in zeroRange()
57 // and copyToRange(). Also check for integer overflow.
58 if (n > std::numeric_limits<unsigned>::max() / sizeof(T))
59 CRASH();
60
61 unsigned initialSize = sizeof(T) * n;
62
56 // 16-byte alignment for 128bit SIMD. 63 // 16-byte alignment for 128bit SIMD.
57 const size_t alignment = 16; 64 const size_t alignment = 16;
58 65
59 if (m_allocation) 66 if (m_allocation)
60 fastFree(m_allocation); 67 fastFree(m_allocation);
61 68
62 bool isAllocationGood = false; 69 bool isAllocationGood = false;
63 70
64 while (!isAllocationGood) { 71 while (!isAllocationGood) {
65 // Initially we try to allocate the exact size, but if it's not alig ned 72 // Initially we try to allocate the exact size, but if it's not alig ned
66 // then we'll have to reallocate and from then on allocate extra. 73 // then we'll have to reallocate and from then on allocate extra.
67 static size_t extraAllocationBytes = 0; 74 static size_t extraAllocationBytes = 0;
68 75
69 T* allocation = static_cast<T*>(fastMalloc(sizeof(T) * n + extraAllo cationBytes)); 76 // Again, check for integer overflow.
77 if (initialSize + extraAllocationBytes < initialSize)
78 CRASH();
79
80 T* allocation = static_cast<T*>(fastMalloc(initialSize + extraAlloca tionBytes));
81 if (!allocation)
82 CRASH();
70 T* alignedData = alignedAddress(allocation, alignment); 83 T* alignedData = alignedAddress(allocation, alignment);
71 84
72 if (alignedData == allocation || extraAllocationBytes == alignment) { 85 if (alignedData == allocation || extraAllocationBytes == alignment) {
73 m_allocation = allocation; 86 m_allocation = allocation;
74 m_alignedData = alignedData; 87 m_alignedData = alignedData;
75 m_size = n; 88 m_size = n;
76 isAllocationGood = true; 89 isAllocationGood = true;
77 zero(); 90 zero();
78 } else { 91 } else {
79 extraAllocationBytes = alignment; // always allocate extra after the first alignment failure. 92 extraAllocationBytes = alignment; // always allocate extra after the first alignment failure.
80 fastFree(allocation); 93 fastFree(allocation);
81 } 94 }
82 } 95 }
83 } 96 }
84 97
85 T* data() { return m_alignedData; } 98 T* data() { return m_alignedData; }
86 const T* data() const { return m_alignedData; } 99 const T* data() const { return m_alignedData; }
87 size_t size() const { return m_size; } 100 size_t size() const { return m_size; }
88 101
89 T& at(size_t i) 102 T& at(size_t i)
90 { 103 {
104 // Note that although it is a size_t, m_size is now guaranteed to be
105 // no greater than max unsigned. This guarantee is enforced in allocate( ).
91 ASSERT(i < size()); 106 ASSERT(i < size());
92 return data()[i]; 107 return data()[i];
93 } 108 }
94 109
95 T& operator[](size_t i) { return at(i); } 110 T& operator[](size_t i) { return at(i); }
96 111
97 void zero() { memset(this->data(), 0, sizeof(T) * this->size()); } 112 void zero()
113 {
114 // This multiplication is made safe by the check in allocate().
115 memset(this->data(), 0, sizeof(T) * this->size());
116 }
98 117
99 void zeroRange(unsigned start, unsigned end) 118 void zeroRange(unsigned start, unsigned end)
100 { 119 {
101 bool isSafe = (start <= end) && (end <= this->size()); 120 bool isSafe = (start <= end) && (end <= this->size());
102 ASSERT(isSafe); 121 ASSERT(isSafe);
103 if (!isSafe) 122 if (!isSafe)
104 return; 123 return;
105 124
125 // This expression cannot overflow because end - start cannot be
126 // greater than m_size, which is safe due to the check in allocate().
106 memset(this->data() + start, 0, sizeof(T) * (end - start)); 127 memset(this->data() + start, 0, sizeof(T) * (end - start));
107 } 128 }
108 129
109 void copyToRange(T* sourceData, unsigned start, unsigned end) 130 void copyToRange(T* sourceData, unsigned start, unsigned end)
110 { 131 {
111 bool isSafe = (start <= end) && (end <= this->size()); 132 bool isSafe = (start <= end) && (end <= this->size());
112 ASSERT(isSafe); 133 ASSERT(isSafe);
113 if (!isSafe) 134 if (!isSafe)
114 return; 135 return;
115 136
137 // This expression cannot overflow because end - start cannot be
138 // greater than m_size, which is safe due to the check in allocate().
116 memcpy(this->data() + start, sourceData, sizeof(T) * (end - start)); 139 memcpy(this->data() + start, sourceData, sizeof(T) * (end - start));
117 } 140 }
118 141
119 private: 142 private:
120 static T* alignedAddress(T* address, intptr_t alignment) 143 static T* alignedAddress(T* address, intptr_t alignment)
121 { 144 {
122 intptr_t value = reinterpret_cast<intptr_t>(address); 145 intptr_t value = reinterpret_cast<intptr_t>(address);
123 return reinterpret_cast<T*>((value + alignment - 1) & ~(alignment - 1)); 146 return reinterpret_cast<T*>((value + alignment - 1) & ~(alignment - 1));
124 } 147 }
125 148
126 T* m_allocation; 149 T* m_allocation;
127 T* m_alignedData; 150 T* m_alignedData;
128 size_t m_size; 151 size_t m_size;
129 }; 152 };
130 153
131 typedef AudioArray<float> AudioFloatArray; 154 typedef AudioArray<float> AudioFloatArray;
132 typedef AudioArray<double> AudioDoubleArray; 155 typedef AudioArray<double> AudioDoubleArray;
133 156
134 } // WebCore 157 } // WebCore
135 158
136 #endif // AudioArray_h 159 #endif // AudioArray_h
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698