@@ -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