CVE-2024-28182: Insufficient Information (NVD-CWE-noinfo)
value: nghttp2 is an implementation of the Hypertext Transfer Protocol version 2 in C. The nghttp2 library prior to version 1.61.0 keeps reading the unbounded number of HTTP/2 CONTINUATION frames even after a stream is reset to keep HPACK context in sync.  This causes excessive CPU usage to decode HPACK stream. nghttp2 v1.61.0 mitigates this vulnerability by limiting the number of CONTINUATION frames it accepts per stream. There is no workaround for this vulnerability.
CWE description: There is insufficient information about the issue to classify it; details are unkown or unspecified.
Published: 2024-04-04T15:15Z
Repository: https://github.com/nghttp2/nghttp2
Language: C
Files changed: doc/Makefile.am, lib/includes/nghttp2/nghttp2.h, lib/nghttp2_option.c, lib/nghttp2_option.h, lib/nghttp2_session.c
Commit date: 2024-04-04 17:08:46 +0900
Commit message: Add nghttp2_option_set_max_continuations

Diff: diff --git a/doc/Makefile.am b/doc/Makefile.am
index 51945e4f0..50d57b221 100644
--- a/doc/Makefile.am
+++ b/doc/Makefile.am
@@ -75,10 +75,11 @@ APIDOCS= \
 	nghttp2_option_set_no_recv_client_magic.rst \
 	nghttp2_option_set_no_rfc9113_leading_and_trailing_ws_validation.rst \
 	nghttp2_option_set_peer_max_concurrent_streams.rst \
 	nghttp2_option_set_server_fallback_rfc7540_priorities.rst \
 	nghttp2_option_set_user_recv_extension_type.rst \
+	nghttp2_option_set_max_continuations.rst \
 	nghttp2_option_set_max_outbound_ack.rst \
 	nghttp2_option_set_max_settings.rst \
 	nghttp2_option_set_stream_reset_rate_limit.rst \
 	nghttp2_pack_settings_payload.rst \
 	nghttp2_pack_settings_payload2.rst \
diff --git a/lib/includes/nghttp2/nghttp2.h b/lib/includes/nghttp2/nghttp2.h
index a9629c782..92c3ccc6e 100644
--- a/lib/includes/nghttp2/nghttp2.h
+++ b/lib/includes/nghttp2/nghttp2.h
@@ -3208,10 +3208,21 @@ nghttp2_option_set_no_rfc9113_leading_and_trailing_ws_validation(
  */
 NGHTTP2_EXTERN void
 nghttp2_option_set_stream_reset_rate_limit(nghttp2_option *option,
                                            uint64_t burst, uint64_t rate);
 
+/**
+ * @function
+ *
+ * This function sets the maximum number of CONTINUATION frames
+ * following an incoming HEADER frame.  If more than those frames are
+ * received, the remote endpoint is considered to be misbehaving and
+ * session will be closed.  The default value is 8.
+ */
+NGHTTP2_EXTERN void nghttp2_option_set_max_continuations(nghttp2_option *option,
+                                                         size_t val);
+
 /**
  * @function
  *
  * Initializes |*session_ptr| for client use.  The all members of
  * |callbacks| are copied to |*session_ptr|.  Therefore |*session_ptr|
diff --git a/lib/nghttp2_option.c b/lib/nghttp2_option.c
index 43d4e9522..53144b9b7 100644
--- a/lib/nghttp2_option.c
+++ b/lib/nghttp2_option.c
@@ -148,5 +148,10 @@ void nghttp2_option_set_stream_reset_rate_limit(nghttp2_option *option,
                                                 uint64_t burst, uint64_t rate) {
   option->opt_set_mask |= NGHTTP2_OPT_STREAM_RESET_RATE_LIMIT;
   option->stream_reset_burst = burst;
   option->stream_reset_rate = rate;
 }
+
+void nghttp2_option_set_max_continuations(nghttp2_option *option, size_t val) {
+  option->opt_set_mask |= NGHTTP2_OPT_MAX_CONTINUATIONS;
+  option->max_continuations = val;
+}
diff --git a/lib/nghttp2_option.h b/lib/nghttp2_option.h
index 2259e1849..c89cb97f8 100644
--- a/lib/nghttp2_option.h
+++ b/lib/nghttp2_option.h
@@ -69,10 +69,11 @@ typedef enum {
   NGHTTP2_OPT_MAX_OUTBOUND_ACK = 1 << 11,
   NGHTTP2_OPT_MAX_SETTINGS = 1 << 12,
   NGHTTP2_OPT_SERVER_FALLBACK_RFC7540_PRIORITIES = 1 << 13,
   NGHTTP2_OPT_NO_RFC9113_LEADING_AND_TRAILING_WS_VALIDATION = 1 << 14,
   NGHTTP2_OPT_STREAM_RESET_RATE_LIMIT = 1 << 15,
+  NGHTTP2_OPT_MAX_CONTINUATIONS = 1 << 16,
 } nghttp2_option_flag;
 
 /**
  * Struct to store option values for nghttp2_session.
  */
@@ -96,10 +97,14 @@ struct nghttp2_option {
   size_t max_outbound_ack;
   /**
    * NGHTTP2_OPT_MAX_SETTINGS
    */
   size_t max_settings;
+  /**
+   * NGHTTP2_OPT_MAX_CONTINUATIONS
+   */
+  size_t max_continuations;
   /**
    * Bitwise OR of nghttp2_option_flag to determine that which fields
    * are specified.
    */
   uint32_t opt_set_mask;
diff --git a/lib/nghttp2_session.c b/lib/nghttp2_session.c
index fc4c77a3f..004a4dffa 100644
--- a/lib/nghttp2_session.c
+++ b/lib/nghttp2_session.c
@@ -584,10 +584,14 @@ static int session_new(nghttp2_session **session_ptr,
     if (option->opt_set_mask & NGHTTP2_OPT_STREAM_RESET_RATE_LIMIT) {
       nghttp2_ratelim_init(&(*session_ptr)->stream_reset_ratelim,
                            option->stream_reset_burst,
                            option->stream_reset_rate);
     }
+
+    if (option->opt_set_mask & NGHTTP2_OPT_MAX_CONTINUATIONS) {
+      (*session_ptr)->max_continuations = option->max_continuations;
+    }
   }
 
   rv = nghttp2_hd_deflate_init2(&(*session_ptr)->hd_deflater,
                                 max_deflate_dynamic_table_size, mem);
   if (rv != 0) {

Fixed code: 	nghttp2_option_set_max_continuations.rst \
/**
 * @function
 *
 * This function sets the maximum number of CONTINUATION frames
 * following an incoming HEADER frame.  If more than those frames are
 * received, the remote endpoint is considered to be misbehaving and
 * session will be closed.  The default value is 8.
 */
NGHTTP2_EXTERN void nghttp2_option_set_max_continuations(nghttp2_option *option,
                                                         size_t val);


void nghttp2_option_set_max_continuations(nghttp2_option *option, size_t val) {
  option->opt_set_mask |= NGHTTP2_OPT_MAX_CONTINUATIONS;
  option->max_continuations = val;
}
  NGHTTP2_OPT_MAX_CONTINUATIONS = 1 << 16,
  /**
   * NGHTTP2_OPT_MAX_CONTINUATIONS
   */
  size_t max_continuations;

    if (option->opt_set_mask & NGHTTP2_OPT_MAX_CONTINUATIONS) {
      (*session_ptr)->max_continuations = option->max_continuations;
    }