Commit 4e3f9653 authored by oliver@apple.com's avatar oliver@apple.com

Add bounds checking for WTF::Vector::operator[]

https://bugs.webkit.org/show_bug.cgi?id=89600

Reviewed by Filip Pizlo.

Source/JavaScriptCore:

Make a few JSC classes opt-out of release mode bounds checking.

* assembler/AssemblerBuffer.h:
(AssemblerBuffer):
* assembler/AssemblerBufferWithConstantPool.h:
(AssemblerBufferWithConstantPool):
* bytecode/CodeBlock.cpp:
(JSC::CodeBlock::CodeBlock):
(JSC::CodeBlock::bytecodeOffset):
(JSC):
(JSC::replaceExistingEntries):
* bytecode/CodeBlock.h:
(JSC::CodeBlock::bytecodeOffsetForCallAtIndex):
(JSC::CodeBlock::callReturnIndexVector):
(JSC::CodeBlock::codeOrigins):
(RareData):
* bytecode/UnlinkedCodeBlock.h:
(JSC::UnlinkedEvalCodeBlock::adoptVariables):
(UnlinkedEvalCodeBlock):
* bytecompiler/BytecodeGenerator.cpp:
(JSC::BytecodeGenerator::BytecodeGenerator):
(JSC::BytecodeGenerator::emitNewArray):
(JSC::BytecodeGenerator::emitCall):
(JSC::BytecodeGenerator::emitConstruct):
* bytecompiler/BytecodeGenerator.h:
(CallArguments):
(JSC::BytecodeGenerator::instructions):
(BytecodeGenerator):
* bytecompiler/StaticPropertyAnalysis.h:
(JSC::StaticPropertyAnalysis::create):
(JSC::StaticPropertyAnalysis::StaticPropertyAnalysis):
(StaticPropertyAnalysis):
* bytecompiler/StaticPropertyAnalyzer.h:
(StaticPropertyAnalyzer):
(JSC::StaticPropertyAnalyzer::StaticPropertyAnalyzer):
* dfg/DFGJITCompiler.cpp:
(JSC::DFG::JITCompiler::link):
* parser/ASTBuilder.h:
(ASTBuilder):
* runtime/ArgList.h:
(MarkedArgumentBuffer):
* runtime/ArrayPrototype.cpp:
(JSC::arrayProtoFuncSort):

Source/WebCore:

Fix exports

* WebCore.exp.in:

Source/WTF:

Add a template parameter to Vector<> that controls whether
bounds checking is performed in release builds or not.
Defaults to crashing on overflow.

* wtf/Forward.h:
(WTF):
* wtf/Vector.h:
(WTF):
(Vector):
(WTF::Vector::at):
(WTF::Vector::removeLast):
(WTF::::Vector):
(WTF::=):
(WTF::::contains):
(WTF::::find):
(WTF::::reverseFind):
(WTF::::fill):
(WTF::::appendRange):
(WTF::::expandCapacity):
(WTF::::tryExpandCapacity):
(WTF::::resize):
(WTF::::shrink):
(WTF::::grow):
(WTF::::reserveCapacity):
(WTF::::tryReserveCapacity):
(WTF::::reserveInitialCapacity):
(WTF::::shrinkCapacity):
(WTF::::append):
(WTF::::tryAppend):
(WTF::::appendSlowCase):
(WTF::::uncheckedAppend):
(WTF::::appendVector):
(WTF::::insert):
(WTF::::prepend):
(WTF::::remove):
(WTF::::reverse):
(WTF::::releaseBuffer):
(WTF::::checkConsistency):
(WTF::deleteAllValues):
(WTF::swap):
(WTF::operator==):
(WTF::operator!=):

git-svn-id: http://svn.webkit.org/repository/webkit/trunk@147892 268f45cc-cd09-0410-ab3c-d52691b4dbfc
parent d4d91ae2
2013-04-07 Oliver Hunt <oliver@apple.com>
Add bounds checking for WTF::Vector::operator[]
https://bugs.webkit.org/show_bug.cgi?id=89600
Reviewed by Filip Pizlo.
Make a few JSC classes opt-out of release mode bounds checking.
* assembler/AssemblerBuffer.h:
(AssemblerBuffer):
* assembler/AssemblerBufferWithConstantPool.h:
(AssemblerBufferWithConstantPool):
* bytecode/CodeBlock.cpp:
(JSC::CodeBlock::CodeBlock):
(JSC::CodeBlock::bytecodeOffset):
(JSC):
(JSC::replaceExistingEntries):
* bytecode/CodeBlock.h:
(JSC::CodeBlock::bytecodeOffsetForCallAtIndex):
(JSC::CodeBlock::callReturnIndexVector):
(JSC::CodeBlock::codeOrigins):
(RareData):
* bytecode/UnlinkedCodeBlock.h:
(JSC::UnlinkedEvalCodeBlock::adoptVariables):
(UnlinkedEvalCodeBlock):
* bytecompiler/BytecodeGenerator.cpp:
(JSC::BytecodeGenerator::BytecodeGenerator):
(JSC::BytecodeGenerator::emitNewArray):
(JSC::BytecodeGenerator::emitCall):
(JSC::BytecodeGenerator::emitConstruct):
* bytecompiler/BytecodeGenerator.h:
(CallArguments):
(JSC::BytecodeGenerator::instructions):
(BytecodeGenerator):
* bytecompiler/StaticPropertyAnalysis.h:
(JSC::StaticPropertyAnalysis::create):
(JSC::StaticPropertyAnalysis::StaticPropertyAnalysis):
(StaticPropertyAnalysis):
* bytecompiler/StaticPropertyAnalyzer.h:
(StaticPropertyAnalyzer):
(JSC::StaticPropertyAnalyzer::StaticPropertyAnalyzer):
* dfg/DFGJITCompiler.cpp:
(JSC::DFG::JITCompiler::link):
* parser/ASTBuilder.h:
(ASTBuilder):
* runtime/ArgList.h:
(MarkedArgumentBuffer):
* runtime/ArrayPrototype.cpp:
(JSC::arrayProtoFuncSort):
2013-04-07 Benjamin Poulain <benjamin@webkit.org>
Use Vector::reserveInitialCapacity() when possible in JavaScriptCore runtime
......@@ -2035,7 +2035,7 @@ public:
offsets[ptr++] = offset;
}
Vector<LinkRecord>& jumpsToLink()
Vector<LinkRecord, 0, UnsafeVectorOverflow>& jumpsToLink()
{
std::sort(m_jumpsToLink.begin(), m_jumpsToLink.end(), linkRecordSourceComparator);
return m_jumpsToLink;
......
......@@ -168,7 +168,7 @@ namespace JSC {
}
private:
Vector<char, inlineCapacity> m_storage;
Vector<char, inlineCapacity, UnsafeVectorOverflow> m_storage;
char* m_buffer;
int m_capacity;
int m_index;
......
......@@ -80,7 +80,7 @@ void LinkBuffer::linkCode(void* ownerUID, JITCompilationEffort effort)
uint8_t* outData = reinterpret_cast<uint8_t*>(m_code);
int readPtr = 0;
int writePtr = 0;
Vector<LinkRecord>& jumpsToLink = m_assembler->jumpsToLink();
Vector<LinkRecord, 0, UnsafeVectorOverflow>& jumpsToLink = m_assembler->jumpsToLink();
unsigned jumpCount = jumpsToLink.size();
for (unsigned i = 0; i < jumpCount; ++i) {
int offset = readPtr - writePtr;
......
......@@ -59,7 +59,7 @@ public:
return value >= -255 && value <= 255;
}
Vector<LinkRecord>& jumpsToLink() { return m_assembler.jumpsToLink(); }
Vector<LinkRecord, 0, UnsafeVectorOverflow>& jumpsToLink() { return m_assembler.jumpsToLink(); }
void* unlinkedCode() { return m_assembler.unlinkedCode(); }
bool canCompact(JumpType jumpType) { return m_assembler.canCompact(jumpType); }
JumpLinkType computeJumpType(JumpType jumpType, const uint8_t* from, const uint8_t* to) { return m_assembler.computeJumpType(jumpType, from, to); }
......
......@@ -1788,7 +1788,7 @@ CodeBlock::CodeBlock(ScriptExecutable* ownerExecutable, UnlinkedCodeBlock* unlin
// Copy and translate the UnlinkedInstructions
size_t instructionCount = unlinkedCodeBlock->instructions().size();
UnlinkedInstruction* pc = unlinkedCodeBlock->instructions().data();
Vector<Instruction> instructions(instructionCount);
Vector<Instruction, 0, UnsafeVectorOverflow> instructions(instructionCount);
for (size_t i = 0; i < unlinkedCodeBlock->instructions().size(); ) {
unsigned opLength = opcodeLength(pc[i].u.opcode);
instructions[i] = globalData()->interpreter->getOpcode(pc[i].u.opcode);
......@@ -2716,7 +2716,7 @@ unsigned CodeBlock::bytecodeOffset(ExecState* exec, ReturnAddressPtr returnAddre
#if ENABLE(JIT)
if (!m_rareData)
return 1;
Vector<CallReturnOffsetToBytecodeOffset>& callIndices = m_rareData->m_callReturnIndexVector;
Vector<CallReturnOffsetToBytecodeOffset, 0, UnsafeVectorOverflow>& callIndices = m_rareData->m_callReturnIndexVector;
if (!callIndices.size())
return 1;
......@@ -2780,8 +2780,8 @@ void CodeBlock::clearEvalCache()
m_rareData->m_evalCodeCache.clear();
}
template<typename T>
inline void replaceExistingEntries(Vector<T>& target, Vector<T>& source)
template<typename T, size_t inlineCapacity, typename U, typename V>
inline void replaceExistingEntries(Vector<T, inlineCapacity, U>& target, Vector<T, inlineCapacity, V>& source)
{
ASSERT(target.size() <= source.size());
for (size_t i = 0; i < target.size(); ++i)
......
......@@ -220,7 +220,7 @@ namespace JSC {
{
if (!m_rareData)
return 1;
Vector<CallReturnOffsetToBytecodeOffset>& callIndices = m_rareData->m_callReturnIndexVector;
Vector<CallReturnOffsetToBytecodeOffset, 0, UnsafeVectorOverflow>& callIndices = m_rareData->m_callReturnIndexVector;
if (!callIndices.size())
return 1;
RELEASE_ASSERT(index < m_rareData->m_callReturnIndexVector.size());
......@@ -748,7 +748,7 @@ namespace JSC {
bool hasExpressionInfo() { return m_unlinkedCode->hasExpressionInfo(); }
#if ENABLE(JIT)
Vector<CallReturnOffsetToBytecodeOffset>& callReturnIndexVector()
Vector<CallReturnOffsetToBytecodeOffset, 0, UnsafeVectorOverflow>& callReturnIndexVector()
{
createRareDataIfNecessary();
return m_rareData->m_callReturnIndexVector;
......@@ -762,7 +762,7 @@ namespace JSC {
return m_rareData->m_inlineCallFrames;
}
Vector<CodeOriginAtCallReturnOffset>& codeOrigins()
Vector<CodeOriginAtCallReturnOffset, 0, UnsafeVectorOverflow>& codeOrigins()
{
createRareDataIfNecessary();
return m_rareData->m_codeOrigins;
......@@ -1283,11 +1283,11 @@ namespace JSC {
EvalCodeCache m_evalCodeCache;
#if ENABLE(JIT)
Vector<CallReturnOffsetToBytecodeOffset> m_callReturnIndexVector;
Vector<CallReturnOffsetToBytecodeOffset, 0, UnsafeVectorOverflow> m_callReturnIndexVector;
#endif
#if ENABLE(DFG_JIT)
SegmentedVector<InlineCallFrame, 4> m_inlineCallFrames;
Vector<CodeOriginAtCallReturnOffset> m_codeOrigins;
Vector<CodeOriginAtCallReturnOffset, 0, UnsafeVectorOverflow> m_codeOrigins;
#endif
};
#if COMPILER(MSVC)
......
......@@ -658,7 +658,7 @@ public:
const Identifier& variable(unsigned index) { return m_variables[index]; }
unsigned numVariables() { return m_variables.size(); }
void adoptVariables(Vector<Identifier>& variables)
void adoptVariables(Vector<Identifier, 0, UnsafeVectorOverflow>& variables)
{
ASSERT(m_variables.isEmpty());
m_variables.swap(variables);
......@@ -670,7 +670,7 @@ private:
{
}
Vector<Identifier> m_variables;
Vector<Identifier, 0, UnsafeVectorOverflow> m_variables;
public:
static Structure* createStructure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue proto)
......
......@@ -276,7 +276,7 @@ BytecodeGenerator::BytecodeGenerator(JSGlobalData& globalData, JSScope* scope, F
bool shouldCaptureAllTheThings = m_shouldEmitDebugHooks || codeBlock->usesEval();
bool capturesAnyArgumentByName = false;
Vector<RegisterID*> capturedArguments;
Vector<RegisterID*, 0, UnsafeVectorOverflow> capturedArguments;
if (functionBody->hasCapturedVariables() || shouldCaptureAllTheThings) {
FunctionParameters& parameters = *functionBody->parameters();
capturedArguments.resize(parameters.size());
......@@ -441,7 +441,7 @@ BytecodeGenerator::BytecodeGenerator(JSGlobalData& globalData, JSScope* scope, E
const DeclarationStacks::VarStack& varStack = evalNode->varStack();
unsigned numVariables = varStack.size();
Vector<Identifier> variables;
Vector<Identifier, 0, UnsafeVectorOverflow> variables;
variables.reserveCapacity(numVariables);
for (size_t i = 0; i < numVariables; ++i)
variables.append(*varStack[i].first);
......@@ -1662,7 +1662,7 @@ RegisterID* BytecodeGenerator::emitNewArray(RegisterID* dst, ElementNode* elemen
}
}
Vector<RefPtr<RegisterID>, 16> argv;
Vector<RefPtr<RegisterID>, 16, UnsafeVectorOverflow> argv;
for (ElementNode* n = elements; n; n = n->next()) {
if (n->elision())
break;
......@@ -1849,7 +1849,7 @@ RegisterID* BytecodeGenerator::emitCall(OpcodeID opcodeID, RegisterID* dst, Regi
emitNode(callArguments.argumentRegister(argument++), n);
// Reserve space for call frame.
Vector<RefPtr<RegisterID>, JSStack::CallFrameHeaderSize> callFrame;
Vector<RefPtr<RegisterID>, JSStack::CallFrameHeaderSize, UnsafeVectorOverflow> callFrame;
for (int i = 0; i < JSStack::CallFrameHeaderSize; ++i)
callFrame.append(newTemporary());
......@@ -1972,7 +1972,7 @@ RegisterID* BytecodeGenerator::emitConstruct(RegisterID* dst, RegisterID* func,
}
// Reserve space for call frame.
Vector<RefPtr<RegisterID>, JSStack::CallFrameHeaderSize> callFrame;
Vector<RefPtr<RegisterID>, JSStack::CallFrameHeaderSize, UnsafeVectorOverflow> callFrame;
for (int i = 0; i < JSStack::CallFrameHeaderSize; ++i)
callFrame.append(newTemporary());
......
......@@ -76,7 +76,7 @@ namespace JSC {
RefPtr<RegisterID> m_profileHookRegister;
ArgumentsNode* m_argumentsNode;
Vector<RefPtr<RegisterID>, 8> m_argv;
Vector<RefPtr<RegisterID>, 8, UnsafeVectorOverflow> m_argv;
};
struct FinallyContext {
......@@ -656,7 +656,7 @@ namespace JSC {
RegisterID* emitInitLazyRegister(RegisterID*);
public:
Vector<UnlinkedInstruction>& instructions() { return m_instructions; }
Vector<UnlinkedInstruction, 0, UnsafeVectorOverflow>& instructions() { return m_instructions; }
SharedSymbolTable& symbolTable() { return *m_symbolTable; }
......@@ -691,7 +691,7 @@ namespace JSC {
void createActivationIfNecessary();
RegisterID* createLazyRegisterIfNecessary(RegisterID*);
Vector<UnlinkedInstruction> m_instructions;
Vector<UnlinkedInstruction, 0, UnsafeVectorOverflow> m_instructions;
bool m_shouldEmitDebugHooks;
bool m_shouldEmitProfileHooks;
......@@ -721,7 +721,7 @@ namespace JSC {
int m_dynamicScopeDepth;
CodeType m_codeType;
Vector<ControlFlowContext> m_scopeContextStack;
Vector<ControlFlowContext, 0, UnsafeVectorOverflow> m_scopeContextStack;
Vector<SwitchInfo> m_switchContextStack;
Vector<ForInContext> m_forInContextStack;
Vector<TryContext> m_tryContextStack;
......
......@@ -35,7 +35,7 @@ namespace JSC {
// Reference count indicates number of live registers that alias this object.
class StaticPropertyAnalysis : public RefCounted<StaticPropertyAnalysis> {
public:
static PassRefPtr<StaticPropertyAnalysis> create(Vector<UnlinkedInstruction>* instructions, unsigned target)
static PassRefPtr<StaticPropertyAnalysis> create(Vector<UnlinkedInstruction, 0, UnsafeVectorOverflow>* instructions, unsigned target)
{
return adoptRef(new StaticPropertyAnalysis(instructions, target));
}
......@@ -50,13 +50,13 @@ public:
int propertyIndexCount() { return m_propertyIndexes.size(); }
private:
StaticPropertyAnalysis(Vector<UnlinkedInstruction>* instructions, unsigned target)
StaticPropertyAnalysis(Vector<UnlinkedInstruction, 0, UnsafeVectorOverflow>* instructions, unsigned target)
: m_instructions(instructions)
, m_target(target)
{
}
Vector<UnlinkedInstruction>* m_instructions;
Vector<UnlinkedInstruction, 0, UnsafeVectorOverflow>* m_instructions;
unsigned m_target;
typedef HashSet<unsigned, WTF::IntHash<unsigned>, WTF::UnsignedWithZeroKeyHashTraits<unsigned> > PropertyIndexSet;
PropertyIndexSet m_propertyIndexes;
......
......@@ -36,7 +36,7 @@ namespace JSC {
// is understood to be lossy, and it's OK if it turns out to be wrong sometimes.
class StaticPropertyAnalyzer {
public:
StaticPropertyAnalyzer(Vector<UnlinkedInstruction>*);
StaticPropertyAnalyzer(Vector<UnlinkedInstruction, 0, UnsafeVectorOverflow>*);
void createThis(int dst, unsigned offsetOfInlineCapacityOperand);
void newObject(int dst, unsigned offsetOfInlineCapacityOperand);
......@@ -49,12 +49,12 @@ public:
private:
void kill(StaticPropertyAnalysis*);
Vector<UnlinkedInstruction>* m_instructions;
Vector<UnlinkedInstruction, 0, UnsafeVectorOverflow>* m_instructions;
typedef HashMap<int, RefPtr<StaticPropertyAnalysis>, WTF::IntHash<int>, WTF::UnsignedWithZeroKeyHashTraits<int> > AnalysisMap;
AnalysisMap m_analyses;
};
inline StaticPropertyAnalyzer::StaticPropertyAnalyzer(Vector<UnlinkedInstruction>* instructions)
inline StaticPropertyAnalyzer::StaticPropertyAnalyzer(Vector<UnlinkedInstruction, 0, UnsafeVectorOverflow>* instructions)
: m_instructions(instructions)
{
}
......
......@@ -162,7 +162,7 @@ void JITCompiler::link(LinkBuffer& linkBuffer)
m_codeBlock->callReturnIndexVector().append(CallReturnOffsetToBytecodeOffset(returnAddressOffset, exceptionInfo));
}
Vector<CodeOriginAtCallReturnOffset>& codeOrigins = m_codeBlock->codeOrigins();
Vector<CodeOriginAtCallReturnOffset, 0, UnsafeVectorOverflow>& codeOrigins = m_codeBlock->codeOrigins();
codeOrigins.resize(m_exceptionChecks.size());
for (unsigned i = 0; i < m_exceptionChecks.size(); ++i) {
......
......@@ -363,12 +363,12 @@ void Heap::markProtectedObjects(HeapRootVisitor& heapRootVisitor)
heapRootVisitor.visit(&it->key);
}
void Heap::pushTempSortVector(Vector<ValueStringPair>* tempVector)
void Heap::pushTempSortVector(Vector<ValueStringPair, 0, UnsafeVectorOverflow>* tempVector)
{
m_tempSortingVectors.append(tempVector);
}
void Heap::popTempSortVector(Vector<ValueStringPair>* tempVector)
void Heap::popTempSortVector(Vector<ValueStringPair, 0, UnsafeVectorOverflow>* tempVector)
{
ASSERT_UNUSED(tempVector, tempVector == m_tempSortingVectors.last());
m_tempSortingVectors.removeLast();
......@@ -376,11 +376,11 @@ void Heap::popTempSortVector(Vector<ValueStringPair>* tempVector)
void Heap::markTempSortVectors(HeapRootVisitor& heapRootVisitor)
{
typedef Vector<Vector<ValueStringPair>* > VectorOfValueStringVectors;
typedef Vector<Vector<ValueStringPair, 0, UnsafeVectorOverflow>* > VectorOfValueStringVectors;
VectorOfValueStringVectors::iterator end = m_tempSortingVectors.end();
for (VectorOfValueStringVectors::iterator it = m_tempSortingVectors.begin(); it != end; ++it) {
Vector<ValueStringPair>* tempSortingVector = *it;
Vector<ValueStringPair, 0, UnsafeVectorOverflow>* tempSortingVector = *it;
Vector<ValueStringPair>::iterator vectorEnd = tempSortingVector->end();
for (Vector<ValueStringPair>::iterator vectorIt = tempSortingVector->begin(); vectorIt != vectorEnd; ++vectorIt) {
......
......@@ -150,8 +150,8 @@ namespace JSC {
JS_EXPORT_PRIVATE PassOwnPtr<TypeCountSet> objectTypeCounts();
void showStatistics();
void pushTempSortVector(Vector<ValueStringPair>*);
void popTempSortVector(Vector<ValueStringPair>*);
void pushTempSortVector(Vector<ValueStringPair, 0, UnsafeVectorOverflow>*);
void popTempSortVector(Vector<ValueStringPair, 0, UnsafeVectorOverflow>*);
HashSet<MarkedArgumentBuffer*>& markListSet() { if (!m_markListSet) m_markListSet = adoptPtr(new HashSet<MarkedArgumentBuffer*>); return *m_markListSet; }
......@@ -242,7 +242,7 @@ namespace JSC {
#endif
ProtectCountSet m_protectedValues;
Vector<Vector<ValueStringPair>* > m_tempSortingVectors;
Vector<Vector<ValueStringPair, 0, UnsafeVectorOverflow>* > m_tempSortingVectors;
OwnPtr<HashSet<MarkedArgumentBuffer*> > m_markListSet;
MachineThreads m_machineThreads;
......
......@@ -654,10 +654,10 @@ private:
JSGlobalData* m_globalData;
SourceCode* m_sourceCode;
Scope m_scope;
Vector<BinaryOperand, 10> m_binaryOperandStack;
Vector<AssignmentInfo, 10> m_assignmentInfoStack;
Vector<pair<int, int>, 10> m_binaryOperatorStack;
Vector<pair<int, int>, 10> m_unaryTokenStack;
Vector<BinaryOperand, 10, UnsafeVectorOverflow> m_binaryOperandStack;
Vector<AssignmentInfo, 10, UnsafeVectorOverflow> m_assignmentInfoStack;
Vector<pair<int, int>, 10, UnsafeVectorOverflow> m_binaryOperatorStack;
Vector<pair<int, int>, 10, UnsafeVectorOverflow> m_unaryTokenStack;
int m_evalCount;
};
......
......@@ -749,7 +749,7 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncSort(ExecState* exec)
if (exec->hadException())
return JSValue::encode(jsUndefined());
Vector<uint32_t> keys;
Vector<uint32_t, 0, UnsafeVectorOverflow> keys;
for (size_t i = 0; i < nameArray.size(); ++i) {
PropertyName name = nameArray[i];
uint32_t index = name.asIndex();
......
......@@ -349,7 +349,7 @@ bool JSArray::setLengthWithArrayStorage(ExecState* exec, unsigned newLength, boo
if (newLength < length) {
// Copy any keys we might be interested in into a vector.
Vector<unsigned> keys;
Vector<unsigned, 0, UnsafeVectorOverflow> keys;
keys.reserveInitialCapacity(min(map->size(), static_cast<size_t>(length - newLength)));
SparseArrayValueMap::const_iterator end = map->end();
for (SparseArrayValueMap::const_iterator it = map->begin(); it != end; ++it) {
......@@ -1101,7 +1101,7 @@ void JSArray::sortCompactedVector(ExecState* exec, ContiguousData<StorageType> d
// buffer. Besides, this protects us from crashing if some objects have custom toString methods that return
// random or otherwise changing results, effectively making compare function inconsistent.
Vector<ValueStringPair> values(relevantLength);
Vector<ValueStringPair, 0, UnsafeVectorOverflow> values(relevantLength);
if (!values.begin()) {
throwOutOfMemoryError(exec);
return;
......@@ -1247,7 +1247,7 @@ struct AVLTreeAbstractorForArrayCompare {
typedef JSValue key;
typedef int32_t size;
Vector<AVLTreeNodeForArrayCompare> m_nodes;
Vector<AVLTreeNodeForArrayCompare, 0, UnsafeVectorOverflow> m_nodes;
ExecState* m_exec;
JSValue m_compareFunction;
CallType m_compareCallType;
......
......@@ -127,7 +127,7 @@ private:
CallData m_replacerCallData;
const String m_gap;
Vector<Holder, 16> m_holderStack;
Vector<Holder, 16, UnsafeVectorOverflow> m_holderStack;
String m_repeatedGap;
String m_indent;
};
......@@ -645,12 +645,12 @@ enum WalkerState { StateUnknown, ArrayStartState, ArrayStartVisitMember, ArrayEn
ObjectStartState, ObjectStartVisitMember, ObjectEndVisitMember };
NEVER_INLINE JSValue Walker::walk(JSValue unfiltered)
{
Vector<PropertyNameArray, 16> propertyStack;
Vector<uint32_t, 16> indexStack;
Vector<PropertyNameArray, 16, UnsafeVectorOverflow> propertyStack;
Vector<uint32_t, 16, UnsafeVectorOverflow> indexStack;
LocalStack<JSObject, 16> objectStack(m_exec->globalData());
LocalStack<JSArray, 16> arrayStack(m_exec->globalData());
Vector<WalkerState, 16> stateStack;
Vector<WalkerState, 16, UnsafeVectorOverflow> stateStack;
WalkerState state = StateUnknown;
JSValue inValue = unfiltered;
JSValue outValue = jsNull();
......
......@@ -1506,7 +1506,7 @@ void JSObject::getOwnPropertyNames(JSObject* object, ExecState* exec, PropertyNa
}
if (SparseArrayValueMap* map = storage->m_sparseMap.get()) {
Vector<unsigned> keys;
Vector<unsigned, 0, UnsafeVectorOverflow> keys;
keys.reserveInitialCapacity(map->size());
SparseArrayValueMap::const_iterator end = map->end();
......
......@@ -154,7 +154,7 @@ void JSRopeString::resolveRope(ExecState* exec) const
void JSRopeString::resolveRopeSlowCase8(LChar* buffer) const
{
LChar* position = buffer + m_length; // We will be working backwards over the rope.
Vector<JSString*, 32> workQueue; // Putting strings into a Vector is only OK because there are no GC points in this method.
Vector<JSString*, 32, UnsafeVectorOverflow> workQueue; // Putting strings into a Vector is only OK because there are no GC points in this method.
for (size_t i = 0; i < s_maxInternalRopeLength && m_fibers[i]; ++i) {
workQueue.append(m_fibers[i].get());
......@@ -186,7 +186,7 @@ void JSRopeString::resolveRopeSlowCase8(LChar* buffer) const
void JSRopeString::resolveRopeSlowCase(UChar* buffer) const
{
UChar* position = buffer + m_length; // We will be working backwards over the rope.
Vector<JSString*, 32> workQueue; // These strings are kept alive by the parent rope, so using a Vector is OK.
Vector<JSString*, 32, UnsafeVectorOverflow> workQueue; // These strings are kept alive by the parent rope, so using a Vector is OK.
for (size_t i = 0; i < s_maxInternalRopeLength && m_fibers[i]; ++i)
workQueue.append(m_fibers[i].get());
......
......@@ -137,8 +137,8 @@ public:
}
protected:
Vector<LChar, 64> buffer8;
Vector<UChar, 64> buffer16;
Vector<LChar, 64, UnsafeVectorOverflow> buffer8;
Vector<UChar, 64, UnsafeVectorOverflow> buffer16;
bool m_okay;
bool m_is8Bit;
};
......
......@@ -546,8 +546,8 @@ JSValue LiteralParser<CharType>::parse(ParserState initialState)
ParserState state = initialState;
MarkedArgumentBuffer objectStack;
JSValue lastValue;
Vector<ParserState, 16> stateStack;
Vector<Identifier, 16> identifierStack;
Vector<ParserState, 16, UnsafeVectorOverflow> stateStack;
Vector<Identifier, 16, UnsafeVectorOverflow> identifierStack;
while (1) {
switch(state) {
startParseArray:
......
2013-04-07 Oliver Hunt <oliver@apple.com>
Add bounds checking for WTF::Vector::operator[]
https://bugs.webkit.org/show_bug.cgi?id=89600
Reviewed by Filip Pizlo.
Add a template parameter to Vector<> that controls whether
bounds checking is performed in release builds or not.
Defaults to crashing on overflow.
* wtf/Forward.h:
(WTF):
* wtf/Vector.h:
(WTF):
(Vector):
(WTF::Vector::at):
(WTF::Vector::removeLast):
(WTF::::Vector):
(WTF::=):
(WTF::::contains):
(WTF::::find):
(WTF::::reverseFind):
(WTF::::fill):
(WTF::::appendRange):
(WTF::::expandCapacity):
(WTF::::tryExpandCapacity):
(WTF::::resize):
(WTF::::shrink):
(WTF::::grow):
(WTF::::reserveCapacity):
(WTF::::tryReserveCapacity):
(WTF::::reserveInitialCapacity):
(WTF::::shrinkCapacity):
(WTF::::append):
(WTF::::tryAppend):
(WTF::::appendSlowCase):
(WTF::::uncheckedAppend):
(WTF::::appendVector):
(WTF::::insert):
(WTF::::prepend):
(WTF::::remove):
(WTF::::reverse):
(WTF::::releaseBuffer):
(WTF::::checkConsistency):
(WTF::deleteAllValues):
(WTF::swap):
(WTF::operator==):
(WTF::operator!=):
2013-04-07 Patrick Gansterer <paroga@webkit.org>
[WIN] Fix problems with export macros of AutodrainedPool
......
......@@ -74,8 +74,8 @@ ENUM_CLASS(CheckedState)
} ENUM_CLASS_END(CheckedState);
class CrashOnOverflow {
protected:
NO_RETURN_DUE_TO_CRASH void overflowed()
public:
static NO_RETURN_DUE_TO_CRASH void overflowed()
{
CRASH();
}
......
......@@ -24,6 +24,7 @@
#include <stddef.h>
namespace WTF {
template<typename T> class Function;
template<typename T> class ListRefPtr;
template<typename T> class OwnArrayPtr;
......@@ -32,7 +33,7 @@ namespace WTF {
template<typename T> class PassOwnPtr;
template<typename T> class PassRefPtr;
template<typename T> class RefPtr;
template<typename T, size_t inlineCapacity> class Vector;
template<typename T, size_t inlineCapacity, typename OverflowHandler> class Vector;
class ArrayBuffer;
class ArrayBufferView;
......
......@@ -329,8 +329,8 @@ void MemoryInstrumentation::Wrapper<T>::callReportMemoryUsage(MemoryObjectInfo*
}
// Link time guard for classes with external memory instrumentation.
template<typename T, size_t inlineCapacity> class Vector;
template<typename T, size_t inlineCapacity> void reportMemoryUsage(const Vector<T, inlineCapacity>*, MemoryObjectInfo*);
template<typename T, size_t inlineCapacity, typename OverflowHandler> class Vector;
template<typename T, size_t inlineCapacity, typename OverflowHandler> void reportMemoryUsage(const Vector<T, inlineCapacity, OverflowHandler>*, MemoryObjectInfo*);
template<typename KeyArg, typename MappedArg, typename HashArg, typename KeyTraitsArg, typename MappedTraitsArg> class HashMap;
template<typename KeyArg, typename MappedArg, typename HashArg, typename KeyTraitsArg, typename MappedTraitsArg> void reportMemoryUsage(const HashMap<KeyArg, MappedArg, HashArg, KeyTraitsArg, MappedTraitsArg>*, MemoryObjectInfo*);
......
This diff is collapsed.
......@@ -444,8 +444,8 @@ public:
static unsigned dataOffset() { return OBJECT_OFFSETOF(StringImpl, m_data8); }
static PassRefPtr<StringImpl> createWithTerminatingNullCharacter(const StringImpl&);
template<typename CharType, size_t inlineCapacity>
static PassRefPtr<StringImpl> adopt(Vector<CharType, inlineCapacity>& vector)
template<typename CharType, size_t inlineCapacity, typename OverflowHandler>
static PassRefPtr<StringImpl> adopt(Vector<CharType, inlineCapacity, OverflowHandler>& vector)
{
if (size_t size = vector.size()) {
ASSERT(vector.data());
......