From cf26dce826a7a6a2d14735c193c53b9103c4a369 Mon Sep 17 00:00:00 2001 From: Filip Pizlo Date: Thu, 25 Sep 2014 11:29:50 +0200 Subject: compileMakeRope does not emit necessary bounds checks https://bugs.webkit.org/show_bug.cgi?id=130684 Reviewed by Oliver Hunt. Add string length bounds checks in a bunch of places. We should never allow a string to have a length greater than 2^31-1 because it's not clear that the language has semantics for it and because there is code that assumes that this cannot happen. Also add a bunch of tests to that effect to cover the various ways in which this was previously allowed to happen. * dfg/DFGOperations.cpp: * dfg/DFGSpeculativeJIT.cpp: (JSC::DFG::SpeculativeJIT::compileMakeRope): * ftl/FTLLowerDFGToLLVM.cpp: (JSC::FTL::LowerDFGToLLVM::compileMakeRope): * runtime/JSString.cpp: (JSC::JSRopeString::RopeBuilder::expand): * runtime/JSString.h: (JSC::JSString::create): (JSC::JSRopeString::RopeBuilder::append): (JSC::JSRopeString::RopeBuilder::release): (JSC::JSRopeString::append): * runtime/Operations.h: (JSC::jsString): (JSC::jsStringFromRegisterArray): (JSC::jsStringFromArguments): * runtime/StringPrototype.cpp: (JSC::stringProtoFuncIndexOf): (JSC::stringProtoFuncSlice): (JSC::stringProtoFuncSubstring): (JSC::stringProtoFuncToLowerCase): * tests/stress/make-large-string-jit-strcat.js: Added. (foo): * tests/stress/make-large-string-jit.js: Added. (foo): * tests/stress/make-large-string-strcat.js: Added. * tests/stress/make-large-string.js: Added. Change-Id: If01dd2a2d2daa3d209eddf0213d2b391e94f54a0 git-svn-id: http://svn.webkit.org/repository/webkit/trunk@167336 268f45cc-cd09-0410-ab3c-d52691b4dbfc Reviewed-by: Jocelyn Turcotte --- Source/JavaScriptCore/dfg/DFGOperations.cpp | 13 +++++++++++++ Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp | 18 +++++++++++++++++- 2 files changed, 30 insertions(+), 1 deletion(-) (limited to 'Source/JavaScriptCore/dfg') diff --git a/Source/JavaScriptCore/dfg/DFGOperations.cpp b/Source/JavaScriptCore/dfg/DFGOperations.cpp index 29a0b2b61..1305c0a5d 100644 --- a/Source/JavaScriptCore/dfg/DFGOperations.cpp +++ b/Source/JavaScriptCore/dfg/DFGOperations.cpp @@ -1644,6 +1644,11 @@ JSCell* DFG_OPERATION operationMakeRope2(ExecState* exec, JSString* left, JSStri VM& vm = exec->vm(); NativeCallFrameTracer tracer(&vm, exec); + if (static_cast(left->length() + right->length()) < 0) { + throwOutOfMemoryError(exec); + return 0; + } + return JSRopeString::create(vm, left, right); } @@ -1652,6 +1657,14 @@ JSCell* DFG_OPERATION operationMakeRope3(ExecState* exec, JSString* a, JSString* VM& vm = exec->vm(); NativeCallFrameTracer tracer(&vm, exec); + Checked length = a->length(); + length += b->length(); + length += c->length(); + if (length.hasOverflowed()) { + throwOutOfMemoryError(exec); + return 0; + } + return JSRopeString::create(vm, a, b, c); } diff --git a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp index 1348f94be..57a338e03 100644 --- a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp +++ b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp @@ -3204,12 +3204,28 @@ void SpeculativeJIT::compileMakeRope(Node* node) m_jit.storePtr(TrustedImmPtr(0), JITCompiler::Address(resultGPR, JSRopeString::offsetOfFibers() + sizeof(WriteBarrier) * i)); m_jit.load32(JITCompiler::Address(opGPRs[0], JSString::offsetOfFlags()), scratchGPR); m_jit.load32(JITCompiler::Address(opGPRs[0], JSString::offsetOfLength()), allocatorGPR); + if (!ASSERT_DISABLED) { + JITCompiler::Jump ok = m_jit.branch32( + JITCompiler::GreaterThanOrEqual, allocatorGPR, TrustedImm32(0)); + m_jit.breakpoint(); + ok.link(&m_jit); + } for (unsigned i = 1; i < numOpGPRs; ++i) { m_jit.and32(JITCompiler::Address(opGPRs[i], JSString::offsetOfFlags()), scratchGPR); - m_jit.add32(JITCompiler::Address(opGPRs[i], JSString::offsetOfLength()), allocatorGPR); + speculationCheck( + Uncountable, JSValueSource(), 0, + m_jit.branchAdd32( + JITCompiler::Overflow, + JITCompiler::Address(opGPRs[i], JSString::offsetOfLength()), allocatorGPR)); } m_jit.and32(JITCompiler::TrustedImm32(JSString::Is8Bit), scratchGPR); m_jit.store32(scratchGPR, JITCompiler::Address(resultGPR, JSString::offsetOfFlags())); + if (!ASSERT_DISABLED) { + JITCompiler::Jump ok = m_jit.branch32( + JITCompiler::GreaterThanOrEqual, allocatorGPR, TrustedImm32(0)); + m_jit.breakpoint(); + ok.link(&m_jit); + } m_jit.store32(allocatorGPR, JITCompiler::Address(resultGPR, JSString::offsetOfLength())); switch (numOpGPRs) { -- cgit v1.2.1