gnunet-svn
[Top][All Lists]
Advanced

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

[GNUnet-SVN] [libmicrohttpd] branch master updated: allow binary zero in


From: gnunet
Subject: [GNUnet-SVN] [libmicrohttpd] branch master updated: allow binary zero in unescaped GET arguments (see mailinglist)
Date: Wed, 20 Mar 2019 10:46:24 +0100

This is an automated email from the git hooks/post-receive script.

grothoff pushed a commit to branch master
in repository libmicrohttpd.

The following commit(s) were added to refs/heads/master by this push:
     new 1b610e5b allow binary zero in unescaped GET arguments (see mailinglist)
1b610e5b is described below

commit 1b610e5b13b7b96e7b3f372c8da1ec9d840f896a
Author: Christian Grothoff <address@hidden>
AuthorDate: Wed Mar 20 10:46:21 2019 +0100

    allow binary zero in unescaped GET arguments (see mailinglist)
---
 ChangeLog                           |  6 +++
 doc/examples/logging.c              | 17 +++++--
 doc/libmicrohttpd.texi              | 13 +++++-
 src/include/microhttpd.h            | 56 +++++++++++++++++++----
 src/microhttpd/connection.c         | 91 ++++++++++++++++++++++++++++++-------
 src/microhttpd/digestauth.c         |  9 +++-
 src/microhttpd/internal.c           | 19 +++++---
 src/microhttpd/internal.h           |  9 +++-
 src/microhttpd/response.c           |  3 +-
 src/testcurl/test_process_headers.c |  8 +++-
 src/testcurl/test_urlparse.c        |  9 +++-
 11 files changed, 195 insertions(+), 45 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index f591642d..32868ca0 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,9 @@
+Wed 20 Mar 2019 10:20:24 AM CET
+       Adding additional "value_length" argument to MHD_KeyValueIterator
+       callback to support binary zeros in values.  This is done in a
+       backwards-compatible way, but may require adding a cast to existing
+       code to avoid a compiler warning. -CG
+
 Sun Feb 10 21:00:37 BRT 2019
        Added example for how to compress a chunked HTTP response. -SC
 
diff --git a/doc/examples/logging.c b/doc/examples/logging.c
index 239fbe7d..a88f461e 100644
--- a/doc/examples/logging.c
+++ b/doc/examples/logging.c
@@ -15,11 +15,16 @@
 
 
 static int
-print_out_key (void *cls, enum MHD_ValueKind kind, const char *key,
-               const char *value)
+print_out_key (void *cls,
+              enum MHD_ValueKind kind,
+              const char *key,
+               const char *value,
+              size_t value_size)
 {
-  (void)cls;    /* Unused. Silent compiler warning. */
-  (void)kind;   /* Unused. Silent compiler warning. */
+  (void) cls;    /* Unused. Silent compiler warning. */
+  (void) kind;   /* Unused. Silent compiler warning. */
+  (void) value_size;
+  
   printf ("%s: %s\n", key, value);
   return MHD_YES;
 }
@@ -38,7 +43,9 @@ answer_to_connection (void *cls, struct MHD_Connection 
*connection,
   (void)con_cls;           /* Unused. Silent compiler warning. */
   printf ("New %s request for %s using version %s\n", method, url, version);
 
-  MHD_get_connection_values (connection, MHD_HEADER_KIND, print_out_key,
+  MHD_get_connection_values (connection,
+                            MHD_HEADER_KIND,
+                            &print_out_key,
                              NULL);
 
   return MHD_NO;
diff --git a/doc/libmicrohttpd.texi b/doc/libmicrohttpd.texi
index f2e3576c..97a79bdc 100644
--- a/doc/libmicrohttpd.texi
+++ b/doc/libmicrohttpd.texi
@@ -1356,7 +1356,7 @@ reason for request termination see 
@code{MHD_OPTION_NOTIFY_COMPLETED}.
 @end deftypefn
 
 
address@hidden {Function Pointer} int {*MHD_KeyValueIterator} (void *cls, enum 
MHD_ValueKind kind, const char *key, const char *value)
address@hidden {Function Pointer} int {*MHD_KeyValueIterator} (void *cls, enum 
MHD_ValueKind kind, const char *key, const char *value, size_t value_size)
 Iterator over key-value pairs.  This iterator can be used to iterate
 over all of the cookies, headers, or @code{POST}-data fields of a
 request, and also to iterate over the headers that have been added to a
@@ -1375,6 +1375,17 @@ key for the value, can be an empty string
 @item value
 value corresponding value, can be NULL
 
address@hidden value_size
+number of bytes in @code{value}. This argument was introduced in
address@hidden 0x00096301 to allow applications to use binary
+zeros in values.  Applications using this argument must ensure that
+they are using a sufficiently recent version of MHD, i.e. by testing
address@hidden()} for values above or equal to 0.9.64.
+Applications that do not need zeros in values and that want to compile
+without warnings against newer versions of MHD should not declare this
+argument and cast the function pointer argument to
address@hidden
+
 @end table
 
 Return @code{MHD_YES} to continue iterating, @code{MHD_NO} to abort the
diff --git a/src/include/microhttpd.h b/src/include/microhttpd.h
index 42f406ed..4917f62b 100644
--- a/src/include/microhttpd.h
+++ b/src/include/microhttpd.h
@@ -1,6 +1,6 @@
 /*
      This file is part of libmicrohttpd
-     Copyright (C) 2006-2018 Christian Grothoff (and other contributing 
authors)
+     Copyright (C) 2006--2019 Christian Grothoff (and other contributing 
authors)
 
      This library is free software; you can redistribute it and/or
      modify it under the terms of the GNU Lesser General Public
@@ -126,7 +126,7 @@ typedef intptr_t ssize_t;
  * Current version of the library.
  * 0x01093001 = 1.9.30-1.
  */
-#define MHD_VERSION 0x00096300
+#define MHD_VERSION 0x00096301
 
 /**
  * MHD-internal return code for "YES".
@@ -1380,10 +1380,12 @@ enum MHD_OPTION
    *                         struct MHD_Connection *c,
    *                         char *s)
    *
-   * where the return value must be "strlen(s)" and "s" should be
-   * updated.  Note that the unescape function must not lengthen "s"
-   * (the result must be shorter than the input and still be
-   * 0-terminated).  "cls" will be set to the second argument
+   * where the return value must be the length of the value left in
+   * "s" (without the 0-terminator) and "s" should be updated.  Note
+   * that the unescape function must not lengthen "s" (the result must
+   * be shorter than the input and must still be 0-terminated).
+   * However, it may also include binary zeros before the
+   * 0-termination.  "cls" will be set to the second argument
    * following #MHD_OPTION_UNESCAPE_CALLBACK.
    */
   MHD_OPTION_UNESCAPE_CALLBACK = 16,
@@ -2025,6 +2027,8 @@ typedef void
  * @param kind kind of the header we are looking at
  * @param key key for the value, can be an empty string
  * @param value corresponding value, can be NULL
+ * @param value_size number of bytes in @a value, NEW since #MHD_VERSION 
0x00096301;
+ *                   for C-strings, the length excludes the 0-terminator
  * @return #MHD_YES to continue iterating,
  *         #MHD_NO to abort the iteration
  * @ingroup request
@@ -2033,7 +2037,8 @@ typedef int
 (*MHD_KeyValueIterator) (void *cls,
                          enum MHD_ValueKind kind,
                          const char *key,
-                         const char *value);
+                         const char *value,
+                        size_t value_size);
 
 
 /**
@@ -2493,6 +2498,40 @@ MHD_set_connection_value (struct MHD_Connection 
*connection,
                          const char *value);
 
 
+/**
+ * This function can be used to add an entry to the HTTP headers of a
+ * connection (so that the #MHD_get_connection_values function will
+ * return them -- and the `struct MHD_PostProcessor` will also see
+ * them).  This maybe required in certain situations (see Mantis
+ * #1399) where (broken) HTTP implementations fail to supply values
+ * needed by the post processor (or other parts of the application).
+ *
+ * This function MUST only be called from within the
+ * #MHD_AccessHandlerCallback (otherwise, access maybe improperly
+ * synchronized).  Furthermore, the client must guarantee that the key
+ * and value arguments are 0-terminated strings that are NOT freed
+ * until the connection is closed.  (The easiest way to do this is by
+ * passing only arguments to permanently allocated strings.).
+ *
+ * @param connection the connection for which a
+ *  value should be set
+ * @param kind kind of the value
+ * @param key key for the value
+ * @param value the value itself 
+ * @param value_size number of bytes in @a value (excluding 0-terminator for 
C-strings)
+ * @return #MHD_NO if the operation could not be
+ *         performed due to insufficient memory;
+ *         #MHD_YES on success
+ * @ingroup request
+ */
+int
+MHD_set_connection_value2 (struct MHD_Connection *connection,
+                          enum MHD_ValueKind kind,
+                          const char *key,
+                          const char *value,
+                          size_t value_size);
+
+
 /**
  * Sets the global error handler to a different implementation.  @a cb
  * will only be called in the case of typically fatal, serious
@@ -3075,7 +3114,8 @@ MHD_del_response_header (struct MHD_Response *response,
  */
 _MHD_EXTERN int
 MHD_get_response_headers (struct MHD_Response *response,
-                          MHD_KeyValueIterator iterator, void *iterator_cls);
+                          MHD_KeyValueIterator iterator,
+                         void *iterator_cls);
 
 
 /**
diff --git a/src/microhttpd/connection.c b/src/microhttpd/connection.c
index bb88b969..4fe66805 100644
--- a/src/microhttpd/connection.c
+++ b/src/microhttpd/connection.c
@@ -1,6 +1,6 @@
 /*
      This file is part of libmicrohttpd
-     Copyright (C) 2007-2017 Daniel Pittman and Christian Grothoff
+     Copyright (C) 2007-2019 Daniel Pittman and Christian Grothoff
 
      This library is free software; you can redistribute it and/or
      modify it under the terms of the GNU Lesser General Public
@@ -706,7 +706,8 @@ MHD_get_connection_values (struct MHD_Connection 
*connection,
              (MHD_YES != iterator (iterator_cls,
                                    pos->kind,
                                    pos->header,
-                                   pos->value)) )
+                                   pos->value,
+                                  pos->value_size)) )
          return ret;
       }
   return ret;
@@ -733,16 +734,18 @@ MHD_get_connection_values (struct MHD_Connection 
*connection,
  * @param kind kind of the value
  * @param key key for the value
  * @param value the value itself
+ * @param value_size number of bytes in @a value
  * @return #MHD_NO if the operation could not be
  *         performed due to insufficient memory;
  *         #MHD_YES on success
  * @ingroup request
  */
 int
-MHD_set_connection_value (struct MHD_Connection *connection,
-                          enum MHD_ValueKind kind,
-                          const char *key,
-                          const char *value)
+MHD_set_connection_value2 (struct MHD_Connection *connection,
+                          enum MHD_ValueKind kind,
+                          const char *key,
+                          const char *value,
+                          size_t value_size)
 {
   struct MHD_HTTP_Header *pos;
 
@@ -753,6 +756,7 @@ MHD_set_connection_value (struct MHD_Connection *connection,
     return MHD_NO;
   pos->header = (char *) key;
   pos->value = (char *) value;
+  pos->value_size = value_size;
   pos->kind = kind;
   pos->next = NULL;
   /* append 'pos' to the linked list of headers */
@@ -770,6 +774,47 @@ MHD_set_connection_value (struct MHD_Connection 
*connection,
 }
 
 
+/**
+ * This function can be used to add an entry to the HTTP headers of a
+ * connection (so that the #MHD_get_connection_values function will
+ * return them -- and the `struct MHD_PostProcessor` will also see
+ * them).  This maybe required in certain situations (see Mantis
+ * #1399) where (broken) HTTP implementations fail to supply values
+ * needed by the post processor (or other parts of the application).
+ *
+ * This function MUST only be called from within the
+ * #MHD_AccessHandlerCallback (otherwise, access maybe improperly
+ * synchronized).  Furthermore, the client must guarantee that the key
+ * and value arguments are 0-terminated strings that are NOT freed
+ * until the connection is closed.  (The easiest way to do this is by
+ * passing only arguments to permanently allocated strings.).
+ *
+ * @param connection the connection for which a
+ *  value should be set
+ * @param kind kind of the value
+ * @param key key for the value
+ * @param value the value itself
+ * @return #MHD_NO if the operation could not be
+ *         performed due to insufficient memory;
+ *         #MHD_YES on success
+ * @ingroup request
+ */
+int
+MHD_set_connection_value (struct MHD_Connection *connection,
+                          enum MHD_ValueKind kind,
+                          const char *key,
+                          const char *value)
+{
+  return MHD_set_connection_value2 (connection,
+                                   kind,
+                                   key,
+                                   value,
+                                   NULL != value
+                                   ? strlen (value)
+                                   : 0);
+}
+
+
 /**
  * Get a particular header value.  If multiple
  * values match the kind, return any one of them.
@@ -2061,19 +2106,22 @@ get_next_header_line (struct MHD_Connection *connection,
  * @param kind kind of the value
  * @param key key for the value
  * @param value the value itself
+ * @param value_size number of bytes in @a value
  * @return #MHD_NO on failure (out of memory), #MHD_YES for success
  */
 static int
 connection_add_header (struct MHD_Connection *connection,
                        const char *key,
                       const char *value,
+                      size_t value_size,
                       enum MHD_ValueKind kind)
 {
   if (MHD_NO ==
-      MHD_set_connection_value (connection,
-                               kind,
-                               key,
-                               value))
+      MHD_set_connection_value2 (connection,
+                                kind,
+                                key,
+                                value,
+                                value_size))
     {
 #ifdef HAVE_MESSAGES
       MHD_DLOG (connection->daemon,
@@ -2104,6 +2152,7 @@ parse_cookie_header (struct MHD_Connection *connection)
   char *semicolon;
   char *equals;
   char *ekill;
+  char *end;
   char old;
   int quotes;
 
@@ -2155,6 +2204,7 @@ parse_cookie_header (struct MHD_Connection *connection)
               connection_add_header (connection,
                                      pos,
                                      "",
+                                    0,
                                      MHD_COOKIE_KIND))
             return MHD_NO;
           if (old == '\0')
@@ -2174,6 +2224,7 @@ parse_cookie_header (struct MHD_Connection *connection)
             quotes = (quotes + 1) & 1;
           semicolon++;
         }
+      end = semicolon;
       if ('\0' == semicolon[0])
         semicolon = NULL;
       if (NULL != semicolon)
@@ -2183,15 +2234,17 @@ parse_cookie_header (struct MHD_Connection *connection)
         }
       /* remove quotes */
       if ( ('"' == equals[0]) &&
-           ('"' == equals[strlen (equals) - 1]) )
+           ('"' == end[-1]) )
         {
-          equals[strlen (equals) - 1] = '\0';
           equals++;
+         end--;
+          *end = '\0';
         }
       if (MHD_NO ==
          connection_add_header (connection,
                                 pos,
                                 equals,
+                                end - equals,
                                 MHD_COOKIE_KIND))
         return MHD_NO;
       pos = semicolon;
@@ -2711,16 +2764,20 @@ process_broken_line (struct MHD_Connection *connection,
                                    REQUEST_TOO_BIG);
           return MHD_NO;
         }
-      memcpy (&last[last_len], tmp, tmp_len + 1);
+      memcpy (&last[last_len],
+             tmp,
+             tmp_len + 1);
       connection->last = last;
       return MHD_YES;           /* possibly more than 2 lines... */
     }
   mhd_assert ( (NULL != last) &&
                 (NULL != connection->colon) );
-  if ((MHD_NO == connection_add_header (connection,
-                                        last,
-                                       connection->colon,
-                                       kind)))
+  if (MHD_NO ==
+      connection_add_header (connection,
+                            last,
+                            connection->colon,
+                            strlen (connection->colon),
+                            kind))
     {
       transmit_error_response (connection,
                                MHD_HTTP_REQUEST_HEADER_FIELDS_TOO_LARGE,
diff --git a/src/microhttpd/digestauth.c b/src/microhttpd/digestauth.c
index c66bcadf..8f04bf38 100644
--- a/src/microhttpd/digestauth.c
+++ b/src/microhttpd/digestauth.c
@@ -732,6 +732,7 @@ calculate_nonce (uint32_t nonce_time,
  * @param connection the connection
  * @param key the key
  * @param value the value, can be NULL
+ * @param value_size number of bytes in @a value
  * @param kind type of the header
  * @return #MHD_YES if the key-value pair is in the headers,
  *         #MHD_NO if not
@@ -740,6 +741,7 @@ static int
 test_header (struct MHD_Connection *connection,
             const char *key,
             const char *value,
+            size_t value_size,
             enum MHD_ValueKind kind)
 {
   struct MHD_HTTP_Header *pos;
@@ -748,6 +750,8 @@ test_header (struct MHD_Connection *connection,
     {
       if (kind != pos->kind)
        continue;
+      if (value_size != pos->value_size)
+       continue;
       if (0 != strcmp (key,
                        pos->header))
        continue;
@@ -756,8 +760,9 @@ test_header (struct MHD_Connection *connection,
        return MHD_YES;
       if ( (NULL == value) ||
           (NULL == pos->value) ||
-          (0 != strcmp (value,
-                         pos->value)) )
+          (0 != memcmp (value,
+                         pos->value,
+                        value_size)) )
        continue;
       return MHD_YES;
     }
diff --git a/src/microhttpd/internal.c b/src/microhttpd/internal.c
index d2532c54..8e9e0aac 100644
--- a/src/microhttpd/internal.c
+++ b/src/microhttpd/internal.c
@@ -162,7 +162,7 @@ MHD_http_unescape (char *val)
        }
     }
   *wpos = '\0'; /* add 0-terminator */
-  return wpos - val; /* = strlen(val) */
+  return wpos - val;
 }
 
 
@@ -190,6 +190,7 @@ MHD_parse_arguments_ (struct MHD_Connection *connection,
   struct MHD_Daemon *daemon = connection->daemon;
   char *equals;
   char *amper;
+  size_t len;
 
   *num_headers = 0;
   while ( (NULL != args) &&
@@ -210,6 +211,7 @@ MHD_parse_arguments_ (struct MHD_Connection *connection,
              if (MHD_YES != cb (connection,
                                 args,
                                 NULL,
+                                0,
                                 kind))
                return MHD_NO;
              (*num_headers)++;
@@ -223,12 +225,13 @@ MHD_parse_arguments_ (struct MHD_Connection *connection,
                                     connection,
                                     args);
           MHD_unescape_plus (equals);
-         daemon->unescape_callback (daemon->unescape_callback_cls,
-                                    connection,
-                                    equals);
+         len = daemon->unescape_callback (daemon->unescape_callback_cls,
+                                          connection,
+                                          equals);
          if (MHD_YES != cb (connection,
                             args,
                             equals,
+                            len,
                             kind))
            return MHD_NO;
          (*num_headers)++;
@@ -248,6 +251,7 @@ MHD_parse_arguments_ (struct MHD_Connection *connection,
          if (MHD_YES != cb (connection,
                             args,
                             NULL,
+                            0,
                             kind))
            return MHD_NO;
          /* continue with 'bar' */
@@ -264,12 +268,13 @@ MHD_parse_arguments_ (struct MHD_Connection *connection,
                                 connection,
                                 args);
       MHD_unescape_plus (equals);
-      daemon->unescape_callback (daemon->unescape_callback_cls,
-                                connection,
-                                equals);
+      len = daemon->unescape_callback (daemon->unescape_callback_cls,
+                                      connection,
+                                      equals);
       if (MHD_YES != cb (connection,
                         args,
                         equals,
+                        len,
                         kind))
         return MHD_NO;
       (*num_headers)++;
diff --git a/src/microhttpd/internal.h b/src/microhttpd/internal.h
index 0ce0b0c8..63bccd94 100644
--- a/src/microhttpd/internal.h
+++ b/src/microhttpd/internal.h
@@ -275,6 +275,11 @@ struct MHD_HTTP_Header
    */
   char *value;
 
+  /**
+   * Number of bytes in @a value.
+   */
+  size_t value_size;
+
   /**
    * Type of the header (where in the HTTP protocol is this header
    * from).
@@ -1881,7 +1886,8 @@ MHD_unescape_plus (char *arg);
  *
  * @param connection context of the iteration
  * @param key 0-terminated key string, never NULL
- * @param value 0-terminated value string, may be NULL
+ * @param value 0-terminated binary data, may include binary zeros, may be NULL
+ * @param value_size number of bytes in value
  * @param kind origin of the key-value pair
  * @return #MHD_YES on success (continue to iterate)
  *         #MHD_NO to signal failure (and abort iteration)
@@ -1890,6 +1896,7 @@ typedef int
 (*MHD_ArgumentIterator_)(struct MHD_Connection *connection,
                         const char *key,
                         const char *value,
+                        size_t value_size,
                         enum MHD_ValueKind kind);
 
 
diff --git a/src/microhttpd/response.c b/src/microhttpd/response.c
index 263f8303..9f328eef 100644
--- a/src/microhttpd/response.c
+++ b/src/microhttpd/response.c
@@ -240,7 +240,8 @@ MHD_get_response_headers (struct MHD_Response *response,
           (MHD_YES != iterator (iterator_cls,
                                 pos->kind,
                                 pos->header,
-                                pos->value)))
+                                pos->value,
+                               pos->value_size)))
         break;
     }
   return numHeaders;
diff --git a/src/testcurl/test_process_headers.c 
b/src/testcurl/test_process_headers.c
index f9c7cd03..3be814e2 100644
--- a/src/testcurl/test_process_headers.c
+++ b/src/testcurl/test_process_headers.c
@@ -65,8 +65,13 @@ copyBuffer (void *ptr, size_t size, size_t nmemb, void *ctx)
   return size * nmemb;
 }
 
+
 static int
-kv_cb (void *cls, enum MHD_ValueKind kind, const char *key, const char *value)
+kv_cb (void *cls,
+       enum MHD_ValueKind kind,
+       const char *key,
+       const char *value,
+       size_t value_size)
 {
   if ((0 == strcmp (key, MHD_HTTP_HEADER_HOST)) &&
       (0 == strncmp (value, "127.0.0.1", strlen("127.0.0.1"))) && (kind == 
MHD_HEADER_KIND))
@@ -77,6 +82,7 @@ kv_cb (void *cls, enum MHD_ValueKind kind, const char *key, 
const char *value)
   return MHD_YES;
 }
 
+
 static int
 ahc_echo (void *cls,
           struct MHD_Connection *connection,
diff --git a/src/testcurl/test_urlparse.c b/src/testcurl/test_urlparse.c
index 8675f19c..1e6cc28c 100644
--- a/src/testcurl/test_urlparse.c
+++ b/src/testcurl/test_urlparse.c
@@ -67,13 +67,18 @@ copyBuffer (void *ptr, size_t size, size_t nmemb, void *ctx)
   return size * nmemb;
 }
 
+
 static int 
 test_values (void *cls,
             enum MHD_ValueKind kind,
             const char *key,
-            const char *value)
+            const char *value,
+            size_t value_size)
 {
-  (void)cls;(void)kind;         /* Unused. Silent compiler warning. */
+  (void) cls;
+  (void) kind;
+  (void) value_size;
+  
   if ( (0 == strcmp (key, "a")) &&
        (0 == strcmp (value, "b")) )
     matches += 1;

-- 
To stop receiving notification emails like this one, please contact
address@hidden



reply via email to

[Prev in Thread] Current Thread [Next in Thread]