/* new header line */
line->name_offset = ctx->input->v_offset;
colon_pos = UINT_MAX;
- ctx->header_block_total_size += ctx->value_buf->used;
buffer_set_used_size(ctx->value_buf, 0);
}
}
}
- line->value_len = I_MIN(line->value_len, ctx->header_block_max_size);
size_t line_value_size = line->value_len;
- size_t header_total_used = ctx->header_block_total_size + ctx->value_buf->used;
- size_t line_available = ctx->header_block_max_size <= header_total_used ? 0 :
- ctx->header_block_max_size - header_total_used;
+ /* Clamp line_value_size against the remaining header_block_max_size
+ budget. header_block_total_size is the running sum of
+ line_value_size across all chunks of all headers; value_buf growth
+ is bounded implicitly because every append to value_buf uses
+ line_value_size. */
+ size_t line_available =
+ ctx->header_block_max_size <= ctx->header_block_total_size ? 0 :
+ ctx->header_block_max_size - ctx->header_block_total_size;
line_value_size = I_MIN(line_value_size, line_available);
+ ctx->header_block_total_size += line_value_size;
if (!line->continued) {
/* first header line. make a copy of the line since we can't
line->full_value = ctx->value_buf->data;
line->full_value_len = ctx->value_buf->used;
+ line->value_len = line_value_size;
} else {
/* we didn't want full_value, and this is a continued line. */
line->full_value = NULL;
line->full_value_len = 0;
+ line->value_len = line_value_size;
}
/* always reset it */
struct message_header_parser_ctx *parser = message_parse_header_init(input, NULL, MESSAGE_HEADER_PARSER_FLAG_CLEAN_ONELINE);
message_parse_header_set_limit(parser, 96);
+ /* hdr->value is now also clamped cumulatively against the same
+ header_block_max_size budget as full_value, so later chunks of a
+ multiline header shrink or disappear once the budget is used up. */
assert_parse_line( 1, "header1", "this is short", "this is short");
assert_parse_line( 2, "header2", "this is multiline", "this is multiline");
assert_parse_line( 3, "header2", " and long 343638404244464850525456586062", "this is multiline and long 343638404244464850525456586062");
- assert_parse_line( 4, "header2", " 64666870727476788082848688909294969800", "this is multiline and long 343638404244464850525456586062 6466687072747678808284868");
- assert_parse_line( 5, "header2", " 02040608101214161820222426283032343638", "this is multiline and long 343638404244464850525456586062 6466687072747678808284868");
+ assert_parse_line( 4, "header2", " 6466687072747678808284868", "this is multiline and long 343638404244464850525456586062 6466687072747678808284868");
+ assert_parse_line( 5, "header2", "", "this is multiline and long 343638404244464850525456586062 6466687072747678808284868");
assert_parse_line( 6, "header3", "", "");
test_assert(message_parse_header_next(parser, &hdr) > 0 && hdr->eoh);
struct message_header_parser_ctx *parser = message_parse_header_init(input, NULL, 0);
message_parse_header_set_limit(parser, 96);
+ /* hdr->value is clamped cumulatively against header_block_max_size.
+ The \n that NO flags inserts between continuations goes into
+ value_buf but is not added to header_block_total_size, so line 4's
+ value hits the same 26-byte cap as in CLEAN_ONELINE and
+ full_value_len is one byte larger than the nominal limit. */
assert_parse_line( 1, "header1", "this is short", "this is short");
assert_parse_line( 2, "header2", "this is multiline", "this is multiline");
assert_parse_line( 3, "header2", " and long 343638404244464850525456586062", "this is multiline\n and long 343638404244464850525456586062");
- assert_parse_line( 4, "header2", " 64666870727476788082848688909294969800", "this is multiline\n and long 343638404244464850525456586062\n 646668707274767880828486");
- assert_parse_line( 5, "header2", " 02040608101214161820222426283032343638", "this is multiline\n and long 343638404244464850525456586062\n 646668707274767880828486");
+ assert_parse_line( 4, "header2", " 6466687072747678808284868", "this is multiline\n and long 343638404244464850525456586062\n 6466687072747678808284868");
+ assert_parse_line( 5, "header2", "", "this is multiline\n and long 343638404244464850525456586062\n 6466687072747678808284868");
assert_parse_line( 6, "header3", "", "");
test_assert(message_parse_header_next(parser, &hdr) > 0 && hdr->eoh);