Skip to content

Commit 79edb68

Browse files
tcareleirocks
authored andcommitted
[CVE-2017-11836] Edge - Assertion only bound check can lead to user controlled allocation size and write - Individual
When parsing a string template literal, we temporarily suspend updating some of the offset counters. If an attacker crafts a string template that contains multibyte characters, it is possible to overflow the minLine counter. The attacker can directly control the size of the overflow, which is then used in an allocation and offset calculation when handling a parse error. Further control can be gained by triggering a scanner capture and restore to propagate this bad counter value. Unfortunately this would have been caught by existing bounds checks, but they are asserts only. There are other instances of these around the codebase, but I did not see any exploits for those. To fix this, we manually update the minLine counter at the point where it would normally have been updated outside of a string template. I also changed the subtraction overflow asserts to be failfasts and added an assert for detecting overflow with multibyte characters. In the non-assert case, we will return 0. Other similar checks in IchMinTok and IchLimTok have also been converted.
1 parent b54e0d6 commit 79edb68

File tree

2 files changed

+36
-7
lines changed

2 files changed

+36
-7
lines changed

lib/Parser/Scan.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1110,6 +1110,10 @@ tokens Scanner<EncodingPolicy>::ScanStringConstant(OLECHAR delim, EncodedCharPtr
11101110
{
11111111
// Notify the scanner to update current line, number of lines etc
11121112
NotifyScannedNewLine();
1113+
1114+
// We haven't updated m_currentCharacter yet, so make sure the MinLine info is correct in case we error out.
1115+
m_pchMinLine = p;
1116+
11131117
break;
11141118
}
11151119

@@ -1400,6 +1404,10 @@ tokens Scanner<EncodingPolicy>::ScanStringConstant(OLECHAR delim, EncodedCharPtr
14001404

14011405
// Template literal strings ignore all escaped line continuation tokens
14021406
NotifyScannedNewLine();
1407+
1408+
// We haven't updated m_currentCharacter yet, so make sure the MinLine info is correct in case we error out.
1409+
m_pchMinLine = p;
1410+
14031411
continue;
14041412
}
14051413

lib/Parser/Scan.h

Lines changed: 28 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -480,17 +480,31 @@ class Scanner : public IScanner, public EncodingPolicy
480480
// have if the entire file was converted to Unicode (UTF16-LE).
481481
charcount_t IchMinTok(void) const
482482
{
483-
Assert(m_pchMinTok - m_pchBase >= 0);
484-
Assert(m_pchMinTok - m_pchBase <= LONG_MAX);
485-
return static_cast< charcount_t >(m_pchMinTok - m_pchBase - m_cMinTokMultiUnits);
483+
484+
AssertOrFailFast(m_pchMinTok - m_pchBase >= 0);
485+
AssertOrFailFast(m_pchMinTok - m_pchBase <= LONG_MAX);
486+
if (static_cast<charcount_t>(m_pchMinTok - m_pchBase) < m_cMinTokMultiUnits)
487+
{
488+
AssertMsg(false, "IchMinTok subtraction overflow");
489+
return 0;
490+
}
491+
492+
return static_cast<charcount_t>(m_pchMinTok - m_pchBase - m_cMinTokMultiUnits);
486493
}
487494

488495
// Returns the character offset of the character immediately following the token. The character offset is the offset the first
489496
// character of the token would have if the entire file was converted to Unicode (UTF16-LE).
490497
charcount_t IchLimTok(void) const
491498
{
492-
Assert(m_currentCharacter - m_pchBase >= 0);
493-
Assert(m_currentCharacter - m_pchBase <= LONG_MAX);
499+
500+
AssertOrFailFast(m_currentCharacter - m_pchBase >= 0);
501+
AssertOrFailFast(m_currentCharacter - m_pchBase <= LONG_MAX);
502+
if (static_cast<charcount_t>(m_currentCharacter - m_pchBase) < this->m_cMultiUnits)
503+
{
504+
AssertMsg(false, "IchLimTok subtraction overflow");
505+
return 0;
506+
}
507+
494508
return static_cast< charcount_t >(m_currentCharacter - m_pchBase - this->m_cMultiUnits);
495509
}
496510

@@ -542,8 +556,15 @@ class Scanner : public IScanner, public EncodingPolicy
542556
// Returns the character offset within the stream of the first character on the current line.
543557
charcount_t IchMinLine(void) const
544558
{
545-
Assert(m_pchMinLine - m_pchBase >= 0);
546-
Assert(m_pchMinLine - m_pchBase <= LONG_MAX);
559+
560+
AssertOrFailFast(m_pchMinLine - m_pchBase >= 0);
561+
AssertOrFailFast(m_pchMinLine - m_pchBase <= LONG_MAX);
562+
if (static_cast<charcount_t>(m_pchMinLine - m_pchBase) < m_cMinLineMultiUnits)
563+
{
564+
AssertMsg(false, "IchMinLine subtraction overflow");
565+
return 0;
566+
}
567+
547568
return static_cast<charcount_t>(m_pchMinLine - m_pchBase - m_cMinLineMultiUnits);
548569
}
549570

0 commit comments

Comments
 (0)