[libsoup/pgriffis/utf8-safe-apis] headers: Ensure untrusted header values are UTF-8




commit 4dd705cad4720ed235a4050e251e2ecb5db60e6f
Author: Patrick Griffis <pgriffis igalia com>
Date:   Thu Jul 22 13:51:00 2021 -0500

    headers: Ensure untrusted header values are UTF-8
    
    Our API uses `char *` for all headers throughout.
    This means that GObject-Introspection assumes it it is valid UTF-8,
    so languages assume it is valid UTF-8.
    Applications using the C API assume it is valid UTF-8.
    
    Passing along unverified bytes is unsafe and will cause issues.

 libsoup/http2/soup-client-message-io-http2.c |  5 +++--
 libsoup/soup-headers.c                       |  3 ++-
 libsoup/soup-message-headers-private.h       |  3 +++
 libsoup/soup-message-headers.c               | 15 +++++++++++++++
 4 files changed, 23 insertions(+), 3 deletions(-)
---
diff --git a/libsoup/http2/soup-client-message-io-http2.c b/libsoup/http2/soup-client-message-io-http2.c
index 592fde68..755901fe 100644
--- a/libsoup/http2/soup-client-message-io-http2.c
+++ b/libsoup/http2/soup-client-message-io-http2.c
@@ -32,6 +32,7 @@
 
 #include "soup-body-input-stream.h"
 #include "soup-message-metrics-private.h"
+#include "soup-message-headers-private.h"
 #include "soup-message-private.h"
 #include "soup-message-io-source.h"
 #include "soup-message-queue-item.h"
@@ -544,8 +545,8 @@ on_header_callback (nghttp2_session     *session,
                 return 0;
         }
 
-        soup_message_headers_append (soup_message_get_response_headers (data->msg),
-                                     (const char *)name, (const char *)value);
+        soup_message_headers_append_untrusted_data (soup_message_get_response_headers (data->msg),
+                                                    name, value);
         return 0;
 }
 
diff --git a/libsoup/soup-headers.c b/libsoup/soup-headers.c
index e7f843b0..87779fcf 100644
--- a/libsoup/soup-headers.c
+++ b/libsoup/soup-headers.c
@@ -14,6 +14,7 @@
 
 #include "soup-misc.h"
 #include "soup-headers.h"
+#include "soup-message-headers-private.h"
 #include "soup.h"
 
 /**
@@ -154,7 +155,7 @@ soup_headers_parse (const char *str, int len, SoupMessageHeaders *dest)
                for (p = strchr (value, '\r'); p; p = strchr (p, '\r'))
                        *p = ' ';
 
-               soup_message_headers_append (dest, name, value);
+               soup_message_headers_append_untrusted_data (dest, name, value);
         }
        success = TRUE;
 
diff --git a/libsoup/soup-message-headers-private.h b/libsoup/soup-message-headers-private.h
index b606a331..98154645 100644
--- a/libsoup/soup-message-headers-private.h
+++ b/libsoup/soup-message-headers-private.h
@@ -10,6 +10,9 @@
 
 G_BEGIN_DECLS
 
+void        soup_message_headers_append_untrusted_data  (SoupMessageHeaders *hdrs,
+                                                         const char         *name,
+                                                         const char         *value);
 void        soup_message_headers_append_common          (SoupMessageHeaders *hdrs,
                                                          SoupHeaderName      name,
                                                          const char         *value);
diff --git a/libsoup/soup-message-headers.c b/libsoup/soup-message-headers.c
index 2dfea525..c602a064 100644
--- a/libsoup/soup-message-headers.c
+++ b/libsoup/soup-message-headers.c
@@ -353,6 +353,21 @@ soup_message_headers_append (SoupMessageHeaders *hdrs,
                g_hash_table_remove (hdrs->uncommon_concat, header.name);
 }
 
+/*
+ * Appends a header value ensuring that it is valid UTF8.
+ */
+void
+soup_message_headers_append_untrusted_data (SoupMessageHeaders *hdrs,
+                                            const char         *name,
+                                            const char         *value)
+{
+        char *safe_value = g_utf8_make_valid (value, -1);
+        char *safe_name = g_utf8_make_valid (name, -1);
+        soup_message_headers_append (hdrs, safe_name, safe_value);
+        g_free (safe_value);
+        g_free (safe_name);
+}
+
 void
 soup_message_headers_replace_common (SoupMessageHeaders *hdrs,
                                      SoupHeaderName      name,


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]