Diff
Modified: trunk/Source/WebCore/ChangeLog (286382 => 286383)
--- trunk/Source/WebCore/ChangeLog 2021-12-01 21:25:07 UTC (rev 286382)
+++ trunk/Source/WebCore/ChangeLog 2021-12-01 21:31:04 UTC (rev 286383)
@@ -1,3 +1,74 @@
+2021-12-01 Alex Christensen <[email protected]>
+
+ Add csp-report resource type to WKContentRuleList
+ https://bugs.webkit.org/show_bug.cgi?id=233675
+ <rdar://71869893>
+
+ Reviewed by Tim Hatcher.
+
+ This feature is trivial to implement and test except for one small thing: we use a uint16_t to represent the
+ resource type and context and first party flags, and we already have 16 of them. So we needed to get another
+ bit from somewhere. What I did was make the flags have a variable length from 1-3 bytes instead of just 2 bytes.
+ I used the unused upper bits in the instruction to indicate the length of the flags, and if the upper bits were 0,
+ then I assume it was 2 bytes, which is binary compatible with existing compiled WKContentRuleLists, so no need
+ to increment the version number and force a recompile. It worked so well that I did the same thing with the actions,
+ which were 4 bytes but are now 1-4 bytes. This reduced the compiled binary size of one of the tests from 313 bytes
+ to 288 bytes, a reduction of about 8% of the binary size of the compiled WKContentRuleLists. Larger lists will see
+ slightly less binary size reduction, but still an improvement.
+
+ * contentextensions/ContentExtension.cpp:
+ (WebCore::ContentExtensions::ContentExtension::ContentExtension):
+ (WebCore::ContentExtensions::ContentExtension::populateConditionCacheIfNeeded):
+ * contentextensions/ContentExtensionsBackend.cpp:
+ (WebCore::ContentExtensions::ContentExtensionsBackend::actionsForResourceLoad const):
+ * contentextensions/DFABytecode.h:
+ (WebCore::ContentExtensions::smallestPossibleJumpSize):
+ (): Deleted.
+ (WebCore::ContentExtensions::instructionSizeWithArguments): Deleted.
+ * contentextensions/DFABytecodeCompiler.cpp:
+ (WebCore::ContentExtensions::append):
+ (WebCore::ContentExtensions::append24BitInteger):
+ (WebCore::ContentExtensions::appendZeroes):
+ (WebCore::ContentExtensions::setBits):
+ (WebCore::ContentExtensions::bytecodeFlagsSize):
+ (WebCore::ContentExtensions::bytecodeActionSize):
+ (WebCore::ContentExtensions::appendVariableLengthInteger):
+ (WebCore::ContentExtensions::DFABytecodeCompiler::emitAppendAction):
+ (WebCore::ContentExtensions::DFABytecodeCompiler::emitJump):
+ (WebCore::ContentExtensions::DFABytecodeCompiler::emitCheckValue):
+ (WebCore::ContentExtensions::DFABytecodeCompiler::emitCheckValueRange):
+ (WebCore::ContentExtensions::DFABytecodeCompiler::transitions):
+ (WebCore::ContentExtensions::DFABytecodeCompiler::compileJumpTable):
+ (WebCore::ContentExtensions::DFABytecodeCompiler::nodeTransitionsMaxBytecodeSize):
+ (WebCore::ContentExtensions::DFABytecodeCompiler::compile):
+ * contentextensions/DFABytecodeInterpreter.cpp:
+ (WebCore::ContentExtensions::getBits):
+ (WebCore::ContentExtensions::get24Bits):
+ (WebCore::ContentExtensions::getInstruction):
+ (WebCore::ContentExtensions::jumpSizeInBytes):
+ (WebCore::ContentExtensions::consumeInteger):
+ (WebCore::ContentExtensions::consume24BitInteger):
+ (WebCore::ContentExtensions::hasFlags):
+ (WebCore::ContentExtensions::hasAction):
+ (WebCore::ContentExtensions::consumeResourceFlagsAndInstruction):
+ (WebCore::ContentExtensions::consumeAction):
+ (WebCore::ContentExtensions::getJumpSize):
+ (WebCore::ContentExtensions::getJumpDistance):
+ (WebCore::ContentExtensions::matchesCondition):
+ (WebCore::ContentExtensions::DFABytecodeInterpreter::interpretAppendAction):
+ (WebCore::ContentExtensions::DFABytecodeInterpreter::interpretTestFlagsAndAppendAction):
+ (WebCore::ContentExtensions::DFABytecodeInterpreter::interpetJumpTable):
+ (WebCore::ContentExtensions::DFABytecodeInterpreter::actionsMatchingEverything):
+ (WebCore::ContentExtensions::DFABytecodeInterpreter::interpretWithConditions):
+ (WebCore::ContentExtensions::DFABytecodeInterpreter::interpret):
+ * contentextensions/DFABytecodeInterpreter.h:
+ (WebCore::ContentExtensions::DFABytecodeInterpreter::DFABytecodeInterpreter):
+ * loader/PingLoader.cpp:
+ (WebCore::PingLoader::sendViolationReport):
+ * loader/ResourceLoadInfo.cpp:
+ (WebCore::ContentExtensions::readResourceType):
+ * loader/ResourceLoadInfo.h:
+
2021-12-01 Rob Buis <[email protected]>
Remove virtual from RenderWidget::paintContents
Modified: trunk/Source/WebCore/contentextensions/ContentExtension.cpp (286382 => 286383)
--- trunk/Source/WebCore/contentextensions/ContentExtension.cpp 2021-12-01 21:25:07 UTC (rev 286382)
+++ trunk/Source/WebCore/contentextensions/ContentExtension.cpp 2021-12-01 21:31:04 UTC (rev 286383)
@@ -46,8 +46,8 @@
, m_compiledExtension(WTFMove(compiledExtension))
, m_extensionBaseURL(WTFMove(extensionBaseURL))
{
- DFABytecodeInterpreter withoutConditions(m_compiledExtension->filtersWithoutConditionsBytecode(), m_compiledExtension->filtersWithoutConditionsBytecodeLength());
- DFABytecodeInterpreter withConditions(m_compiledExtension->filtersWithConditionsBytecode(), m_compiledExtension->filtersWithConditionsBytecodeLength());
+ DFABytecodeInterpreter withoutConditions({ m_compiledExtension->filtersWithoutConditionsBytecode(), m_compiledExtension->filtersWithoutConditionsBytecodeLength() });
+ DFABytecodeInterpreter withConditions({ m_compiledExtension->filtersWithConditionsBytecode(), m_compiledExtension->filtersWithConditionsBytecodeLength() });
for (uint64_t action : withoutConditions.actionsMatchingEverything()) {
ASSERT(static_cast<uint32_t>(action) == action);
m_universalActionsWithoutConditions.append(static_cast<uint32_t>(action));
@@ -123,8 +123,8 @@
void ContentExtension::populateConditionCacheIfNeeded(const URL& topURL)
{
if (m_cachedTopURL != topURL) {
- DFABytecodeInterpreter interpreter(m_compiledExtension->topURLFiltersBytecode(), m_compiledExtension->topURLFiltersBytecodeLength());
- constexpr uint16_t allLoadTypesAndResourceTypes = LoadTypeMask | ResourceTypeMask | LoadContextMask;
+ DFABytecodeInterpreter interpreter({ m_compiledExtension->topURLFiltersBytecode(), m_compiledExtension->topURLFiltersBytecodeLength() });
+ constexpr ResourceFlags allLoadTypesAndResourceTypes = LoadTypeMask | ResourceTypeMask | LoadContextMask;
String string = m_compiledExtension->conditionsApplyOnlyToDomain() ? topURL.host().toString() : topURL.string();
auto topURLActions = interpreter.interpret(string.utf8(), allLoadTypesAndResourceTypes);
Modified: trunk/Source/WebCore/contentextensions/ContentExtensionsBackend.cpp (286382 => 286383)
--- trunk/Source/WebCore/contentextensions/ContentExtensionsBackend.cpp 2021-12-01 21:25:07 UTC (rev 286382)
+++ trunk/Source/WebCore/contentextensions/ContentExtensionsBackend.cpp 2021-12-01 21:31:04 UTC (rev 286383)
@@ -121,11 +121,11 @@
const CompiledContentExtension& compiledExtension = contentExtension->compiledExtension();
- DFABytecodeInterpreter withoutConditionsInterpreter(compiledExtension.filtersWithoutConditionsBytecode(), compiledExtension.filtersWithoutConditionsBytecodeLength());
+ DFABytecodeInterpreter withoutConditionsInterpreter({ compiledExtension.filtersWithoutConditionsBytecode(), compiledExtension.filtersWithoutConditionsBytecodeLength() });
DFABytecodeInterpreter::Actions withoutConditionsActions = withoutConditionsInterpreter.interpret(urlCString, flags);
URL topURL = resourceLoadInfo.mainDocumentURL;
- DFABytecodeInterpreter withConditionsInterpreter(compiledExtension.filtersWithConditionsBytecode(), compiledExtension.filtersWithConditionsBytecodeLength());
+ DFABytecodeInterpreter withConditionsInterpreter({ compiledExtension.filtersWithConditionsBytecode(), compiledExtension.filtersWithConditionsBytecodeLength() });
DFABytecodeInterpreter::Actions withConditionsActions = withConditionsInterpreter.interpretWithConditions(urlCString, flags, contentExtension->topURLActions(topURL));
const SerializedActionByte* actions = compiledExtension.actions();
Modified: trunk/Source/WebCore/contentextensions/DFABytecode.h (286382 => 286383)
--- trunk/Source/WebCore/contentextensions/DFABytecode.h 2021-12-01 21:25:07 UTC (rev 286382)
+++ trunk/Source/WebCore/contentextensions/DFABytecode.h 2021-12-01 21:31:04 UTC (rev 286383)
@@ -27,11 +27,9 @@
#if ENABLE(CONTENT_EXTENSIONS)
-namespace WebCore {
-
-namespace ContentExtensions {
+namespace WebCore::ContentExtensions {
-typedef uint8_t DFABytecode;
+using DFABytecode = uint8_t;
// Increment ContentExtensionStore::CurrentContentExtensionFileVersion
// when making any non-backwards-compatible changes to the bytecode.
@@ -60,13 +58,13 @@
CheckValueRangeCaseSensitive = 0x5,
// AppendAction has one argument:
- // The action to append (4 bytes).
+ // The action to append (1-4 bytes).
AppendAction = 0x6,
AppendActionWithIfCondition = 0x7,
// TestFlagsAndAppendAction has two arguments:
- // The flags to check before appending (2 bytes).
- // The action to append (4 bytes).
+ // The flags to check before appending (1-3 bytes).
+ // The action to append (1-4 bytes).
TestFlagsAndAppendAction = 0x8,
TestFlagsAndAppendActionWithIfCondition = 0x9,
@@ -79,57 +77,51 @@
};
// The last four bits contain the instruction type.
-const uint8_t DFABytecodeInstructionMask = 0x0F;
-const uint8_t DFABytecodeJumpSizeMask = 0xF0;
+static constexpr uint8_t DFABytecodeInstructionMask = 0x0F;
+static constexpr uint8_t DFABytecodeJumpSizeMask = 0xF0;
+static constexpr uint8_t DFABytecodeFlagsSizeMask = 0x30;
+static constexpr uint8_t DFABytecodeActionSizeMask = 0xC0;
// DFA bytecode starts with a 4 byte header which contains the size of this DFA.
-typedef uint32_t DFAHeader;
+using DFAHeader = uint32_t;
+// DFABytecodeFlagsSize and DFABytecodeActionSize are stored in the top four bits of the DFABytecodeInstructions that have flags and actions.
+enum class DFABytecodeFlagsSize : uint8_t {
+ UInt8 = 0x10,
+ UInt16 = 0x00, // Needs to be zero to be binary compatible with bytecode compiled with fixed-size flags.
+ UInt24 = 0x20,
+};
+enum class DFABytecodeActionSize : uint8_t {
+ UInt8 = 0x40,
+ UInt16 = 0x80,
+ UInt24 = 0xC0,
+ UInt32 = 0x00, // Needs to be zero to be binary compatible with bytecode compiled with fixed-size actions.
+};
+
// A DFABytecodeJumpSize is stored in the top four bits of the DFABytecodeInstructions that have a jump.
-enum DFABytecodeJumpSize {
+enum class DFABytecodeJumpSize : uint8_t {
Int8 = 0x10,
Int16 = 0x20,
Int24 = 0x30,
Int32 = 0x40,
};
-const int32_t Int24Max = (1 << 23) - 1;
-const int32_t Int24Min = -(1 << 23);
+static constexpr int32_t UInt24Max = (1 << 24) - 1;
+static constexpr int32_t Int24Max = (1 << 23) - 1;
+static constexpr int32_t Int24Min = -(1 << 23);
+static constexpr size_t Int24Size = 3;
+static constexpr size_t UInt24Size = 3;
static inline DFABytecodeJumpSize smallestPossibleJumpSize(int32_t longestPossibleJump)
{
if (longestPossibleJump <= std::numeric_limits<int8_t>::max() && longestPossibleJump >= std::numeric_limits<int8_t>::min())
- return Int8;
+ return DFABytecodeJumpSize::Int8;
if (longestPossibleJump <= std::numeric_limits<int16_t>::max() && longestPossibleJump >= std::numeric_limits<int16_t>::min())
- return Int16;
+ return DFABytecodeJumpSize::Int16;
if (longestPossibleJump <= Int24Max && longestPossibleJump >= Int24Min)
- return Int24;
- return Int32;
+ return DFABytecodeJumpSize::Int24;
+ return DFABytecodeJumpSize::Int32;
}
-
-static inline size_t instructionSizeWithArguments(DFABytecodeInstruction instruction)
-{
- switch (instruction) {
- case DFABytecodeInstruction::CheckValueCaseSensitive:
- case DFABytecodeInstruction::CheckValueCaseInsensitive:
- case DFABytecodeInstruction::JumpTableCaseInsensitive:
- case DFABytecodeInstruction::JumpTableCaseSensitive:
- case DFABytecodeInstruction::CheckValueRangeCaseSensitive:
- case DFABytecodeInstruction::CheckValueRangeCaseInsensitive:
- case DFABytecodeInstruction::Jump:
- RELEASE_ASSERT_NOT_REACHED(); // Variable instruction size.
- case DFABytecodeInstruction::AppendAction:
- case DFABytecodeInstruction::AppendActionWithIfCondition:
- return sizeof(DFABytecodeInstruction) + sizeof(uint32_t);
- case DFABytecodeInstruction::TestFlagsAndAppendAction:
- case DFABytecodeInstruction::TestFlagsAndAppendActionWithIfCondition:
- return sizeof(DFABytecodeInstruction) + sizeof(uint16_t) + sizeof(uint32_t);
- case DFABytecodeInstruction::Terminate:
- return sizeof(DFABytecodeInstruction);
- }
- RELEASE_ASSERT_NOT_REACHED();
-}
-
-} // namespace ContentExtensions
-} // namespace WebCore
+} // namespace WebCore::ContentExtensions
+
#endif // ENABLE(CONTENT_EXTENSIONS)
Modified: trunk/Source/WebCore/contentextensions/DFABytecodeCompiler.cpp (286382 => 286383)
--- trunk/Source/WebCore/contentextensions/DFABytecodeCompiler.cpp 2021-12-01 21:25:07 UTC (rev 286382)
+++ trunk/Source/WebCore/contentextensions/DFABytecodeCompiler.cpp 2021-12-01 21:31:04 UTC (rev 286383)
@@ -32,19 +32,23 @@
#include "DFA.h"
#include "DFANode.h"
-namespace WebCore {
-
-namespace ContentExtensions {
+namespace WebCore::ContentExtensions {
template <typename IntType>
-inline void append(Vector<DFABytecode>& bytecode, IntType value)
+void append(Vector<DFABytecode>& bytecode, IntType value)
{
bytecode.grow(bytecode.size() + sizeof(IntType));
memcpy(&bytecode[bytecode.size() - sizeof(IntType)], &value, sizeof(IntType));
}
-inline void appendZeroes(Vector<DFABytecode>& bytecode, DFABytecodeJumpSize jumpSize)
+static void append24BitUnsignedInteger(Vector<DFABytecode>& bytecode, uint32_t value)
{
+ append<uint16_t>(bytecode, value);
+ append<uint8_t>(bytecode, value >> 16);
+}
+
+static void appendZeroes(Vector<DFABytecode>& bytecode, DFABytecodeJumpSize jumpSize)
+{
switch (jumpSize) {
case DFABytecodeJumpSize::Int8:
append<int8_t>(bytecode, 0); // This value will be set when linking.
@@ -63,7 +67,7 @@
}
template <typename IntType>
-inline void setBits(Vector<DFABytecode>& bytecode, uint32_t index, IntType value)
+void setBits(Vector<DFABytecode>& bytecode, uint32_t index, IntType value)
{
RELEASE_ASSERT(index + sizeof(IntType) <= bytecode.size());
ASSERT_WITH_MESSAGE(!*reinterpret_cast<IntType*>(&bytecode[index]), "Right now we should only be using setBits to overwrite values that were zero as a placeholder.");
@@ -76,24 +80,59 @@
return sizeof(DFABytecodeInstruction) + sizeof(uint16_t) + sizeof(uint32_t);
return sizeof(DFABytecodeInstruction) + sizeof(uint32_t);
}
-
+
+static DFABytecodeFlagsSize bytecodeFlagsSize(ResourceFlags flags)
+{
+ if (flags <= std::numeric_limits<uint8_t>::max())
+ return DFABytecodeFlagsSize::UInt8;
+ if (flags <= std::numeric_limits<uint16_t>::max())
+ return DFABytecodeFlagsSize::UInt16;
+ RELEASE_ASSERT(flags <= UInt24Max);
+ return DFABytecodeFlagsSize::UInt24;
+}
+
+static DFABytecodeActionSize bytecodeActionSize(uint32_t actionWithoutFlags)
+{
+ if (actionWithoutFlags <= std::numeric_limits<uint8_t>::max())
+ return DFABytecodeActionSize::UInt8;
+ if (actionWithoutFlags <= std::numeric_limits<uint16_t>::max())
+ return DFABytecodeActionSize::UInt16;
+ if (actionWithoutFlags <= UInt24Max)
+ return DFABytecodeActionSize::UInt24;
+ return DFABytecodeActionSize::UInt32;
+}
+
+static void appendVariableLengthUnsignedInteger(Vector<DFABytecode>& bytecode, uint32_t integer)
+{
+ if (integer <= std::numeric_limits<uint8_t>::max())
+ return append<uint8_t>(bytecode, integer);
+ if (integer <= std::numeric_limits<uint16_t>::max())
+ return append<uint16_t>(bytecode, integer);
+ if (integer <= UInt24Max)
+ return append24BitUnsignedInteger(bytecode, integer);
+ return append<uint32_t>(bytecode, integer);
+}
+
void DFABytecodeCompiler::emitAppendAction(uint64_t action)
{
+ uint32_t actionWithoutFlags = action;
+ auto actionSize = bytecodeActionSize(actionWithoutFlags);
+
// High bits are used to store flags. See compileRuleList.
- if (action & ActionFlagMask) {
- if (action & IfConditionFlag)
- append<DFABytecodeInstruction>(m_bytecode, DFABytecodeInstruction::TestFlagsAndAppendActionWithIfCondition);
- else
- append<DFABytecodeInstruction>(m_bytecode, DFABytecodeInstruction::TestFlagsAndAppendAction);
- append<uint16_t>(m_bytecode, static_cast<uint16_t>(action >> 32));
- append<uint32_t>(m_bytecode, static_cast<uint32_t>(action));
- } else {
- if (action & IfConditionFlag)
- append<DFABytecodeInstruction>(m_bytecode, DFABytecodeInstruction::AppendActionWithIfCondition);
- else
- append<DFABytecodeInstruction>(m_bytecode, DFABytecodeInstruction::AppendAction);
- append<uint32_t>(m_bytecode, static_cast<uint32_t>(action));
+ if (ResourceFlags flags = (action & ActionFlagMask) >> 32) {
+ auto flagsSize = bytecodeFlagsSize(flags);
+ auto instruction = (action & IfConditionFlag) ? DFABytecodeInstruction::TestFlagsAndAppendActionWithIfCondition : DFABytecodeInstruction::TestFlagsAndAppendAction;
+ ASSERT(!(static_cast<uint8_t>(instruction) & static_cast<uint8_t>(flagsSize) & static_cast<uint8_t>(actionSize)));
+ append<uint8_t>(m_bytecode, static_cast<uint8_t>(instruction) | static_cast<uint8_t>(flagsSize) | static_cast<uint8_t>(actionSize));
+ appendVariableLengthUnsignedInteger(m_bytecode, flags);
+ appendVariableLengthUnsignedInteger(m_bytecode, actionWithoutFlags);
+ return;
}
+
+ auto instruction = (action & IfConditionFlag) ? DFABytecodeInstruction::AppendActionWithIfCondition : DFABytecodeInstruction::AppendAction;
+ ASSERT(!(static_cast<uint8_t>(instruction) & static_cast<uint8_t>(actionSize)));
+ append<uint8_t>(m_bytecode, static_cast<uint8_t>(instruction) | static_cast<uint8_t>(actionSize));
+ appendVariableLengthUnsignedInteger(m_bytecode, actionWithoutFlags);
}
int32_t DFABytecodeCompiler::longestPossibleJump(uint32_t instructionLocation, uint32_t sourceNodeIndex, uint32_t destinationNodeIndex)
@@ -119,7 +158,7 @@
uint32_t jumpLocation = instructionLocation + sizeof(uint8_t);
int32_t longestPossibleJumpDistance = longestPossibleJump(instructionLocation, sourceNodeIndex, destinationNodeIndex);
DFABytecodeJumpSize jumpSize = smallestPossibleJumpSize(longestPossibleJumpDistance);
- append<uint8_t>(m_bytecode, static_cast<uint8_t>(DFABytecodeInstruction::Jump) | jumpSize);
+ append<uint8_t>(m_bytecode, static_cast<uint8_t>(DFABytecodeInstruction::Jump) | static_cast<uint8_t>(jumpSize));
m_linkRecords.append(LinkRecord({jumpSize, longestPossibleJumpDistance, instructionLocation, jumpLocation, destinationNodeIndex}));
appendZeroes(m_bytecode, jumpSize);
@@ -132,7 +171,7 @@
int32_t longestPossibleJumpDistance = longestPossibleJump(instructionLocation, sourceNodeIndex, destinationNodeIndex);
DFABytecodeJumpSize jumpSize = smallestPossibleJumpSize(longestPossibleJumpDistance);
DFABytecodeInstruction instruction = caseSensitive ? DFABytecodeInstruction::CheckValueCaseSensitive : DFABytecodeInstruction::CheckValueCaseInsensitive;
- append<uint8_t>(m_bytecode, static_cast<uint8_t>(instruction) | jumpSize);
+ append<uint8_t>(m_bytecode, static_cast<uint8_t>(instruction) | static_cast<uint8_t>(jumpSize));
append<uint8_t>(m_bytecode, value);
m_linkRecords.append(LinkRecord({jumpSize, longestPossibleJumpDistance, instructionLocation, jumpLocation, destinationNodeIndex}));
appendZeroes(m_bytecode, jumpSize);
@@ -147,7 +186,7 @@
int32_t longestPossibleJumpDistance = longestPossibleJump(instructionLocation, sourceNodeIndex, destinationNodeIndex);
DFABytecodeJumpSize jumpSize = smallestPossibleJumpSize(longestPossibleJumpDistance);
DFABytecodeInstruction instruction = caseSensitive ? DFABytecodeInstruction::CheckValueRangeCaseSensitive : DFABytecodeInstruction::CheckValueRangeCaseInsensitive;
- append<uint8_t>(m_bytecode, static_cast<uint8_t>(instruction) | jumpSize);
+ append<uint8_t>(m_bytecode, static_cast<uint8_t>(instruction) | static_cast<uint8_t>(jumpSize));
append<uint8_t>(m_bytecode, lowValue);
append<uint8_t>(m_bytecode, highValue);
m_linkRecords.append(LinkRecord({jumpSize, longestPossibleJumpDistance, instructionLocation, jumpLocation, destinationNodeIndex}));
@@ -226,7 +265,7 @@
return jumpTable;
}
-DFABytecodeCompiler::Transitions DFABytecodeCompiler::transitions(const DFANode& node)
+auto DFABytecodeCompiler::transitions(const DFANode& node) -> Transitions
{
Transitions transitions;
@@ -350,7 +389,7 @@
ASSERT(jumpTable.min <= jumpTable.max);
uint32_t instructionLocation = m_bytecode.size();
- DFABytecodeJumpSize jumpSize = Int8;
+ auto jumpSize = DFABytecodeJumpSize::Int8;
for (uint32_t destinationNodeIndex : jumpTable.destinations) {
int32_t longestPossibleJumpDistance = longestPossibleJump(instructionLocation, nodeIndex, destinationNodeIndex);
DFABytecodeJumpSize localJumpSize = smallestPossibleJumpSize(longestPossibleJumpDistance);
@@ -358,7 +397,7 @@
}
DFABytecodeInstruction instruction = jumpTable.caseSensitive ? DFABytecodeInstruction::JumpTableCaseSensitive : DFABytecodeInstruction::JumpTableCaseInsensitive;
- append<uint8_t>(m_bytecode, static_cast<uint8_t>(instruction) | jumpSize);
+ append<uint8_t>(m_bytecode, static_cast<uint8_t>(instruction) | static_cast<uint8_t>(jumpSize));
append<uint8_t>(m_bytecode, jumpTable.min);
append<uint8_t>(m_bytecode, jumpTable.max);
@@ -397,7 +436,7 @@
if (nodeTransitions.useFallbackTransition)
size += sizeof(DFABytecodeInstruction::Jump) + sizeof(uint32_t);
else
- size += instructionSizeWithArguments(DFABytecodeInstruction::Terminate);
+ size += sizeof(DFABytecodeInstruction::Terminate);
return size;
}
@@ -466,20 +505,20 @@
ASSERT(abs(distance) <= abs(linkRecord.longestPossibleJump));
switch (linkRecord.jumpSize) {
- case Int8:
+ case DFABytecodeJumpSize::Int8:
RELEASE_ASSERT(distance == static_cast<int8_t>(distance));
setBits<int8_t>(m_bytecode, linkRecord.jumpLocation, static_cast<int8_t>(distance));
break;
- case Int16:
+ case DFABytecodeJumpSize::Int16:
RELEASE_ASSERT(distance == static_cast<int16_t>(distance));
setBits<int16_t>(m_bytecode, linkRecord.jumpLocation, static_cast<int16_t>(distance));
break;
- case Int24:
+ case DFABytecodeJumpSize::Int24:
RELEASE_ASSERT(distance >= Int24Min && distance <= Int24Max);
setBits<uint16_t>(m_bytecode, linkRecord.jumpLocation, static_cast<uint16_t>(distance));
setBits<int8_t>(m_bytecode, linkRecord.jumpLocation + sizeof(int16_t), static_cast<int8_t>(distance >> 16));
break;
- case Int32:
+ case DFABytecodeJumpSize::Int32:
setBits<int32_t>(m_bytecode, linkRecord.jumpLocation, distance);
break;
}
@@ -487,9 +526,7 @@
setBits<DFAHeader>(m_bytecode, startLocation, m_bytecode.size() - startLocation);
}
-
-} // namespace ContentExtensions
-} // namespace WebCore
+} // namespace WebCore::ContentExtensions
#endif // ENABLE(CONTENT_EXTENSIONS)
Modified: trunk/Source/WebCore/contentextensions/DFABytecodeInterpreter.cpp (286382 => 286383)
--- trunk/Source/WebCore/contentextensions/DFABytecodeInterpreter.cpp 2021-12-01 21:25:07 UTC (rev 286382)
+++ trunk/Source/WebCore/contentextensions/DFABytecodeInterpreter.cpp 2021-12-01 21:31:04 UTC (rev 286383)
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2015 Apple Inc. All rights reserved.
+ * Copyright (C) 2015-2021 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -31,62 +31,155 @@
#if ENABLE(CONTENT_EXTENSIONS)
-namespace WebCore {
-
-namespace ContentExtensions {
+namespace WebCore::ContentExtensions {
template <typename IntType>
-static inline IntType getBits(const DFABytecode* bytecode, uint32_t bytecodeLength, uint32_t index)
+static IntType getBits(Span<const uint8_t> bytecode, uint32_t index)
{
- ASSERT_UNUSED(bytecodeLength, index + sizeof(IntType) <= bytecodeLength);
- return *reinterpret_cast<const IntType*>(&bytecode[index]);
+ ASSERT(index + sizeof(IntType) <= bytecode.size());
+ return *reinterpret_cast<const IntType*>(bytecode.data() + index);
}
-static inline DFABytecodeInstruction getInstruction(const DFABytecode* bytecode, uint32_t bytecodeLength, uint32_t index)
+static uint32_t get24BitsUnsigned(Span<const uint8_t> bytecode, uint32_t index)
{
- return static_cast<DFABytecodeInstruction>(getBits<uint8_t>(bytecode, bytecodeLength, index) & DFABytecodeInstructionMask);
+ ASSERT(index + UInt24Size <= bytecode.size());
+ uint32_t highBits = getBits<uint8_t>(bytecode, index + sizeof(uint16_t));
+ uint32_t lowBits = getBits<uint16_t>(bytecode, index);
+ return (highBits << 16) | lowBits;
}
-static inline size_t jumpSizeInBytes(DFABytecodeJumpSize jumpSize)
+static DFABytecodeInstruction getInstruction(Span<const uint8_t> bytecode, uint32_t index)
{
+ return static_cast<DFABytecodeInstruction>(getBits<uint8_t>(bytecode, index) & DFABytecodeInstructionMask);
+}
+
+static size_t jumpSizeInBytes(DFABytecodeJumpSize jumpSize)
+{
switch (jumpSize) {
- case Int8:
+ case DFABytecodeJumpSize::Int8:
return sizeof(int8_t);
- case Int16:
+ case DFABytecodeJumpSize::Int16:
return sizeof(int16_t);
- case Int24:
- return sizeof(uint16_t) + sizeof(int8_t);
- case Int32:
+ case DFABytecodeJumpSize::Int24:
+ return Int24Size;
+ case DFABytecodeJumpSize::Int32:
return sizeof(int32_t);
- default:
- RELEASE_ASSERT_NOT_REACHED();
}
+ RELEASE_ASSERT_NOT_REACHED();
}
-static inline DFABytecodeJumpSize getJumpSize(const DFABytecode* bytecode, uint32_t bytecodeLength, uint32_t index)
+template<typename T> uint32_t consumeInteger(Span<const uint8_t> bytecode, uint32_t& programCounter)
{
- DFABytecodeJumpSize jumpSize = static_cast<DFABytecodeJumpSize>(getBits<uint8_t>(bytecode, bytecodeLength, index) & DFABytecodeJumpSizeMask);
- ASSERT(jumpSize == DFABytecodeJumpSize::Int32 || jumpSize == DFABytecodeJumpSize::Int24 || jumpSize == DFABytecodeJumpSize::Int16 || jumpSize == DFABytecodeJumpSize::Int8);
+ programCounter += sizeof(T);
+ return getBits<T>(bytecode, programCounter - sizeof(T));
+}
+static uint32_t consume24BitUnsignedInteger(Span<const uint8_t> bytecode, uint32_t& programCounter)
+{
+ programCounter += UInt24Size;
+ return get24BitsUnsigned(bytecode, programCounter - UInt24Size);
+}
+
+static constexpr bool hasFlags(DFABytecodeInstruction instruction)
+{
+ switch (instruction) {
+ case DFABytecodeInstruction::TestFlagsAndAppendAction:
+ case DFABytecodeInstruction::TestFlagsAndAppendActionWithIfCondition:
+ return true;
+ case DFABytecodeInstruction::CheckValueCaseSensitive:
+ case DFABytecodeInstruction::CheckValueCaseInsensitive:
+ case DFABytecodeInstruction::JumpTableCaseInsensitive:
+ case DFABytecodeInstruction::JumpTableCaseSensitive:
+ case DFABytecodeInstruction::CheckValueRangeCaseSensitive:
+ case DFABytecodeInstruction::CheckValueRangeCaseInsensitive:
+ case DFABytecodeInstruction::Jump:
+ case DFABytecodeInstruction::AppendAction:
+ case DFABytecodeInstruction::AppendActionWithIfCondition:
+ case DFABytecodeInstruction::Terminate:
+ break;
+ }
+ return false;
+}
+
+static constexpr bool hasAction(DFABytecodeInstruction instruction)
+{
+ switch (instruction) {
+ case DFABytecodeInstruction::TestFlagsAndAppendAction:
+ case DFABytecodeInstruction::TestFlagsAndAppendActionWithIfCondition:
+ case DFABytecodeInstruction::AppendAction:
+ case DFABytecodeInstruction::AppendActionWithIfCondition:
+ return true;
+ case DFABytecodeInstruction::CheckValueCaseSensitive:
+ case DFABytecodeInstruction::CheckValueCaseInsensitive:
+ case DFABytecodeInstruction::JumpTableCaseInsensitive:
+ case DFABytecodeInstruction::JumpTableCaseSensitive:
+ case DFABytecodeInstruction::CheckValueRangeCaseSensitive:
+ case DFABytecodeInstruction::CheckValueRangeCaseInsensitive:
+ case DFABytecodeInstruction::Jump:
+ case DFABytecodeInstruction::Terminate:
+ break;
+ }
+ return false;
+}
+
+static ResourceFlags consumeResourceFlagsAndInstruction(Span<const uint8_t> bytecode, uint32_t& programCounter)
+{
+ ASSERT_UNUSED(hasFlags, hasFlags(getInstruction(bytecode, programCounter)));
+ switch (static_cast<DFABytecodeFlagsSize>(bytecode[programCounter++] & DFABytecodeFlagsSizeMask)) {
+ case DFABytecodeFlagsSize::UInt8:
+ return consumeInteger<uint8_t>(bytecode, programCounter);
+ case DFABytecodeFlagsSize::UInt16:
+ return consumeInteger<uint16_t>(bytecode, programCounter);
+ case DFABytecodeFlagsSize::UInt24:
+ return consume24BitUnsignedInteger(bytecode, programCounter);
+ }
+ ASSERT_NOT_REACHED();
+ return 0;
+}
+
+static uint32_t consumeAction(Span<const uint8_t> bytecode, uint32_t& programCounter, uint32_t instructionLocation)
+{
+ ASSERT_UNUSED(hasAction, hasAction(getInstruction(bytecode, instructionLocation)));
+ ASSERT(programCounter > instructionLocation);
+ switch (static_cast<DFABytecodeActionSize>(bytecode[instructionLocation] & DFABytecodeActionSizeMask)) {
+ case DFABytecodeActionSize::UInt8:
+ return consumeInteger<uint8_t>(bytecode, programCounter);
+ case DFABytecodeActionSize::UInt16:
+ return consumeInteger<uint16_t>(bytecode, programCounter);
+ case DFABytecodeActionSize::UInt24:
+ return consume24BitUnsignedInteger(bytecode, programCounter);
+ case DFABytecodeActionSize::UInt32:
+ return consumeInteger<uint32_t>(bytecode, programCounter);
+ }
+ ASSERT_NOT_REACHED();
+ return 0;
+}
+
+static DFABytecodeJumpSize getJumpSize(Span<const uint8_t> bytecode, uint32_t index)
+{
+ auto jumpSize = static_cast<DFABytecodeJumpSize>(getBits<uint8_t>(bytecode, index) & DFABytecodeJumpSizeMask);
+ ASSERT(jumpSize == DFABytecodeJumpSize::Int32
+ || jumpSize == DFABytecodeJumpSize::Int24
+ || jumpSize == DFABytecodeJumpSize::Int16
+ || jumpSize == DFABytecodeJumpSize::Int8);
return jumpSize;
}
-static inline int32_t getJumpDistance(const DFABytecode* bytecode, uint32_t bytecodeLength, uint32_t index, DFABytecodeJumpSize jumpSize)
+static int32_t getJumpDistance(Span<const uint8_t> bytecode, uint32_t index, DFABytecodeJumpSize jumpSize)
{
switch (jumpSize) {
- case Int8:
- return getBits<int8_t>(bytecode, bytecodeLength, index);
- case Int16:
- return getBits<int16_t>(bytecode, bytecodeLength, index);
- case Int24:
- return getBits<uint16_t>(bytecode, bytecodeLength, index) | (static_cast<int32_t>(getBits<int8_t>(bytecode, bytecodeLength, index + sizeof(uint16_t))) << 16);
- case Int32:
- return getBits<int32_t>(bytecode, bytecodeLength, index);
- default:
- RELEASE_ASSERT_NOT_REACHED();
+ case DFABytecodeJumpSize::Int8:
+ return getBits<int8_t>(bytecode, index);
+ case DFABytecodeJumpSize::Int16:
+ return getBits<int16_t>(bytecode, index);
+ case DFABytecodeJumpSize::Int24:
+ return getBits<uint16_t>(bytecode, index) | (static_cast<int32_t>(getBits<int8_t>(bytecode, index + sizeof(uint16_t))) << 16);
+ case DFABytecodeJumpSize::Int32:
+ return getBits<int32_t>(bytecode, index);
}
+ RELEASE_ASSERT_NOT_REACHED();
}
-static inline bool matchesCondition(uint64_t actionAndFlags, const DFABytecodeInterpreter::Actions& conditionActions)
+static bool matchesCondition(uint64_t actionAndFlags, const DFABytecodeInterpreter::Actions& conditionActions)
{
bool ifCondition = actionAndFlags & IfConditionFlag;
bool condition = conditionActions.contains(actionAndFlags);
@@ -95,51 +188,48 @@
void DFABytecodeInterpreter::interpretAppendAction(uint32_t& programCounter, Actions& actions, bool ifCondition)
{
- ASSERT(getInstruction(m_bytecode, m_bytecodeLength, programCounter) == DFABytecodeInstruction::AppendAction
- || getInstruction(m_bytecode, m_bytecodeLength, programCounter) == DFABytecodeInstruction::AppendActionWithIfCondition);
- uint64_t action = "" ? IfConditionFlag : 0) | static_cast<uint64_t>(getBits<uint32_t>(m_bytecode, m_bytecodeLength, programCounter + sizeof(DFABytecodeInstruction)));
+ ASSERT(getInstruction(m_bytecode, programCounter) == DFABytecodeInstruction::AppendAction
+ || getInstruction(m_bytecode, programCounter) == DFABytecodeInstruction::AppendActionWithIfCondition);
+ auto instructionLocation = programCounter++;
+ uint64_t actionWithoutFlags = consumeAction(m_bytecode, programCounter, instructionLocation);
+ uint64_t action = "" ? IfConditionFlag : 0) | actionWithoutFlags;
if (!m_topURLActions || matchesCondition(action, *m_topURLActions))
actions.add(action);
-
- programCounter += instructionSizeWithArguments(DFABytecodeInstruction::AppendAction);
- ASSERT(instructionSizeWithArguments(DFABytecodeInstruction::AppendAction) == instructionSizeWithArguments(DFABytecodeInstruction::AppendActionWithIfCondition));
}
-void DFABytecodeInterpreter::interpretTestFlagsAndAppendAction(uint32_t& programCounter, uint16_t flags, Actions& actions, bool ifCondition)
+void DFABytecodeInterpreter::interpretTestFlagsAndAppendAction(uint32_t& programCounter, ResourceFlags flags, Actions& actions, bool ifCondition)
{
- ASSERT(getInstruction(m_bytecode, m_bytecodeLength, programCounter) == DFABytecodeInstruction::TestFlagsAndAppendAction
- || getInstruction(m_bytecode, m_bytecodeLength, programCounter) == DFABytecodeInstruction::TestFlagsAndAppendActionWithIfCondition);
- uint16_t flagsToCheck = getBits<uint16_t>(m_bytecode, m_bytecodeLength, programCounter + sizeof(DFABytecodeInstruction));
+ auto instructionLocation = programCounter;
+ auto flagsToCheck = consumeResourceFlagsAndInstruction(m_bytecode, programCounter);
- uint16_t loadTypeFlags = flagsToCheck & LoadTypeMask;
- uint16_t loadContextFlags = flagsToCheck & LoadContextMask;
- uint16_t resourceTypeFlags = flagsToCheck & ResourceTypeMask;
+ ResourceFlags loadTypeFlags = flagsToCheck & LoadTypeMask;
+ ResourceFlags loadContextFlags = flagsToCheck & LoadContextMask;
+ ResourceFlags resourceTypeFlags = flagsToCheck & ResourceTypeMask;
bool loadTypeMatches = loadTypeFlags ? (loadTypeFlags & flags) : true;
bool loadContextMatches = loadContextFlags ? (loadContextFlags & flags) : true;
bool resourceTypeMatches = resourceTypeFlags ? (resourceTypeFlags & flags) : true;
+ auto actionWithoutFlags = consumeAction(m_bytecode, programCounter, instructionLocation);
if (loadTypeMatches && loadContextMatches && resourceTypeMatches) {
- uint64_t actionAndFlags = (ifCondition ? IfConditionFlag : 0) | (static_cast<uint64_t>(flagsToCheck) << 32) | static_cast<uint64_t>(getBits<uint32_t>(m_bytecode, m_bytecodeLength, programCounter + sizeof(DFABytecodeInstruction) + sizeof(uint16_t)));
+ uint64_t actionAndFlags = (ifCondition ? IfConditionFlag : 0) | (static_cast<uint64_t>(flagsToCheck) << 32) | static_cast<uint64_t>(actionWithoutFlags);
if (!m_topURLActions || matchesCondition(actionAndFlags, *m_topURLActions))
actions.add(actionAndFlags);
}
- programCounter += instructionSizeWithArguments(DFABytecodeInstruction::TestFlagsAndAppendAction);
- ASSERT(instructionSizeWithArguments(DFABytecodeInstruction::TestFlagsAndAppendAction) == instructionSizeWithArguments(DFABytecodeInstruction::TestFlagsAndAppendActionWithIfCondition));
}
template<bool caseSensitive>
inline void DFABytecodeInterpreter::interpetJumpTable(const char* url, uint32_t& urlIndex, uint32_t& programCounter, bool& urlIndexIsAfterEndOfString)
{
- DFABytecodeJumpSize jumpSize = getJumpSize(m_bytecode, m_bytecodeLength, programCounter);
+ DFABytecodeJumpSize jumpSize = getJumpSize(m_bytecode, programCounter);
char character = caseSensitive ? url[urlIndex] : toASCIILower(url[urlIndex]);
- uint8_t firstCharacter = getBits<uint8_t>(m_bytecode, m_bytecodeLength, programCounter + sizeof(DFABytecodeInstruction));
- uint8_t lastCharacter = getBits<uint8_t>(m_bytecode, m_bytecodeLength, programCounter + sizeof(DFABytecodeInstruction) + sizeof(uint8_t));
+ uint8_t firstCharacter = getBits<uint8_t>(m_bytecode, programCounter + sizeof(DFABytecodeInstruction));
+ uint8_t lastCharacter = getBits<uint8_t>(m_bytecode, programCounter + sizeof(DFABytecodeInstruction) + sizeof(uint8_t));
if (character >= firstCharacter && character <= lastCharacter) {
uint32_t startOffset = programCounter + sizeof(DFABytecodeInstruction) + 2 * sizeof(uint8_t);
uint32_t jumpLocation = startOffset + (character - firstCharacter) * jumpSizeInBytes(jumpSize);
- programCounter += getJumpDistance(m_bytecode, m_bytecodeLength, jumpLocation, jumpSize);
+ programCounter += getJumpDistance(m_bytecode, jumpLocation, jumpSize);
if (!character)
urlIndexIsAfterEndOfString = true;
urlIndex++; // This represents an edge in the DFA.
@@ -147,40 +237,41 @@
programCounter += sizeof(DFABytecodeInstruction) + 2 * sizeof(uint8_t) + jumpSizeInBytes(jumpSize) * (lastCharacter - firstCharacter + 1);
}
-DFABytecodeInterpreter::Actions DFABytecodeInterpreter::actionsMatchingEverything()
+auto DFABytecodeInterpreter::actionsMatchingEverything() -> Actions
{
Actions actions;
// DFA header.
- uint32_t dfaBytecodeLength = getBits<uint32_t>(m_bytecode, m_bytecodeLength, 0);
- uint32_t programCounter = sizeof(uint32_t);
+ uint32_t dfaBytecodeLength = getBits<uint32_t>(m_bytecode, 0);
+ uint32_t programCounter = sizeof(DFAHeader);
while (programCounter < dfaBytecodeLength) {
- DFABytecodeInstruction instruction = getInstruction(m_bytecode, m_bytecodeLength, programCounter);
+ DFABytecodeInstruction instruction = getInstruction(m_bytecode, programCounter);
if (instruction == DFABytecodeInstruction::AppendAction)
interpretAppendAction(programCounter, actions, false);
else if (instruction == DFABytecodeInstruction::AppendActionWithIfCondition)
interpretAppendAction(programCounter, actions, true);
- else if (instruction == DFABytecodeInstruction::TestFlagsAndAppendAction)
- programCounter += instructionSizeWithArguments(DFABytecodeInstruction::TestFlagsAndAppendAction);
- else if (instruction == DFABytecodeInstruction::TestFlagsAndAppendActionWithIfCondition)
- programCounter += instructionSizeWithArguments(DFABytecodeInstruction::TestFlagsAndAppendActionWithIfCondition);
- else
+ else if (instruction == DFABytecodeInstruction::TestFlagsAndAppendAction
+ || instruction == DFABytecodeInstruction::TestFlagsAndAppendActionWithIfCondition) {
+ auto programCounterAtInstruction = programCounter;
+ consumeResourceFlagsAndInstruction(m_bytecode, programCounter);
+ consumeAction(m_bytecode, programCounter, programCounterAtInstruction);
+ } else
break;
}
return actions;
}
-DFABytecodeInterpreter::Actions DFABytecodeInterpreter::interpretWithConditions(const CString& urlCString, uint16_t flags, const DFABytecodeInterpreter::Actions& topURLActions)
+auto DFABytecodeInterpreter::interpretWithConditions(const CString& urlCString, ResourceFlags flags, const Actions& topURLActions) -> Actions
{
ASSERT(!m_topURLActions);
m_topURLActions = &topURLActions;
- DFABytecodeInterpreter::Actions actions = interpret(urlCString, flags);
+ auto actions = interpret(urlCString, flags);
m_topURLActions = nullptr;
return actions;
}
-DFABytecodeInterpreter::Actions DFABytecodeInterpreter::interpret(const CString& urlCString, uint16_t flags)
+auto DFABytecodeInterpreter::interpret(const CString& urlCString, ResourceFlags flags) -> Actions
{
const char* url = ""
ASSERT(url);
@@ -188,22 +279,21 @@
Actions actions;
uint32_t programCounter = 0;
- while (programCounter < m_bytecodeLength) {
+ while (programCounter < m_bytecode.size()) {
// DFA header.
uint32_t dfaStart = programCounter;
- uint32_t dfaBytecodeLength = getBits<uint32_t>(m_bytecode, m_bytecodeLength, programCounter);
+ uint32_t dfaBytecodeLength = getBits<uint32_t>(m_bytecode, programCounter);
programCounter += sizeof(uint32_t);
// Skip the actions without flags on the DFA root. These are accessed via actionsMatchingEverything.
if (!dfaStart) {
while (programCounter < dfaBytecodeLength) {
- DFABytecodeInstruction instruction = getInstruction(m_bytecode, m_bytecodeLength, programCounter);
- if (instruction == DFABytecodeInstruction::AppendAction)
- programCounter += instructionSizeWithArguments(DFABytecodeInstruction::AppendAction);
- else if (instruction == DFABytecodeInstruction::AppendActionWithIfCondition)
- programCounter += instructionSizeWithArguments(DFABytecodeInstruction::AppendActionWithIfCondition);
- else if (instruction == DFABytecodeInstruction::TestFlagsAndAppendAction)
+ DFABytecodeInstruction instruction = getInstruction(m_bytecode, programCounter);
+ if (instruction == DFABytecodeInstruction::AppendAction || instruction == DFABytecodeInstruction::AppendActionWithIfCondition) {
+ auto instructionLocation = programCounter++;
+ consumeAction(m_bytecode, programCounter, instructionLocation);
+ } else if (instruction == DFABytecodeInstruction::TestFlagsAndAppendAction)
interpretTestFlagsAndAppendAction(programCounter, flags, actions, false);
else if (instruction == DFABytecodeInstruction::TestFlagsAndAppendActionWithIfCondition)
interpretTestFlagsAndAppendAction(programCounter, flags, actions, true);
@@ -210,13 +300,13 @@
else
break;
}
- if (programCounter >= m_bytecodeLength)
+ if (programCounter >= m_bytecode.size())
return actions;
} else {
- ASSERT_WITH_MESSAGE(getInstruction(m_bytecode, m_bytecodeLength, programCounter) != DFABytecodeInstruction::AppendAction
- && getInstruction(m_bytecode, m_bytecodeLength, programCounter) != DFABytecodeInstruction::AppendActionWithIfCondition
- && getInstruction(m_bytecode, m_bytecodeLength, programCounter) != DFABytecodeInstruction::TestFlagsAndAppendAction
- && getInstruction(m_bytecode, m_bytecodeLength, programCounter) != DFABytecodeInstruction::TestFlagsAndAppendActionWithIfCondition,
+ ASSERT_WITH_MESSAGE(getInstruction(m_bytecode, programCounter) != DFABytecodeInstruction::AppendAction
+ && getInstruction(m_bytecode, programCounter) != DFABytecodeInstruction::AppendActionWithIfCondition
+ && getInstruction(m_bytecode, programCounter) != DFABytecodeInstruction::TestFlagsAndAppendAction
+ && getInstruction(m_bytecode, programCounter) != DFABytecodeInstruction::TestFlagsAndAppendActionWithIfCondition,
"Triggers that match everything should only be in the first DFA.");
}
@@ -225,8 +315,8 @@
uint32_t urlIndex = 0;
bool urlIndexIsAfterEndOfString = false;
while (true) {
- ASSERT(programCounter <= m_bytecodeLength);
- switch (getInstruction(m_bytecode, m_bytecodeLength, programCounter)) {
+ ASSERT(programCounter <= m_bytecode.size());
+ switch (getInstruction(m_bytecode, programCounter)) {
case DFABytecodeInstruction::Terminate:
goto nextDFA;
@@ -237,10 +327,10 @@
// Check to see if the next character in the url is the value stored with the bytecode.
char character = url[urlIndex];
- DFABytecodeJumpSize jumpSize = getJumpSize(m_bytecode, m_bytecodeLength, programCounter);
- if (character == getBits<uint8_t>(m_bytecode, m_bytecodeLength, programCounter + sizeof(DFABytecodeInstruction))) {
+ DFABytecodeJumpSize jumpSize = getJumpSize(m_bytecode, programCounter);
+ if (character == getBits<uint8_t>(m_bytecode, programCounter + sizeof(DFABytecodeInstruction))) {
uint32_t jumpLocation = programCounter + sizeof(DFABytecodeInstruction) + sizeof(uint8_t);
- programCounter += getJumpDistance(m_bytecode, m_bytecodeLength, jumpLocation, jumpSize);
+ programCounter += getJumpDistance(m_bytecode, jumpLocation, jumpSize);
if (!character)
urlIndexIsAfterEndOfString = true;
urlIndex++; // This represents an edge in the DFA.
@@ -255,10 +345,10 @@
// Check to see if the next character in the url is the value stored with the bytecode.
char character = toASCIILower(url[urlIndex]);
- DFABytecodeJumpSize jumpSize = getJumpSize(m_bytecode, m_bytecodeLength, programCounter);
- if (character == getBits<uint8_t>(m_bytecode, m_bytecodeLength, programCounter + sizeof(DFABytecodeInstruction))) {
+ DFABytecodeJumpSize jumpSize = getJumpSize(m_bytecode, programCounter);
+ if (character == getBits<uint8_t>(m_bytecode, programCounter + sizeof(DFABytecodeInstruction))) {
uint32_t jumpLocation = programCounter + sizeof(DFABytecodeInstruction) + sizeof(uint8_t);
- programCounter += getJumpDistance(m_bytecode, m_bytecodeLength, jumpLocation, jumpSize);
+ programCounter += getJumpDistance(m_bytecode, jumpLocation, jumpSize);
if (!character)
urlIndexIsAfterEndOfString = true;
urlIndex++; // This represents an edge in the DFA.
@@ -285,11 +375,11 @@
goto nextDFA;
char character = url[urlIndex];
- DFABytecodeJumpSize jumpSize = getJumpSize(m_bytecode, m_bytecodeLength, programCounter);
- if (character >= getBits<uint8_t>(m_bytecode, m_bytecodeLength, programCounter + sizeof(DFABytecodeInstruction))
- && character <= getBits<uint8_t>(m_bytecode, m_bytecodeLength, programCounter + sizeof(DFABytecodeInstruction) + sizeof(uint8_t))) {
+ DFABytecodeJumpSize jumpSize = getJumpSize(m_bytecode, programCounter);
+ if (character >= getBits<uint8_t>(m_bytecode, programCounter + sizeof(DFABytecodeInstruction))
+ && character <= getBits<uint8_t>(m_bytecode, programCounter + sizeof(DFABytecodeInstruction) + sizeof(uint8_t))) {
uint32_t jumpLocation = programCounter + sizeof(DFABytecodeInstruction) + 2 * sizeof(uint8_t);
- programCounter += getJumpDistance(m_bytecode, m_bytecodeLength, jumpLocation, jumpSize);
+ programCounter += getJumpDistance(m_bytecode, jumpLocation, jumpSize);
if (!character)
urlIndexIsAfterEndOfString = true;
urlIndex++; // This represents an edge in the DFA.
@@ -303,11 +393,11 @@
goto nextDFA;
char character = toASCIILower(url[urlIndex]);
- DFABytecodeJumpSize jumpSize = getJumpSize(m_bytecode, m_bytecodeLength, programCounter);
- if (character >= getBits<uint8_t>(m_bytecode, m_bytecodeLength, programCounter + sizeof(DFABytecodeInstruction))
- && character <= getBits<uint8_t>(m_bytecode, m_bytecodeLength, programCounter + sizeof(DFABytecodeInstruction) + sizeof(uint8_t))) {
+ DFABytecodeJumpSize jumpSize = getJumpSize(m_bytecode, programCounter);
+ if (character >= getBits<uint8_t>(m_bytecode, programCounter + sizeof(DFABytecodeInstruction))
+ && character <= getBits<uint8_t>(m_bytecode, programCounter + sizeof(DFABytecodeInstruction) + sizeof(uint8_t))) {
uint32_t jumpLocation = programCounter + sizeof(DFABytecodeInstruction) + 2 * sizeof(uint8_t);
- programCounter += getJumpDistance(m_bytecode, m_bytecodeLength, jumpLocation, jumpSize);
+ programCounter += getJumpDistance(m_bytecode, jumpLocation, jumpSize);
if (!character)
urlIndexIsAfterEndOfString = true;
urlIndex++; // This represents an edge in the DFA.
@@ -321,8 +411,8 @@
goto nextDFA;
uint32_t jumpLocation = programCounter + sizeof(DFABytecodeInstruction);
- DFABytecodeJumpSize jumpSize = getJumpSize(m_bytecode, m_bytecodeLength, programCounter);
- programCounter += getJumpDistance(m_bytecode, m_bytecodeLength, jumpLocation, jumpSize);
+ DFABytecodeJumpSize jumpSize = getJumpSize(m_bytecode, programCounter);
+ programCounter += getJumpDistance(m_bytecode, jumpLocation, jumpSize);
urlIndex++; // This represents an edge in the DFA.
break;
}
@@ -357,8 +447,6 @@
return actions;
}
-} // namespace ContentExtensions
-
-} // namespace WebCore
+} // namespace WebCore::ContentExtensions
#endif // ENABLE(CONTENT_EXTENSIONS)
Modified: trunk/Source/WebCore/contentextensions/DFABytecodeInterpreter.h (286382 => 286383)
--- trunk/Source/WebCore/contentextensions/DFABytecodeInterpreter.h 2021-12-01 21:25:07 UTC (rev 286382)
+++ trunk/Source/WebCore/contentextensions/DFABytecodeInterpreter.h 2021-12-01 21:31:04 UTC (rev 286383)
@@ -33,37 +33,30 @@
#include <wtf/DataLog.h>
#include <wtf/HashSet.h>
-namespace WebCore {
-
-namespace ContentExtensions {
+namespace WebCore::ContentExtensions {
-class WEBCORE_EXPORT DFABytecodeInterpreter {
+class DFABytecodeInterpreter {
public:
- DFABytecodeInterpreter(const DFABytecode* bytecode, unsigned bytecodeLength)
- : m_bytecode(bytecode)
- , m_bytecodeLength(bytecodeLength)
- {
- }
-
- typedef HashSet<uint64_t, DefaultHash<uint64_t>, WTF::UnsignedWithZeroKeyHashTraits<uint64_t>> Actions;
-
- Actions interpret(const CString&, uint16_t flags);
- Actions interpretWithConditions(const CString&, uint16_t flags, const DFABytecodeInterpreter::Actions& conditionActions);
+ DFABytecodeInterpreter(Span<const uint8_t> bytecode)
+ : m_bytecode(bytecode) { }
+
+ using Actions = HashSet<uint64_t, DefaultHash<uint64_t>, WTF::UnsignedWithZeroKeyHashTraits<uint64_t>>;
+
+ WEBCORE_EXPORT Actions interpret(const CString&, ResourceFlags);
+ Actions interpretWithConditions(const CString&, ResourceFlags, const Actions& conditionActions);
Actions actionsMatchingEverything();
private:
void interpretAppendAction(unsigned& programCounter, Actions&, bool ifCondition);
- void interpretTestFlagsAndAppendAction(unsigned& programCounter, uint16_t flags, Actions&, bool ifCondition);
+ void interpretTestFlagsAndAppendAction(unsigned& programCounter, ResourceFlags, Actions&, bool ifCondition);
template<bool caseSensitive>
void interpetJumpTable(const char* url, uint32_t& urlIndex, uint32_t& programCounter, bool& urlIndexIsAfterEndOfString);
- const DFABytecode* m_bytecode;
- const unsigned m_bytecodeLength;
+ const Span<const uint8_t> m_bytecode;
const DFABytecodeInterpreter::Actions* m_topURLActions { nullptr };
};
-} // namespace ContentExtensions
-} // namespace WebCore
+} // namespace WebCore::ContentExtensions
#endif // ENABLE(CONTENT_EXTENSIONS)
Modified: trunk/Source/WebCore/loader/PingLoader.cpp (286382 => 286383)
--- trunk/Source/WebCore/loader/PingLoader.cpp 2021-12-01 21:25:07 UTC (rev 286382)
+++ trunk/Source/WebCore/loader/PingLoader.cpp 2021-12-01 21:31:04 UTC (rev 286383)
@@ -159,7 +159,7 @@
ResourceRequest request(reportURL);
#if ENABLE(CONTENT_EXTENSIONS)
- if (processContentRuleListsForLoad(frame, request, ContentExtensions::ResourceType::Other))
+ if (processContentRuleListsForLoad(frame, request, ContentExtensions::ResourceType::CSPReport))
return;
#endif
Modified: trunk/Source/WebCore/loader/ResourceLoadInfo.cpp (286382 => 286383)
--- trunk/Source/WebCore/loader/ResourceLoadInfo.cpp 2021-12-01 21:25:07 UTC (rev 286382)
+++ trunk/Source/WebCore/loader/ResourceLoadInfo.cpp 2021-12-01 21:31:04 UTC (rev 286383)
@@ -32,8 +32,7 @@
#include "RegistrableDomain.h"
#include "SecurityOrigin.h"
-namespace WebCore {
-namespace ContentExtensions {
+namespace WebCore::ContentExtensions {
OptionSet<ResourceType> toResourceType(CachedResource::Type type, ResourceRequestBase::Requester requester)
{
@@ -98,13 +97,13 @@
if (name == "font")
return { ResourceType::Font };
if (name == "raw")
- return {{ ResourceType::Fetch, ResourceType::WebSocket, ResourceType::Other, ResourceType::Ping }};
+ return { { ResourceType::Fetch, ResourceType::WebSocket, ResourceType::Other, ResourceType::Ping } };
if (name == "websocket")
return { ResourceType::WebSocket };
if (name == "fetch")
return { ResourceType::Fetch };
if (name == "other")
- return {{ ResourceType::Other, ResourceType::Ping }};
+ return { { ResourceType::Other, ResourceType::Ping, ResourceType::CSPReport } };
if (name == "svg-document")
return { ResourceType::SVGDocument };
if (name == "media")
@@ -113,6 +112,8 @@
return { ResourceType::Popup };
if (name == "ping")
return { ResourceType::Ping };
+ if (name == "csp-report")
+ return { ResourceType::CSPReport };
return std::nullopt;
}
@@ -149,7 +150,6 @@
return flags;
}
-} // namespace ContentExtensions
-} // namespace WebCore
+} // namespace WebCore::ContentExtensions
#endif // ENABLE(CONTENT_EXTENSIONS)
Modified: trunk/Source/WebCore/loader/ResourceLoadInfo.h (286382 => 286383)
--- trunk/Source/WebCore/loader/ResourceLoadInfo.h 2021-12-01 21:25:07 UTC (rev 286382)
+++ trunk/Source/WebCore/loader/ResourceLoadInfo.h 2021-12-01 21:31:04 UTC (rev 286383)
@@ -31,10 +31,9 @@
#include <wtf/OptionSet.h>
#include <wtf/URL.h>
-namespace WebCore {
-namespace ContentExtensions {
+namespace WebCore::ContentExtensions {
-enum class ResourceType : uint16_t {
+enum class ResourceType : uint32_t {
Document = 0x0001,
Image = 0x0002,
StyleSheet = 0x0004,
@@ -47,36 +46,37 @@
Fetch = 0x0200,
WebSocket = 0x0400,
Other = 0x0800,
+ CSPReport = 0x10000,
};
-const uint16_t ResourceTypeMask = 0x0FFF;
+static constexpr uint32_t ResourceTypeMask = 0x10FFF;
-enum class LoadType : uint16_t {
+enum class LoadType : uint32_t {
FirstParty = 0x1000,
ThirdParty = 0x2000,
};
-const uint16_t LoadTypeMask = 0x3000;
+static constexpr uint32_t LoadTypeMask = 0x3000;
-enum class LoadContext : uint16_t {
+enum class LoadContext : uint32_t {
TopFrame = 0x4000,
ChildFrame = 0x8000,
};
-const uint16_t LoadContextMask = 0xC000;
+static constexpr uint32_t LoadContextMask = 0xC000;
-static_assert(!(ResourceTypeMask & LoadTypeMask), "ResourceTypeMask and LoadTypeMask should be mutually exclusive because they are stored in the same uint16_t");
-static_assert(!(ResourceTypeMask & LoadContextMask), "ResourceTypeMask and LoadContextMask should be mutually exclusive because they are stored in the same uint16_t");
-static_assert(!(LoadContextMask & LoadTypeMask), "LoadContextMask and LoadTypeMask should be mutually exclusive because they are stored in the same uint16_t");
+static_assert(!(ResourceTypeMask & LoadTypeMask), "ResourceTypeMask and LoadTypeMask should be mutually exclusive because they are stored in the same uint32_t");
+static_assert(!(ResourceTypeMask & LoadContextMask), "ResourceTypeMask and LoadContextMask should be mutually exclusive because they are stored in the same uint32_t");
+static_assert(!(LoadContextMask & LoadTypeMask), "LoadContextMask and LoadTypeMask should be mutually exclusive because they are stored in the same uint32_t");
-typedef uint16_t ResourceFlags;
+using ResourceFlags = uint32_t;
// The first 32 bits of a uint64_t action are used for the action location.
-// The next 16 bits are used for the flags (ResourceType and LoadType).
+// The next 24 bits are used for the flags (ResourceType and LoadType).
// The next bit is used to mark actions that are from a rule with an if-domain.
// Actions from rules with unless-domain conditions are distinguished from
// rules with if-domain conditions by not having this bit set.
// Actions from rules with no conditions are put in the DFA without conditions.
// The values -1 and -2 are used for removed and empty values in HashTables.
-const uint64_t ActionFlagMask = 0x0000FFFF00000000;
-const uint64_t IfConditionFlag = 0x0001000000000000;
+static constexpr uint64_t ActionFlagMask = 0x00FFFFFF00000000;
+static constexpr uint64_t IfConditionFlag = 0x0100000000000000;
OptionSet<ResourceType> toResourceType(CachedResource::Type, ResourceRequestBase::Requester);
std::optional<OptionSet<ResourceType>> readResourceType(StringView);
@@ -93,7 +93,6 @@
ResourceFlags getResourceFlags() const;
};
-} // namespace ContentExtensions
-} // namespace WebCore
+} // namespace WebCore::ContentExtensions
#endif
Modified: trunk/Tools/ChangeLog (286382 => 286383)
--- trunk/Tools/ChangeLog 2021-12-01 21:25:07 UTC (rev 286382)
+++ trunk/Tools/ChangeLog 2021-12-01 21:31:04 UTC (rev 286383)
@@ -1,3 +1,17 @@
+2021-12-01 Alex Christensen <[email protected]>
+
+ Add csp-report resource type to WKContentRuleList
+ https://bugs.webkit.org/show_bug.cgi?id=233675
+ <rdar://71869893>
+
+ Reviewed by Tim Hatcher.
+
+ * TestWebKitAPI/Tests/WebCore/ContentExtensions.cpp:
+ (TestWebKitAPI::compareContents):
+ (TestWebKitAPI::TEST_F):
+ * TestWebKitAPI/Tests/WebKitCocoa/ContentRuleListNotification.mm:
+ (TEST):
+
2021-12-01 Ryan Haddad <[email protected]>
[ iOS ] TestWebKitAPI.ApplicationManifest.IconCoding is a constant failure
Modified: trunk/Tools/TestWebKitAPI/Tests/WebCore/ContentExtensions.cpp (286382 => 286383)
--- trunk/Tools/TestWebKitAPI/Tests/WebCore/ContentExtensions.cpp 2021-12-01 21:25:07 UTC (rev 286382)
+++ trunk/Tools/TestWebKitAPI/Tests/WebCore/ContentExtensions.cpp 2021-12-01 21:31:04 UTC (rev 286383)
@@ -540,7 +540,7 @@
testRequest(backend, mainDocumentRequest("http://foo.orgg/"), { variantIndex<ContentExtensions::BlockLoadAction> });
}
-static void compareContents(const ContentExtensions::DFABytecodeInterpreter::Actions& a, const Vector<uint64_t>& b)
+static void compareContents(const DFABytecodeInterpreter::Actions& a, const Vector<uint64_t>& b)
{
EXPECT_EQ(a.size(), b.size());
for (unsigned i = 0; i < b.size(); ++i)
@@ -562,7 +562,7 @@
Vector<ContentExtensions::DFABytecode> bytecode;
ContentExtensions::DFABytecodeCompiler compiler(dfa, bytecode);
compiler.compile();
- ContentExtensions::DFABytecodeInterpreter interpreter(bytecode.data(), bytecode.size());
+ DFABytecodeInterpreter interpreter({ bytecode.data(), bytecode.size() });
compareContents(interpreter.interpret("foo.org", 0), { 0 });
compareContents(interpreter.interpret("ba.org", 0), { 0 });
compareContents(interpreter.interpret("bar.org", 0), { });
@@ -588,7 +588,7 @@
Vector<ContentExtensions::DFABytecode> bytecode;
ContentExtensions::DFABytecodeCompiler compiler(dfa, bytecode);
compiler.compile();
- ContentExtensions::DFABytecodeInterpreter interpreter(bytecode.data(), bytecode.size());
+ DFABytecodeInterpreter interpreter({ bytecode.data(), bytecode.size() });
compareContents(interpreter.interpret("foo.org", 0), { 0 });
compareContents(interpreter.interpret("ba.org", 0), { 1 });
compareContents(interpreter.interpret("bar.org", 0), { });
@@ -971,9 +971,9 @@
ASSERT_EQ(sequenceInstances(data.actions, "GGG"), 1);
ASSERT_EQ(data.actions.size(), 78u);
- ASSERT_EQ(data.filtersWithoutConditions.size(), 313u);
- ASSERT_EQ(data.filtersWithConditions.size(), 5u);
- ASSERT_EQ(data.topURLFilters.size(), 5u);
+ ASSERT_EQ(data.filtersWithoutConditions.size(), 288u);
+ ASSERT_EQ(data.filtersWithConditions.size(), 5u);
+ ASSERT_EQ(data.topURLFilters.size(), 5u);
ASSERT_FALSE(data.conditionsApplyOnlyToDomain);
auto extensionWithFlags = InMemoryCompiledContentExtension::create("["
@@ -1108,7 +1108,7 @@
Vector<ContentExtensions::DFABytecode> bytecode;
ContentExtensions::DFABytecodeCompiler compiler(dfa, bytecode);
compiler.compile();
- ContentExtensions::DFABytecodeInterpreter interpreter(bytecode.data(), bytecode.size());
+ DFABytecodeInterpreter interpreter({ bytecode.data(), bytecode.size() });
compareContents(interpreter.interpret("eb", 0), { });
compareContents(interpreter.interpret("we", 0), { });
compareContents(interpreter.interpret("weeb", 0), { });
@@ -1267,7 +1267,7 @@
combinedBytecode.appendVector(bytecode);
}
- ContentExtensions::DFABytecodeInterpreter interpreter(&combinedBytecode[0], combinedBytecode.size());
+ DFABytecodeInterpreter interpreter({ combinedBytecode.data(), combinedBytecode.size() });
patternId = 0;
for (char c1 = 'A'; c1 <= 'Z'; ++c1) {
@@ -1708,7 +1708,7 @@
combinedBytecode.appendVector(bytecode);
}
- ContentExtensions::DFABytecodeInterpreter interpreter(&combinedBytecode[0], combinedBytecode.size());
+ DFABytecodeInterpreter interpreter({ combinedBytecode.data(), combinedBytecode.size() });
EXPECT_EQ(interpreter.interpret("ABBBX", 0).size(), 1ull);
EXPECT_EQ(interpreter.interpret("ACCCX", 0).size(), 1ull);
Modified: trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/ContentRuleListNotification.mm (286382 => 286383)
--- trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/ContentRuleListNotification.mm 2021-12-01 21:25:07 UTC (rev 286382)
+++ trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/ContentRuleListNotification.mm 2021-12-01 21:31:04 UTC (rev 286383)
@@ -416,6 +416,26 @@
EXPECT_WK_STREQ([webView _test_waitForAlert], "iframe fetched successfully");
}
+TEST(ContentRuleList, CSPReport)
+{
+ TestWebKitAPI::HTTPServer server({ { "/", { {
+ { "Content-Security-Policy", "frame-src 'none'; report-uri resources/save-report.py" }
+ }, "<iframe src="" } } });
+
+ auto configuration = adoptNS([WKWebViewConfiguration new]);
+ [[configuration userContentController] addContentRuleList:makeContentRuleList(@"[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\".*\",\"resource-type\":[\"csp-report\"]}}]").get()];
+ auto webView = adoptNS([[WKWebView alloc] initWithFrame:NSZeroRect configuration:configuration.get()]);
+ auto delegate = adoptNS([ContentRuleListNotificationDelegate new]);
+ [webView setNavigationDelegate:delegate.get()];
+ [webView loadRequest:server.request()];
+ while (notificationList.isEmpty())
+ TestWebKitAPI::Util::spinRunLoop();
+
+ URL expectedURL = server.request().URL;
+ expectedURL.setPath("/resources/save-report.py");
+ EXPECT_STREQ(expectedURL.string().utf8().data(), notificationList.first().url.utf8().data());
+}
+
TEST(ContentRuleList, LegacyVersionAndName)
{
NSString *directory = [NSTemporaryDirectory() stringByAppendingPathComponent:@"ContentRuleListTestDirectory"];
Modified: trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/WKContentExtensionStore.mm (286382 => 286383)
--- trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/WKContentExtensionStore.mm 2021-12-01 21:25:07 UTC (rev 286382)
+++ trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/WKContentExtensionStore.mm 2021-12-01 21:31:04 UTC (rev 286383)
@@ -252,7 +252,7 @@
NSData *data = "" dataWithContentsOfURL:[tempDir URLByAppendingPathComponent:fileName]];
EXPECT_NOT_NULL(data);
- EXPECT_EQ(data.length, 228u);
+ EXPECT_EQ(data.length, 225u);
__block bool doneCheckingSource = false;
[store _getContentRuleListSourceForIdentifier:identifier completionHandler:^(NSString *source) {