1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36 package io.netty.handler.codec.http.websocketx;
37
38 import io.netty.buffer.ByteBuf;
39 import io.netty.buffer.ByteBufProcessor;
40 import io.netty.handler.codec.CorruptedFrameException;
41
42
43
44
45 final class Utf8Validator implements ByteBufProcessor {
46 private static final int UTF8_ACCEPT = 0;
47 private static final int UTF8_REJECT = 12;
48
49 private static final byte[] TYPES = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
50 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
51 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
52 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
53 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1,
54 1, 1, 1, 1, 1, 1, 1, 1, 1, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 7, 7, 7, 7,
55 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 8,
56 8, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
57 2, 2, 10, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 3, 3, 11, 6, 6, 6, 5, 8, 8, 8, 8, 8,
58 8, 8, 8, 8, 8, 8 };
59
60 private static final byte[] STATES = { 0, 12, 24, 36, 60, 96, 84, 12, 12, 12, 48, 72, 12, 12,
61 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 0, 12, 12, 12, 12, 12, 0, 12, 0, 12, 12,
62 12, 24, 12, 12, 12, 12, 12, 24, 12, 24, 12, 12, 12, 12, 12, 12, 12, 12, 12, 24, 12, 12,
63 12, 12, 12, 24, 12, 12, 12, 12, 12, 12, 12, 24, 12, 12, 12, 12, 12, 12, 12, 12, 12, 36,
64 12, 36, 12, 12, 12, 36, 12, 12, 12, 12, 12, 36, 12, 36, 12, 12, 12, 36, 12, 12, 12, 12,
65 12, 12, 12, 12, 12, 12 };
66
67 @SuppressWarnings("RedundantFieldInitialization")
68 private int state = UTF8_ACCEPT;
69 private int codep;
70 private boolean checking;
71
72 public void check(ByteBuf buffer) {
73 checking = true;
74 buffer.forEachByte(this);
75 }
76
77 public void finish() {
78 checking = false;
79 codep = 0;
80 if (state != UTF8_ACCEPT) {
81 state = UTF8_ACCEPT;
82 throw new CorruptedFrameException("bytes are not UTF-8");
83 }
84 }
85
86 @Override
87 public boolean process(byte b) throws Exception {
88 byte type = TYPES[b & 0xFF];
89
90 codep = state != UTF8_ACCEPT ? b & 0x3f | codep << 6 : 0xff >> type & b;
91
92 state = STATES[state + type];
93
94 if (state == UTF8_REJECT) {
95 checking = false;
96 throw new CorruptedFrameException("bytes are not UTF-8");
97 }
98 return true;
99 }
100
101 public boolean isChecking() {
102 return checking;
103 }
104 }