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
30namespace WebCore {
31
32namespace ContentExtensions {
33
34typedef 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.
39enum 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.
82const uint8_t DFABytecodeInstructionMask = 0x0F;
83const uint8_t DFABytecodeJumpSizeMask = 0xF0;
84
85// DFA bytecode starts with a 4 byte header which contains the size of this DFA.
86typedef uint32_t DFAHeader;
87
88// A DFABytecodeJumpSize is stored in the top four bits of the DFABytecodeInstructions that have a jump.
89enum DFABytecodeJumpSize {
90 Int8 = 0x10,
91 Int16 = 0x20,
92 Int24 = 0x30,
93 Int32 = 0x40,
94};
95const int32_t Int24Max = (1 << 23) - 1;
96const int32_t Int24Min = -(1 << 23);
97
98static 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
109static 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