WebAssembly: mask indexed accesses to Table
https://bugs.webkit.org/show_bug.cgi?id=181412
<rdar://problem/36363236>
Reviewed by Saam Barati.
JSTests:
Update error messages.
* wasm/js-api/table.js:
(assert.throws.WebAssembly.Table.prototype.grow):
Source/JavaScriptCore:
WebAssembly Table indexed accesses are user-controlled and
bounds-checked. Force allocations of Table data to be a
power-of-two, and explicitly mask accesses after bounds-check
branches.
Rename misleading usage of "size" when "length" of a Table was
intended.
Rename the Spectre option from "disable" to "enable".
* dfg/DFGSpeculativeJIT.cpp:
(JSC::DFG::SpeculativeJIT::SpeculativeJIT):
* ftl/FTLLowerDFGToB3.cpp:
(JSC::FTL::DFG::LowerDFGToB3::LowerDFGToB3):
* jit/JIT.cpp:
(JSC::JIT::JIT):
* runtime/Options.h:
* wasm/WasmB3IRGenerator.cpp:
(JSC::Wasm::B3IRGenerator::emitCheckAndPreparePointer):
(JSC::Wasm::B3IRGenerator::addCallIndirect):
* wasm/WasmTable.cpp:
(JSC::Wasm::Table::allocatedLength):
(JSC::Wasm::Table::setLength):
(JSC::Wasm::Table::create):
(JSC::Wasm::Table::Table):
(JSC::Wasm::Table::grow):
(JSC::Wasm::Table::clearFunction):
(JSC::Wasm::Table::setFunction):
* wasm/WasmTable.h:
(JSC::Wasm::Table::length const):
(JSC::Wasm::Table::offsetOfLength):
(JSC::Wasm::Table::offsetOfMask):
(JSC::Wasm::Table::mask const):
(JSC::Wasm::Table::isValidLength):
* wasm/js/JSWebAssemblyInstance.cpp:
(JSC::JSWebAssemblyInstance::create):
* wasm/js/JSWebAssemblyTable.cpp:
(JSC::JSWebAssemblyTable::JSWebAssemblyTable):
(JSC::JSWebAssemblyTable::visitChildren):
(JSC::JSWebAssemblyTable::grow):
(JSC::JSWebAssemblyTable::getFunction):
(JSC::JSWebAssemblyTable::clearFunction):
(JSC::JSWebAssemblyTable::setFunction):
* wasm/js/JSWebAssemblyTable.h:
(JSC::JSWebAssemblyTable::isValidLength):
(JSC::JSWebAssemblyTable::length const):
(JSC::JSWebAssemblyTable::allocatedLength const):
* wasm/js/WebAssemblyModuleRecord.cpp:
(JSC::WebAssemblyModuleRecord::evaluate):
* wasm/js/WebAssemblyTablePrototype.cpp:
(JSC::webAssemblyTableProtoFuncLength):
(JSC::webAssemblyTableProtoFuncGrow):
(JSC::webAssemblyTableProtoFuncGet):
(JSC::webAssemblyTableProtoFuncSet):
git-svn-id: http://svn.webkit.org/repository/webkit/trunk@226615 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/Source/JavaScriptCore/wasm/WasmTable.h b/Source/JavaScriptCore/wasm/WasmTable.h
index 529dfcf..0aaf456 100644
--- a/Source/JavaScriptCore/wasm/WasmTable.h
+++ b/Source/JavaScriptCore/wasm/WasmTable.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2017 Apple Inc. All rights reserved.
+ * Copyright (C) 2017-2018 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -45,25 +45,31 @@
JS_EXPORT_PRIVATE ~Table();
std::optional<uint32_t> maximum() const { return m_maximum; }
- uint32_t size() const { return m_size; }
+ uint32_t length() const { return m_length; }
std::optional<uint32_t> grow(uint32_t delta) WARN_UNUSED_RETURN;
void clearFunction(uint32_t);
void setFunction(uint32_t, CallableFunction, Instance*);
- static ptrdiff_t offsetOfSize() { return OBJECT_OFFSETOF(Table, m_size); }
static ptrdiff_t offsetOfFunctions() { return OBJECT_OFFSETOF(Table, m_functions); }
static ptrdiff_t offsetOfInstances() { return OBJECT_OFFSETOF(Table, m_instances); }
+ static ptrdiff_t offsetOfLength() { return OBJECT_OFFSETOF(Table, m_length); }
+ static ptrdiff_t offsetOfMask() { return OBJECT_OFFSETOF(Table, m_mask); }
- static bool isValidSize(uint32_t size) { return size < maxTableEntries; }
+ static uint32_t allocatedLength(uint32_t length);
+ uint32_t mask() const { return m_mask; }
+ static bool isValidLength(uint32_t length) { return length < maxTableEntries; }
private:
Table(uint32_t initial, std::optional<uint32_t> maximum);
- std::optional<uint32_t> m_maximum;
- uint32_t m_size;
+ void setLength(uint32_t);
+
MallocPtr<CallableFunction> m_functions;
// call_indirect needs to do an Instance check to potentially context switch when calling a function to another instance. We can hold raw pointers to Instance here because the embedder ensures that Table keeps all the instances alive. We couldn't hold a Ref here because it would cause cycles.
MallocPtr<Instance*> m_instances;
+ uint32_t m_length;
+ uint32_t m_mask;
+ std::optional<uint32_t> m_maximum;
};
} } // namespace JSC::Wasm