Modified: trunk/Source/_javascript_Core/ChangeLog (208289 => 208290)
--- trunk/Source/_javascript_Core/ChangeLog 2016-11-02 17:43:32 UTC (rev 208289)
+++ trunk/Source/_javascript_Core/ChangeLog 2016-11-02 17:48:23 UTC (rev 208290)
@@ -1,3 +1,23 @@
+2016-11-02 Keith Miller <[email protected]>
+
+ We should not pop from an empty stack in the Wasm function parser.
+ https://bugs.webkit.org/show_bug.cgi?id=164275
+
+ Reviewed by Filip Pizlo.
+
+ This patch prevents an issue in the wasm parser where we might
+ accidentially pop from the _expression_ stack without if there
+ are no entries. It also fixes a similar issue with else
+ blocks where a user might try to put an else on the top level
+ of a function.
+
+ * wasm/WasmB3IRGenerator.cpp:
+ * wasm/WasmFunctionParser.h:
+ (JSC::Wasm::FunctionParser<Context>::parseExpression):
+ (JSC::Wasm::FunctionParser<Context>::popExpressionStack):
+ * wasm/WasmValidate.cpp:
+ (JSC::Wasm::Validate::setErrorMessage):
+
2016-11-02 Romain Bellessort <[email protected]>
[Readable Streams API] Enable creation of ReadableByteStreamController
Modified: trunk/Source/_javascript_Core/wasm/WasmB3IRGenerator.cpp (208289 => 208290)
--- trunk/Source/_javascript_Core/wasm/WasmB3IRGenerator.cpp 2016-11-02 17:43:32 UTC (rev 208289)
+++ trunk/Source/_javascript_Core/wasm/WasmB3IRGenerator.cpp 2016-11-02 17:48:23 UTC (rev 208290)
@@ -212,6 +212,8 @@
void dump(const Vector<ControlType>& controlStack, const ExpressionList& expressionStack);
+ void setErrorMessage(String&&) { UNREACHABLE_FOR_PLATFORM(); }
+
private:
ExpressionType emitCheckAndPreparePointer(ExpressionType pointer, uint32_t offset, uint32_t sizeOfOp);
ExpressionType emitLoadOp(LoadOpType, Origin, ExpressionType pointer, uint32_t offset);
Modified: trunk/Source/_javascript_Core/wasm/WasmFunctionParser.h (208289 => 208290)
--- trunk/Source/_javascript_Core/wasm/WasmFunctionParser.h 2016-11-02 17:43:32 UTC (rev 208289)
+++ trunk/Source/_javascript_Core/wasm/WasmFunctionParser.h 2016-11-02 17:48:23 UTC (rev 208290)
@@ -56,6 +56,8 @@
bool WARN_UNUSED_RETURN parseUnreachableExpression(OpType);
bool WARN_UNUSED_RETURN unifyControl(Vector<ExpressionType>&, unsigned level);
+ bool WARN_UNUSED_RETURN popExpressionStack(ExpressionType& result);
+
Context& m_context;
Vector<ExpressionType, 1> m_expressionStack;
Vector<ControlType> m_controlStack;
@@ -144,8 +146,14 @@
{
switch (op) {
FOR_EACH_WASM_BINARY_OP(CREATE_CASE) {
- ExpressionType right = m_expressionStack.takeLast();
- ExpressionType left = m_expressionStack.takeLast();
+ ExpressionType right;
+ if (!popExpressionStack(right))
+ return false;
+
+ ExpressionType left;
+ if (!popExpressionStack(left))
+ return false;
+
ExpressionType result;
if (!m_context.binaryOp(static_cast<BinaryOpType>(op), left, right, result))
return false;
@@ -154,9 +162,12 @@
}
FOR_EACH_WASM_UNARY_OP(CREATE_CASE) {
- ExpressionType arg = m_expressionStack.takeLast();
+ ExpressionType value;
+ if (!popExpressionStack(value))
+ return false;
+
ExpressionType result;
- if (!m_context.unaryOp(static_cast<UnaryOpType>(op), arg, result))
+ if (!m_context.unaryOp(static_cast<UnaryOpType>(op), value, result))
return false;
m_expressionStack.append(result);
return true;
@@ -171,7 +182,10 @@
if (!parseVarUInt32(offset))
return false;
- ExpressionType pointer = m_expressionStack.takeLast();
+ ExpressionType pointer;
+ if (!popExpressionStack(pointer))
+ return false;
+
ExpressionType result;
if (!m_context.load(static_cast<LoadOpType>(op), pointer, result, offset))
return false;
@@ -188,8 +202,14 @@
if (!parseVarUInt32(offset))
return false;
- ExpressionType value = m_expressionStack.takeLast();
- ExpressionType pointer = m_expressionStack.takeLast();
+ ExpressionType value;
+ if (!popExpressionStack(value))
+ return false;
+
+ ExpressionType pointer;
+ if (!popExpressionStack(pointer))
+ return false;
+
return m_context.store(static_cast<StoreOpType>(op), pointer, value, offset);
}
@@ -227,7 +247,9 @@
uint32_t index;
if (!parseVarUInt32(index))
return false;
- ExpressionType value = m_expressionStack.takeLast();
+ ExpressionType value;
+ if (!popExpressionStack(value))
+ return false;
return m_context.setLocal(index, value);
}
@@ -284,7 +306,10 @@
if (!parseValueType(inlineSignature))
return false;
- ExpressionType condition = m_expressionStack.takeLast();
+ ExpressionType condition;
+ if (!popExpressionStack(condition))
+ return false;
+
ControlType control;
if (!m_context.addIf(condition, inlineSignature, control))
return false;
@@ -294,6 +319,10 @@
}
case OpType::Else: {
+ if (!m_controlStack.size()) {
+ m_context.setErrorMessage("Attempted to use else block at the top-level of a function");
+ return false;
+ }
return m_context.addElse(m_controlStack.last(), m_expressionStack);
}
@@ -304,9 +333,10 @@
return false;
ExpressionType condition = Context::emptyExpression;
- if (op == OpType::BrIf)
- condition = m_expressionStack.takeLast();
- else
+ if (op == OpType::BrIf) {
+ if (!popExpressionStack(condition))
+ return false;
+ } else
m_unreachableBlocks = 1;
ControlType& data = "" - 1 - target];
@@ -316,8 +346,11 @@
case OpType::Return: {
Vector<ExpressionType, 1> returnValues;
- if (m_signature->returnType != Void)
- returnValues.append(m_expressionStack.takeLast());
+ if (m_signature->returnType != Void) {
+ ExpressionType returnValue;
+ if (!popExpressionStack(returnValue))
+ returnValues.append(returnValue);
+ }
m_unreachableBlocks = 1;
return m_context.addReturn(returnValues);
@@ -403,6 +436,18 @@
return true;
}
+template<typename Context>
+bool FunctionParser<Context>::popExpressionStack(ExpressionType& result)
+{
+ if (!m_expressionStack.size()) {
+ result = m_expressionStack.takeLast();
+ return true;
+ }
+
+ m_context.setErrorMessage("Attempted to use an stack value when none existed");
+ return false;
+}
+
#undef CREATE_CASE
} } // namespace JSC::Wasm
Modified: trunk/Source/_javascript_Core/wasm/WasmValidate.cpp (208289 => 208290)
--- trunk/Source/_javascript_Core/wasm/WasmValidate.cpp 2016-11-02 17:43:32 UTC (rev 208289)
+++ trunk/Source/_javascript_Core/wasm/WasmValidate.cpp 2016-11-02 17:48:23 UTC (rev 208290)
@@ -104,6 +104,7 @@
void dump(const Vector<ControlType>& controlStack, const ExpressionList& expressionStack);
+ void setErrorMessage(String&& message) { ASSERT(m_errorMessage.isNull()); m_errorMessage = WTFMove(message); }
String errorMessage() const { return m_errorMessage; }
Validate(ExpressionType returnType)
: m_returnType(returnType)