aboutsummaryrefslogtreecommitdiffstats
path: root/meta-oe/recipes-support/libmicrohttpd/libmicrohttpd/CVE-2021-3466.patch
blob: ff792d4daab04b81f6d1c0b9b0242e358e0bc20a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
From 86d9a61be6395220714b1a50d5144e65668961f6 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Ernst=20Sj=C3=B6strand?= <ernst.sjostrand@verisure.com>
Date: Tue, 21 Dec 2021 11:05:22 +0000
Subject: [PATCH] Fix buffer overflow in url parser and add test

Reference:
https://git.gnunet.org/libmicrohttpd.git/commit/?id=a110ae6276660bee3caab30e9ff3f12f85cf3241

Upstream-Status: Backport
CVE: CVE-2021-3466

Signed-off-by: Ernst Sj�strand <ernst.sjostrand@verisure.com>
---
 src/microhttpd/postprocessor.c      | 18 ++++++--
 src/microhttpd/test_postprocessor.c | 66 +++++++++++++++++++++++++++++
 2 files changed, 80 insertions(+), 4 deletions(-)

diff --git a/src/microhttpd/postprocessor.c b/src/microhttpd/postprocessor.c
index b7f6b10..ebd1686 100644
--- a/src/microhttpd/postprocessor.c
+++ b/src/microhttpd/postprocessor.c
@@ -137,8 +137,7 @@ struct MHD_PostProcessor
   void *cls;
 
   /**
-   * Encoding as given by the headers of the
-   * connection.
+   * Encoding as given by the headers of the connection.
    */
   const char *encoding;
 
@@ -586,7 +585,7 @@ post_process_urlencoded (struct MHD_PostProcessor *pp,
       pp->state = PP_Error;
       break;
     case PP_Callback:
-      if ( (pp->buffer_pos + (end_key - start_key) >
+      if ( (pp->buffer_pos + (end_key - start_key) >=
             pp->buffer_size) ||
            (pp->buffer_pos + (end_key - start_key) <
             pp->buffer_pos) )
@@ -636,6 +635,11 @@ post_process_urlencoded (struct MHD_PostProcessor *pp,
   {
     if (NULL == end_key) 
       end_key = &post_data[poff];
+    if (pp->buffer_pos + (end_key - start_key) >= pp->buffer_size)
+    {
+      pp->state = PP_Error;
+      return MHD_NO;
+    }
     memcpy (&kbuf[pp->buffer_pos],
             start_key,
             end_key - start_key);
@@ -663,6 +667,11 @@ post_process_urlencoded (struct MHD_PostProcessor *pp,
                    last_escape);
     pp->must_ikvi = false;
   }
+  if (PP_Error == pp->state)
+  {
+    /* State in error, returning failure */
+    return MHD_NO;
+  }
   return MHD_YES;
 }
 
@@ -1424,7 +1433,8 @@ MHD_destroy_post_processor (struct MHD_PostProcessor *pp)
      the post-processing may have been interrupted
      at any stage */
   if ( (pp->xbuf_pos > 0) ||
-       (pp->state != PP_Done) )
+       ( (pp->state != PP_Done) &&
+         (pp->state != PP_Init) ) )
     ret = MHD_NO;
   else
     ret = MHD_YES;
diff --git a/src/microhttpd/test_postprocessor.c b/src/microhttpd/test_postprocessor.c
index 2c37565..cba486d 100644
--- a/src/microhttpd/test_postprocessor.c
+++ b/src/microhttpd/test_postprocessor.c
@@ -451,6 +451,71 @@ test_empty_value (void)
 }
 
 
+static enum MHD_Result
+value_checker2 (void *cls,
+                enum MHD_ValueKind kind,
+                const char *key,
+                const char *filename,
+                const char *content_type,
+                const char *transfer_encoding,
+                const char *data,
+                uint64_t off,
+                size_t size)
+{
+  return MHD_YES;
+}
+
+
+static int
+test_overflow ()
+{
+  struct MHD_Connection connection;
+  struct MHD_HTTP_Header header;
+  struct MHD_PostProcessor *pp;
+  size_t i;
+  size_t j;
+  size_t delta;
+  char *buf;
+
+  memset (&connection, 0, sizeof (struct MHD_Connection));
+  memset (&header, 0, sizeof (struct MHD_HTTP_Header));
+  connection.headers_received = &header;
+  header.header = MHD_HTTP_HEADER_CONTENT_TYPE;
+  header.value = MHD_HTTP_POST_ENCODING_FORM_URLENCODED;
+  header.header_size = strlen (header.header);
+  header.value_size = strlen (header.value);
+  header.kind = MHD_HEADER_KIND;
+  for (i = 128; i < 1024 * 1024; i += 1024)
+  {
+    pp = MHD_create_post_processor (&connection,
+                                    1024,
+                                    &value_checker2,
+                                    NULL);
+    buf = malloc (i);
+    if (NULL == buf)
+      return 1;
+    memset (buf, 'A', i);
+    buf[i / 2] = '=';
+    delta = 1 + (MHD_random_ () % (i - 1));
+    j = 0;
+    while (j < i)
+    {
+      if (j + delta > i)
+        delta = i - j;
+      if (MHD_NO ==
+          MHD_post_process (pp,
+                            &buf[j],
+                            delta))
+        break;
+      j += delta;
+    }
+    free (buf);
+    MHD_destroy_post_processor (pp);
+  }
+  return 0;
+}
+
+
 int
 main (int argc, char *const *argv)
 {
@@ -463,6 +528,7 @@ main (int argc, char *const *argv)
   errorCount += test_multipart ();
   errorCount += test_nested_multipart ();
   errorCount += test_empty_value ();
+  errorCount += test_overflow ();
   if (errorCount != 0)
     fprintf (stderr, "Error (code: %u)\n", errorCount);
   return errorCount != 0;       /* 0 == pass */