aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorthegeorg <thegeorg@yandex-team.com>2022-09-15 12:50:39 +0300
committerthegeorg <thegeorg@yandex-team.com>2022-09-15 12:50:39 +0300
commit239edf05410a4716215db2bf9a0027c05b5d8126 (patch)
tree9275e8632007661f1897e73bb8ace977d4e1586a
parent883652acb26e399a42efb42c90d38480af15cee2 (diff)
downloadydb-239edf05410a4716215db2bf9a0027c05b5d8126.tar.gz
curl + nghttp2: Backport PRs to make ltws validation less picky
This is backport of: * curl [PR #9448](https://github.com/curl/curl/pull/9448) * nghttp2 [PR #1792](https://github.com/nghttp2/nghttp2/pull/1792)
-rw-r--r--contrib/libs/curl/lib/http2.c23
-rw-r--r--contrib/libs/nghttp2/lib/includes/nghttp2/nghttp2.h12
-rw-r--r--contrib/libs/nghttp2/lib/includes/nghttp2/nghttp2ver.h4
-rw-r--r--contrib/libs/nghttp2/lib/nghttp2_http.c32
-rw-r--r--contrib/libs/nghttp2/lib/nghttp2_option.c7
-rw-r--r--contrib/libs/nghttp2/lib/nghttp2_option.h5
-rw-r--r--contrib/libs/nghttp2/lib/nghttp2_session.c12
-rw-r--r--contrib/libs/nghttp2/lib/nghttp2_session.h3
-rw-r--r--contrib/libs/nghttp2/lib/nghttp2_stream.h3
9 files changed, 96 insertions, 5 deletions
diff --git a/contrib/libs/curl/lib/http2.c b/contrib/libs/curl/lib/http2.c
index f6364d0e02..3a70528e4a 100644
--- a/contrib/libs/curl/lib/http2.c
+++ b/contrib/libs/curl/lib/http2.c
@@ -1277,6 +1277,27 @@ void Curl_http2_done(struct Curl_easy *data, bool premature)
}
}
+static int client_new(struct connectdata *conn,
+ nghttp2_session_callbacks *callbacks)
+{
+#if NGHTTP2_VERSION_NUM < 0x013200
+ /* before 1.50.0 */
+ return nghttp2_session_client_new(&conn->proto.httpc.h2, callbacks, conn);
+#else
+ nghttp2_option *o;
+ int rc = nghttp2_option_new(&o);
+ if(rc)
+ return rc;
+ /* turn off RFC 9113 leading and trailing white spaces validation against
+ HTTP field value. */
+ nghttp2_option_set_no_rfc9113_leading_and_trailing_ws_validation(o, 1);
+ rc = nghttp2_session_client_new2(&conn->proto.httpc.h2, callbacks, conn,
+ o);
+ nghttp2_option_del(o);
+ return rc;
+#endif
+}
+
/*
* Initialize nghttp2 for a Curl connection
*/
@@ -1317,7 +1338,7 @@ static CURLcode http2_init(struct Curl_easy *data, struct connectdata *conn)
nghttp2_session_callbacks_set_error_callback(callbacks, error_callback);
/* The nghttp2 session is not yet setup, do it */
- rc = nghttp2_session_client_new(&conn->proto.httpc.h2, callbacks, conn);
+ rc = client_new(conn, callbacks);
nghttp2_session_callbacks_del(callbacks);
diff --git a/contrib/libs/nghttp2/lib/includes/nghttp2/nghttp2.h b/contrib/libs/nghttp2/lib/includes/nghttp2/nghttp2.h
index bb8aa1d329..61a14d99eb 100644
--- a/contrib/libs/nghttp2/lib/includes/nghttp2/nghttp2.h
+++ b/contrib/libs/nghttp2/lib/includes/nghttp2/nghttp2.h
@@ -2753,6 +2753,18 @@ nghttp2_option_set_server_fallback_rfc7540_priorities(nghttp2_option *option,
/**
* @function
*
+ * This option, if set to nonzero, turns off RFC 9113 leading and
+ * trailing white spaces validation against HTTP field value. Some
+ * important fields, such as HTTP/2 pseudo header fields, are
+ * validated more strictly and this option does not apply to them.
+ */
+NGHTTP2_EXTERN void
+nghttp2_option_set_no_rfc9113_leading_and_trailing_ws_validation(
+ nghttp2_option *option, int val);
+
+/**
+ * @function
+ *
* Initializes |*session_ptr| for client use. The all members of
* |callbacks| are copied to |*session_ptr|. Therefore |*session_ptr|
* does not store |callbacks|. The |user_data| is an arbitrary user
diff --git a/contrib/libs/nghttp2/lib/includes/nghttp2/nghttp2ver.h b/contrib/libs/nghttp2/lib/includes/nghttp2/nghttp2ver.h
index d0a4626ca9..0e503610ba 100644
--- a/contrib/libs/nghttp2/lib/includes/nghttp2/nghttp2ver.h
+++ b/contrib/libs/nghttp2/lib/includes/nghttp2/nghttp2ver.h
@@ -29,7 +29,7 @@
* @macro
* Version number of the nghttp2 library release
*/
-#define NGHTTP2_VERSION "1.49.0"
+#define NGHTTP2_VERSION "1.50.0"
/**
* @macro
@@ -37,6 +37,6 @@
* release. This is a 24 bit number with 8 bits for major number, 8 bits
* for minor and 8 bits for patch. Version 1.2.3 becomes 0x010203.
*/
-#define NGHTTP2_VERSION_NUM 0x013100
+#define NGHTTP2_VERSION_NUM 0x013200
#endif /* NGHTTP2VER_H */
diff --git a/contrib/libs/nghttp2/lib/nghttp2_http.c b/contrib/libs/nghttp2/lib/nghttp2_http.c
index 71491f0eb5..83e5e6685f 100644
--- a/contrib/libs/nghttp2/lib/nghttp2_http.c
+++ b/contrib/libs/nghttp2/lib/nghttp2_http.c
@@ -336,6 +336,16 @@ static int check_scheme(const uint8_t *value, size_t len) {
return 1;
}
+static int lws(const uint8_t *s, size_t n) {
+ size_t i;
+ for (i = 0; i < n; ++i) {
+ if (s[i] != ' ' && s[i] != '\t') {
+ return 0;
+ }
+ }
+ return 1;
+}
+
int nghttp2_http_on_header(nghttp2_session *session, nghttp2_stream *stream,
nghttp2_frame *frame, nghttp2_hd_nv *nv,
int trailer) {
@@ -378,6 +388,10 @@ int nghttp2_http_on_header(nghttp2_session *session, nghttp2_stream *stream,
case NGHTTP2_TOKEN_HOST:
if (session->server || frame->hd.type == NGHTTP2_PUSH_PROMISE) {
rv = nghttp2_check_authority(nv->value->base, nv->value->len);
+ } else if (
+ stream->flags &
+ NGHTTP2_STREAM_FLAG_NO_RFC9113_LEADING_AND_TRAILING_WS_VALIDATION) {
+ rv = nghttp2_check_header_value(nv->value->base, nv->value->len);
} else {
rv = nghttp2_check_header_value_rfc9113(nv->value->base, nv->value->len);
}
@@ -385,8 +399,24 @@ int nghttp2_http_on_header(nghttp2_session *session, nghttp2_stream *stream,
case NGHTTP2_TOKEN__SCHEME:
rv = check_scheme(nv->value->base, nv->value->len);
break;
+ case NGHTTP2_TOKEN__PROTOCOL:
+ /* Check the value consists of just white spaces, which was done
+ in check_pseudo_header before
+ nghttp2_check_header_value_rfc9113 has been introduced. */
+ if ((stream->flags &
+ NGHTTP2_STREAM_FLAG_NO_RFC9113_LEADING_AND_TRAILING_WS_VALIDATION) &&
+ lws(nv->value->base, nv->value->len)) {
+ rv = 0;
+ break;
+ }
+ /* fall through */
default:
- rv = nghttp2_check_header_value_rfc9113(nv->value->base, nv->value->len);
+ if (stream->flags &
+ NGHTTP2_STREAM_FLAG_NO_RFC9113_LEADING_AND_TRAILING_WS_VALIDATION) {
+ rv = nghttp2_check_header_value(nv->value->base, nv->value->len);
+ } else {
+ rv = nghttp2_check_header_value_rfc9113(nv->value->base, nv->value->len);
+ }
}
if (rv == 0) {
diff --git a/contrib/libs/nghttp2/lib/nghttp2_option.c b/contrib/libs/nghttp2/lib/nghttp2_option.c
index ffd20322ee..ee0cd0f022 100644
--- a/contrib/libs/nghttp2/lib/nghttp2_option.c
+++ b/contrib/libs/nghttp2/lib/nghttp2_option.c
@@ -136,3 +136,10 @@ void nghttp2_option_set_server_fallback_rfc7540_priorities(
option->opt_set_mask |= NGHTTP2_OPT_SERVER_FALLBACK_RFC7540_PRIORITIES;
option->server_fallback_rfc7540_priorities = val;
}
+
+void nghttp2_option_set_no_rfc9113_leading_and_trailing_ws_validation(
+ nghttp2_option *option, int val) {
+ option->opt_set_mask |=
+ NGHTTP2_OPT_NO_RFC9113_LEADING_AND_TRAILING_WS_VALIDATION;
+ option->no_rfc9113_leading_and_trailing_ws_validation = val;
+}
diff --git a/contrib/libs/nghttp2/lib/nghttp2_option.h b/contrib/libs/nghttp2/lib/nghttp2_option.h
index 0400d56dfc..b228a0754c 100644
--- a/contrib/libs/nghttp2/lib/nghttp2_option.h
+++ b/contrib/libs/nghttp2/lib/nghttp2_option.h
@@ -69,6 +69,7 @@ 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_option_flag;
/**
@@ -133,6 +134,10 @@ struct nghttp2_option {
*/
int server_fallback_rfc7540_priorities;
/**
+ * NGHTTP2_OPT_NO_RFC9113_LEADING_AND_TRAILING_WS_VALIDATION
+ */
+ int no_rfc9113_leading_and_trailing_ws_validation;
+ /**
* NGHTTP2_OPT_USER_RECV_EXT_TYPES
*/
uint8_t user_recv_ext_types[32];
diff --git a/contrib/libs/nghttp2/lib/nghttp2_session.c b/contrib/libs/nghttp2/lib/nghttp2_session.c
index 134b0efb12..93f3f07cf7 100644
--- a/contrib/libs/nghttp2/lib/nghttp2_session.c
+++ b/contrib/libs/nghttp2/lib/nghttp2_session.c
@@ -566,6 +566,13 @@ static int session_new(nghttp2_session **session_ptr,
(*session_ptr)->opt_flags |=
NGHTTP2_OPTMASK_SERVER_FALLBACK_RFC7540_PRIORITIES;
}
+
+ if ((option->opt_set_mask &
+ NGHTTP2_OPT_NO_RFC9113_LEADING_AND_TRAILING_WS_VALIDATION) &&
+ option->no_rfc9113_leading_and_trailing_ws_validation) {
+ (*session_ptr)->opt_flags |=
+ NGHTTP2_OPTMASK_NO_RFC9113_LEADING_AND_TRAILING_WS_VALIDATION;
+ }
}
rv = nghttp2_hd_deflate_init2(&(*session_ptr)->hd_deflater,
@@ -1296,6 +1303,11 @@ nghttp2_stream *nghttp2_session_open_stream(nghttp2_session *session,
mem = &session->mem;
stream = nghttp2_session_get_stream_raw(session, stream_id);
+ if (session->opt_flags &
+ NGHTTP2_OPTMASK_NO_RFC9113_LEADING_AND_TRAILING_WS_VALIDATION) {
+ flags |= NGHTTP2_STREAM_FLAG_NO_RFC9113_LEADING_AND_TRAILING_WS_VALIDATION;
+ }
+
if (stream) {
assert(stream->state == NGHTTP2_STREAM_IDLE);
assert((stream->flags & NGHTTP2_STREAM_FLAG_NO_RFC7540_PRIORITIES) ||
diff --git a/contrib/libs/nghttp2/lib/nghttp2_session.h b/contrib/libs/nghttp2/lib/nghttp2_session.h
index 164b5fd957..34d2d58528 100644
--- a/contrib/libs/nghttp2/lib/nghttp2_session.h
+++ b/contrib/libs/nghttp2/lib/nghttp2_session.h
@@ -53,7 +53,8 @@ typedef enum {
NGHTTP2_OPTMASK_NO_HTTP_MESSAGING = 1 << 2,
NGHTTP2_OPTMASK_NO_AUTO_PING_ACK = 1 << 3,
NGHTTP2_OPTMASK_NO_CLOSED_STREAMS = 1 << 4,
- NGHTTP2_OPTMASK_SERVER_FALLBACK_RFC7540_PRIORITIES = 1 << 5
+ NGHTTP2_OPTMASK_SERVER_FALLBACK_RFC7540_PRIORITIES = 1 << 5,
+ NGHTTP2_OPTMASK_NO_RFC9113_LEADING_AND_TRAILING_WS_VALIDATION = 1 << 6,
} nghttp2_optmask;
/*
diff --git a/contrib/libs/nghttp2/lib/nghttp2_stream.h b/contrib/libs/nghttp2/lib/nghttp2_stream.h
index 0ec77bf071..7a8e4c6c1d 100644
--- a/contrib/libs/nghttp2/lib/nghttp2_stream.h
+++ b/contrib/libs/nghttp2/lib/nghttp2_stream.h
@@ -96,6 +96,9 @@ typedef enum {
NGHTTP2_STREAM_FLAG_NO_RFC7540_PRIORITIES = 0x10,
/* Ignore client RFC 9218 priority signal. */
NGHTTP2_STREAM_FLAG_IGNORE_CLIENT_PRIORITIES = 0x20,
+ /* Indicates that RFC 9113 leading and trailing white spaces
+ validation against a field value is not performed. */
+ NGHTTP2_STREAM_FLAG_NO_RFC9113_LEADING_AND_TRAILING_WS_VALIDATION = 0x40,
} nghttp2_stream_flag;
/* HTTP related flags to enforce HTTP semantics */