Skip to content

Commit 21c0f7f

Browse files
committed
feat: require \r\n before all boundaries but the first
1 parent 099777b commit 21c0f7f

File tree

3 files changed

+39
-8
lines changed

3 files changed

+39
-8
lines changed

src/multipart_form/tiny_httpd_multipart_form_data.ml

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ type st = {
2727
boundary: string;
2828
ic: Iostream.In.t;
2929
buf: buf; (** Used to split on the boundary *)
30+
mutable first: bool; (** Are we parsing the first boundary? *)
3031
mutable eof_split: bool;
3132
buf_out: buf; (** Used to return output slices *)
3233
mutable st_out: out_state;
@@ -37,6 +38,7 @@ let create ?(buf_size = 64 * 1024) ?(out_buf_size = 8 * 1024) ~boundary ic : st
3738
let ic = (ic : #Iostream.In.t :> Iostream.In.t) in
3839
{
3940
boundary;
41+
first = true;
4042
ic;
4143
buf = { bs = Bytes.create buf_size; len = 0 };
4244
eof_split = false;
@@ -46,7 +48,14 @@ let create ?(buf_size = 64 * 1024) ?(out_buf_size = 8 * 1024) ~boundary ic : st
4648

4749
type chunk = Delim | Eof | Read of int
4850

49-
let[@inline] min_len_ (self : st) : int = 2 + String.length self.boundary
51+
let[@inline] prefix_size_ (self : st) : int =
52+
if self.first then
53+
2
54+
else
55+
4
56+
57+
let[@inline] min_len_ (self : st) : int =
58+
prefix_size_ self + String.length self.boundary
5059

5160
exception Found_boundary of int
5261

@@ -74,15 +83,27 @@ let rec read_chunk_ (self : st) buf i_buf len : chunk =
7483
) else (
7584
try
7685
let i = ref 0 in
77-
let end_pos = min len self.buf.len - 2 - String.length self.boundary in
86+
let end_pos =
87+
min len self.buf.len - prefix_size_ self - String.length self.boundary
88+
in
7889
while !i <= end_pos do
7990
if
80-
Bytes.unsafe_get self.buf.bs !i = '-'
91+
self.first
92+
&& Bytes.unsafe_get self.buf.bs !i = '-'
8193
&& Bytes.unsafe_get self.buf.bs (!i + 1) = '-'
8294
&& Utils_.string_eq
8395
~a:(Bytes.unsafe_to_string self.buf.bs)
8496
~a_start:(!i + 2) ~b:self.boundary
8597
~len:(String.length self.boundary)
98+
|| (not self.first)
99+
&& Bytes.unsafe_get self.buf.bs !i = '\r'
100+
&& Bytes.unsafe_get self.buf.bs (!i + 1) = '\n'
101+
&& Bytes.unsafe_get self.buf.bs (!i + 2) = '-'
102+
&& Bytes.unsafe_get self.buf.bs (!i + 3) = '-'
103+
&& Utils_.string_eq
104+
~a:(Bytes.unsafe_to_string self.buf.bs)
105+
~a_start:(!i + 4) ~b:self.boundary
106+
~len:(String.length self.boundary)
86107
then
87108
raise_notrace (Found_boundary !i);
88109
incr i
@@ -93,7 +114,8 @@ let rec read_chunk_ (self : st) buf i_buf len : chunk =
93114
Read n_read
94115
with
95116
| Found_boundary 0 ->
96-
shift_left_ self.buf (2 + String.length self.boundary);
117+
shift_left_ self.buf (prefix_size_ self + String.length self.boundary);
118+
self.first <- false;
97119
Delim
98120
| Found_boundary n ->
99121
let n_read = min n len in
@@ -189,6 +211,7 @@ and parse_headers_rec (self : st) acc : Headers.t =
189211
)
190212
| i ->
191213
let line = Bytes.sub_string self.buf_out.bs 0 i in
214+
Printf.eprintf "parse header line %S\n%!" line;
192215
shift_left_ self.buf_out (i + 2);
193216
if line = "" then
194217
List.rev acc

tests/multipart_form/t_chunk.ml

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -40,11 +40,14 @@ let () =
4040
test
4141
"hello--YOLO\n\
4242
\ world\n\
43-
\ what is the meaning of--YOLOthis??--YOLOok ok ok--YOLO";
43+
\ what is the meaning of\r\n\
44+
--YOLOthis??\r\n\
45+
--YOLOok ok ok\r\n\
46+
--YOLO";
4447
pf "T2\n";
45-
test "--YOLO--YOLOah bon--YOLOaight--YOLO--YOLO";
48+
test "--YOLO\r\n--YOLOah bon\r\n--YOLOaight\r\n--YOLO\r\n--YOLO";
4649
pf "T3\n";
4750
test
48-
(spf "--YOLO%s--YOLO--YOLO%s--YOLO%s" (String.make 400 'a')
51+
(spf "--YOLO%s\r\n--YOLO\r\n--YOLO%s\r\n--YOLO%s" (String.make 400 'a')
4952
(String.make 512 'b') (String.make 400 'c'));
5053
()

tests/multipart_form/t_parse.ml

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,10 +46,12 @@ let () =
4646
ohlook: here\r\n\
4747
\r\n\
4848
and now for the b-o-d-y 👏\n\
49+
\r\n\
4950
--YOLO\r\n\
5051
more: headers\r\n\
5152
\r\n\
5253
and another body\r\n\
54+
\r\n\
5355
--YOLO--";
5456
pf "T1\n";
5557
test
@@ -60,8 +62,11 @@ let () =
6062
\r\n\
6163
and now for the bigger body:\n\
6264
%s\n\
65+
\r\n\
6366
--YOLO\r\n\
6467
more: headers\r\n\
6568
\r\n\
66-
and another body--YOLO--" (String.make 500 'a'));
69+
and another body\r\n\
70+
--YOLO--"
71+
(String.make 500 'a'));
6772
()

0 commit comments

Comments
 (0)