Changeset 167336 in webkit
- Timestamp:
- Apr 15, 2014, 4:33:11 PM (11 years ago)
- Location:
- trunk/Source/JavaScriptCore
- Files:
-
- 4 added
- 8 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/JavaScriptCore/ChangeLog
r167329 r167336 1 2014-04-15 Filip Pizlo <fpizlo@apple.com> 2 3 compileMakeRope does not emit necessary bounds checks 4 https://bugs.webkit.org/show_bug.cgi?id=130684 5 <rdar://problem/16398388> 6 7 Reviewed by Oliver Hunt. 8 9 Add string length bounds checks in a bunch of places. We should never allow a string 10 to have a length greater than 2^31-1 because it's not clear that the language has 11 semantics for it and because there is code that assumes that this cannot happen. 12 13 Also add a bunch of tests to that effect to cover the various ways in which this was 14 previously allowed to happen. 15 16 * dfg/DFGOperations.cpp: 17 * dfg/DFGSpeculativeJIT.cpp: 18 (JSC::DFG::SpeculativeJIT::compileMakeRope): 19 * ftl/FTLLowerDFGToLLVM.cpp: 20 (JSC::FTL::LowerDFGToLLVM::compileMakeRope): 21 * runtime/JSString.cpp: 22 (JSC::JSRopeString::RopeBuilder::expand): 23 * runtime/JSString.h: 24 (JSC::JSString::create): 25 (JSC::JSRopeString::RopeBuilder::append): 26 (JSC::JSRopeString::RopeBuilder::release): 27 (JSC::JSRopeString::append): 28 * runtime/Operations.h: 29 (JSC::jsString): 30 (JSC::jsStringFromRegisterArray): 31 (JSC::jsStringFromArguments): 32 * runtime/StringPrototype.cpp: 33 (JSC::stringProtoFuncIndexOf): 34 (JSC::stringProtoFuncSlice): 35 (JSC::stringProtoFuncSubstring): 36 (JSC::stringProtoFuncToLowerCase): 37 * tests/stress/make-large-string-jit-strcat.js: Added. 38 (foo): 39 * tests/stress/make-large-string-jit.js: Added. 40 (foo): 41 * tests/stress/make-large-string-strcat.js: Added. 42 * tests/stress/make-large-string.js: Added. 43 1 44 2014-04-15 Julien Brianceau <jbriance@cisco.com> 2 45 -
trunk/Source/JavaScriptCore/dfg/DFGOperations.cpp
r167036 r167336 969 969 VM& vm = exec->vm(); 970 970 NativeCallFrameTracer tracer(&vm, exec); 971 972 if (static_cast<int32_t>(left->length() + right->length()) < 0) { 973 throwOutOfMemoryError(exec); 974 return 0; 975 } 971 976 972 977 return JSRopeString::create(vm, left, right); … … 977 982 VM& vm = exec->vm(); 978 983 NativeCallFrameTracer tracer(&vm, exec); 984 985 Checked<int32_t, RecordOverflow> length = a->length(); 986 length += b->length(); 987 length += c->length(); 988 if (length.hasOverflowed()) { 989 throwOutOfMemoryError(exec); 990 return 0; 991 } 979 992 980 993 return JSRopeString::create(vm, a, b, c); -
trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp
r167325 r167336 2794 2794 m_jit.load32(JITCompiler::Address(opGPRs[0], JSString::offsetOfFlags()), scratchGPR); 2795 2795 m_jit.load32(JITCompiler::Address(opGPRs[0], JSString::offsetOfLength()), allocatorGPR); 2796 if (!ASSERT_DISABLED) { 2797 JITCompiler::Jump ok = m_jit.branch32( 2798 JITCompiler::GreaterThanOrEqual, allocatorGPR, TrustedImm32(0)); 2799 m_jit.breakpoint(); 2800 ok.link(&m_jit); 2801 } 2796 2802 for (unsigned i = 1; i < numOpGPRs; ++i) { 2797 2803 m_jit.and32(JITCompiler::Address(opGPRs[i], JSString::offsetOfFlags()), scratchGPR); 2798 m_jit.add32(JITCompiler::Address(opGPRs[i], JSString::offsetOfLength()), allocatorGPR); 2804 speculationCheck( 2805 Uncountable, JSValueSource(), nullptr, 2806 m_jit.branchAdd32( 2807 JITCompiler::Overflow, 2808 JITCompiler::Address(opGPRs[i], JSString::offsetOfLength()), allocatorGPR)); 2799 2809 } 2800 2810 m_jit.and32(JITCompiler::TrustedImm32(JSString::Is8Bit), scratchGPR); 2801 2811 m_jit.store32(scratchGPR, JITCompiler::Address(resultGPR, JSString::offsetOfFlags())); 2812 if (!ASSERT_DISABLED) { 2813 JITCompiler::Jump ok = m_jit.branch32( 2814 JITCompiler::GreaterThanOrEqual, allocatorGPR, TrustedImm32(0)); 2815 m_jit.breakpoint(); 2816 ok.link(&m_jit); 2817 } 2802 2818 m_jit.store32(allocatorGPR, JITCompiler::Address(resultGPR, JSString::offsetOfLength())); 2803 2819 -
trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp
r167325 r167336 2944 2944 for (unsigned i = 1; i < numKids; ++i) { 2945 2945 flags = m_out.bitAnd(flags, m_out.load32(kids[i], m_heaps.JSString_flags)); 2946 length = m_out.add(length, m_out.load32(kids[i], m_heaps.JSString_length)); 2946 LValue lengthAndOverflow = m_out.addWithOverflow32( 2947 length, m_out.load32(kids[i], m_heaps.JSString_length)); 2948 speculate(Uncountable, noValue(), 0, m_out.extractValue(lengthAndOverflow, 1)); 2949 length = m_out.extractValue(lengthAndOverflow, 0); 2947 2950 } 2948 2951 m_out.store32( -
trunk/Source/JavaScriptCore/runtime/JSString.cpp
r166837 r167336 39 39 ASSERT(m_index == JSRopeString::s_maxInternalRopeLength); 40 40 JSString* jsString = m_jsString; 41 RELEASE_ASSERT(jsString); 41 42 m_jsString = jsStringBuilder(&m_vm); 42 43 m_index = 0; -
trunk/Source/JavaScriptCore/runtime/JSString.h
r166837 r167336 2 2 * Copyright (C) 1999-2001 Harri Porten (porten@kde.org) 3 3 * Copyright (C) 2001 Peter Kelly (pmk@post.com) 4 * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.4 * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2014 Apple Inc. All rights reserved. 5 5 * 6 6 * This library is free software; you can redistribute it and/or … … 124 124 { 125 125 ASSERT(value); 126 size_t length = value->length(); 126 int32_t length = value->length(); 127 RELEASE_ASSERT(length >= 0); 127 128 size_t cost = value->cost(); 128 129 JSString* newString = new (NotNull, allocateCell<JSString>(vm.heap)) JSString(vm, value); … … 229 230 } 230 231 231 voidappend(JSString* jsString)232 bool append(JSString* jsString) 232 233 { 233 234 if (m_index == JSRopeString::s_maxInternalRopeLength) 234 235 expand(); 236 if (static_cast<int32_t>(m_jsString->length() + jsString->length()) < 0) { 237 m_jsString = 0; 238 return false; 239 } 235 240 m_jsString->append(m_vm, m_index++, jsString); 241 return true; 236 242 } 237 243 238 244 JSRopeString* release() 239 245 { 246 RELEASE_ASSERT(m_jsString); 240 247 JSRopeString* tmp = m_jsString; 241 248 m_jsString = 0; … … 287 294 m_fibers[index].set(vm, this, jsString); 288 295 m_length += jsString->m_length; 296 RELEASE_ASSERT(static_cast<int32_t>(m_length) >= 0); 289 297 setIs8Bit(is8Bit() && jsString->is8Bit()); 290 298 } -
trunk/Source/JavaScriptCore/runtime/Operations.h
r164764 r167336 39 39 VM& vm = exec->vm(); 40 40 41 unsignedlength1 = s1->length();41 int32_t length1 = s1->length(); 42 42 if (!length1) 43 43 return s2; 44 unsignedlength2 = s2->length();44 int32_t length2 = s2->length(); 45 45 if (!length2) 46 46 return s1; 47 if ((length1 + length2) < length1)47 if ((length1 + length2) < 0) 48 48 return throwOutOfMemoryError(exec); 49 49 … … 55 55 VM* vm = &exec->vm(); 56 56 57 unsigned length1 = u1.length(); 58 unsigned length2 = u2.length(); 59 unsigned length3 = u3.length(); 57 int32_t length1 = u1.length(); 58 int32_t length2 = u2.length(); 59 int32_t length3 = u3.length(); 60 61 if (length1 < 0 || length2 < 0 || length3 < 0) 62 return throwOutOfMemoryError(exec); 63 60 64 if (!length1) 61 65 return jsString(exec, jsString(vm, u2), jsString(vm, u3)); … … 65 69 return jsString(exec, jsString(vm, u1), jsString(vm, u2)); 66 70 67 if ((length1 + length2) < length1)68 return throwOutOfMemoryError(exec); 69 if ((length1 + length2 + length3) < length3)71 if ((length1 + length2) < 0) 72 return throwOutOfMemoryError(exec); 73 if ((length1 + length2 + length3) < 0) 70 74 return throwOutOfMemoryError(exec); 71 75 … … 78 82 JSRopeString::RopeBuilder ropeBuilder(*vm); 79 83 80 unsigned oldLength = 0;81 82 84 for (unsigned i = 0; i < count; ++i) { 83 85 JSValue v = strings[-static_cast<int>(i)].jsValue(); 84 ropeBuilder.append(v.toString(exec)); 85 86 if (ropeBuilder.length() < oldLength) // True for overflow 86 if (!ropeBuilder.append(v.toString(exec))) 87 87 return throwOutOfMemoryError(exec); 88 oldLength = ropeBuilder.length();89 88 } 90 89 … … 98 97 ropeBuilder.append(thisValue.toString(exec)); 99 98 100 unsigned oldLength = 0;101 102 99 for (unsigned i = 0; i < exec->argumentCount(); ++i) { 103 100 JSValue v = exec->argument(i); 104 ropeBuilder.append(v.toString(exec)); 105 106 if (ropeBuilder.length() < oldLength) // True for overflow 101 if (!ropeBuilder.append(v.toString(exec))) 107 102 return throwOutOfMemoryError(exec); 108 oldLength = ropeBuilder.length();109 103 } 110 104 -
trunk/Source/JavaScriptCore/runtime/StringPrototype.cpp
r166493 r167336 763 763 if (!a1.isUndefined()) { 764 764 int len = thisJSString->length(); 765 RELEASE_ASSERT(len >= 0); 765 766 if (a1.isUInt32()) 766 767 pos = std::min<uint32_t>(a1.asUInt32(), len); … … 917 918 String s = thisValue.toString(exec)->value(exec); 918 919 int len = s.length(); 920 RELEASE_ASSERT(len >= 0); 919 921 920 922 JSValue a0 = exec->argument(0); … … 1228 1230 JSValue a1 = exec->argument(1); 1229 1231 int len = jsString->length(); 1232 RELEASE_ASSERT(len >= 0); 1230 1233 1231 1234 double start = a0.toNumber(exec); … … 1265 1268 if (!sSize) 1266 1269 return JSValue::encode(sVal); 1270 RELEASE_ASSERT(sSize >= 0); 1267 1271 1268 1272 StringImpl* ourImpl = s.impl();
Note:
See TracChangeset
for help on using the changeset viewer.