Changeset 286383 in webkit


Ignore:
Timestamp:
Dec 1, 2021 1:31:04 PM (2 years ago)
Author:
achristensen@apple.com
Message:

Add csp-report resource type to WKContentRuleList
https://bugs.webkit.org/show_bug.cgi?id=233675
<rdar://71869893>

Reviewed by Tim Hatcher.

Source/WebCore:

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:

Tools:

  • TestWebKitAPI/Tests/WebCore/ContentExtensions.cpp:

(TestWebKitAPI::compareContents):
(TestWebKitAPI::TEST_F):

  • TestWebKitAPI/Tests/WebKitCocoa/ContentRuleListNotification.mm:

(TEST):

Location:
trunk
Files:
14 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/ChangeLog

    r286379 r286383  
     12021-12-01  Alex Christensen  <achristensen@webkit.org>
     2
     3        Add csp-report resource type to WKContentRuleList
     4        https://bugs.webkit.org/show_bug.cgi?id=233675
     5        <rdar://71869893>
     6
     7        Reviewed by Tim Hatcher.
     8
     9        This feature is trivial to implement and test except for one small thing: we use a uint16_t to represent the
     10        resource type and context and first party flags, and we already have 16 of them.  So we needed to get another
     11        bit from somewhere.  What I did was make the flags have a variable length from 1-3 bytes instead of just 2 bytes.
     12        I used the unused upper bits in the instruction to indicate the length of the flags, and if the upper bits were 0,
     13        then I assume it was 2 bytes, which is binary compatible with existing compiled WKContentRuleLists, so no need
     14        to increment the version number and force a recompile.  It worked so well that I did the same thing with the actions,
     15        which were 4 bytes but are now 1-4 bytes.  This reduced the compiled binary size of one of the tests from 313 bytes
     16        to 288 bytes, a reduction of about 8% of the binary size of the compiled WKContentRuleLists.  Larger lists will see
     17        slightly less binary size reduction, but still an improvement.
     18
     19        * contentextensions/ContentExtension.cpp:
     20        (WebCore::ContentExtensions::ContentExtension::ContentExtension):
     21        (WebCore::ContentExtensions::ContentExtension::populateConditionCacheIfNeeded):
     22        * contentextensions/ContentExtensionsBackend.cpp:
     23        (WebCore::ContentExtensions::ContentExtensionsBackend::actionsForResourceLoad const):
     24        * contentextensions/DFABytecode.h:
     25        (WebCore::ContentExtensions::smallestPossibleJumpSize):
     26        (): Deleted.
     27        (WebCore::ContentExtensions::instructionSizeWithArguments): Deleted.
     28        * contentextensions/DFABytecodeCompiler.cpp:
     29        (WebCore::ContentExtensions::append):
     30        (WebCore::ContentExtensions::append24BitInteger):
     31        (WebCore::ContentExtensions::appendZeroes):
     32        (WebCore::ContentExtensions::setBits):
     33        (WebCore::ContentExtensions::bytecodeFlagsSize):
     34        (WebCore::ContentExtensions::bytecodeActionSize):
     35        (WebCore::ContentExtensions::appendVariableLengthInteger):
     36        (WebCore::ContentExtensions::DFABytecodeCompiler::emitAppendAction):
     37        (WebCore::ContentExtensions::DFABytecodeCompiler::emitJump):
     38        (WebCore::ContentExtensions::DFABytecodeCompiler::emitCheckValue):
     39        (WebCore::ContentExtensions::DFABytecodeCompiler::emitCheckValueRange):
     40        (WebCore::ContentExtensions::DFABytecodeCompiler::transitions):
     41        (WebCore::ContentExtensions::DFABytecodeCompiler::compileJumpTable):
     42        (WebCore::ContentExtensions::DFABytecodeCompiler::nodeTransitionsMaxBytecodeSize):
     43        (WebCore::ContentExtensions::DFABytecodeCompiler::compile):
     44        * contentextensions/DFABytecodeInterpreter.cpp:
     45        (WebCore::ContentExtensions::getBits):
     46        (WebCore::ContentExtensions::get24Bits):
     47        (WebCore::ContentExtensions::getInstruction):
     48        (WebCore::ContentExtensions::jumpSizeInBytes):
     49        (WebCore::ContentExtensions::consumeInteger):
     50        (WebCore::ContentExtensions::consume24BitInteger):
     51        (WebCore::ContentExtensions::hasFlags):
     52        (WebCore::ContentExtensions::hasAction):
     53        (WebCore::ContentExtensions::consumeResourceFlagsAndInstruction):
     54        (WebCore::ContentExtensions::consumeAction):
     55        (WebCore::ContentExtensions::getJumpSize):
     56        (WebCore::ContentExtensions::getJumpDistance):
     57        (WebCore::ContentExtensions::matchesCondition):
     58        (WebCore::ContentExtensions::DFABytecodeInterpreter::interpretAppendAction):
     59        (WebCore::ContentExtensions::DFABytecodeInterpreter::interpretTestFlagsAndAppendAction):
     60        (WebCore::ContentExtensions::DFABytecodeInterpreter::interpetJumpTable):
     61        (WebCore::ContentExtensions::DFABytecodeInterpreter::actionsMatchingEverything):
     62        (WebCore::ContentExtensions::DFABytecodeInterpreter::interpretWithConditions):
     63        (WebCore::ContentExtensions::DFABytecodeInterpreter::interpret):
     64        * contentextensions/DFABytecodeInterpreter.h:
     65        (WebCore::ContentExtensions::DFABytecodeInterpreter::DFABytecodeInterpreter):
     66        * loader/PingLoader.cpp:
     67        (WebCore::PingLoader::sendViolationReport):
     68        * loader/ResourceLoadInfo.cpp:
     69        (WebCore::ContentExtensions::readResourceType):
     70        * loader/ResourceLoadInfo.h:
     71
    1722021-12-01  Rob Buis  <rbuis@igalia.com>
    273
  • trunk/Source/WebCore/contentextensions/ContentExtension.cpp

    r286084 r286383  
    4747    , m_extensionBaseURL(WTFMove(extensionBaseURL))
    4848{
    49     DFABytecodeInterpreter withoutConditions(m_compiledExtension->filtersWithoutConditionsBytecode(), m_compiledExtension->filtersWithoutConditionsBytecodeLength());
    50     DFABytecodeInterpreter withConditions(m_compiledExtension->filtersWithConditionsBytecode(), m_compiledExtension->filtersWithConditionsBytecodeLength());
     49    DFABytecodeInterpreter withoutConditions({ m_compiledExtension->filtersWithoutConditionsBytecode(), m_compiledExtension->filtersWithoutConditionsBytecodeLength() });
     50    DFABytecodeInterpreter withConditions({ m_compiledExtension->filtersWithConditionsBytecode(), m_compiledExtension->filtersWithConditionsBytecodeLength() });
    5151    for (uint64_t action : withoutConditions.actionsMatchingEverything()) {
    5252        ASSERT(static_cast<uint32_t>(action) == action);
     
    124124{
    125125    if (m_cachedTopURL != topURL) {
    126         DFABytecodeInterpreter interpreter(m_compiledExtension->topURLFiltersBytecode(), m_compiledExtension->topURLFiltersBytecodeLength());
    127         constexpr uint16_t allLoadTypesAndResourceTypes = LoadTypeMask | ResourceTypeMask | LoadContextMask;
     126        DFABytecodeInterpreter interpreter({ m_compiledExtension->topURLFiltersBytecode(), m_compiledExtension->topURLFiltersBytecodeLength() });
     127        constexpr ResourceFlags allLoadTypesAndResourceTypes = LoadTypeMask | ResourceTypeMask | LoadContextMask;
    128128        String string = m_compiledExtension->conditionsApplyOnlyToDomain() ? topURL.host().toString() : topURL.string();
    129129        auto topURLActions = interpreter.interpret(string.utf8(), allLoadTypesAndResourceTypes);
  • trunk/Source/WebCore/contentextensions/ContentExtensionsBackend.cpp

    r286084 r286383  
    122122        const CompiledContentExtension& compiledExtension = contentExtension->compiledExtension();
    123123       
    124         DFABytecodeInterpreter withoutConditionsInterpreter(compiledExtension.filtersWithoutConditionsBytecode(), compiledExtension.filtersWithoutConditionsBytecodeLength());
     124        DFABytecodeInterpreter withoutConditionsInterpreter({ compiledExtension.filtersWithoutConditionsBytecode(), compiledExtension.filtersWithoutConditionsBytecodeLength() });
    125125        DFABytecodeInterpreter::Actions withoutConditionsActions = withoutConditionsInterpreter.interpret(urlCString, flags);
    126126       
    127127        URL topURL = resourceLoadInfo.mainDocumentURL;
    128         DFABytecodeInterpreter withConditionsInterpreter(compiledExtension.filtersWithConditionsBytecode(), compiledExtension.filtersWithConditionsBytecodeLength());
     128        DFABytecodeInterpreter withConditionsInterpreter({ compiledExtension.filtersWithConditionsBytecode(), compiledExtension.filtersWithConditionsBytecodeLength() });
    129129        DFABytecodeInterpreter::Actions withConditionsActions = withConditionsInterpreter.interpretWithConditions(urlCString, flags, contentExtension->topURLActions(topURL));
    130130       
  • trunk/Source/WebCore/contentextensions/DFABytecode.h

    r241316 r286383  
    2828#if ENABLE(CONTENT_EXTENSIONS)
    2929
    30 namespace WebCore {
    31    
    32 namespace ContentExtensions {
     30namespace WebCore::ContentExtensions {
    3331
    34 typedef uint8_t DFABytecode;
     32using DFABytecode = uint8_t;
    3533
    3634// Increment ContentExtensionStore::CurrentContentExtensionFileVersion
     
    6159
    6260    // AppendAction has one argument:
    63     // The action to append (4 bytes).
     61    // The action to append (1-4 bytes).
    6462    AppendAction = 0x6,
    6563    AppendActionWithIfCondition = 0x7,
    6664   
    6765    // TestFlagsAndAppendAction has two arguments:
    68     // The flags to check before appending (2 bytes).
    69     // The action to append (4 bytes).
     66    // The flags to check before appending (1-3 bytes).
     67    // The action to append (1-4 bytes).
    7068    TestFlagsAndAppendAction = 0x8,
    7169    TestFlagsAndAppendActionWithIfCondition = 0x9,
     
    8078
    8179// The last four bits contain the instruction type.
    82 const uint8_t DFABytecodeInstructionMask = 0x0F;
    83 const uint8_t DFABytecodeJumpSizeMask = 0xF0;
     80static constexpr uint8_t DFABytecodeInstructionMask = 0x0F;
     81static constexpr uint8_t DFABytecodeJumpSizeMask = 0xF0;
     82static constexpr uint8_t DFABytecodeFlagsSizeMask = 0x30;
     83static constexpr uint8_t DFABytecodeActionSizeMask = 0xC0;
    8484
    8585// DFA bytecode starts with a 4 byte header which contains the size of this DFA.
    86 typedef uint32_t DFAHeader;
     86using DFAHeader = uint32_t;
     87
     88// DFABytecodeFlagsSize and DFABytecodeActionSize are stored in the top four bits of the DFABytecodeInstructions that have flags and actions.
     89enum class DFABytecodeFlagsSize : uint8_t {
     90    UInt8 = 0x10,
     91    UInt16 = 0x00, // Needs to be zero to be binary compatible with bytecode compiled with fixed-size flags.
     92    UInt24 = 0x20,
     93};
     94enum class DFABytecodeActionSize : uint8_t {
     95    UInt8 = 0x40,
     96    UInt16 = 0x80,
     97    UInt24 = 0xC0,
     98    UInt32 = 0x00, // Needs to be zero to be binary compatible with bytecode compiled with fixed-size actions.
     99};
    87100
    88101// A DFABytecodeJumpSize is stored in the top four bits of the DFABytecodeInstructions that have a jump.
    89 enum DFABytecodeJumpSize {
     102enum class DFABytecodeJumpSize : uint8_t {
    90103    Int8 = 0x10,
    91104    Int16 = 0x20,
     
    93106    Int32 = 0x40,
    94107};
    95 const int32_t Int24Max = (1 << 23) - 1;
    96 const int32_t Int24Min = -(1 << 23);
     108static constexpr int32_t UInt24Max = (1 << 24) - 1;
     109static constexpr int32_t Int24Max = (1 << 23) - 1;
     110static constexpr int32_t Int24Min = -(1 << 23);
     111static constexpr size_t Int24Size = 3;
     112static constexpr size_t UInt24Size = 3;
    97113
    98114static inline DFABytecodeJumpSize smallestPossibleJumpSize(int32_t longestPossibleJump)
    99115{
    100116    if (longestPossibleJump <= std::numeric_limits<int8_t>::max() && longestPossibleJump >= std::numeric_limits<int8_t>::min())
    101         return Int8;
     117        return DFABytecodeJumpSize::Int8;
    102118    if (longestPossibleJump <= std::numeric_limits<int16_t>::max() && longestPossibleJump >= std::numeric_limits<int16_t>::min())
    103         return Int16;
     119        return DFABytecodeJumpSize::Int16;
    104120    if (longestPossibleJump <= Int24Max && longestPossibleJump >= Int24Min)
    105         return Int24;
    106     return Int32;
     121        return DFABytecodeJumpSize::Int24;
     122    return DFABytecodeJumpSize::Int32;
    107123}
    108    
    109 static inline size_t instructionSizeWithArguments(DFABytecodeInstruction instruction)
    110 {
    111     switch (instruction) {
    112     case DFABytecodeInstruction::CheckValueCaseSensitive:
    113     case DFABytecodeInstruction::CheckValueCaseInsensitive:
    114     case DFABytecodeInstruction::JumpTableCaseInsensitive:
    115     case DFABytecodeInstruction::JumpTableCaseSensitive:
    116     case DFABytecodeInstruction::CheckValueRangeCaseSensitive:
    117     case DFABytecodeInstruction::CheckValueRangeCaseInsensitive:
    118     case DFABytecodeInstruction::Jump:
    119         RELEASE_ASSERT_NOT_REACHED(); // Variable instruction size.
    120     case DFABytecodeInstruction::AppendAction:
    121     case DFABytecodeInstruction::AppendActionWithIfCondition:
    122         return sizeof(DFABytecodeInstruction) + sizeof(uint32_t);
    123     case DFABytecodeInstruction::TestFlagsAndAppendAction:
    124     case DFABytecodeInstruction::TestFlagsAndAppendActionWithIfCondition:
    125         return sizeof(DFABytecodeInstruction) + sizeof(uint16_t) + sizeof(uint32_t);
    126     case DFABytecodeInstruction::Terminate:
    127         return sizeof(DFABytecodeInstruction);
    128     }
    129     RELEASE_ASSERT_NOT_REACHED();
    130 }
    131    
    132 } // namespace ContentExtensions   
    133 } // namespace WebCore
     124
     125} // namespace WebCore::ContentExtensions
    134126
    135127#endif // ENABLE(CONTENT_EXTENSIONS)
  • trunk/Source/WebCore/contentextensions/DFABytecodeCompiler.cpp

    r275049 r286383  
    3333#include "DFANode.h"
    3434
    35 namespace WebCore {
    36    
    37 namespace ContentExtensions {
     35namespace WebCore::ContentExtensions {
    3836
    3937template <typename IntType>
    40 inline void append(Vector<DFABytecode>& bytecode, IntType value)
     38void append(Vector<DFABytecode>& bytecode, IntType value)
    4139{
    4240    bytecode.grow(bytecode.size() + sizeof(IntType));
     
    4442}
    4543
    46 inline void appendZeroes(Vector<DFABytecode>& bytecode, DFABytecodeJumpSize jumpSize)
     44static void append24BitUnsignedInteger(Vector<DFABytecode>& bytecode, uint32_t value)
     45{
     46    append<uint16_t>(bytecode, value);
     47    append<uint8_t>(bytecode, value >> 16);
     48}
     49
     50static void appendZeroes(Vector<DFABytecode>& bytecode, DFABytecodeJumpSize jumpSize)
    4751{
    4852    switch (jumpSize) {
     
    6468
    6569template <typename IntType>
    66 inline void setBits(Vector<DFABytecode>& bytecode, uint32_t index, IntType value)
     70void setBits(Vector<DFABytecode>& bytecode, uint32_t index, IntType value)
    6771{
    6872    RELEASE_ASSERT(index + sizeof(IntType) <= bytecode.size());
     
    7781    return sizeof(DFABytecodeInstruction) + sizeof(uint32_t);
    7882}
    79    
     83
     84static DFABytecodeFlagsSize bytecodeFlagsSize(ResourceFlags flags)
     85{
     86    if (flags <= std::numeric_limits<uint8_t>::max())
     87        return DFABytecodeFlagsSize::UInt8;
     88    if (flags <= std::numeric_limits<uint16_t>::max())
     89        return DFABytecodeFlagsSize::UInt16;
     90    RELEASE_ASSERT(flags <= UInt24Max);
     91    return DFABytecodeFlagsSize::UInt24;
     92}
     93
     94static DFABytecodeActionSize bytecodeActionSize(uint32_t actionWithoutFlags)
     95{
     96    if (actionWithoutFlags <= std::numeric_limits<uint8_t>::max())
     97        return DFABytecodeActionSize::UInt8;
     98    if (actionWithoutFlags <= std::numeric_limits<uint16_t>::max())
     99        return DFABytecodeActionSize::UInt16;
     100    if (actionWithoutFlags <= UInt24Max)
     101        return DFABytecodeActionSize::UInt24;
     102    return DFABytecodeActionSize::UInt32;
     103}
     104
     105static void appendVariableLengthUnsignedInteger(Vector<DFABytecode>& bytecode, uint32_t integer)
     106{
     107    if (integer <= std::numeric_limits<uint8_t>::max())
     108        return append<uint8_t>(bytecode, integer);
     109    if (integer <= std::numeric_limits<uint16_t>::max())
     110        return append<uint16_t>(bytecode, integer);
     111    if (integer <= UInt24Max)
     112        return append24BitUnsignedInteger(bytecode, integer);
     113    return append<uint32_t>(bytecode, integer);
     114}
     115
    80116void DFABytecodeCompiler::emitAppendAction(uint64_t action)
    81117{
     118    uint32_t actionWithoutFlags = action;
     119    auto actionSize = bytecodeActionSize(actionWithoutFlags);
     120   
    82121    // High bits are used to store flags. See compileRuleList.
    83     if (action & ActionFlagMask) {
    84         if (action & IfConditionFlag)
    85             append<DFABytecodeInstruction>(m_bytecode, DFABytecodeInstruction::TestFlagsAndAppendActionWithIfCondition);
    86         else
    87             append<DFABytecodeInstruction>(m_bytecode, DFABytecodeInstruction::TestFlagsAndAppendAction);
    88         append<uint16_t>(m_bytecode, static_cast<uint16_t>(action >> 32));
    89         append<uint32_t>(m_bytecode, static_cast<uint32_t>(action));
    90     } else {
    91         if (action & IfConditionFlag)
    92             append<DFABytecodeInstruction>(m_bytecode, DFABytecodeInstruction::AppendActionWithIfCondition);
    93         else
    94             append<DFABytecodeInstruction>(m_bytecode, DFABytecodeInstruction::AppendAction);
    95         append<uint32_t>(m_bytecode, static_cast<uint32_t>(action));
    96     }
     122    if (ResourceFlags flags = (action & ActionFlagMask) >> 32) {
     123        auto flagsSize = bytecodeFlagsSize(flags);
     124        auto instruction = (action & IfConditionFlag) ? DFABytecodeInstruction::TestFlagsAndAppendActionWithIfCondition : DFABytecodeInstruction::TestFlagsAndAppendAction;
     125        ASSERT(!(static_cast<uint8_t>(instruction) & static_cast<uint8_t>(flagsSize) & static_cast<uint8_t>(actionSize)));
     126        append<uint8_t>(m_bytecode, static_cast<uint8_t>(instruction) | static_cast<uint8_t>(flagsSize) | static_cast<uint8_t>(actionSize));
     127        appendVariableLengthUnsignedInteger(m_bytecode, flags);
     128        appendVariableLengthUnsignedInteger(m_bytecode, actionWithoutFlags);
     129        return;
     130    }
     131
     132    auto instruction = (action & IfConditionFlag) ? DFABytecodeInstruction::AppendActionWithIfCondition : DFABytecodeInstruction::AppendAction;
     133    ASSERT(!(static_cast<uint8_t>(instruction) & static_cast<uint8_t>(actionSize)));
     134    append<uint8_t>(m_bytecode, static_cast<uint8_t>(instruction) | static_cast<uint8_t>(actionSize));
     135    appendVariableLengthUnsignedInteger(m_bytecode, actionWithoutFlags);
    97136}
    98137
     
    120159    int32_t longestPossibleJumpDistance = longestPossibleJump(instructionLocation, sourceNodeIndex, destinationNodeIndex);
    121160    DFABytecodeJumpSize jumpSize = smallestPossibleJumpSize(longestPossibleJumpDistance);
    122     append<uint8_t>(m_bytecode, static_cast<uint8_t>(DFABytecodeInstruction::Jump) | jumpSize);
     161    append<uint8_t>(m_bytecode, static_cast<uint8_t>(DFABytecodeInstruction::Jump) | static_cast<uint8_t>(jumpSize));
    123162
    124163    m_linkRecords.append(LinkRecord({jumpSize, longestPossibleJumpDistance, instructionLocation, jumpLocation, destinationNodeIndex}));
     
    133172    DFABytecodeJumpSize jumpSize = smallestPossibleJumpSize(longestPossibleJumpDistance);
    134173    DFABytecodeInstruction instruction = caseSensitive ? DFABytecodeInstruction::CheckValueCaseSensitive : DFABytecodeInstruction::CheckValueCaseInsensitive;
    135     append<uint8_t>(m_bytecode, static_cast<uint8_t>(instruction) | jumpSize);
     174    append<uint8_t>(m_bytecode, static_cast<uint8_t>(instruction) | static_cast<uint8_t>(jumpSize));
    136175    append<uint8_t>(m_bytecode, value);
    137176    m_linkRecords.append(LinkRecord({jumpSize, longestPossibleJumpDistance, instructionLocation, jumpLocation, destinationNodeIndex}));
     
    148187    DFABytecodeJumpSize jumpSize = smallestPossibleJumpSize(longestPossibleJumpDistance);
    149188    DFABytecodeInstruction instruction = caseSensitive ? DFABytecodeInstruction::CheckValueRangeCaseSensitive : DFABytecodeInstruction::CheckValueRangeCaseInsensitive;
    150     append<uint8_t>(m_bytecode, static_cast<uint8_t>(instruction) | jumpSize);
     189    append<uint8_t>(m_bytecode, static_cast<uint8_t>(instruction) | static_cast<uint8_t>(jumpSize));
    151190    append<uint8_t>(m_bytecode, lowValue);
    152191    append<uint8_t>(m_bytecode, highValue);
     
    227266}
    228267
    229 DFABytecodeCompiler::Transitions DFABytecodeCompiler::transitions(const DFANode& node)
     268auto DFABytecodeCompiler::transitions(const DFANode& node) -> Transitions
    230269{
    231270    Transitions transitions;
     
    351390
    352391    uint32_t instructionLocation = m_bytecode.size();
    353     DFABytecodeJumpSize jumpSize = Int8;
     392    auto jumpSize = DFABytecodeJumpSize::Int8;
    354393    for (uint32_t destinationNodeIndex : jumpTable.destinations) {
    355394        int32_t longestPossibleJumpDistance = longestPossibleJump(instructionLocation, nodeIndex, destinationNodeIndex);
     
    359398
    360399    DFABytecodeInstruction instruction = jumpTable.caseSensitive ? DFABytecodeInstruction::JumpTableCaseSensitive : DFABytecodeInstruction::JumpTableCaseInsensitive;
    361     append<uint8_t>(m_bytecode, static_cast<uint8_t>(instruction) | jumpSize);
     400    append<uint8_t>(m_bytecode, static_cast<uint8_t>(instruction) | static_cast<uint8_t>(jumpSize));
    362401    append<uint8_t>(m_bytecode, jumpTable.min);
    363402    append<uint8_t>(m_bytecode, jumpTable.max);
     
    398437        size += sizeof(DFABytecodeInstruction::Jump) + sizeof(uint32_t);
    399438    else
    400         size += instructionSizeWithArguments(DFABytecodeInstruction::Terminate);
     439        size += sizeof(DFABytecodeInstruction::Terminate);
    401440    return size;
    402441}
     
    467506       
    468507        switch (linkRecord.jumpSize) {
    469         case Int8:
     508        case DFABytecodeJumpSize::Int8:
    470509            RELEASE_ASSERT(distance == static_cast<int8_t>(distance));
    471510            setBits<int8_t>(m_bytecode, linkRecord.jumpLocation, static_cast<int8_t>(distance));
    472511            break;
    473         case Int16:
     512        case DFABytecodeJumpSize::Int16:
    474513            RELEASE_ASSERT(distance == static_cast<int16_t>(distance));
    475514            setBits<int16_t>(m_bytecode, linkRecord.jumpLocation, static_cast<int16_t>(distance));
    476515            break;
    477         case Int24:
     516        case DFABytecodeJumpSize::Int24:
    478517            RELEASE_ASSERT(distance >= Int24Min && distance <= Int24Max);
    479518            setBits<uint16_t>(m_bytecode, linkRecord.jumpLocation, static_cast<uint16_t>(distance));
    480519            setBits<int8_t>(m_bytecode, linkRecord.jumpLocation + sizeof(int16_t), static_cast<int8_t>(distance >> 16));
    481520            break;
    482         case Int32:
     521        case DFABytecodeJumpSize::Int32:
    483522            setBits<int32_t>(m_bytecode, linkRecord.jumpLocation, distance);
    484523            break;
     
    488527    setBits<DFAHeader>(m_bytecode, startLocation, m_bytecode.size() - startLocation);
    489528}
    490    
    491 } // namespace ContentExtensions
    492 
    493 } // namespace WebCore
     529
     530} // namespace WebCore::ContentExtensions
    494531
    495532#endif // ENABLE(CONTENT_EXTENSIONS)
  • trunk/Source/WebCore/contentextensions/DFABytecodeInterpreter.cpp

    r275078 r286383  
    11/*
    2  * Copyright (C) 2015 Apple Inc. All rights reserved.
     2 * Copyright (C) 2015-2021 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    3232#if ENABLE(CONTENT_EXTENSIONS)
    3333
    34 namespace WebCore {
    35    
    36 namespace ContentExtensions {
     34namespace WebCore::ContentExtensions {
    3735
    3836template <typename IntType>
    39 static inline IntType getBits(const DFABytecode* bytecode, uint32_t bytecodeLength, uint32_t index)
    40 {
    41     ASSERT_UNUSED(bytecodeLength, index + sizeof(IntType) <= bytecodeLength);
    42     return *reinterpret_cast<const IntType*>(&bytecode[index]);
    43 }
    44 
    45 static inline DFABytecodeInstruction getInstruction(const DFABytecode* bytecode, uint32_t bytecodeLength, uint32_t index)
    46 {
    47     return static_cast<DFABytecodeInstruction>(getBits<uint8_t>(bytecode, bytecodeLength, index) & DFABytecodeInstructionMask);
    48 }
    49 
    50 static inline size_t jumpSizeInBytes(DFABytecodeJumpSize jumpSize)
     37static IntType getBits(Span<const uint8_t> bytecode, uint32_t index)
     38{
     39    ASSERT(index + sizeof(IntType) <= bytecode.size());
     40    return *reinterpret_cast<const IntType*>(bytecode.data() + index);
     41}
     42
     43static uint32_t get24BitsUnsigned(Span<const uint8_t> bytecode, uint32_t index)
     44{
     45    ASSERT(index + UInt24Size <= bytecode.size());
     46    uint32_t highBits = getBits<uint8_t>(bytecode, index + sizeof(uint16_t));
     47    uint32_t lowBits = getBits<uint16_t>(bytecode, index);
     48    return (highBits << 16) | lowBits;
     49}
     50
     51static DFABytecodeInstruction getInstruction(Span<const uint8_t> bytecode, uint32_t index)
     52{
     53    return static_cast<DFABytecodeInstruction>(getBits<uint8_t>(bytecode, index) & DFABytecodeInstructionMask);
     54}
     55
     56static size_t jumpSizeInBytes(DFABytecodeJumpSize jumpSize)
    5157{
    5258    switch (jumpSize) {
    53     case Int8:
     59    case DFABytecodeJumpSize::Int8:
    5460        return sizeof(int8_t);
    55     case Int16:
     61    case DFABytecodeJumpSize::Int16:
    5662        return sizeof(int16_t);
    57     case Int24:
    58         return sizeof(uint16_t) + sizeof(int8_t);
    59     case Int32:
     63    case DFABytecodeJumpSize::Int24:
     64        return Int24Size;
     65    case DFABytecodeJumpSize::Int32:
    6066        return sizeof(int32_t);
    61     default:
    62         RELEASE_ASSERT_NOT_REACHED();
    63     }
    64 }
    65 
    66 static inline DFABytecodeJumpSize getJumpSize(const DFABytecode* bytecode, uint32_t bytecodeLength, uint32_t index)
    67 {
    68     DFABytecodeJumpSize jumpSize = static_cast<DFABytecodeJumpSize>(getBits<uint8_t>(bytecode, bytecodeLength, index) & DFABytecodeJumpSizeMask);
    69     ASSERT(jumpSize == DFABytecodeJumpSize::Int32 || jumpSize == DFABytecodeJumpSize::Int24 || jumpSize == DFABytecodeJumpSize::Int16 || jumpSize == DFABytecodeJumpSize::Int8);
     67    }
     68    RELEASE_ASSERT_NOT_REACHED();
     69}
     70
     71template<typename T> uint32_t consumeInteger(Span<const uint8_t> bytecode, uint32_t& programCounter)
     72{
     73    programCounter += sizeof(T);
     74    return getBits<T>(bytecode, programCounter - sizeof(T));
     75}
     76static uint32_t consume24BitUnsignedInteger(Span<const uint8_t> bytecode, uint32_t& programCounter)
     77{
     78    programCounter += UInt24Size;
     79    return get24BitsUnsigned(bytecode, programCounter - UInt24Size);
     80}
     81
     82static constexpr bool hasFlags(DFABytecodeInstruction instruction)
     83{
     84    switch (instruction) {
     85    case DFABytecodeInstruction::TestFlagsAndAppendAction:
     86    case DFABytecodeInstruction::TestFlagsAndAppendActionWithIfCondition:
     87        return true;
     88    case DFABytecodeInstruction::CheckValueCaseSensitive:
     89    case DFABytecodeInstruction::CheckValueCaseInsensitive:
     90    case DFABytecodeInstruction::JumpTableCaseInsensitive:
     91    case DFABytecodeInstruction::JumpTableCaseSensitive:
     92    case DFABytecodeInstruction::CheckValueRangeCaseSensitive:
     93    case DFABytecodeInstruction::CheckValueRangeCaseInsensitive:
     94    case DFABytecodeInstruction::Jump:
     95    case DFABytecodeInstruction::AppendAction:
     96    case DFABytecodeInstruction::AppendActionWithIfCondition:
     97    case DFABytecodeInstruction::Terminate:
     98        break;
     99    }
     100    return false;
     101}
     102
     103static constexpr bool hasAction(DFABytecodeInstruction instruction)
     104{
     105    switch (instruction) {
     106    case DFABytecodeInstruction::TestFlagsAndAppendAction:
     107    case DFABytecodeInstruction::TestFlagsAndAppendActionWithIfCondition:
     108    case DFABytecodeInstruction::AppendAction:
     109    case DFABytecodeInstruction::AppendActionWithIfCondition:
     110        return true;
     111    case DFABytecodeInstruction::CheckValueCaseSensitive:
     112    case DFABytecodeInstruction::CheckValueCaseInsensitive:
     113    case DFABytecodeInstruction::JumpTableCaseInsensitive:
     114    case DFABytecodeInstruction::JumpTableCaseSensitive:
     115    case DFABytecodeInstruction::CheckValueRangeCaseSensitive:
     116    case DFABytecodeInstruction::CheckValueRangeCaseInsensitive:
     117    case DFABytecodeInstruction::Jump:
     118    case DFABytecodeInstruction::Terminate:
     119        break;
     120    }
     121    return false;
     122}
     123
     124static ResourceFlags consumeResourceFlagsAndInstruction(Span<const uint8_t> bytecode, uint32_t& programCounter)
     125{
     126    ASSERT_UNUSED(hasFlags, hasFlags(getInstruction(bytecode, programCounter)));
     127    switch (static_cast<DFABytecodeFlagsSize>(bytecode[programCounter++] & DFABytecodeFlagsSizeMask)) {
     128    case DFABytecodeFlagsSize::UInt8:
     129        return consumeInteger<uint8_t>(bytecode, programCounter);
     130    case DFABytecodeFlagsSize::UInt16:
     131        return consumeInteger<uint16_t>(bytecode, programCounter);
     132    case DFABytecodeFlagsSize::UInt24:
     133        return consume24BitUnsignedInteger(bytecode, programCounter);
     134    }
     135    ASSERT_NOT_REACHED();
     136    return 0;
     137}
     138
     139static uint32_t consumeAction(Span<const uint8_t> bytecode, uint32_t& programCounter, uint32_t instructionLocation)
     140{
     141    ASSERT_UNUSED(hasAction, hasAction(getInstruction(bytecode, instructionLocation)));
     142    ASSERT(programCounter > instructionLocation);
     143    switch (static_cast<DFABytecodeActionSize>(bytecode[instructionLocation] & DFABytecodeActionSizeMask)) {
     144    case DFABytecodeActionSize::UInt8:
     145        return consumeInteger<uint8_t>(bytecode, programCounter);
     146    case DFABytecodeActionSize::UInt16:
     147        return consumeInteger<uint16_t>(bytecode, programCounter);
     148    case DFABytecodeActionSize::UInt24:
     149        return consume24BitUnsignedInteger(bytecode, programCounter);
     150    case DFABytecodeActionSize::UInt32:
     151        return consumeInteger<uint32_t>(bytecode, programCounter);
     152    }
     153    ASSERT_NOT_REACHED();
     154    return 0;
     155}
     156
     157static DFABytecodeJumpSize getJumpSize(Span<const uint8_t> bytecode, uint32_t index)
     158{
     159    auto jumpSize = static_cast<DFABytecodeJumpSize>(getBits<uint8_t>(bytecode, index) & DFABytecodeJumpSizeMask);
     160    ASSERT(jumpSize == DFABytecodeJumpSize::Int32
     161        || jumpSize == DFABytecodeJumpSize::Int24
     162        || jumpSize == DFABytecodeJumpSize::Int16
     163        || jumpSize == DFABytecodeJumpSize::Int8);
    70164    return jumpSize;
    71165}
    72166
    73 static inline int32_t getJumpDistance(const DFABytecode* bytecode, uint32_t bytecodeLength, uint32_t index, DFABytecodeJumpSize jumpSize)
     167static int32_t getJumpDistance(Span<const uint8_t> bytecode, uint32_t index, DFABytecodeJumpSize jumpSize)
    74168{
    75169    switch (jumpSize) {
    76     case Int8:
    77         return getBits<int8_t>(bytecode, bytecodeLength, index);
    78     case Int16:
    79         return getBits<int16_t>(bytecode, bytecodeLength, index);
    80     case Int24:
    81         return getBits<uint16_t>(bytecode, bytecodeLength, index) | (static_cast<int32_t>(getBits<int8_t>(bytecode, bytecodeLength, index + sizeof(uint16_t))) << 16);
    82     case Int32:
    83         return getBits<int32_t>(bytecode, bytecodeLength, index);
    84     default:
    85         RELEASE_ASSERT_NOT_REACHED();
    86     }
    87 }
    88 
    89 static inline bool matchesCondition(uint64_t actionAndFlags, const DFABytecodeInterpreter::Actions& conditionActions)
     170    case DFABytecodeJumpSize::Int8:
     171        return getBits<int8_t>(bytecode, index);
     172    case DFABytecodeJumpSize::Int16:
     173        return getBits<int16_t>(bytecode, index);
     174    case DFABytecodeJumpSize::Int24:
     175        return getBits<uint16_t>(bytecode, index) | (static_cast<int32_t>(getBits<int8_t>(bytecode, index + sizeof(uint16_t))) << 16);
     176    case DFABytecodeJumpSize::Int32:
     177        return getBits<int32_t>(bytecode, index);
     178    }
     179    RELEASE_ASSERT_NOT_REACHED();
     180}
     181
     182static bool matchesCondition(uint64_t actionAndFlags, const DFABytecodeInterpreter::Actions& conditionActions)
    90183{
    91184    bool ifCondition = actionAndFlags & IfConditionFlag;
     
    96189void DFABytecodeInterpreter::interpretAppendAction(uint32_t& programCounter, Actions& actions, bool ifCondition)
    97190{
    98     ASSERT(getInstruction(m_bytecode, m_bytecodeLength, programCounter) == DFABytecodeInstruction::AppendAction
    99         || getInstruction(m_bytecode, m_bytecodeLength, programCounter) == DFABytecodeInstruction::AppendActionWithIfCondition);
    100     uint64_t action = (ifCondition ? IfConditionFlag : 0) | static_cast<uint64_t>(getBits<uint32_t>(m_bytecode, m_bytecodeLength, programCounter + sizeof(DFABytecodeInstruction)));
     191    ASSERT(getInstruction(m_bytecode, programCounter) == DFABytecodeInstruction::AppendAction
     192        || getInstruction(m_bytecode, programCounter) == DFABytecodeInstruction::AppendActionWithIfCondition);
     193    auto instructionLocation = programCounter++;
     194    uint64_t actionWithoutFlags = consumeAction(m_bytecode, programCounter, instructionLocation);
     195    uint64_t action = (ifCondition ? IfConditionFlag : 0) | actionWithoutFlags;
    101196    if (!m_topURLActions || matchesCondition(action, *m_topURLActions))
    102197        actions.add(action);
    103    
    104     programCounter += instructionSizeWithArguments(DFABytecodeInstruction::AppendAction);
    105     ASSERT(instructionSizeWithArguments(DFABytecodeInstruction::AppendAction) == instructionSizeWithArguments(DFABytecodeInstruction::AppendActionWithIfCondition));
    106 }
    107 
    108 void DFABytecodeInterpreter::interpretTestFlagsAndAppendAction(uint32_t& programCounter, uint16_t flags, Actions& actions, bool ifCondition)
    109 {
    110     ASSERT(getInstruction(m_bytecode, m_bytecodeLength, programCounter) == DFABytecodeInstruction::TestFlagsAndAppendAction
    111         || getInstruction(m_bytecode, m_bytecodeLength, programCounter) == DFABytecodeInstruction::TestFlagsAndAppendActionWithIfCondition);
    112     uint16_t flagsToCheck = getBits<uint16_t>(m_bytecode, m_bytecodeLength, programCounter + sizeof(DFABytecodeInstruction));
    113 
    114     uint16_t loadTypeFlags = flagsToCheck & LoadTypeMask;
    115     uint16_t loadContextFlags = flagsToCheck & LoadContextMask;
    116     uint16_t resourceTypeFlags = flagsToCheck & ResourceTypeMask;
     198}
     199
     200void DFABytecodeInterpreter::interpretTestFlagsAndAppendAction(uint32_t& programCounter, ResourceFlags flags, Actions& actions, bool ifCondition)
     201{
     202    auto instructionLocation = programCounter;
     203    auto flagsToCheck = consumeResourceFlagsAndInstruction(m_bytecode, programCounter);
     204
     205    ResourceFlags loadTypeFlags = flagsToCheck & LoadTypeMask;
     206    ResourceFlags loadContextFlags = flagsToCheck & LoadContextMask;
     207    ResourceFlags resourceTypeFlags = flagsToCheck & ResourceTypeMask;
    117208
    118209    bool loadTypeMatches = loadTypeFlags ? (loadTypeFlags & flags) : true;
     
    120211    bool resourceTypeMatches = resourceTypeFlags ? (resourceTypeFlags & flags) : true;
    121212   
     213    auto actionWithoutFlags = consumeAction(m_bytecode, programCounter, instructionLocation);
    122214    if (loadTypeMatches && loadContextMatches && resourceTypeMatches) {
    123         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)));
     215        uint64_t actionAndFlags = (ifCondition ? IfConditionFlag : 0) | (static_cast<uint64_t>(flagsToCheck) << 32) | static_cast<uint64_t>(actionWithoutFlags);
    124216        if (!m_topURLActions || matchesCondition(actionAndFlags, *m_topURLActions))
    125217            actions.add(actionAndFlags);
    126218    }
    127     programCounter += instructionSizeWithArguments(DFABytecodeInstruction::TestFlagsAndAppendAction);
    128     ASSERT(instructionSizeWithArguments(DFABytecodeInstruction::TestFlagsAndAppendAction) == instructionSizeWithArguments(DFABytecodeInstruction::TestFlagsAndAppendActionWithIfCondition));
    129219}
    130220
     
    132222inline void DFABytecodeInterpreter::interpetJumpTable(const char* url, uint32_t& urlIndex, uint32_t& programCounter, bool& urlIndexIsAfterEndOfString)
    133223{
    134     DFABytecodeJumpSize jumpSize = getJumpSize(m_bytecode, m_bytecodeLength, programCounter);
     224    DFABytecodeJumpSize jumpSize = getJumpSize(m_bytecode, programCounter);
    135225
    136226    char character = caseSensitive ? url[urlIndex] : toASCIILower(url[urlIndex]);
    137     uint8_t firstCharacter = getBits<uint8_t>(m_bytecode, m_bytecodeLength, programCounter + sizeof(DFABytecodeInstruction));
    138     uint8_t lastCharacter = getBits<uint8_t>(m_bytecode, m_bytecodeLength, programCounter + sizeof(DFABytecodeInstruction) + sizeof(uint8_t));
     227    uint8_t firstCharacter = getBits<uint8_t>(m_bytecode, programCounter + sizeof(DFABytecodeInstruction));
     228    uint8_t lastCharacter = getBits<uint8_t>(m_bytecode, programCounter + sizeof(DFABytecodeInstruction) + sizeof(uint8_t));
    139229    if (character >= firstCharacter && character <= lastCharacter) {
    140230        uint32_t startOffset = programCounter + sizeof(DFABytecodeInstruction) + 2 * sizeof(uint8_t);
    141231        uint32_t jumpLocation = startOffset + (character - firstCharacter) * jumpSizeInBytes(jumpSize);
    142         programCounter += getJumpDistance(m_bytecode, m_bytecodeLength, jumpLocation, jumpSize);
     232        programCounter += getJumpDistance(m_bytecode, jumpLocation, jumpSize);
    143233        if (!character)
    144234            urlIndexIsAfterEndOfString = true;
     
    148238}
    149239
    150 DFABytecodeInterpreter::Actions DFABytecodeInterpreter::actionsMatchingEverything()
     240auto DFABytecodeInterpreter::actionsMatchingEverything() -> Actions
    151241{
    152242    Actions actions;
    153243
    154244    // DFA header.
    155     uint32_t dfaBytecodeLength = getBits<uint32_t>(m_bytecode, m_bytecodeLength, 0);
    156     uint32_t programCounter = sizeof(uint32_t);
     245    uint32_t dfaBytecodeLength = getBits<uint32_t>(m_bytecode, 0);
     246    uint32_t programCounter = sizeof(DFAHeader);
    157247
    158248    while (programCounter < dfaBytecodeLength) {
    159         DFABytecodeInstruction instruction = getInstruction(m_bytecode, m_bytecodeLength, programCounter);
     249        DFABytecodeInstruction instruction = getInstruction(m_bytecode, programCounter);
    160250        if (instruction == DFABytecodeInstruction::AppendAction)
    161251            interpretAppendAction(programCounter, actions, false);
    162252        else if (instruction == DFABytecodeInstruction::AppendActionWithIfCondition)
    163253            interpretAppendAction(programCounter, actions, true);
    164         else if (instruction == DFABytecodeInstruction::TestFlagsAndAppendAction)
    165             programCounter += instructionSizeWithArguments(DFABytecodeInstruction::TestFlagsAndAppendAction);
    166         else if (instruction == DFABytecodeInstruction::TestFlagsAndAppendActionWithIfCondition)
    167             programCounter += instructionSizeWithArguments(DFABytecodeInstruction::TestFlagsAndAppendActionWithIfCondition);
    168         else
     254        else if (instruction == DFABytecodeInstruction::TestFlagsAndAppendAction
     255            || instruction == DFABytecodeInstruction::TestFlagsAndAppendActionWithIfCondition) {
     256            auto programCounterAtInstruction = programCounter;
     257            consumeResourceFlagsAndInstruction(m_bytecode, programCounter);
     258            consumeAction(m_bytecode, programCounter, programCounterAtInstruction);
     259        } else
    169260            break;
    170261    }
     
    172263}
    173264   
    174 DFABytecodeInterpreter::Actions DFABytecodeInterpreter::interpretWithConditions(const CString& urlCString, uint16_t flags, const DFABytecodeInterpreter::Actions& topURLActions)
     265auto DFABytecodeInterpreter::interpretWithConditions(const CString& urlCString, ResourceFlags flags, const Actions& topURLActions) -> Actions
    175266{
    176267    ASSERT(!m_topURLActions);
    177268    m_topURLActions = &topURLActions;
    178     DFABytecodeInterpreter::Actions actions = interpret(urlCString, flags);
     269    auto actions = interpret(urlCString, flags);
    179270    m_topURLActions = nullptr;
    180271    return actions;
    181272}
    182273
    183 DFABytecodeInterpreter::Actions DFABytecodeInterpreter::interpret(const CString& urlCString, uint16_t flags)
     274auto DFABytecodeInterpreter::interpret(const CString& urlCString, ResourceFlags flags) -> Actions
    184275{
    185276    const char* url = urlCString.data();
     
    189280   
    190281    uint32_t programCounter = 0;
    191     while (programCounter < m_bytecodeLength) {
     282    while (programCounter < m_bytecode.size()) {
    192283
    193284        // DFA header.
    194285        uint32_t dfaStart = programCounter;
    195         uint32_t dfaBytecodeLength = getBits<uint32_t>(m_bytecode, m_bytecodeLength, programCounter);
     286        uint32_t dfaBytecodeLength = getBits<uint32_t>(m_bytecode, programCounter);
    196287        programCounter += sizeof(uint32_t);
    197288
     
    199290        if (!dfaStart) {
    200291            while (programCounter < dfaBytecodeLength) {
    201                 DFABytecodeInstruction instruction = getInstruction(m_bytecode, m_bytecodeLength, programCounter);
    202                 if (instruction == DFABytecodeInstruction::AppendAction)
    203                     programCounter += instructionSizeWithArguments(DFABytecodeInstruction::AppendAction);
    204                 else if (instruction == DFABytecodeInstruction::AppendActionWithIfCondition)
    205                     programCounter += instructionSizeWithArguments(DFABytecodeInstruction::AppendActionWithIfCondition);
    206                 else if (instruction == DFABytecodeInstruction::TestFlagsAndAppendAction)
     292                DFABytecodeInstruction instruction = getInstruction(m_bytecode, programCounter);
     293                if (instruction == DFABytecodeInstruction::AppendAction || instruction == DFABytecodeInstruction::AppendActionWithIfCondition) {
     294                    auto instructionLocation = programCounter++;
     295                    consumeAction(m_bytecode, programCounter, instructionLocation);
     296                } else if (instruction == DFABytecodeInstruction::TestFlagsAndAppendAction)
    207297                    interpretTestFlagsAndAppendAction(programCounter, flags, actions, false);
    208298                else if (instruction == DFABytecodeInstruction::TestFlagsAndAppendActionWithIfCondition)
     
    211301                    break;
    212302            }
    213             if (programCounter >= m_bytecodeLength)
     303            if (programCounter >= m_bytecode.size())
    214304                return actions;
    215305        } else {
    216             ASSERT_WITH_MESSAGE(getInstruction(m_bytecode, m_bytecodeLength, programCounter) != DFABytecodeInstruction::AppendAction
    217                 && getInstruction(m_bytecode, m_bytecodeLength, programCounter) != DFABytecodeInstruction::AppendActionWithIfCondition
    218                 && getInstruction(m_bytecode, m_bytecodeLength, programCounter) != DFABytecodeInstruction::TestFlagsAndAppendAction
    219                 && getInstruction(m_bytecode, m_bytecodeLength, programCounter) != DFABytecodeInstruction::TestFlagsAndAppendActionWithIfCondition,
     306            ASSERT_WITH_MESSAGE(getInstruction(m_bytecode, programCounter) != DFABytecodeInstruction::AppendAction
     307                && getInstruction(m_bytecode, programCounter) != DFABytecodeInstruction::AppendActionWithIfCondition
     308                && getInstruction(m_bytecode, programCounter) != DFABytecodeInstruction::TestFlagsAndAppendAction
     309                && getInstruction(m_bytecode, programCounter) != DFABytecodeInstruction::TestFlagsAndAppendActionWithIfCondition,
    220310                "Triggers that match everything should only be in the first DFA.");
    221311        }
     
    226316        bool urlIndexIsAfterEndOfString = false;
    227317        while (true) {
    228             ASSERT(programCounter <= m_bytecodeLength);
    229             switch (getInstruction(m_bytecode, m_bytecodeLength, programCounter)) {
     318            ASSERT(programCounter <= m_bytecode.size());
     319            switch (getInstruction(m_bytecode, programCounter)) {
    230320
    231321            case DFABytecodeInstruction::Terminate:
     
    238328                // Check to see if the next character in the url is the value stored with the bytecode.
    239329                char character = url[urlIndex];
    240                 DFABytecodeJumpSize jumpSize = getJumpSize(m_bytecode, m_bytecodeLength, programCounter);
    241                 if (character == getBits<uint8_t>(m_bytecode, m_bytecodeLength, programCounter + sizeof(DFABytecodeInstruction))) {
     330                DFABytecodeJumpSize jumpSize = getJumpSize(m_bytecode, programCounter);
     331                if (character == getBits<uint8_t>(m_bytecode, programCounter + sizeof(DFABytecodeInstruction))) {
    242332                    uint32_t jumpLocation = programCounter + sizeof(DFABytecodeInstruction) + sizeof(uint8_t);
    243                     programCounter += getJumpDistance(m_bytecode, m_bytecodeLength, jumpLocation, jumpSize);
     333                    programCounter += getJumpDistance(m_bytecode, jumpLocation, jumpSize);
    244334                    if (!character)
    245335                        urlIndexIsAfterEndOfString = true;
     
    256346                // Check to see if the next character in the url is the value stored with the bytecode.
    257347                char character = toASCIILower(url[urlIndex]);
    258                 DFABytecodeJumpSize jumpSize = getJumpSize(m_bytecode, m_bytecodeLength, programCounter);
    259                 if (character == getBits<uint8_t>(m_bytecode, m_bytecodeLength, programCounter + sizeof(DFABytecodeInstruction))) {
     348                DFABytecodeJumpSize jumpSize = getJumpSize(m_bytecode, programCounter);
     349                if (character == getBits<uint8_t>(m_bytecode, programCounter + sizeof(DFABytecodeInstruction))) {
    260350                    uint32_t jumpLocation = programCounter + sizeof(DFABytecodeInstruction) + sizeof(uint8_t);
    261                     programCounter += getJumpDistance(m_bytecode, m_bytecodeLength, jumpLocation, jumpSize);
     351                    programCounter += getJumpDistance(m_bytecode, jumpLocation, jumpSize);
    262352                    if (!character)
    263353                        urlIndexIsAfterEndOfString = true;
     
    286376               
    287377                char character = url[urlIndex];
    288                 DFABytecodeJumpSize jumpSize = getJumpSize(m_bytecode, m_bytecodeLength, programCounter);
    289                 if (character >= getBits<uint8_t>(m_bytecode, m_bytecodeLength, programCounter + sizeof(DFABytecodeInstruction))
    290                     && character <= getBits<uint8_t>(m_bytecode, m_bytecodeLength, programCounter + sizeof(DFABytecodeInstruction) + sizeof(uint8_t))) {
     378                DFABytecodeJumpSize jumpSize = getJumpSize(m_bytecode, programCounter);
     379                if (character >= getBits<uint8_t>(m_bytecode, programCounter + sizeof(DFABytecodeInstruction))
     380                    && character <= getBits<uint8_t>(m_bytecode, programCounter + sizeof(DFABytecodeInstruction) + sizeof(uint8_t))) {
    291381                    uint32_t jumpLocation = programCounter + sizeof(DFABytecodeInstruction) + 2 * sizeof(uint8_t);
    292                     programCounter += getJumpDistance(m_bytecode, m_bytecodeLength, jumpLocation, jumpSize);
     382                    programCounter += getJumpDistance(m_bytecode, jumpLocation, jumpSize);
    293383                    if (!character)
    294384                        urlIndexIsAfterEndOfString = true;
     
    304394               
    305395                char character = toASCIILower(url[urlIndex]);
    306                 DFABytecodeJumpSize jumpSize = getJumpSize(m_bytecode, m_bytecodeLength, programCounter);
    307                 if (character >= getBits<uint8_t>(m_bytecode, m_bytecodeLength, programCounter + sizeof(DFABytecodeInstruction))
    308                     && character <= getBits<uint8_t>(m_bytecode, m_bytecodeLength, programCounter + sizeof(DFABytecodeInstruction) + sizeof(uint8_t))) {
     396                DFABytecodeJumpSize jumpSize = getJumpSize(m_bytecode, programCounter);
     397                if (character >= getBits<uint8_t>(m_bytecode, programCounter + sizeof(DFABytecodeInstruction))
     398                    && character <= getBits<uint8_t>(m_bytecode, programCounter + sizeof(DFABytecodeInstruction) + sizeof(uint8_t))) {
    309399                    uint32_t jumpLocation = programCounter + sizeof(DFABytecodeInstruction) + 2 * sizeof(uint8_t);
    310                     programCounter += getJumpDistance(m_bytecode, m_bytecodeLength, jumpLocation, jumpSize);
     400                    programCounter += getJumpDistance(m_bytecode, jumpLocation, jumpSize);
    311401                    if (!character)
    312402                        urlIndexIsAfterEndOfString = true;
     
    322412               
    323413                uint32_t jumpLocation = programCounter + sizeof(DFABytecodeInstruction);
    324                 DFABytecodeJumpSize jumpSize = getJumpSize(m_bytecode, m_bytecodeLength, programCounter);
    325                 programCounter += getJumpDistance(m_bytecode, m_bytecodeLength, jumpLocation, jumpSize);
     414                DFABytecodeJumpSize jumpSize = getJumpSize(m_bytecode, programCounter);
     415                programCounter += getJumpDistance(m_bytecode, jumpLocation, jumpSize);
    326416                urlIndex++; // This represents an edge in the DFA.
    327417                break;
     
    358448}
    359449
    360 } // namespace ContentExtensions
    361    
    362 } // namespace WebCore
     450} // namespace WebCore::ContentExtensions
    363451
    364452#endif // ENABLE(CONTENT_EXTENSIONS)
  • trunk/Source/WebCore/contentextensions/DFABytecodeInterpreter.h

    r264488 r286383  
    3434#include <wtf/HashSet.h>
    3535
    36 namespace WebCore {
    37    
    38 namespace ContentExtensions {
     36namespace WebCore::ContentExtensions {
    3937
    40 class WEBCORE_EXPORT DFABytecodeInterpreter {
     38class DFABytecodeInterpreter {
    4139public:
    42     DFABytecodeInterpreter(const DFABytecode* bytecode, unsigned bytecodeLength)
    43         : m_bytecode(bytecode)
    44         , m_bytecodeLength(bytecodeLength)
    45     {
    46     }
    47    
    48     typedef HashSet<uint64_t, DefaultHash<uint64_t>, WTF::UnsignedWithZeroKeyHashTraits<uint64_t>> Actions;
    49    
    50     Actions interpret(const CString&, uint16_t flags);
    51     Actions interpretWithConditions(const CString&, uint16_t flags, const DFABytecodeInterpreter::Actions& conditionActions);
     40    DFABytecodeInterpreter(Span<const uint8_t> bytecode)
     41        : m_bytecode(bytecode) { }
     42
     43    using Actions = HashSet<uint64_t, DefaultHash<uint64_t>, WTF::UnsignedWithZeroKeyHashTraits<uint64_t>>;
     44
     45    WEBCORE_EXPORT Actions interpret(const CString&, ResourceFlags);
     46    Actions interpretWithConditions(const CString&, ResourceFlags, const Actions& conditionActions);
    5247    Actions actionsMatchingEverything();
    5348
    5449private:
    5550    void interpretAppendAction(unsigned& programCounter, Actions&, bool ifCondition);
    56     void interpretTestFlagsAndAppendAction(unsigned& programCounter, uint16_t flags, Actions&, bool ifCondition);
     51    void interpretTestFlagsAndAppendAction(unsigned& programCounter, ResourceFlags, Actions&, bool ifCondition);
    5752
    5853    template<bool caseSensitive>
    5954    void interpetJumpTable(const char* url, uint32_t& urlIndex, uint32_t& programCounter, bool& urlIndexIsAfterEndOfString);
    6055
    61     const DFABytecode* m_bytecode;
    62     const unsigned m_bytecodeLength;
     56    const Span<const uint8_t> m_bytecode;
    6357    const DFABytecodeInterpreter::Actions* m_topURLActions { nullptr };
    6458};
    6559
    66 } // namespace ContentExtensions   
    67 } // namespace WebCore
     60} // namespace WebCore::ContentExtensions
    6861
    6962#endif // ENABLE(CONTENT_EXTENSIONS)
  • trunk/Source/WebCore/loader/PingLoader.cpp

    r282860 r286383  
    160160    ResourceRequest request(reportURL);
    161161#if ENABLE(CONTENT_EXTENSIONS)
    162     if (processContentRuleListsForLoad(frame, request, ContentExtensions::ResourceType::Other))
     162    if (processContentRuleListsForLoad(frame, request, ContentExtensions::ResourceType::CSPReport))
    163163        return;
    164164#endif
  • trunk/Source/WebCore/loader/ResourceLoadInfo.cpp

    r278253 r286383  
    3333#include "SecurityOrigin.h"
    3434
    35 namespace WebCore {
    36 namespace ContentExtensions {
     35namespace WebCore::ContentExtensions {
    3736
    3837OptionSet<ResourceType> toResourceType(CachedResource::Type type, ResourceRequestBase::Requester requester)
     
    9998        return { ResourceType::Font };
    10099    if (name == "raw")
    101         return {{ ResourceType::Fetch, ResourceType::WebSocket, ResourceType::Other, ResourceType::Ping }};
     100        return { { ResourceType::Fetch, ResourceType::WebSocket, ResourceType::Other, ResourceType::Ping } };
    102101    if (name == "websocket")
    103102        return { ResourceType::WebSocket };
     
    105104        return { ResourceType::Fetch };
    106105    if (name == "other")
    107         return {{ ResourceType::Other, ResourceType::Ping }};
     106        return { { ResourceType::Other, ResourceType::Ping, ResourceType::CSPReport } };
    108107    if (name == "svg-document")
    109108        return { ResourceType::SVGDocument };
     
    114113    if (name == "ping")
    115114        return { ResourceType::Ping };
     115    if (name == "csp-report")
     116        return { ResourceType::CSPReport };
    116117    return std::nullopt;
    117118}
     
    150151}
    151152
    152 } // namespace ContentExtensions
    153 } // namespace WebCore
     153} // namespace WebCore::ContentExtensions
    154154
    155155#endif // ENABLE(CONTENT_EXTENSIONS)
  • trunk/Source/WebCore/loader/ResourceLoadInfo.h

    r278253 r286383  
    3232#include <wtf/URL.h>
    3333
    34 namespace WebCore {
    35 namespace ContentExtensions {
     34namespace WebCore::ContentExtensions {
    3635
    37 enum class ResourceType : uint16_t {
     36enum class ResourceType : uint32_t {
    3837    Document = 0x0001,
    3938    Image = 0x0002,
     
    4847    WebSocket = 0x0400,
    4948    Other = 0x0800,
     49    CSPReport = 0x10000,
    5050};
    51 const uint16_t ResourceTypeMask = 0x0FFF;
     51static constexpr uint32_t ResourceTypeMask = 0x10FFF;
    5252
    53 enum class LoadType : uint16_t {
     53enum class LoadType : uint32_t {
    5454    FirstParty = 0x1000,
    5555    ThirdParty = 0x2000,
    5656};
    57 const uint16_t LoadTypeMask = 0x3000;
     57static constexpr uint32_t LoadTypeMask = 0x3000;
    5858
    59 enum class LoadContext : uint16_t {
     59enum class LoadContext : uint32_t {
    6060    TopFrame = 0x4000,
    6161    ChildFrame = 0x8000,
    6262};
    63 const uint16_t LoadContextMask = 0xC000;
     63static constexpr uint32_t LoadContextMask = 0xC000;
    6464
    65 static_assert(!(ResourceTypeMask & LoadTypeMask), "ResourceTypeMask and LoadTypeMask should be mutually exclusive because they are stored in the same uint16_t");
    66 static_assert(!(ResourceTypeMask & LoadContextMask), "ResourceTypeMask and LoadContextMask should be mutually exclusive because they are stored in the same uint16_t");
    67 static_assert(!(LoadContextMask & LoadTypeMask), "LoadContextMask and LoadTypeMask should be mutually exclusive because they are stored in the same uint16_t");
     65static_assert(!(ResourceTypeMask & LoadTypeMask), "ResourceTypeMask and LoadTypeMask should be mutually exclusive because they are stored in the same uint32_t");
     66static_assert(!(ResourceTypeMask & LoadContextMask), "ResourceTypeMask and LoadContextMask should be mutually exclusive because they are stored in the same uint32_t");
     67static_assert(!(LoadContextMask & LoadTypeMask), "LoadContextMask and LoadTypeMask should be mutually exclusive because they are stored in the same uint32_t");
    6868
    69 typedef uint16_t ResourceFlags;
     69using ResourceFlags = uint32_t;
    7070
    7171// The first 32 bits of a uint64_t action are used for the action location.
    72 // The next 16 bits are used for the flags (ResourceType and LoadType).
     72// The next 24 bits are used for the flags (ResourceType and LoadType).
    7373// The next bit is used to mark actions that are from a rule with an if-domain.
    7474//     Actions from rules with unless-domain conditions are distinguished from
     
    7676//     Actions from rules with no conditions are put in the DFA without conditions.
    7777// The values -1 and -2 are used for removed and empty values in HashTables.
    78 const uint64_t ActionFlagMask = 0x0000FFFF00000000;
    79 const uint64_t IfConditionFlag = 0x0001000000000000;
     78static constexpr uint64_t ActionFlagMask = 0x00FFFFFF00000000;
     79static constexpr uint64_t IfConditionFlag = 0x0100000000000000;
    8080
    8181OptionSet<ResourceType> toResourceType(CachedResource::Type, ResourceRequestBase::Requester);
     
    9494};
    9595
    96 } // namespace ContentExtensions
    97 } // namespace WebCore
     96} // namespace WebCore::ContentExtensions
    9897
    9998#endif
  • trunk/Tools/ChangeLog

    r286376 r286383  
     12021-12-01  Alex Christensen  <achristensen@webkit.org>
     2
     3        Add csp-report resource type to WKContentRuleList
     4        https://bugs.webkit.org/show_bug.cgi?id=233675
     5        <rdar://71869893>
     6
     7        Reviewed by Tim Hatcher.
     8
     9        * TestWebKitAPI/Tests/WebCore/ContentExtensions.cpp:
     10        (TestWebKitAPI::compareContents):
     11        (TestWebKitAPI::TEST_F):
     12        * TestWebKitAPI/Tests/WebKitCocoa/ContentRuleListNotification.mm:
     13        (TEST):
     14
    1152021-12-01  Ryan Haddad  <ryanhaddad@apple.com>
    216
  • trunk/Tools/TestWebKitAPI/Tests/WebCore/ContentExtensions.cpp

    r286084 r286383  
    541541}
    542542
    543 static void compareContents(const ContentExtensions::DFABytecodeInterpreter::Actions& a, const Vector<uint64_t>& b)
     543static void compareContents(const DFABytecodeInterpreter::Actions& a, const Vector<uint64_t>& b)
    544544{
    545545    EXPECT_EQ(a.size(), b.size());
     
    563563    ContentExtensions::DFABytecodeCompiler compiler(dfa, bytecode);
    564564    compiler.compile();
    565     ContentExtensions::DFABytecodeInterpreter interpreter(bytecode.data(), bytecode.size());
     565    DFABytecodeInterpreter interpreter({ bytecode.data(), bytecode.size() });
    566566    compareContents(interpreter.interpret("foo.org", 0), { 0 });
    567567    compareContents(interpreter.interpret("ba.org", 0), { 0 });
     
    589589    ContentExtensions::DFABytecodeCompiler compiler(dfa, bytecode);
    590590    compiler.compile();
    591     ContentExtensions::DFABytecodeInterpreter interpreter(bytecode.data(), bytecode.size());
     591    DFABytecodeInterpreter interpreter({ bytecode.data(), bytecode.size() });
    592592    compareContents(interpreter.interpret("foo.org", 0), { 0 });
    593593    compareContents(interpreter.interpret("ba.org", 0), { 1 });
     
    972972
    973973    ASSERT_EQ(data.actions.size(), 78u);
    974     ASSERT_EQ(data.filtersWithoutConditions.size(),  313u);
    975     ASSERT_EQ(data.filtersWithConditions.size(),  5u);
    976     ASSERT_EQ(data.topURLFilters.size(),  5u);
     974    ASSERT_EQ(data.filtersWithoutConditions.size(), 288u);
     975    ASSERT_EQ(data.filtersWithConditions.size(), 5u);
     976    ASSERT_EQ(data.topURLFilters.size(), 5u);
    977977    ASSERT_FALSE(data.conditionsApplyOnlyToDomain);
    978978
     
    11091109    ContentExtensions::DFABytecodeCompiler compiler(dfa, bytecode);
    11101110    compiler.compile();
    1111     ContentExtensions::DFABytecodeInterpreter interpreter(bytecode.data(), bytecode.size());
     1111    DFABytecodeInterpreter interpreter({ bytecode.data(), bytecode.size() });
    11121112    compareContents(interpreter.interpret("eb", 0), { });
    11131113    compareContents(interpreter.interpret("we", 0), { });
     
    12681268    }
    12691269   
    1270     ContentExtensions::DFABytecodeInterpreter interpreter(&combinedBytecode[0], combinedBytecode.size());
     1270    DFABytecodeInterpreter interpreter({ combinedBytecode.data(), combinedBytecode.size() });
    12711271   
    12721272    patternId = 0;
     
    17091709        }
    17101710       
    1711         ContentExtensions::DFABytecodeInterpreter interpreter(&combinedBytecode[0], combinedBytecode.size());
     1711        DFABytecodeInterpreter interpreter({ combinedBytecode.data(), combinedBytecode.size() });
    17121712       
    17131713        EXPECT_EQ(interpreter.interpret("ABBBX", 0).size(), 1ull);
  • trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/ContentRuleListNotification.mm

    r284557 r286383  
    417417}
    418418
     419TEST(ContentRuleList, CSPReport)
     420{
     421    TestWebKitAPI::HTTPServer server({ { "/", { {
     422        { "Content-Security-Policy", "frame-src 'none'; report-uri resources/save-report.py" }
     423    }, "<iframe src=\"https://webkit.org/\"></iframe>" } } });
     424
     425    auto configuration = adoptNS([WKWebViewConfiguration new]);
     426    [[configuration userContentController] addContentRuleList:makeContentRuleList(@"[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\".*\",\"resource-type\":[\"csp-report\"]}}]").get()];
     427    auto webView = adoptNS([[WKWebView alloc] initWithFrame:NSZeroRect configuration:configuration.get()]);
     428    auto delegate = adoptNS([ContentRuleListNotificationDelegate new]);
     429    [webView setNavigationDelegate:delegate.get()];
     430    [webView loadRequest:server.request()];
     431    while (notificationList.isEmpty())
     432        TestWebKitAPI::Util::spinRunLoop();
     433
     434    URL expectedURL = server.request().URL;
     435    expectedURL.setPath("/resources/save-report.py");
     436    EXPECT_STREQ(expectedURL.string().utf8().data(), notificationList.first().url.utf8().data());
     437}
     438
    419439TEST(ContentRuleList, LegacyVersionAndName)
    420440{
  • trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/WKContentExtensionStore.mm

    r286084 r286383  
    253253    NSData *data = [NSData dataWithContentsOfURL:[tempDir URLByAppendingPathComponent:fileName]];
    254254    EXPECT_NOT_NULL(data);
    255     EXPECT_EQ(data.length, 228u);
     255    EXPECT_EQ(data.length, 225u);
    256256   
    257257    __block bool doneCheckingSource = false;
Note: See TracChangeset for help on using the changeset viewer.