Changeset 286383 in webkit
- Timestamp:
- Dec 1, 2021 1:31:04 PM (2 years ago)
- Location:
- trunk
- Files:
-
- 14 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/WebCore/ChangeLog
r286379 r286383 1 2021-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 1 72 2021-12-01 Rob Buis <rbuis@igalia.com> 2 73 -
trunk/Source/WebCore/contentextensions/ContentExtension.cpp
r286084 r286383 47 47 , m_extensionBaseURL(WTFMove(extensionBaseURL)) 48 48 { 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() }); 51 51 for (uint64_t action : withoutConditions.actionsMatchingEverything()) { 52 52 ASSERT(static_cast<uint32_t>(action) == action); … … 124 124 { 125 125 if (m_cachedTopURL != topURL) { 126 DFABytecodeInterpreter interpreter( m_compiledExtension->topURLFiltersBytecode(), m_compiledExtension->topURLFiltersBytecodeLength());127 constexpr uint16_tallLoadTypesAndResourceTypes = LoadTypeMask | ResourceTypeMask | LoadContextMask;126 DFABytecodeInterpreter interpreter({ m_compiledExtension->topURLFiltersBytecode(), m_compiledExtension->topURLFiltersBytecodeLength() }); 127 constexpr ResourceFlags allLoadTypesAndResourceTypes = LoadTypeMask | ResourceTypeMask | LoadContextMask; 128 128 String string = m_compiledExtension->conditionsApplyOnlyToDomain() ? topURL.host().toString() : topURL.string(); 129 129 auto topURLActions = interpreter.interpret(string.utf8(), allLoadTypesAndResourceTypes); -
trunk/Source/WebCore/contentextensions/ContentExtensionsBackend.cpp
r286084 r286383 122 122 const CompiledContentExtension& compiledExtension = contentExtension->compiledExtension(); 123 123 124 DFABytecodeInterpreter withoutConditionsInterpreter( compiledExtension.filtersWithoutConditionsBytecode(), compiledExtension.filtersWithoutConditionsBytecodeLength());124 DFABytecodeInterpreter withoutConditionsInterpreter({ compiledExtension.filtersWithoutConditionsBytecode(), compiledExtension.filtersWithoutConditionsBytecodeLength() }); 125 125 DFABytecodeInterpreter::Actions withoutConditionsActions = withoutConditionsInterpreter.interpret(urlCString, flags); 126 126 127 127 URL topURL = resourceLoadInfo.mainDocumentURL; 128 DFABytecodeInterpreter withConditionsInterpreter( compiledExtension.filtersWithConditionsBytecode(), compiledExtension.filtersWithConditionsBytecodeLength());128 DFABytecodeInterpreter withConditionsInterpreter({ compiledExtension.filtersWithConditionsBytecode(), compiledExtension.filtersWithConditionsBytecodeLength() }); 129 129 DFABytecodeInterpreter::Actions withConditionsActions = withConditionsInterpreter.interpretWithConditions(urlCString, flags, contentExtension->topURLActions(topURL)); 130 130 -
trunk/Source/WebCore/contentextensions/DFABytecode.h
r241316 r286383 28 28 #if ENABLE(CONTENT_EXTENSIONS) 29 29 30 namespace WebCore { 31 32 namespace ContentExtensions { 30 namespace WebCore::ContentExtensions { 33 31 34 typedef uint8_t DFABytecode;32 using DFABytecode = uint8_t; 35 33 36 34 // Increment ContentExtensionStore::CurrentContentExtensionFileVersion … … 61 59 62 60 // AppendAction has one argument: 63 // The action to append ( 4 bytes).61 // The action to append (1-4 bytes). 64 62 AppendAction = 0x6, 65 63 AppendActionWithIfCondition = 0x7, 66 64 67 65 // TestFlagsAndAppendAction has two arguments: 68 // The flags to check before appending ( 2bytes).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). 70 68 TestFlagsAndAppendAction = 0x8, 71 69 TestFlagsAndAppendActionWithIfCondition = 0x9, … … 80 78 81 79 // The last four bits contain the instruction type. 82 const uint8_t DFABytecodeInstructionMask = 0x0F; 83 const uint8_t DFABytecodeJumpSizeMask = 0xF0; 80 static constexpr uint8_t DFABytecodeInstructionMask = 0x0F; 81 static constexpr uint8_t DFABytecodeJumpSizeMask = 0xF0; 82 static constexpr uint8_t DFABytecodeFlagsSizeMask = 0x30; 83 static constexpr uint8_t DFABytecodeActionSizeMask = 0xC0; 84 84 85 85 // DFA bytecode starts with a 4 byte header which contains the size of this DFA. 86 typedef uint32_t DFAHeader; 86 using DFAHeader = uint32_t; 87 88 // DFABytecodeFlagsSize and DFABytecodeActionSize are stored in the top four bits of the DFABytecodeInstructions that have flags and actions. 89 enum 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 }; 94 enum 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 }; 87 100 88 101 // A DFABytecodeJumpSize is stored in the top four bits of the DFABytecodeInstructions that have a jump. 89 enum DFABytecodeJumpSize{102 enum class DFABytecodeJumpSize : uint8_t { 90 103 Int8 = 0x10, 91 104 Int16 = 0x20, … … 93 106 Int32 = 0x40, 94 107 }; 95 const int32_t Int24Max = (1 << 23) - 1; 96 const int32_t Int24Min = -(1 << 23); 108 static constexpr int32_t UInt24Max = (1 << 24) - 1; 109 static constexpr int32_t Int24Max = (1 << 23) - 1; 110 static constexpr int32_t Int24Min = -(1 << 23); 111 static constexpr size_t Int24Size = 3; 112 static constexpr size_t UInt24Size = 3; 97 113 98 114 static inline DFABytecodeJumpSize smallestPossibleJumpSize(int32_t longestPossibleJump) 99 115 { 100 116 if (longestPossibleJump <= std::numeric_limits<int8_t>::max() && longestPossibleJump >= std::numeric_limits<int8_t>::min()) 101 return Int8;117 return DFABytecodeJumpSize::Int8; 102 118 if (longestPossibleJump <= std::numeric_limits<int16_t>::max() && longestPossibleJump >= std::numeric_limits<int16_t>::min()) 103 return Int16;119 return DFABytecodeJumpSize::Int16; 104 120 if (longestPossibleJump <= Int24Max && longestPossibleJump >= Int24Min) 105 return Int24;106 return Int32;121 return DFABytecodeJumpSize::Int24; 122 return DFABytecodeJumpSize::Int32; 107 123 } 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 134 126 135 127 #endif // ENABLE(CONTENT_EXTENSIONS) -
trunk/Source/WebCore/contentextensions/DFABytecodeCompiler.cpp
r275049 r286383 33 33 #include "DFANode.h" 34 34 35 namespace WebCore { 36 37 namespace ContentExtensions { 35 namespace WebCore::ContentExtensions { 38 36 39 37 template <typename IntType> 40 inlinevoid append(Vector<DFABytecode>& bytecode, IntType value)38 void append(Vector<DFABytecode>& bytecode, IntType value) 41 39 { 42 40 bytecode.grow(bytecode.size() + sizeof(IntType)); … … 44 42 } 45 43 46 inline void appendZeroes(Vector<DFABytecode>& bytecode, DFABytecodeJumpSize jumpSize) 44 static void append24BitUnsignedInteger(Vector<DFABytecode>& bytecode, uint32_t value) 45 { 46 append<uint16_t>(bytecode, value); 47 append<uint8_t>(bytecode, value >> 16); 48 } 49 50 static void appendZeroes(Vector<DFABytecode>& bytecode, DFABytecodeJumpSize jumpSize) 47 51 { 48 52 switch (jumpSize) { … … 64 68 65 69 template <typename IntType> 66 inlinevoid setBits(Vector<DFABytecode>& bytecode, uint32_t index, IntType value)70 void setBits(Vector<DFABytecode>& bytecode, uint32_t index, IntType value) 67 71 { 68 72 RELEASE_ASSERT(index + sizeof(IntType) <= bytecode.size()); … … 77 81 return sizeof(DFABytecodeInstruction) + sizeof(uint32_t); 78 82 } 79 83 84 static 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 94 static 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 105 static 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 80 116 void DFABytecodeCompiler::emitAppendAction(uint64_t action) 81 117 { 118 uint32_t actionWithoutFlags = action; 119 auto actionSize = bytecodeActionSize(actionWithoutFlags); 120 82 121 // 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 else87 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 else94 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); 97 136 } 98 137 … … 120 159 int32_t longestPossibleJumpDistance = longestPossibleJump(instructionLocation, sourceNodeIndex, destinationNodeIndex); 121 160 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)); 123 162 124 163 m_linkRecords.append(LinkRecord({jumpSize, longestPossibleJumpDistance, instructionLocation, jumpLocation, destinationNodeIndex})); … … 133 172 DFABytecodeJumpSize jumpSize = smallestPossibleJumpSize(longestPossibleJumpDistance); 134 173 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)); 136 175 append<uint8_t>(m_bytecode, value); 137 176 m_linkRecords.append(LinkRecord({jumpSize, longestPossibleJumpDistance, instructionLocation, jumpLocation, destinationNodeIndex})); … … 148 187 DFABytecodeJumpSize jumpSize = smallestPossibleJumpSize(longestPossibleJumpDistance); 149 188 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)); 151 190 append<uint8_t>(m_bytecode, lowValue); 152 191 append<uint8_t>(m_bytecode, highValue); … … 227 266 } 228 267 229 DFABytecodeCompiler::Transitions DFABytecodeCompiler::transitions(const DFANode& node) 268 auto DFABytecodeCompiler::transitions(const DFANode& node) -> Transitions 230 269 { 231 270 Transitions transitions; … … 351 390 352 391 uint32_t instructionLocation = m_bytecode.size(); 353 DFABytecodeJumpSize jumpSize =Int8;392 auto jumpSize = DFABytecodeJumpSize::Int8; 354 393 for (uint32_t destinationNodeIndex : jumpTable.destinations) { 355 394 int32_t longestPossibleJumpDistance = longestPossibleJump(instructionLocation, nodeIndex, destinationNodeIndex); … … 359 398 360 399 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)); 362 401 append<uint8_t>(m_bytecode, jumpTable.min); 363 402 append<uint8_t>(m_bytecode, jumpTable.max); … … 398 437 size += sizeof(DFABytecodeInstruction::Jump) + sizeof(uint32_t); 399 438 else 400 size += instructionSizeWithArguments(DFABytecodeInstruction::Terminate);439 size += sizeof(DFABytecodeInstruction::Terminate); 401 440 return size; 402 441 } … … 467 506 468 507 switch (linkRecord.jumpSize) { 469 case Int8:508 case DFABytecodeJumpSize::Int8: 470 509 RELEASE_ASSERT(distance == static_cast<int8_t>(distance)); 471 510 setBits<int8_t>(m_bytecode, linkRecord.jumpLocation, static_cast<int8_t>(distance)); 472 511 break; 473 case Int16:512 case DFABytecodeJumpSize::Int16: 474 513 RELEASE_ASSERT(distance == static_cast<int16_t>(distance)); 475 514 setBits<int16_t>(m_bytecode, linkRecord.jumpLocation, static_cast<int16_t>(distance)); 476 515 break; 477 case Int24:516 case DFABytecodeJumpSize::Int24: 478 517 RELEASE_ASSERT(distance >= Int24Min && distance <= Int24Max); 479 518 setBits<uint16_t>(m_bytecode, linkRecord.jumpLocation, static_cast<uint16_t>(distance)); 480 519 setBits<int8_t>(m_bytecode, linkRecord.jumpLocation + sizeof(int16_t), static_cast<int8_t>(distance >> 16)); 481 520 break; 482 case Int32:521 case DFABytecodeJumpSize::Int32: 483 522 setBits<int32_t>(m_bytecode, linkRecord.jumpLocation, distance); 484 523 break; … … 488 527 setBits<DFAHeader>(m_bytecode, startLocation, m_bytecode.size() - startLocation); 489 528 } 490 491 } // namespace ContentExtensions 492 493 } // namespace WebCore 529 530 } // namespace WebCore::ContentExtensions 494 531 495 532 #endif // ENABLE(CONTENT_EXTENSIONS) -
trunk/Source/WebCore/contentextensions/DFABytecodeInterpreter.cpp
r275078 r286383 1 1 /* 2 * Copyright (C) 2015 Apple Inc. All rights reserved.2 * Copyright (C) 2015-2021 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 32 32 #if ENABLE(CONTENT_EXTENSIONS) 33 33 34 namespace WebCore { 35 36 namespace ContentExtensions { 34 namespace WebCore::ContentExtensions { 37 35 38 36 template <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) 37 static 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 43 static 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 51 static DFABytecodeInstruction getInstruction(Span<const uint8_t> bytecode, uint32_t index) 52 { 53 return static_cast<DFABytecodeInstruction>(getBits<uint8_t>(bytecode, index) & DFABytecodeInstructionMask); 54 } 55 56 static size_t jumpSizeInBytes(DFABytecodeJumpSize jumpSize) 51 57 { 52 58 switch (jumpSize) { 53 case Int8:59 case DFABytecodeJumpSize::Int8: 54 60 return sizeof(int8_t); 55 case Int16:61 case DFABytecodeJumpSize::Int16: 56 62 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: 60 66 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 71 template<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 } 76 static uint32_t consume24BitUnsignedInteger(Span<const uint8_t> bytecode, uint32_t& programCounter) 77 { 78 programCounter += UInt24Size; 79 return get24BitsUnsigned(bytecode, programCounter - UInt24Size); 80 } 81 82 static 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 103 static 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 124 static 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 139 static 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 157 static 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); 70 164 return jumpSize; 71 165 } 72 166 73 static in line int32_t getJumpDistance(const DFABytecode* bytecode, uint32_t bytecodeLength, uint32_t index, DFABytecodeJumpSize jumpSize)167 static int32_t getJumpDistance(Span<const uint8_t> bytecode, uint32_t index, DFABytecodeJumpSize jumpSize) 74 168 { 75 169 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 182 static bool matchesCondition(uint64_t actionAndFlags, const DFABytecodeInterpreter::Actions& conditionActions) 90 183 { 91 184 bool ifCondition = actionAndFlags & IfConditionFlag; … … 96 189 void DFABytecodeInterpreter::interpretAppendAction(uint32_t& programCounter, Actions& actions, bool ifCondition) 97 190 { 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; 101 196 if (!m_topURLActions || matchesCondition(action, *m_topURLActions)) 102 197 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 200 void 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; 117 208 118 209 bool loadTypeMatches = loadTypeFlags ? (loadTypeFlags & flags) : true; … … 120 211 bool resourceTypeMatches = resourceTypeFlags ? (resourceTypeFlags & flags) : true; 121 212 213 auto actionWithoutFlags = consumeAction(m_bytecode, programCounter, instructionLocation); 122 214 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); 124 216 if (!m_topURLActions || matchesCondition(actionAndFlags, *m_topURLActions)) 125 217 actions.add(actionAndFlags); 126 218 } 127 programCounter += instructionSizeWithArguments(DFABytecodeInstruction::TestFlagsAndAppendAction);128 ASSERT(instructionSizeWithArguments(DFABytecodeInstruction::TestFlagsAndAppendAction) == instructionSizeWithArguments(DFABytecodeInstruction::TestFlagsAndAppendActionWithIfCondition));129 219 } 130 220 … … 132 222 inline void DFABytecodeInterpreter::interpetJumpTable(const char* url, uint32_t& urlIndex, uint32_t& programCounter, bool& urlIndexIsAfterEndOfString) 133 223 { 134 DFABytecodeJumpSize jumpSize = getJumpSize(m_bytecode, m_bytecodeLength,programCounter);224 DFABytecodeJumpSize jumpSize = getJumpSize(m_bytecode, programCounter); 135 225 136 226 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)); 139 229 if (character >= firstCharacter && character <= lastCharacter) { 140 230 uint32_t startOffset = programCounter + sizeof(DFABytecodeInstruction) + 2 * sizeof(uint8_t); 141 231 uint32_t jumpLocation = startOffset + (character - firstCharacter) * jumpSizeInBytes(jumpSize); 142 programCounter += getJumpDistance(m_bytecode, m_bytecodeLength,jumpLocation, jumpSize);232 programCounter += getJumpDistance(m_bytecode, jumpLocation, jumpSize); 143 233 if (!character) 144 234 urlIndexIsAfterEndOfString = true; … … 148 238 } 149 239 150 DFABytecodeInterpreter::Actions DFABytecodeInterpreter::actionsMatchingEverything() 240 auto DFABytecodeInterpreter::actionsMatchingEverything() -> Actions 151 241 { 152 242 Actions actions; 153 243 154 244 // 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); 157 247 158 248 while (programCounter < dfaBytecodeLength) { 159 DFABytecodeInstruction instruction = getInstruction(m_bytecode, m_bytecodeLength,programCounter);249 DFABytecodeInstruction instruction = getInstruction(m_bytecode, programCounter); 160 250 if (instruction == DFABytecodeInstruction::AppendAction) 161 251 interpretAppendAction(programCounter, actions, false); 162 252 else if (instruction == DFABytecodeInstruction::AppendActionWithIfCondition) 163 253 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 169 260 break; 170 261 } … … 172 263 } 173 264 174 DFABytecodeInterpreter::Actions DFABytecodeInterpreter::interpretWithConditions(const CString& urlCString, uint16_t flags, const DFABytecodeInterpreter::Actions& topURLActions) 265 auto DFABytecodeInterpreter::interpretWithConditions(const CString& urlCString, ResourceFlags flags, const Actions& topURLActions) -> Actions 175 266 { 176 267 ASSERT(!m_topURLActions); 177 268 m_topURLActions = &topURLActions; 178 DFABytecodeInterpreter::Actionsactions = interpret(urlCString, flags);269 auto actions = interpret(urlCString, flags); 179 270 m_topURLActions = nullptr; 180 271 return actions; 181 272 } 182 273 183 DFABytecodeInterpreter::Actions DFABytecodeInterpreter::interpret(const CString& urlCString, uint16_t flags) 274 auto DFABytecodeInterpreter::interpret(const CString& urlCString, ResourceFlags flags) -> Actions 184 275 { 185 276 const char* url = urlCString.data(); … … 189 280 190 281 uint32_t programCounter = 0; 191 while (programCounter < m_bytecode Length) {282 while (programCounter < m_bytecode.size()) { 192 283 193 284 // DFA header. 194 285 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); 196 287 programCounter += sizeof(uint32_t); 197 288 … … 199 290 if (!dfaStart) { 200 291 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) 207 297 interpretTestFlagsAndAppendAction(programCounter, flags, actions, false); 208 298 else if (instruction == DFABytecodeInstruction::TestFlagsAndAppendActionWithIfCondition) … … 211 301 break; 212 302 } 213 if (programCounter >= m_bytecode Length)303 if (programCounter >= m_bytecode.size()) 214 304 return actions; 215 305 } else { 216 ASSERT_WITH_MESSAGE(getInstruction(m_bytecode, m_bytecodeLength,programCounter) != DFABytecodeInstruction::AppendAction217 && getInstruction(m_bytecode, m_bytecodeLength,programCounter) != DFABytecodeInstruction::AppendActionWithIfCondition218 && getInstruction(m_bytecode, m_bytecodeLength,programCounter) != DFABytecodeInstruction::TestFlagsAndAppendAction219 && 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, 220 310 "Triggers that match everything should only be in the first DFA."); 221 311 } … … 226 316 bool urlIndexIsAfterEndOfString = false; 227 317 while (true) { 228 ASSERT(programCounter <= m_bytecode Length);229 switch (getInstruction(m_bytecode, m_bytecodeLength,programCounter)) {318 ASSERT(programCounter <= m_bytecode.size()); 319 switch (getInstruction(m_bytecode, programCounter)) { 230 320 231 321 case DFABytecodeInstruction::Terminate: … … 238 328 // Check to see if the next character in the url is the value stored with the bytecode. 239 329 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))) { 242 332 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); 244 334 if (!character) 245 335 urlIndexIsAfterEndOfString = true; … … 256 346 // Check to see if the next character in the url is the value stored with the bytecode. 257 347 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))) { 260 350 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); 262 352 if (!character) 263 353 urlIndexIsAfterEndOfString = true; … … 286 376 287 377 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))) { 291 381 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); 293 383 if (!character) 294 384 urlIndexIsAfterEndOfString = true; … … 304 394 305 395 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))) { 309 399 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); 311 401 if (!character) 312 402 urlIndexIsAfterEndOfString = true; … … 322 412 323 413 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); 326 416 urlIndex++; // This represents an edge in the DFA. 327 417 break; … … 358 448 } 359 449 360 } // namespace ContentExtensions 361 362 } // namespace WebCore 450 } // namespace WebCore::ContentExtensions 363 451 364 452 #endif // ENABLE(CONTENT_EXTENSIONS) -
trunk/Source/WebCore/contentextensions/DFABytecodeInterpreter.h
r264488 r286383 34 34 #include <wtf/HashSet.h> 35 35 36 namespace WebCore { 37 38 namespace ContentExtensions { 36 namespace WebCore::ContentExtensions { 39 37 40 class WEBCORE_EXPORTDFABytecodeInterpreter {38 class DFABytecodeInterpreter { 41 39 public: 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); 52 47 Actions actionsMatchingEverything(); 53 48 54 49 private: 55 50 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); 57 52 58 53 template<bool caseSensitive> 59 54 void interpetJumpTable(const char* url, uint32_t& urlIndex, uint32_t& programCounter, bool& urlIndexIsAfterEndOfString); 60 55 61 const DFABytecode* m_bytecode; 62 const unsigned m_bytecodeLength; 56 const Span<const uint8_t> m_bytecode; 63 57 const DFABytecodeInterpreter::Actions* m_topURLActions { nullptr }; 64 58 }; 65 59 66 } // namespace ContentExtensions 67 } // namespace WebCore 60 } // namespace WebCore::ContentExtensions 68 61 69 62 #endif // ENABLE(CONTENT_EXTENSIONS) -
trunk/Source/WebCore/loader/PingLoader.cpp
r282860 r286383 160 160 ResourceRequest request(reportURL); 161 161 #if ENABLE(CONTENT_EXTENSIONS) 162 if (processContentRuleListsForLoad(frame, request, ContentExtensions::ResourceType:: Other))162 if (processContentRuleListsForLoad(frame, request, ContentExtensions::ResourceType::CSPReport)) 163 163 return; 164 164 #endif -
trunk/Source/WebCore/loader/ResourceLoadInfo.cpp
r278253 r286383 33 33 #include "SecurityOrigin.h" 34 34 35 namespace WebCore { 36 namespace ContentExtensions { 35 namespace WebCore::ContentExtensions { 37 36 38 37 OptionSet<ResourceType> toResourceType(CachedResource::Type type, ResourceRequestBase::Requester requester) … … 99 98 return { ResourceType::Font }; 100 99 if (name == "raw") 101 return { { ResourceType::Fetch, ResourceType::WebSocket, ResourceType::Other, ResourceType::Ping }};100 return { { ResourceType::Fetch, ResourceType::WebSocket, ResourceType::Other, ResourceType::Ping } }; 102 101 if (name == "websocket") 103 102 return { ResourceType::WebSocket }; … … 105 104 return { ResourceType::Fetch }; 106 105 if (name == "other") 107 return { { ResourceType::Other, ResourceType::Ping }};106 return { { ResourceType::Other, ResourceType::Ping, ResourceType::CSPReport } }; 108 107 if (name == "svg-document") 109 108 return { ResourceType::SVGDocument }; … … 114 113 if (name == "ping") 115 114 return { ResourceType::Ping }; 115 if (name == "csp-report") 116 return { ResourceType::CSPReport }; 116 117 return std::nullopt; 117 118 } … … 150 151 } 151 152 152 } // namespace ContentExtensions 153 } // namespace WebCore 153 } // namespace WebCore::ContentExtensions 154 154 155 155 #endif // ENABLE(CONTENT_EXTENSIONS) -
trunk/Source/WebCore/loader/ResourceLoadInfo.h
r278253 r286383 32 32 #include <wtf/URL.h> 33 33 34 namespace WebCore { 35 namespace ContentExtensions { 34 namespace WebCore::ContentExtensions { 36 35 37 enum class ResourceType : uint 16_t {36 enum class ResourceType : uint32_t { 38 37 Document = 0x0001, 39 38 Image = 0x0002, … … 48 47 WebSocket = 0x0400, 49 48 Other = 0x0800, 49 CSPReport = 0x10000, 50 50 }; 51 const uint16_t ResourceTypeMask = 0x0FFF;51 static constexpr uint32_t ResourceTypeMask = 0x10FFF; 52 52 53 enum class LoadType : uint 16_t {53 enum class LoadType : uint32_t { 54 54 FirstParty = 0x1000, 55 55 ThirdParty = 0x2000, 56 56 }; 57 const uint16_t LoadTypeMask = 0x3000;57 static constexpr uint32_t LoadTypeMask = 0x3000; 58 58 59 enum class LoadContext : uint 16_t {59 enum class LoadContext : uint32_t { 60 60 TopFrame = 0x4000, 61 61 ChildFrame = 0x8000, 62 62 }; 63 const uint16_t LoadContextMask = 0xC000;63 static constexpr uint32_t LoadContextMask = 0xC000; 64 64 65 static_assert(!(ResourceTypeMask & LoadTypeMask), "ResourceTypeMask and LoadTypeMask should be mutually exclusive because they are stored in the same uint 16_t");66 static_assert(!(ResourceTypeMask & LoadContextMask), "ResourceTypeMask and LoadContextMask should be mutually exclusive because they are stored in the same uint 16_t");67 static_assert(!(LoadContextMask & LoadTypeMask), "LoadContextMask and LoadTypeMask should be mutually exclusive because they are stored in the same uint 16_t");65 static_assert(!(ResourceTypeMask & LoadTypeMask), "ResourceTypeMask and LoadTypeMask should be mutually exclusive because they are stored in the same uint32_t"); 66 static_assert(!(ResourceTypeMask & LoadContextMask), "ResourceTypeMask and LoadContextMask should be mutually exclusive because they are stored in the same uint32_t"); 67 static_assert(!(LoadContextMask & LoadTypeMask), "LoadContextMask and LoadTypeMask should be mutually exclusive because they are stored in the same uint32_t"); 68 68 69 typedef uint16_t ResourceFlags;69 using ResourceFlags = uint32_t; 70 70 71 71 // The first 32 bits of a uint64_t action are used for the action location. 72 // The next 16bits are used for the flags (ResourceType and LoadType).72 // The next 24 bits are used for the flags (ResourceType and LoadType). 73 73 // The next bit is used to mark actions that are from a rule with an if-domain. 74 74 // Actions from rules with unless-domain conditions are distinguished from … … 76 76 // Actions from rules with no conditions are put in the DFA without conditions. 77 77 // 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;78 static constexpr uint64_t ActionFlagMask = 0x00FFFFFF00000000; 79 static constexpr uint64_t IfConditionFlag = 0x0100000000000000; 80 80 81 81 OptionSet<ResourceType> toResourceType(CachedResource::Type, ResourceRequestBase::Requester); … … 94 94 }; 95 95 96 } // namespace ContentExtensions 97 } // namespace WebCore 96 } // namespace WebCore::ContentExtensions 98 97 99 98 #endif -
trunk/Tools/ChangeLog
r286376 r286383 1 2021-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 1 15 2021-12-01 Ryan Haddad <ryanhaddad@apple.com> 2 16 -
trunk/Tools/TestWebKitAPI/Tests/WebCore/ContentExtensions.cpp
r286084 r286383 541 541 } 542 542 543 static void compareContents(const ContentExtensions::DFABytecodeInterpreter::Actions& a, const Vector<uint64_t>& b)543 static void compareContents(const DFABytecodeInterpreter::Actions& a, const Vector<uint64_t>& b) 544 544 { 545 545 EXPECT_EQ(a.size(), b.size()); … … 563 563 ContentExtensions::DFABytecodeCompiler compiler(dfa, bytecode); 564 564 compiler.compile(); 565 ContentExtensions::DFABytecodeInterpreter interpreter(bytecode.data(), bytecode.size());565 DFABytecodeInterpreter interpreter({ bytecode.data(), bytecode.size() }); 566 566 compareContents(interpreter.interpret("foo.org", 0), { 0 }); 567 567 compareContents(interpreter.interpret("ba.org", 0), { 0 }); … … 589 589 ContentExtensions::DFABytecodeCompiler compiler(dfa, bytecode); 590 590 compiler.compile(); 591 ContentExtensions::DFABytecodeInterpreter interpreter(bytecode.data(), bytecode.size());591 DFABytecodeInterpreter interpreter({ bytecode.data(), bytecode.size() }); 592 592 compareContents(interpreter.interpret("foo.org", 0), { 0 }); 593 593 compareContents(interpreter.interpret("ba.org", 0), { 1 }); … … 972 972 973 973 ASSERT_EQ(data.actions.size(), 78u); 974 ASSERT_EQ(data.filtersWithoutConditions.size(), 313u);975 ASSERT_EQ(data.filtersWithConditions.size(), 976 ASSERT_EQ(data.topURLFilters.size(), 974 ASSERT_EQ(data.filtersWithoutConditions.size(), 288u); 975 ASSERT_EQ(data.filtersWithConditions.size(), 5u); 976 ASSERT_EQ(data.topURLFilters.size(), 5u); 977 977 ASSERT_FALSE(data.conditionsApplyOnlyToDomain); 978 978 … … 1109 1109 ContentExtensions::DFABytecodeCompiler compiler(dfa, bytecode); 1110 1110 compiler.compile(); 1111 ContentExtensions::DFABytecodeInterpreter interpreter(bytecode.data(), bytecode.size());1111 DFABytecodeInterpreter interpreter({ bytecode.data(), bytecode.size() }); 1112 1112 compareContents(interpreter.interpret("eb", 0), { }); 1113 1113 compareContents(interpreter.interpret("we", 0), { }); … … 1268 1268 } 1269 1269 1270 ContentExtensions::DFABytecodeInterpreter interpreter(&combinedBytecode[0], combinedBytecode.size());1270 DFABytecodeInterpreter interpreter({ combinedBytecode.data(), combinedBytecode.size() }); 1271 1271 1272 1272 patternId = 0; … … 1709 1709 } 1710 1710 1711 ContentExtensions::DFABytecodeInterpreter interpreter(&combinedBytecode[0], combinedBytecode.size());1711 DFABytecodeInterpreter interpreter({ combinedBytecode.data(), combinedBytecode.size() }); 1712 1712 1713 1713 EXPECT_EQ(interpreter.interpret("ABBBX", 0).size(), 1ull); -
trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/ContentRuleListNotification.mm
r284557 r286383 417 417 } 418 418 419 TEST(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 419 439 TEST(ContentRuleList, LegacyVersionAndName) 420 440 { -
trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/WKContentExtensionStore.mm
r286084 r286383 253 253 NSData *data = [NSData dataWithContentsOfURL:[tempDir URLByAppendingPathComponent:fileName]]; 254 254 EXPECT_NOT_NULL(data); 255 EXPECT_EQ(data.length, 22 8u);255 EXPECT_EQ(data.length, 225u); 256 256 257 257 __block bool doneCheckingSource = false;
Note: See TracChangeset
for help on using the changeset viewer.