OLD | NEW |
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 Loading... |
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 |
OLD | NEW |