Changeset 241991 in webkit
- Timestamp:
- Feb 23, 2019 10:15:41 AM (5 years ago)
- Location:
- trunk/Source
- Files:
-
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/JavaScriptCore/ChangeLog
r241990 r241991 1 2019-02-23 Mark Lam <mark.lam@apple.com> 2 3 Add an exception check and some assertions in StringPrototype.cpp. 4 https://bugs.webkit.org/show_bug.cgi?id=194962 5 <rdar://problem/48013416> 6 7 Reviewed by Yusuke Suzuki and Saam Barati. 8 9 * runtime/StringPrototype.cpp: 10 (JSC::jsSpliceSubstrings): 11 (JSC::jsSpliceSubstringsWithSeparators): 12 (JSC::operationStringProtoFuncReplaceRegExpEmptyStr): 13 1 14 2019-02-23 Keith Miller <keith_miller@apple.com> 2 15 -
trunk/Source/JavaScriptCore/runtime/StringPrototype.cpp
r240641 r241991 1 1 /* 2 2 * Copyright (C) 1999-2001 Harri Porten (porten@kde.org) 3 * Copyright (C) 2004-201 7Apple Inc. All rights reserved.3 * Copyright (C) 2004-2019 Apple Inc. All rights reserved. 4 4 * Copyright (C) 2009 Torch Mobile, Inc. 5 5 * Copyright (C) 2015 Jordan Harband (ljharb@gmail.com) … … 325 325 } 326 326 327 int totalLength = 0; 327 // We know that the sum of substringRanges lengths cannot exceed length of 328 // source because the substringRanges were computed from the source string 329 // in removeUsingRegExpSearch(). Hence, totalLength cannot exceed 330 // String::MaxLength, and therefore, cannot overflow. 331 Checked<int, AssertNoOverflow> totalLength = 0; 328 332 for (int i = 0; i < rangeCount; i++) 329 333 totalLength += substringRanges[i].length; 334 ASSERT(totalLength <= String::MaxLength); 330 335 331 336 if (!totalLength) … … 335 340 LChar* buffer; 336 341 const LChar* sourceData = source.characters8(); 337 auto impl = StringImpl::tryCreateUninitialized(totalLength , buffer);342 auto impl = StringImpl::tryCreateUninitialized(totalLength.unsafeGet(), buffer); 338 343 if (!impl) { 339 344 throwOutOfMemoryError(exec, scope); … … 341 346 } 342 347 343 intbufferPos = 0;348 Checked<int, AssertNoOverflow> bufferPos = 0; 344 349 for (int i = 0; i < rangeCount; i++) { 345 350 if (int srcLen = substringRanges[i].length) { 346 StringImpl::copyCharacters(buffer + bufferPos , sourceData + substringRanges[i].position, srcLen);351 StringImpl::copyCharacters(buffer + bufferPos.unsafeGet(), sourceData + substringRanges[i].position, srcLen); 347 352 bufferPos += srcLen; 348 353 } … … 355 360 const UChar* sourceData = source.characters16(); 356 361 357 auto impl = StringImpl::tryCreateUninitialized(totalLength , buffer);362 auto impl = StringImpl::tryCreateUninitialized(totalLength.unsafeGet(), buffer); 358 363 if (!impl) { 359 364 throwOutOfMemoryError(exec, scope); … … 361 366 } 362 367 363 intbufferPos = 0;368 Checked<int, AssertNoOverflow> bufferPos = 0; 364 369 for (int i = 0; i < rangeCount; i++) { 365 370 if (int srcLen = substringRanges[i].length) { 366 StringImpl::copyCharacters(buffer + bufferPos , sourceData + substringRanges[i].position, srcLen);371 StringImpl::copyCharacters(buffer + bufferPos.unsafeGet(), sourceData + substringRanges[i].position, srcLen); 367 372 bufferPos += srcLen; 368 373 } … … 415 420 416 421 int maxCount = std::max(rangeCount, separatorCount); 417 intbufferPos = 0;422 Checked<int, AssertNoOverflow> bufferPos = 0; 418 423 for (int i = 0; i < maxCount; i++) { 419 424 if (i < rangeCount) { 420 425 if (int srcLen = substringRanges[i].length) { 421 StringImpl::copyCharacters(buffer + bufferPos , sourceData + substringRanges[i].position, srcLen);426 StringImpl::copyCharacters(buffer + bufferPos.unsafeGet(), sourceData + substringRanges[i].position, srcLen); 422 427 bufferPos += srcLen; 423 428 } … … 425 430 if (i < separatorCount) { 426 431 if (int sepLen = separators[i].length()) { 427 StringImpl::copyCharacters(buffer + bufferPos , separators[i].characters8(), sepLen);432 StringImpl::copyCharacters(buffer + bufferPos.unsafeGet(), separators[i].characters8(), sepLen); 428 433 bufferPos += sepLen; 429 434 } … … 442 447 443 448 int maxCount = std::max(rangeCount, separatorCount); 444 intbufferPos = 0;449 Checked<int, AssertNoOverflow> bufferPos = 0; 445 450 for (int i = 0; i < maxCount; i++) { 446 451 if (i < rangeCount) { 447 452 if (int srcLen = substringRanges[i].length) { 448 453 if (source.is8Bit()) 449 StringImpl::copyCharacters(buffer + bufferPos , source.characters8() + substringRanges[i].position, srcLen);454 StringImpl::copyCharacters(buffer + bufferPos.unsafeGet(), source.characters8() + substringRanges[i].position, srcLen); 450 455 else 451 StringImpl::copyCharacters(buffer + bufferPos , source.characters16() + substringRanges[i].position, srcLen);456 StringImpl::copyCharacters(buffer + bufferPos.unsafeGet(), source.characters16() + substringRanges[i].position, srcLen); 452 457 bufferPos += srcLen; 453 458 } … … 456 461 if (int sepLen = separators[i].length()) { 457 462 if (separators[i].is8Bit()) 458 StringImpl::copyCharacters(buffer + bufferPos , separators[i].characters8(), sepLen);463 StringImpl::copyCharacters(buffer + bufferPos.unsafeGet(), separators[i].characters8(), sepLen); 459 464 else 460 StringImpl::copyCharacters(buffer + bufferPos , separators[i].characters16(), sepLen);465 StringImpl::copyCharacters(buffer + bufferPos.unsafeGet(), separators[i].characters16(), sepLen); 461 466 bufferPos += sepLen; 462 467 } … … 730 735 searchValue->setLastIndex(exec, 0); 731 736 RETURN_IF_EXCEPTION(scope, nullptr); 732 RELEASE_AND_RETURN(scope, removeUsingRegExpSearch(vm, exec, thisValue, thisValue->value(exec), regExp)); 737 const String& source = thisValue->value(exec); 738 RETURN_IF_EXCEPTION(scope, nullptr); 739 RELEASE_AND_RETURN(scope, removeUsingRegExpSearch(vm, exec, thisValue, source, regExp)); 733 740 } 734 741 -
trunk/Source/WTF/ChangeLog
r241990 r241991 1 2019-02-23 Mark Lam <mark.lam@apple.com> 2 3 Add an exception check and some assertions in StringPrototype.cpp. 4 https://bugs.webkit.org/show_bug.cgi?id=194962 5 <rdar://problem/48013416> 6 7 Reviewed by Yusuke Suzuki and Saam Barati. 8 9 Add an AssertNoOverflow overflow handler which allows us to do CheckedArithmetic 10 for assertion purpose only on debug builds but sacrifices no performance on 11 release builds. 12 13 * wtf/CheckedArithmetic.h: 14 (WTF::AssertNoOverflow::overflowed): 15 (WTF::AssertNoOverflow::clearOverflow): 16 (WTF::AssertNoOverflow::crash): 17 (WTF::AssertNoOverflow::hasOverflowed const): 18 (WTF::observesOverflow): 19 (WTF::observesOverflow<AssertNoOverflow>): 20 (WTF::safeAdd): 21 (WTF::safeSub): 22 (WTF::safeMultiply): 23 (WTF::Checked::operator+=): 24 (WTF::Checked::operator-=): 25 (WTF::Checked::operator*=): 26 (WTF::operator+): 27 (WTF::operator-): 28 (WTF::operator*): 29 1 30 2019-02-23 Keith Miller <keith_miller@apple.com> 2 31 -
trunk/Source/WTF/wtf/CheckedArithmetic.h
r237577 r241991 1 1 /* 2 * Copyright (C) 2011-201 8Apple Inc. All rights reserved.2 * Copyright (C) 2011-2019 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 71 71 }; 72 72 73 class AssertNoOverflow { 74 public: 75 static NO_RETURN_DUE_TO_ASSERT void overflowed() 76 { 77 ASSERT_NOT_REACHED(); 78 } 79 80 void clearOverflow() { } 81 82 static NO_RETURN_DUE_TO_CRASH void crash() 83 { 84 CRASH(); 85 } 86 87 public: 88 constexpr bool hasOverflowed() const { return false; } 89 }; 90 73 91 class ConditionalCrashOnOverflow { 74 92 public: … … 524 542 }; 525 543 544 template <class OverflowHandler, typename = std::enable_if_t<!std::is_scalar<OverflowHandler>::value>> 545 inline constexpr bool observesOverflow() { return true; } 546 547 template <> 548 inline constexpr bool observesOverflow<AssertNoOverflow>() { return !ASSERT_DISABLED; } 549 526 550 template <typename U, typename V, typename R> static inline bool safeAdd(U lhs, V rhs, R& result) 527 551 { 528 552 return ArithmeticOperations<U, V, R>::add(lhs, rhs, result); 553 return true; 554 } 555 556 template <class OverflowHandler, typename U, typename V, typename R, typename = std::enable_if_t<!std::is_scalar<OverflowHandler>::value>> 557 static inline bool safeAdd(U lhs, V rhs, R& result) 558 { 559 if (observesOverflow<OverflowHandler>()) 560 return safeAdd(lhs, rhs, result); 561 result = lhs + rhs; 562 return true; 529 563 } 530 564 … … 534 568 } 535 569 570 template <class OverflowHandler, typename U, typename V, typename R, typename = std::enable_if_t<!std::is_scalar<OverflowHandler>::value>> 571 static inline bool safeSub(U lhs, V rhs, R& result) 572 { 573 if (observesOverflow<OverflowHandler>()) 574 return safeSub(lhs, rhs, result); 575 result = lhs - rhs; 576 return true; 577 } 578 536 579 template <typename U, typename V, typename R> static inline bool safeMultiply(U lhs, V rhs, R& result) 537 580 { 538 581 return ArithmeticOperations<U, V, R>::multiply(lhs, rhs, result); 582 } 583 584 template <class OverflowHandler, typename U, typename V, typename R, typename = std::enable_if_t<!std::is_scalar<OverflowHandler>::value>> 585 static inline bool safeMultiply(U lhs, V rhs, R& result) 586 { 587 if (observesOverflow<OverflowHandler>()) 588 return safeMultiply(lhs, rhs, result); 589 result = lhs * rhs; 590 return true; 539 591 } 540 592 … … 677 729 template <typename U> const Checked operator+=(U rhs) 678 730 { 679 if (!safeAdd (m_value, rhs, m_value))731 if (!safeAdd<OverflowHandler>(m_value, rhs, m_value)) 680 732 this->overflowed(); 681 733 return *this; … … 684 736 template <typename U> const Checked operator-=(U rhs) 685 737 { 686 if (!safeSub (m_value, rhs, m_value))738 if (!safeSub<OverflowHandler>(m_value, rhs, m_value)) 687 739 this->overflowed(); 688 740 return *this; … … 691 743 template <typename U> const Checked operator*=(U rhs) 692 744 { 693 if (!safeMultiply (m_value, rhs, m_value))745 if (!safeMultiply<OverflowHandler>(m_value, rhs, m_value)) 694 746 this->overflowed(); 695 747 return *this; … … 815 867 bool overflowed = lhs.safeGet(x) == CheckedState::DidOverflow || rhs.safeGet(y) == CheckedState::DidOverflow; 816 868 typename Result<U, V>::ResultType result = 0; 817 overflowed |= !safeAdd (x, y, result);869 overflowed |= !safeAdd<OverflowHandler>(x, y, result); 818 870 if (overflowed) 819 871 return ResultOverflowed; … … 827 879 bool overflowed = lhs.safeGet(x) == CheckedState::DidOverflow || rhs.safeGet(y) == CheckedState::DidOverflow; 828 880 typename Result<U, V>::ResultType result = 0; 829 overflowed |= !safeSub (x, y, result);881 overflowed |= !safeSub<OverflowHandler>(x, y, result); 830 882 if (overflowed) 831 883 return ResultOverflowed; … … 839 891 bool overflowed = lhs.safeGet(x) == CheckedState::DidOverflow || rhs.safeGet(y) == CheckedState::DidOverflow; 840 892 typename Result<U, V>::ResultType result = 0; 841 overflowed |= !safeMultiply (x, y, result);893 overflowed |= !safeMultiply<OverflowHandler>(x, y, result); 842 894 if (overflowed) 843 895 return ResultOverflowed; … … 931 983 } 932 984 985 using WTF::AssertNoOverflow; 933 986 using WTF::Checked; 934 987 using WTF::CheckedState;
Note: See TracChangeset
for help on using the changeset viewer.