1 | /* |
2 | * Copyright (C) 2015 Apple Inc. All rights reserved. |
3 | * |
4 | * Redistribution and use in source and binary forms, with or without |
5 | * modification, are permitted provided that the following conditions |
6 | * are met: |
7 | * 1. Redistributions of source code must retain the above copyright |
8 | * notice, this list of conditions and the following disclaimer. |
9 | * 2. Redistributions in binary form must reproduce the above copyright |
10 | * notice, this list of conditions and the following disclaimer in the |
11 | * documentation and/or other materials provided with the distribution. |
12 | * |
13 | * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' |
14 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, |
15 | * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
16 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS |
17 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
18 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
19 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
20 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
21 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
22 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF |
23 | * THE POSSIBILITY OF SUCH DAMAGE. |
24 | */ |
25 | |
26 | #pragma once |
27 | |
28 | #if ENABLE(CONTENT_EXTENSIONS) |
29 | |
30 | namespace WebCore { |
31 | |
32 | namespace ContentExtensions { |
33 | |
34 | typedef uint8_t DFABytecode; |
35 | |
36 | // Increment ContentExtensionStore::CurrentContentExtensionFileVersion |
37 | // when making any non-backwards-compatible changes to the bytecode. |
38 | // FIXME: Changes here should not require changes in WebKit2. Move all versioning to WebCore. |
39 | enum class DFABytecodeInstruction : uint8_t { |
40 | |
41 | // CheckValue has two arguments: |
42 | // The value to check (1 byte), |
43 | // The distance to jump if the values are equal (1-4 bytes, signed). |
44 | CheckValueCaseInsensitive = 0x0, |
45 | CheckValueCaseSensitive = 0x1, |
46 | |
47 | // Jump table if the input value is within a certain range. |
48 | // The lower value (1 byte). |
49 | // The higher value (1 byte). |
50 | // The distance to jump if the value is in the range |
51 | // for every character in the range (1-4 bytes, signed). |
52 | JumpTableCaseInsensitive = 0x2, |
53 | JumpTableCaseSensitive = 0x3, |
54 | |
55 | // Jump to an offset if the input value is within a certain range. |
56 | // The lower value (1 byte). |
57 | // The higher value (1 byte). |
58 | // The distance to jump if the value is in the range (1-4 bytes, signed). |
59 | CheckValueRangeCaseInsensitive = 0x4, |
60 | CheckValueRangeCaseSensitive = 0x5, |
61 | |
62 | // AppendAction has one argument: |
63 | // The action to append (4 bytes). |
64 | AppendAction = 0x6, |
65 | AppendActionWithIfCondition = 0x7, |
66 | |
67 | // TestFlagsAndAppendAction has two arguments: |
68 | // The flags to check before appending (2 bytes). |
69 | // The action to append (4 bytes). |
70 | TestFlagsAndAppendAction = 0x8, |
71 | TestFlagsAndAppendActionWithIfCondition = 0x9, |
72 | |
73 | // Terminate has no arguments. |
74 | Terminate = 0xA, |
75 | |
76 | // Jump has one argument: |
77 | // The distance to jump (1-4 bytes, signed). |
78 | Jump = 0xB, |
79 | }; |
80 | |
81 | // The last four bits contain the instruction type. |
82 | const uint8_t DFABytecodeInstructionMask = 0x0F; |
83 | const uint8_t DFABytecodeJumpSizeMask = 0xF0; |
84 | |
85 | // DFA bytecode starts with a 4 byte header which contains the size of this DFA. |
86 | typedef uint32_t ; |
87 | |
88 | // A DFABytecodeJumpSize is stored in the top four bits of the DFABytecodeInstructions that have a jump. |
89 | enum DFABytecodeJumpSize { |
90 | Int8 = 0x10, |
91 | Int16 = 0x20, |
92 | Int24 = 0x30, |
93 | Int32 = 0x40, |
94 | }; |
95 | const int32_t Int24Max = (1 << 23) - 1; |
96 | const int32_t Int24Min = -(1 << 23); |
97 | |
98 | static inline DFABytecodeJumpSize smallestPossibleJumpSize(int32_t longestPossibleJump) |
99 | { |
100 | if (longestPossibleJump <= std::numeric_limits<int8_t>::max() && longestPossibleJump >= std::numeric_limits<int8_t>::min()) |
101 | return Int8; |
102 | if (longestPossibleJump <= std::numeric_limits<int16_t>::max() && longestPossibleJump >= std::numeric_limits<int16_t>::min()) |
103 | return Int16; |
104 | if (longestPossibleJump <= Int24Max && longestPossibleJump >= Int24Min) |
105 | return Int24; |
106 | return Int32; |
107 | } |
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 |
134 | |
135 | #endif // ENABLE(CONTENT_EXTENSIONS) |
136 | |