From 593485c652049db4158c8ee19557dc9a14582176 Mon Sep 17 00:00:00 2001 From: Tatsuhiro Tsujikawa Date: Wed, 2 Jul 2014 22:25:32 +0900 Subject: [PATCH] Put a limit for total contiguous headers length currently receiving --- lib/nghttp2_frame.h | 7 +++++++ lib/nghttp2_session.c | 30 ++++++++++++++++++++++++++++-- lib/nghttp2_session.h | 3 +++ 3 files changed, 38 insertions(+), 2 deletions(-) diff --git a/lib/nghttp2_frame.h b/lib/nghttp2_frame.h index 950e6086..0bd2e77c 100644 --- a/lib/nghttp2_frame.h +++ b/lib/nghttp2_frame.h @@ -50,9 +50,16 @@ #define NGHTTP2_FRAMEBUF_CHUNKLEN \ (NGHTTP2_FRAME_HDLEN + 1 + NGHTTP2_MAX_PAYLOADLEN) +/* Number of inbound buffer */ +#define NGHTTP2_FRAMEBUF_MAX_NUM 5 + /* The maximum length of DATA frame payload. */ #define NGHTTP2_DATA_PAYLOADLEN 4096 +/* Maximum headers payload length, calculated in compressed form. + This applies to both transmission and reception. */ +#define NGHTTP2_MAX_HEADERSLEN 65536 + /* The number of bytes for each SETTINGS entry */ #define NGHTTP2_FRAME_SETTINGS_ENTRY_LENGTH 6 diff --git a/lib/nghttp2_session.c b/lib/nghttp2_session.c index 9ae6cff1..f8816400 100644 --- a/lib/nghttp2_session.c +++ b/lib/nghttp2_session.c @@ -257,6 +257,7 @@ static void session_inbound_frame_reset(nghttp2_session *session) iframe->niv = 0; iframe->payloadleft = 0; iframe->padlen = 0; + iframe->headers_payload_length = 0; } static void init_settings(nghttp2_settings_storage *settings) @@ -342,8 +343,8 @@ static int session_new(nghttp2_session **session_ptr, /* 1 for Pad Field. */ rv = nghttp2_bufs_init3(&(*session_ptr)->aob.framebufs, - NGHTTP2_FRAMEBUF_CHUNKLEN, 4, 1, - NGHTTP2_FRAME_HDLEN + 1); + NGHTTP2_FRAMEBUF_CHUNKLEN, NGHTTP2_FRAMEBUF_MAX_NUM, + 1, NGHTTP2_FRAME_HDLEN + 1); if(rv != 0) { goto fail_aob_framebuf; } @@ -4192,6 +4193,8 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, NGHTTP2_FLAG_PADDED | NGHTTP2_FLAG_PRIORITY); + iframe->headers_payload_length = iframe->frame.hd.length; + rv = inbound_frame_handle_pad(iframe, &iframe->frame.hd); if(rv < 0) { busy = 1; @@ -4317,6 +4320,8 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, iframe->frame.hd.flags &= (NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_PADDED); + iframe->headers_payload_length = iframe->frame.hd.length; + rv = inbound_frame_handle_pad(iframe, &iframe->frame.hd); if(rv < 0) { busy = 1; @@ -4891,6 +4896,27 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, break; } + iframe->headers_payload_length += cont_hd.length; + + if(iframe->headers_payload_length > NGHTTP2_MAX_HEADERSLEN) { + + DEBUGF(fprintf(stderr, + "recv: headers too large %zu\n", + iframe->headers_payload_length)); + + rv = nghttp2_session_terminate_session(session, + NGHTTP2_INTERNAL_ERROR); + if(nghttp2_is_fatal(rv)) { + return rv; + } + + busy = 1; + + iframe->state = NGHTTP2_IB_IGN_PAYLOAD; + + break; + } + /* CONTINUATION won't bear NGHTTP2_PADDED flag */ iframe->frame.hd.flags |= cont_hd.flags & NGHTTP2_FLAG_END_HEADERS; diff --git a/lib/nghttp2_session.h b/lib/nghttp2_session.h index 0cf28ffc..fd424634 100644 --- a/lib/nghttp2_session.h +++ b/lib/nghttp2_session.h @@ -102,6 +102,9 @@ typedef struct { size_t payloadleft; /* padding length for the current frame */ size_t padlen; + /* Sum of payload of (HEADERS | PUSH_PROMISE) + possible + CONTINUATION received so far. */ + size_t headers_payload_length; nghttp2_inbound_state state; uint8_t raw_sbuf[8]; } nghttp2_inbound_frame;