Skip to content

Commit 3ad284a

Browse files
atulkattiAtul Katti
authored andcommitted
[CVE-2018-8280] Edge - Js::DataView SetValue and GetValue to a detached buffer allows for semi arbitrary memory read write.
1 parent b2f092e commit 3ad284a

File tree

3 files changed

+26
-17
lines changed

3 files changed

+26
-17
lines changed

lib/Runtime/Library/DataView.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,12 @@ namespace Js
116116
mappedLength = byteLength - offset;
117117
}
118118

119+
// Evaluation of the argument(s) above is reentrant and can detach the array.
120+
if (arrayBuffer->IsDetached())
121+
{
122+
JavascriptError::ThrowTypeError(scriptContext, JSERR_DetachedTypedArray);
123+
}
124+
119125
//10. Let O be OrdinaryCreateFromConstructor(NewTarget, "%DataViewPrototype%", [[DataView]], [[ViewedArrayBuffer]], [[ByteLength]], [[ByteOffset]]).
120126
//11. Set O's[[DataView]] internal slot to true.
121127
//12. Set O's[[ViewedArrayBuffer]] internal slot to buffer.

lib/Runtime/Library/DataView.h

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -107,17 +107,18 @@ namespace Js
107107
Var GetValue(Var offset, const char16* funcName, BOOL isLittleEndian = FALSE)
108108
{
109109
ScriptContext* scriptContext = GetScriptContext();
110-
if (this->GetArrayBuffer()->IsDetached())
111-
{
112-
JavascriptError::ThrowTypeError(scriptContext, JSERR_DetachedTypedArray, funcName);
113-
}
114110

115111
uint32 length = GetLength();
116112
if (length < sizeof(TypeName))
117113
{
118114
JavascriptError::ThrowRangeError(scriptContext, JSERR_DataView_InvalidOffset, funcName);
119115
}
116+
120117
uint32 byteOffset = ArrayBuffer::ToIndex(offset, JSERR_DataView_InvalidOffset, scriptContext, length - sizeof(TypeName), false);
118+
if (this->GetArrayBuffer()->IsDetached())
119+
{
120+
JavascriptError::ThrowTypeError(scriptContext, JSERR_DetachedTypedArray, funcName);
121+
}
121122

122123
TypeName item;
123124
TypeName* typedBuffer = (TypeName*)(buffer + byteOffset);
@@ -142,17 +143,18 @@ namespace Js
142143
Var GetValueWithCheck(Var offset, BOOL isLittleEndian, const char16* funcName)
143144
{
144145
ScriptContext* scriptContext = GetScriptContext();
145-
if (this->GetArrayBuffer()->IsDetached())
146-
{
147-
JavascriptError::ThrowTypeError(scriptContext, JSERR_DetachedTypedArray, funcName);
148-
}
149146

150147
uint32 length = GetLength();
151148
if (length < sizeof(TypeName))
152149
{
153150
JavascriptError::ThrowRangeError(scriptContext, JSERR_DataView_InvalidOffset, funcName);
154151
}
152+
155153
uint32 byteOffset = ArrayBuffer::ToIndex(offset, JSERR_DataView_InvalidOffset, scriptContext, length - sizeof(TypeName), false);
154+
if (this->GetArrayBuffer()->IsDetached())
155+
{
156+
JavascriptError::ThrowTypeError(scriptContext, JSERR_DetachedTypedArray, funcName);
157+
}
156158

157159
TypeName item;
158160
TypeName *typedBuffer = (TypeName*)(buffer + byteOffset);
@@ -177,17 +179,18 @@ namespace Js
177179
void SetValue(Var offset, TypeName value, BOOL isLittleEndian, const char16 *funcName)
178180
{
179181
ScriptContext* scriptContext = GetScriptContext();
180-
if (this->GetArrayBuffer()->IsDetached())
181-
{
182-
JavascriptError::ThrowTypeError(scriptContext, JSERR_DetachedTypedArray, funcName);
183-
}
184182

185183
uint32 length = GetLength();
186184
if (length < sizeof(TypeName))
187185
{
188186
JavascriptError::ThrowRangeError(scriptContext, JSERR_DataView_InvalidOffset, funcName);
189187
}
188+
190189
uint32 byteOffset = ArrayBuffer::ToIndex(offset, JSERR_DataView_InvalidOffset, scriptContext, length - sizeof(TypeName), false);
190+
if (this->GetArrayBuffer()->IsDetached())
191+
{
192+
JavascriptError::ThrowTypeError(scriptContext, JSERR_DetachedTypedArray, funcName);
193+
}
191194

192195
TypeName* typedBuffer = (TypeName*)(buffer + byteOffset);
193196
if (!isLittleEndian)

lib/Runtime/Library/WebAssemblyMemory.cpp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -134,17 +134,17 @@ WebAssemblyMemory::EntryGrow(RecyclableObject* function, CallInfo callInfo, ...)
134134
WebAssemblyMemory* memory = WebAssemblyMemory::FromVar(args[0]);
135135
Assert(ArrayBufferBase::Is(memory->m_buffer));
136136

137-
if (memory->m_buffer->IsDetached())
138-
{
139-
JavascriptError::ThrowTypeError(scriptContext, JSERR_DetachedTypedArray);
140-
}
141-
142137
Var deltaVar = scriptContext->GetLibrary()->GetUndefined();
143138
if (args.Info.Count >= 2)
144139
{
145140
deltaVar = args[1];
146141
}
142+
147143
uint32 deltaPages = WebAssembly::ToNonWrappingUint32(deltaVar, scriptContext);
144+
if (memory->m_buffer->IsDetached())
145+
{
146+
JavascriptError::ThrowTypeError(scriptContext, JSERR_DetachedTypedArray);
147+
}
148148

149149
int32 oldPageCount = memory->GrowInternal(deltaPages);
150150
if (oldPageCount == -1)

0 commit comments

Comments
 (0)