Modified: trunk/Source/_javascript_Core/ChangeLog (202462 => 202463)
--- trunk/Source/_javascript_Core/ChangeLog 2016-06-24 23:54:22 UTC (rev 202462)
+++ trunk/Source/_javascript_Core/ChangeLog 2016-06-25 00:03:44 UTC (rev 202463)
@@ -1,3 +1,29 @@
+2016-06-24 Filip Pizlo <[email protected]>
+
+ B3 should die sooner if a Value has the wrong number of children
+ https://bugs.webkit.org/show_bug.cgi?id=159108
+
+ Reviewed by Mark Lam.
+
+ I've been looking at a bug (rdar://problem/26500743) that's about a Vector OOB crash in
+ ReduceStrength::rangeFor(). The only Vector accesses are to Value::m_children, and all of
+ the accesses in rangeFor() are for child(0) or child(1) of binary arithmetic opcodes.
+ Clearly those should never go out-of-bounds.
+
+ Maybe we have horrible memory corruption. Or maybe some path creates a Value with the
+ wrong number of children, and that path is not tested by any of our tests. This patch adds
+ release assertions that will catch the latter.
+
+ I've tested this a lot. It's not a regression on our benchmarks.
+
+ * b3/B3Opcode.h:
+ * b3/B3Value.cpp:
+ (JSC::B3::Value::dumpMeta):
+ (JSC::B3::Value::typeFor):
+ (JSC::B3::Value::badOpcode):
+ (JSC::B3::Value::checkOpcode): Deleted.
+ * b3/B3Value.h:
+
2016-06-24 Mark Lam <[email protected]>
[JSC] Error prototypes are called on remote scripts.
Modified: trunk/Source/_javascript_Core/b3/B3Opcode.h (202462 => 202463)
--- trunk/Source/_javascript_Core/b3/B3Opcode.h 2016-06-24 23:54:22 UTC (rev 202462)
+++ trunk/Source/_javascript_Core/b3/B3Opcode.h 2016-06-25 00:03:44 UTC (rev 202463)
@@ -265,7 +265,7 @@
class PrintStream;
-void printInternal(PrintStream&, JSC::B3::Opcode);
+JS_EXPORT_PRIVATE void printInternal(PrintStream&, JSC::B3::Opcode);
} // namespace WTF
Modified: trunk/Source/_javascript_Core/b3/B3Value.cpp (202462 => 202463)
--- trunk/Source/_javascript_Core/b3/B3Value.cpp 2016-06-24 23:54:22 UTC (rev 202462)
+++ trunk/Source/_javascript_Core/b3/B3Value.cpp 2016-06-25 00:03:44 UTC (rev 202463)
@@ -633,25 +633,6 @@
{
}
-#if !ASSERT_DISABLED
-void Value::checkOpcode(Opcode opcode)
-{
- ASSERT(!ArgumentRegValue::accepts(opcode));
- ASSERT(!CCallValue::accepts(opcode));
- ASSERT(!CheckValue::accepts(opcode));
- ASSERT(!Const32Value::accepts(opcode));
- ASSERT(!Const64Value::accepts(opcode));
- ASSERT(!ConstDoubleValue::accepts(opcode));
- ASSERT(!ConstFloatValue::accepts(opcode));
- ASSERT(!ControlValue::accepts(opcode));
- ASSERT(!MemoryValue::accepts(opcode));
- ASSERT(!PatchpointValue::accepts(opcode));
- ASSERT(!SlotBaseValue::accepts(opcode));
- ASSERT(!UpsilonValue::accepts(opcode));
- ASSERT(!VariableValue::accepts(opcode));
-}
-#endif // !ASSERT_DISABLED
-
Type Value::typeFor(Opcode opcode, Value* firstChild, Value* secondChild)
{
switch (opcode) {
@@ -729,6 +710,12 @@
}
}
+void Value::badOpcode(Opcode opcode, unsigned numArgs)
+{
+ dataLog("Bad opcode ", opcode, " with ", numArgs, " args.\n");
+ RELEASE_ASSERT_NOT_REACHED();
+}
+
} } // namespace JSC::B3
#endif // ENABLE(B3_JIT)
Modified: trunk/Source/_javascript_Core/b3/B3Value.h (202462 => 202463)
--- trunk/Source/_javascript_Core/b3/B3Value.h 2016-06-24 23:54:22 UTC (rev 202462)
+++ trunk/Source/_javascript_Core/b3/B3Value.h 2016-06-25 00:03:44 UTC (rev 202463)
@@ -235,11 +235,71 @@
friend class SparseCollection<Value>;
// Checks that this opcode is valid for use with B3::Value.
-#if ASSERT_DISABLED
- static void checkOpcode(Opcode) { }
-#else
- static void checkOpcode(Opcode);
-#endif
+ ALWAYS_INLINE static void checkOpcode(Opcode opcode, unsigned numArgs)
+ {
+ switch (opcode) {
+ case FramePointer:
+ case Nop:
+ case Phi:
+ if (UNLIKELY(numArgs))
+ badOpcode(opcode, numArgs);
+ break;
+ case Identity:
+ case Neg:
+ case Clz:
+ case Abs:
+ case Ceil:
+ case Floor:
+ case Sqrt:
+ case SExt8:
+ case SExt16:
+ case Trunc:
+ case SExt32:
+ case ZExt32:
+ case FloatToDouble:
+ case IToD:
+ case DoubleToFloat:
+ case IToF:
+ case BitwiseCast:
+ if (UNLIKELY(numArgs != 1))
+ badOpcode(opcode, numArgs);
+ break;
+ case Add:
+ case Sub:
+ case Mul:
+ case Div:
+ case Mod:
+ case ChillDiv:
+ case ChillMod:
+ case BitAnd:
+ case BitOr:
+ case BitXor:
+ case Shl:
+ case SShr:
+ case ZShr:
+ case Equal:
+ case NotEqual:
+ case LessThan:
+ case GreaterThan:
+ case LessEqual:
+ case GreaterEqual:
+ case Above:
+ case Below:
+ case AboveEqual:
+ case BelowEqual:
+ case EqualOrUnordered:
+ if (UNLIKELY(numArgs != 2))
+ badOpcode(opcode, numArgs);
+ break;
+ case Select:
+ if (UNLIKELY(numArgs != 3))
+ badOpcode(opcode, numArgs);
+ break;
+ default:
+ badOpcode(opcode, numArgs);
+ break;
+ }
+ }
protected:
enum CheckedOpcodeTag { CheckedOpcode };
@@ -309,11 +369,35 @@
// This is the constructor you end up actually calling, if you're instantiating Value
// directly.
template<typename... Arguments>
- explicit Value(Opcode opcode, Arguments&&... arguments)
- : Value(CheckedOpcode, opcode, std::forward<Arguments>(arguments)...)
+ explicit Value(Opcode opcode, Type type, Origin origin)
+ : Value(CheckedOpcode, opcode, type, origin)
{
- checkOpcode(opcode);
+ checkOpcode(opcode, 0);
}
+ template<typename... Arguments>
+ explicit Value(Opcode opcode, Type type, Origin origin, Value* firstChild, Arguments&&... arguments)
+ : Value(CheckedOpcode, opcode, type, origin, firstChild, std::forward<Arguments>(arguments)...)
+ {
+ checkOpcode(opcode, 1 + sizeof...(arguments));
+ }
+ template<typename... Arguments>
+ explicit Value(Opcode opcode, Type type, Origin origin, const AdjacencyList& children)
+ : Value(CheckedOpcode, opcode, type, origin, children)
+ {
+ checkOpcode(opcode, children.size());
+ }
+ template<typename... Arguments>
+ explicit Value(Opcode opcode, Type type, Origin origin, AdjacencyList&& children)
+ : Value(CheckedOpcode, opcode, type, origin, WTFMove(children))
+ {
+ checkOpcode(opcode, m_children.size());
+ }
+ template<typename... Arguments>
+ explicit Value(Opcode opcode, Origin origin, Arguments&&... arguments)
+ : Value(CheckedOpcode, opcode, origin, std::forward<Arguments>(arguments)...)
+ {
+ checkOpcode(opcode, sizeof...(arguments));
+ }
private:
friend class CheckValue; // CheckValue::convertToAdd() modifies m_opcode.
@@ -330,6 +414,8 @@
Origin m_origin;
AdjacencyList m_children;
+ JS_EXPORT_PRIVATE NO_RETURN_DUE_TO_CRASH static void badOpcode(Opcode, unsigned);
+
public:
BasicBlock* owner { nullptr }; // computed by Procedure::resetValueOwners().
};