Skip to content

Commit def8b58

Browse files
Merge pull request #7018 from maxteufel/push-mwpwurrquzkp
http: handle extensions for chunked transfer encoding
2 parents 32be061 + 557d1e1 commit def8b58

1 file changed

Lines changed: 37 additions & 0 deletions

File tree

modules/http/src/http/Message.fz

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -239,6 +239,7 @@ body_reader_chunked(LM type : mutate) : io.Read_Handler is
239239

240240
chunk_start is
241241
chunk_size is
242+
chunk_extension is
242243
chunk_post_size is
243244
chunk_end_start is
244245
chunk_end_finalize is
@@ -250,6 +251,7 @@ body_reader_chunked(LM type : mutate) : io.Read_Handler is
250251
chunk_enum : choice
251252
chunk_start
252253
chunk_size
254+
chunk_extension
253255
chunk_post_size
254256
chunk_end_start
255257
chunk_end_finalize
@@ -258,8 +260,11 @@ body_reader_chunked(LM type : mutate) : io.Read_Handler is
258260
chunk_post_body_finalize
259261
chunk_end_of_file is
260262

263+
extension_limit := (u64 1024) * 64 # arbitrary value, see below
264+
261265
position := mut chunk_enum chunk_start
262266
current_chunk_size := mut u64 0
267+
extension_size := mut u64 0
263268

264269
update_current_chunk_size (new option u64) choice (Sequence u8) io.end_of_file error =>
265270
match new
@@ -300,6 +305,9 @@ body_reader_chunked(LM type : mutate) : io.Read_Handler is
300305
else if c = 0x0d
301306
position <- chunk_post_size
302307
Sequence u8 .empty
308+
else if c = 0x3b
309+
position <- chunk_extension
310+
Sequence u8 .empty
303311
else
304312
error "chunk size invalid"
305313

@@ -388,6 +396,34 @@ body_reader_chunked(LM type : mutate) : io.Read_Handler is
388396
error "invalid termination of body, expected LF found {c}"
389397

390398

399+
handle_extension (s Sequence u8) choice (Sequence u8) io.end_of_file error =>
400+
c := s.first.or_panic
401+
402+
(io.buffered LM).reader.env.discard 1
403+
404+
if c = 0x0d
405+
position <- chunk_end_finalize
406+
Sequence u8 .empty
407+
else if c = 0x0a
408+
error "invalid newline in chunk extension"
409+
else
410+
extension_size <- extension_size.get + 1
411+
412+
if extension_size.get > extension_limit
413+
# this static limit is kinda arbitrary, we could add more magic to allow
414+
# extensions proportional to the content size, but this does not matter
415+
# yet
416+
#
417+
# the limit exists to protect against DoS attacks where the sender of
418+
# the message sends a small chunk with a long extension part
419+
error "chunk extensions too long"
420+
else
421+
# we do nothing with the extensions, as per the spec they must be
422+
# ignored if they are not understood
423+
position <- chunk_extension
424+
Sequence u8 .empty
425+
426+
391427
public redef read(max_count i32) choice (Sequence u8) io.end_of_file error =>
392428
match (io.buffered LM).reader.env.read
393429
s Sequence =>
@@ -397,6 +433,7 @@ body_reader_chunked(LM type : mutate) : io.Read_Handler is
397433
match position.get
398434
chunk_start => handle_start s
399435
chunk_size => handle_size s
436+
chunk_extension => handle_extension s
400437
chunk_post_size => handle_post_size s
401438
chunk_end_start => handle_end_start s
402439
chunk_end_finalize => handle_end_finalize s

0 commit comments

Comments
 (0)