From 54d6d085987e2c399863940179db67b594d7f0a3 Mon Sep 17 00:00:00 2001 From: Satheesh Ravindranath Date: Mon, 27 Feb 2017 12:40:57 -0800 Subject: [PATCH] [CVE-2017-0208] Fix integer overflow in string.repeat When using repeat API on javascript strings, we aren't checking for the upper cap of the length property. Fix: Instead of directly setting the length property in the constructor - We are now calling SetLength() - which also checks for the upper cap and throws OOM. i --- lib/Runtime/Library/JavascriptString.cpp | 8 ++++---- lib/Runtime/Library/JavascriptString.h | 4 ++-- test/Strings/repeatBug.js | 21 +++++++++++++++++++++ test/Strings/rlexe.xml | 6 ++++++ 4 files changed, 33 insertions(+), 6 deletions(-) create mode 100644 test/Strings/repeatBug.js diff --git a/lib/Runtime/Library/JavascriptString.cpp b/lib/Runtime/Library/JavascriptString.cpp index 0db870d0c85..53914b1b6ac 100644 --- a/lib/Runtime/Library/JavascriptString.cpp +++ b/lib/Runtime/Library/JavascriptString.cpp @@ -199,10 +199,10 @@ namespace Js } JavascriptString::JavascriptString(StaticType * type, charcount_t charLength, const char16* szValue) - : RecyclableObject(type), m_charLength(charLength), m_pszValue(szValue) + : RecyclableObject(type), m_pszValue(szValue) { Assert(type->GetTypeId() == TypeIds_String); - AssertMsg(IsValidCharCount(charLength), "String length is out of range"); + SetLength(charLength); } _Ret_range_(m_charLength, m_charLength) @@ -3353,7 +3353,7 @@ namespace Js return builder.ToString(); } - int JavascriptString::IndexOfUsingJmpTable(JmpTable jmpTable, const char16* inputStr, int len, const char16* searchStr, int searchLen, int position) + int JavascriptString::IndexOfUsingJmpTable(JmpTable jmpTable, const char16* inputStr, charcount_t len, const char16* searchStr, int searchLen, int position) { int result = -1; @@ -3400,7 +3400,7 @@ namespace Js return result; } - int JavascriptString::LastIndexOfUsingJmpTable(JmpTable jmpTable, const char16* inputStr, int len, const char16* searchStr, int searchLen, int position) + int JavascriptString::LastIndexOfUsingJmpTable(JmpTable jmpTable, const char16* inputStr, charcount_t len, const char16* searchStr, charcount_t searchLen, charcount_t position) { const char16 searchFirst = searchStr[0]; uint32 lMatchedJump = searchLen; diff --git a/lib/Runtime/Library/JavascriptString.h b/lib/Runtime/Library/JavascriptString.h index b9b8bcdbc43..40141dffcf4 100644 --- a/lib/Runtime/Library/JavascriptString.h +++ b/lib/Runtime/Library/JavascriptString.h @@ -157,8 +157,8 @@ namespace Js char16* GetSzCopy(); // get a copy of the inner string without compacting the chunks static Var ToCaseCore(JavascriptString* pThis, ToCase toCase); - static int IndexOfUsingJmpTable(JmpTable jmpTable, const char16* inputStr, int len, const char16* searchStr, int searchLen, int position); - static int LastIndexOfUsingJmpTable(JmpTable jmpTable, const char16* inputStr, int len, const char16* searchStr, int searchLen, int position); + static int IndexOfUsingJmpTable(JmpTable jmpTable, const char16* inputStr, charcount_t len, const char16* searchStr, int searchLen, int position); + static int LastIndexOfUsingJmpTable(JmpTable jmpTable, const char16* inputStr, charcount_t len, const char16* searchStr, charcount_t searchLen, charcount_t position); static bool BuildLastCharForwardBoyerMooreTable(JmpTable jmpTable, const char16* searchStr, int searchLen); static bool BuildFirstCharBackwardBoyerMooreTable(JmpTable jmpTable, const char16* searchStr, int searchLen); static charcount_t ConvertToIndex(Var varIndex, ScriptContext *scriptContext); diff --git a/test/Strings/repeatBug.js b/test/Strings/repeatBug.js new file mode 100644 index 00000000000..1ed7740f4cb --- /dev/null +++ b/test/Strings/repeatBug.js @@ -0,0 +1,21 @@ +//------------------------------------------------------------------------------------------------------- +// Copyright (C) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE.txt file in the project root for full license information. +//------------------------------------------------------------------------------------------------------- + +try +{ + var str = "+".repeat(0x80000000); + str = str.replace(str, "+"); + + WScript.Echo("FAIL: Was expecting Out of Memory exception."); +} +catch (e) +{ + if(e.number == -2146828281) //Out of Memory + WScript.Echo("PASS"); + else + WScript.Echo("FAIL: Got the wrong exception code."); +} + + diff --git a/test/Strings/rlexe.xml b/test/Strings/rlexe.xml index 7fcb113051e..ac6393757ea 100644 --- a/test/Strings/rlexe.xml +++ b/test/Strings/rlexe.xml @@ -242,4 +242,10 @@ exclude_win7 + + + repeatBug.js + exclude_chk, Slow + +