Skip to content

Commit f4bccae

Browse files
committed
bugfix
1 parent 3220a9f commit f4bccae

1 file changed

Lines changed: 75 additions & 70 deletions

File tree

websocket_parser.c

Lines changed: 75 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,6 @@
11
#include "websocket_parser.h"
22
#include <assert.h>
3-
#include <stddef.h>
4-
#include <stdlib.h>
53
#include <string.h>
6-
#include <limits.h>
74

85

96
#ifdef __GNUC__
@@ -14,13 +11,16 @@
1411
# define UNEXPECTED(X) (X)
1512
#endif
1613

17-
#define OPCODE_MASK 0xF
14+
#define SET_STATE(V) parser->state = V
15+
#define HAS_DATA() (p < end )
16+
#define CC (*p)
17+
#define GET_PARSED() ( (p == end) ? len : (p - data) )
1818

1919
#define NOTIFY_CB(FOR) \
2020
do { \
2121
if (settings->on_##FOR) { \
2222
if (settings->on_##FOR(parser) != 0) { \
23-
return i; \
23+
return GET_PARSED(); \
2424
} \
2525
} \
2626
} while (0)
@@ -29,7 +29,7 @@ do { \
2929
do { \
3030
if (settings->on_##FOR) { \
3131
if (settings->on_##FOR(parser, ptr, len) != 0) { \
32-
return i; \
32+
return GET_PARSED(); \
3333
} \
3434
} \
3535
} while (0)
@@ -55,114 +55,119 @@ void websocket_parser_settings_init(websocket_parser_settings *settings) {
5555
}
5656

5757
size_t websocket_parser_execute(websocket_parser *parser, const websocket_parser_settings *settings, const char *data, size_t len) {
58-
size_t i = 0;
59-
size_t r = 0;
60-
char c;
58+
const char * p;
59+
const char * end = data + len;
60+
uint8_t header_size = 0;
6161

62-
while(EXPECTED(i < len)) {
63-
c = data[i];
62+
for(p = data; p != end; p++) {
6463
switch(parser->state) {
6564
case s_start:
66-
parser->length = 0;
67-
parser->flags = (uint32_t) (c & WS_OP_MASK);
68-
c >>= 7;
69-
if(EXPECTED(c & 1)) {
65+
parser->length = 0;
66+
parser->mask_offset = 0;
67+
parser->flags = (uint32_t) (CC & WS_OP_MASK);
68+
if(EXPECTED(CC & (1<<7))) {
7069
parser->flags |= WS_FIN;
7170
}
72-
parser->state = s_head;
71+
SET_STATE(s_head);
72+
73+
header_size++;
7374
break;
7475
case s_head:
75-
parser->length = (size_t)c & 0x7F;
76-
if(c & 0x80) {
76+
parser->length = (size_t)CC & 0x7F;
77+
if(CC & 0x80) {
7778
parser->flags |= WS_HAS_MASK;
7879
}
7980
if(EXPECTED(parser->length >= 126)) {
8081
if(EXPECTED(parser->length == 127)) {
81-
if(EXPECTED(len - i > 8)) {
82-
parser->length = (uint16_t)data[i+1];
83-
i += 8;
84-
} else {
85-
parser->require = 8;
86-
parser->state = s_length;
87-
}
82+
parser->require = 8;
8883
} else {
89-
if(EXPECTED(len - i >= 2)) {
90-
parser->length = (uint16_t)data[i+1];
91-
i += 2;
92-
} else {
93-
parser->require = 2;
94-
}
84+
parser->require = 2;
9585
}
86+
SET_STATE(s_length);
87+
} else if (EXPECTED(parser->flags & WS_HAS_MASK)) {
88+
SET_STATE(s_mask);
89+
parser->require = 4;
90+
} else if (EXPECTED(parser->length)) {
91+
SET_STATE(s_body);
92+
parser->require = parser->length;
93+
NOTIFY_CB(frame_header);
9694
} else {
95+
SET_STATE(s_start);
96+
NOTIFY_CB(frame_header);
97+
NOTIFY_CB(frame_end);
9798
}
98-
if(EXPECTED(parser->require)) {
99-
parser->state = s_length;
100-
} else {
101-
if(EXPECTED(parser->flags & WS_HAS_MASK)) {
102-
parser->state = s_mask;
99+
100+
header_size++;
101+
break;
102+
case s_length:
103+
while(HAS_DATA() && parser->require) {
104+
parser->length <<= 8;
105+
parser->length |= (unsigned char)CC;
106+
parser->require--;
107+
header_size++;
108+
p++;
109+
}
110+
p--;
111+
if(UNEXPECTED(!parser->require)) {
112+
if (EXPECTED(parser->flags & WS_HAS_MASK)) {
113+
SET_STATE(s_mask);
103114
parser->require = 4;
104-
} else if(EXPECTED(parser->length)) {
115+
} else if (EXPECTED(parser->length)) {
116+
SET_STATE(s_body);
105117
parser->require = parser->length;
106118
NOTIFY_CB(frame_header);
107-
parser->state = s_body;
108119
} else {
120+
SET_STATE(s_start);
109121
NOTIFY_CB(frame_header);
110122
NOTIFY_CB(frame_end);
111-
parser->state = s_start;
112123
}
113124
}
114125
break;
115-
case s_length:
116-
while(i < len && parser->require) {
117-
parser->length <<= 8;
118-
parser->length |= (unsigned char)data[i++];
119-
parser->require--;
120-
}
121-
i--;
122-
if(!UNEXPECTED(parser->require)) {
123-
parser->require = parser->length;
124-
NOTIFY_CB(frame_header);
125-
parser->state = s_body;
126-
}
127-
break;
128126
case s_mask:
129-
while(i < len && parser->require) {
130-
parser->mask[4 - parser->require--] = data[i++];
127+
while(HAS_DATA() && parser->require) {
128+
parser->mask[4 - parser->require--] = CC;
129+
header_size++;
130+
p++;
131131
}
132-
i--;
133-
if(!UNEXPECTED(parser->require)) {
132+
p--;
133+
if(UNEXPECTED(!parser->require)) {
134134
if(parser->length) {
135+
SET_STATE(s_body);
135136
parser->require = parser->length;
136137
NOTIFY_CB(frame_header);
137-
parser->state = s_body;
138138
} else {
139+
SET_STATE(s_start);
139140
NOTIFY_CB(frame_header);
140141
NOTIFY_CB(frame_end);
141-
parser->state = s_start;
142142
}
143143
}
144144
break;
145145
case s_body:
146146
if(EXPECTED(parser->require)) {
147-
r = parser->require;
148-
parser->require -= len - i;
149-
EMIT_DATA_CB(frame_body, &data[i], len - i);
150-
parser->offset = len - parser->require;
151-
i+=r;
147+
if(p + parser->require <= end) {
148+
EMIT_DATA_CB(frame_body, p, parser->require);
149+
p += parser->require;
150+
parser->require = 0;
151+
} else {
152+
EMIT_DATA_CB(frame_body, p, end - p);
153+
parser->require -= end - p;
154+
p = end;
155+
parser->offset += p - data - header_size;
156+
}
157+
158+
p--;
152159
}
153-
if(!UNEXPECTED(parser->require)) {
160+
if(UNEXPECTED(!parser->require)) {
154161
NOTIFY_CB(frame_end);
155-
parser->state = s_start;
162+
SET_STATE(s_start);
156163
}
157164
break;
158165
default:
159-
parser->error = ERR_UNKNOWN_STATE;
160-
return i;
166+
assert(0 && "Unreachable case");
161167
}
162-
i++;
163168
}
164169

165-
return i;
170+
return GET_PARSED();
166171
}
167172

168173
void websocket_parser_decode(char * dst, const char * src, size_t len, websocket_parser * parser) {
@@ -171,7 +176,7 @@ void websocket_parser_decode(char * dst, const char * src, size_t len, websocket
171176
dst[i] = src[i] ^ parser->mask[(i + parser->mask_offset) % 4];
172177
}
173178

174-
parser->mask_offset = (uint8_t) ((i + parser->mask_offset + 1) % 4);
179+
parser->mask_offset = (uint8_t) ((i + parser->mask_offset) % 4);
175180
}
176181

177182
uint8_t websocket_decode(char * dst, const char * src, size_t len, char mask[4], uint8_t mask_offset) {

0 commit comments

Comments
 (0)