summaryrefslogtreecommitdiff
path: root/gnu/packages/patches/icecat-CVE-2015-7193.patch
blob: 798799de9f06d57ff2f134d47c859ff9d60c7dca (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
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
From d135e3b3c48811c577e1632a41c5c50bc55c035c Mon Sep 17 00:00:00 2001
From: Ehsan Akhgari <ehsan@mozilla.com>
Date: Tue, 20 Oct 2015 11:40:12 +0200
Subject: [PATCH] Bug 1210302 - Add a NS_ParseRequestContentType API; ba=al, 
 r=mcmanus, r=sicking, a=al

--HG--
extra : amend_source : d93021b626709b03f6499029dc3d1813cccba386
---
 docshell/base/nsDocShell.cpp       |  2 +-
 dom/base/Navigator.cpp             |  4 +--
 dom/base/nsContentUtils.cpp        |  2 +-
 dom/html/nsHTMLDocument.cpp        |  2 +-
 dom/manifest/ManifestProcessor.jsm |  6 ++--
 netwerk/base/moz.build             |  1 +
 netwerk/base/nsINetUtil_ESR_38.idl | 14 +++++++++
 netwerk/base/nsIOService.cpp       | 12 ++++++++
 netwerk/base/nsIOService.h         |  3 ++
 netwerk/base/nsNetUtil.h           | 21 +++++++++++++
 netwerk/base/nsURLHelper.cpp       | 60 +++++++++++++++++++++++++++++++++++---
 netwerk/base/nsURLHelper.h         | 32 +++++++++++++++-----
 12 files changed, 139 insertions(+), 20 deletions(-)
 create mode 100644 netwerk/base/nsINetUtil_ESR_38.idl

diff --git a/docshell/base/nsDocShell.cpp b/docshell/base/nsDocShell.cpp
index bcc205c..4fc7c34 100644
--- a/docshell/base/nsDocShell.cpp
+++ b/docshell/base/nsDocShell.cpp
@@ -13519,7 +13519,7 @@ nsDocShell::OnLinkClickSync(nsIContent* aContent,
     anchor->GetType(typeHint);
     NS_ConvertUTF16toUTF8 utf8Hint(typeHint);
     nsAutoCString type, dummy;
-    NS_ParseContentType(utf8Hint, type, dummy);
+    NS_ParseRequestContentType(utf8Hint, type, dummy);
     CopyUTF8toUTF16(type, typeHint);
   }
 
diff --git a/dom/base/Navigator.cpp b/dom/base/Navigator.cpp
index f4ea502..7288420 100644
--- a/dom/base/Navigator.cpp
+++ b/dom/base/Navigator.cpp
@@ -1221,9 +1221,9 @@ Navigator::SendBeacon(const nsAString& aUrl,
   rv = secMan->CheckSameOriginURI(documentURI, uri, false);
   bool crossOrigin = NS_FAILED(rv);
   nsAutoCString contentType, parsedCharset;
-  rv = NS_ParseContentType(mimeType, contentType, parsedCharset);
+  rv = NS_ParseRequestContentType(mimeType, contentType, parsedCharset);
   if (crossOrigin &&
-      contentType.Length() > 0 &&
+      mimeType.Length() > 0 &&
       !contentType.Equals(APPLICATION_WWW_FORM_URLENCODED) &&
       !contentType.Equals(MULTIPART_FORM_DATA) &&
       !contentType.Equals(TEXT_PLAIN)) {
diff --git a/dom/base/nsContentUtils.cpp b/dom/base/nsContentUtils.cpp
index 5e8dbd6..686f7bf 100644
--- a/dom/base/nsContentUtils.cpp
+++ b/dom/base/nsContentUtils.cpp
@@ -7001,7 +7001,7 @@ nsContentUtils::IsAllowedNonCorsContentType(const nsACString& aHeaderValue)
   nsAutoCString contentType;
   nsAutoCString unused;
 
-  nsresult rv = NS_ParseContentType(aHeaderValue, contentType, unused);
+  nsresult rv = NS_ParseRequestContentType(aHeaderValue, contentType, unused);
   if (NS_FAILED(rv)) {
     return false;
   }
diff --git a/dom/html/nsHTMLDocument.cpp b/dom/html/nsHTMLDocument.cpp
index 7481109..d195792 100644
--- a/dom/html/nsHTMLDocument.cpp
+++ b/dom/html/nsHTMLDocument.cpp
@@ -1422,7 +1422,7 @@ nsHTMLDocument::Open(JSContext* cx,
   nsAutoString type;
   nsContentUtils::ASCIIToLower(aType, type);
   nsAutoCString actualType, dummy;
-  NS_ParseContentType(NS_ConvertUTF16toUTF8(type), actualType, dummy);
+  NS_ParseRequestContentType(NS_ConvertUTF16toUTF8(type), actualType, dummy);
   if (!actualType.EqualsLiteral("text/html") &&
       !type.EqualsLiteral("replace")) {
     contentType.AssignLiteral("text/plain");
diff --git a/dom/manifest/ManifestProcessor.jsm b/dom/manifest/ManifestProcessor.jsm
index b6df920..f16881a 100644
--- a/dom/manifest/ManifestProcessor.jsm
+++ b/dom/manifest/ManifestProcessor.jsm
@@ -31,7 +31,7 @@ const imports = {};
 Cu.import('resource://gre/modules/Services.jsm', imports);
 Cu.importGlobalProperties(['URL']);
 const securityManager = imports.Services.scriptSecurityManager;
-const netutil = Cc['@mozilla.org/network/util;1'].getService(Ci.nsINetUtil);
+const netutil = Cc['@mozilla.org/network/util;1'].getService(Ci.nsINetUtil_ESR_38);
 const defaultDisplayMode = 'browser';
 const displayModes = new Set([
   'fullscreen',
@@ -258,7 +258,7 @@ this.ManifestProcessor.prototype.process = function({
         };
       let value = extractValue(obj),
         isParsable = (typeof value === 'string' && value.length > 0);
-      value = (isParsable) ? netutil.parseContentType(value.trim(), charset, hadCharset) : undefined;
+      value = (isParsable) ? netutil.parseRequestContentType(value.trim(), charset, hadCharset) : undefined;
       return (value === '') ? undefined : value;
     }
 
@@ -354,4 +354,4 @@ this.ManifestProcessor.prototype.process = function({
   };
   processedManifest.scope = processScopeMember(manifest, manifestURL, docURL, processedManifest.start_url);
   return processedManifest;
-};
\ No newline at end of file
+};
diff --git a/netwerk/base/moz.build b/netwerk/base/moz.build
index 877365b..deedf76 100644
--- a/netwerk/base/moz.build
+++ b/netwerk/base/moz.build
@@ -59,6 +59,7 @@ XPIDL_SOURCES += [
     'nsINestedURI.idl',
     'nsINetAddr.idl',
     'nsINetUtil.idl',
+    'nsINetUtil_ESR_38.idl',
     'nsINetworkInterceptController.idl',
     'nsINetworkLinkService.idl',
     'nsINetworkPredictor.idl',
diff --git a/netwerk/base/nsINetUtil_ESR_38.idl b/netwerk/base/nsINetUtil_ESR_38.idl
new file mode 100644
index 0000000..7ef40e9
--- /dev/null
+++ b/netwerk/base/nsINetUtil_ESR_38.idl
@@ -0,0 +1,14 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "nsISupports.idl"
+
+[scriptable, uuid(e82f2b9d-8bac-48bb-ade7-26a7cd4fb894)]
+interface nsINetUtil_ESR_38 : nsISupports
+{
+  AUTF8String parseRequestContentType(in AUTF8String aTypeHeader,
+                                      out AUTF8String aCharset,
+                                      out boolean aHadCharset);
+};
diff --git a/netwerk/base/nsIOService.cpp b/netwerk/base/nsIOService.cpp
index 83db86f..9a17e8b 100644
--- a/netwerk/base/nsIOService.cpp
+++ b/netwerk/base/nsIOService.cpp
@@ -321,6 +321,7 @@ NS_IMPL_ISUPPORTS(nsIOService,
                   nsIIOService,
                   nsIIOService2,
                   nsINetUtil,
+                  nsINetUtil_ESR_38,
                   nsISpeculativeConnect,
                   nsIObserver,
                   nsISupportsWeakReference)
@@ -1280,6 +1281,17 @@ nsIOService::Observe(nsISupports *subject,
 
 // nsINetUtil interface
 NS_IMETHODIMP
+nsIOService::ParseRequestContentType(const nsACString &aTypeHeader,
+                                     nsACString &aCharset,
+                                     bool *aHadCharset,
+                                     nsACString &aContentType)
+{
+    net_ParseRequestContentType(aTypeHeader, aContentType, aCharset, aHadCharset);
+    return NS_OK;
+}
+
+// nsINetUtil interface
+NS_IMETHODIMP
 nsIOService::ParseContentType(const nsACString &aTypeHeader,
                               nsACString &aCharset,
                               bool *aHadCharset,
diff --git a/netwerk/base/nsIOService.h b/netwerk/base/nsIOService.h
index acd501c..b125709 100644
--- a/netwerk/base/nsIOService.h
+++ b/netwerk/base/nsIOService.h
@@ -14,6 +14,7 @@
 #include "nsIObserver.h"
 #include "nsWeakReference.h"
 #include "nsINetUtil.h"
+#include "nsINetUtil_ESR_38.h"
 #include "nsIChannelEventSink.h"
 #include "nsCategoryCache.h"
 #include "nsISpeculativeConnect.h"
@@ -47,6 +48,7 @@ namespace net {
 class nsIOService final : public nsIIOService2
                             , public nsIObserver
                             , public nsINetUtil
+                            , public nsINetUtil_ESR_38
                             , public nsISpeculativeConnect
                             , public nsSupportsWeakReference
 {
@@ -56,6 +58,7 @@ public:
     NS_DECL_NSIIOSERVICE2
     NS_DECL_NSIOBSERVER
     NS_DECL_NSINETUTIL
+    NS_DECL_NSINETUTIL_ESR_38
     NS_DECL_NSISPECULATIVECONNECT
 
     // Gets the singleton instance of the IO Service, creating it as needed
diff --git a/netwerk/base/nsNetUtil.h b/netwerk/base/nsNetUtil.h
index ec69716..df8874c 100644
--- a/netwerk/base/nsNetUtil.h
+++ b/netwerk/base/nsNetUtil.h
@@ -56,6 +56,7 @@
 #include "nsISyncStreamListener.h"
 #include "nsInterfaceRequestorAgg.h"
 #include "nsINetUtil.h"
+#include "nsINetUtil_ESR_38.h"
 #include "nsIURIWithPrincipal.h"
 #include "nsIAuthPrompt.h"
 #include "nsIAuthPrompt2.h"
@@ -1228,6 +1229,26 @@ NS_GetReferrerFromChannel(nsIChannel *channel,
 }
 
 inline nsresult
+NS_ParseRequestContentType(const nsACString &rawContentType,
+                           nsCString        &contentType,
+                           nsCString        &contentCharset)
+{
+    // contentCharset is left untouched if not present in rawContentType
+    nsresult rv;
+    nsCOMPtr<nsINetUtil> util = do_GetNetUtil(&rv);
+    NS_ENSURE_SUCCESS(rv, rv);
+    nsCOMPtr<nsINetUtil_ESR_38> utilESR38 = do_QueryInterface(util, &rv);
+    NS_ENSURE_SUCCESS(rv, rv);
+    nsCString charset;
+    bool hadCharset;
+    rv = utilESR38->ParseRequestContentType(rawContentType, charset, &hadCharset,
+                                            contentType);
+    if (NS_SUCCEEDED(rv) && hadCharset)
+        contentCharset = charset;
+    return rv;
+}
+
+inline nsresult
 NS_ParseContentType(const nsACString &rawContentType,
                     nsCString        &contentType,
                     nsCString        &contentCharset)
diff --git a/netwerk/base/nsURLHelper.cpp b/netwerk/base/nsURLHelper.cpp
index 10ea849..cdb2120 100644
--- a/netwerk/base/nsURLHelper.cpp
+++ b/netwerk/base/nsURLHelper.cpp
@@ -803,7 +803,8 @@ net_ParseMediaType(const nsACString &aMediaTypeStr,
                    int32_t          aOffset,
                    bool             *aHadCharset,
                    int32_t          *aCharsetStart,
-                   int32_t          *aCharsetEnd)
+                   int32_t          *aCharsetEnd,
+                   bool             aStrict)
 {
     const nsCString& flatStr = PromiseFlatCString(aMediaTypeStr);
     const char* start = flatStr.get();
@@ -820,6 +821,8 @@ net_ParseMediaType(const nsACString &aMediaTypeStr,
     int32_t charsetParamStart = 0;
     int32_t charsetParamEnd = 0;
 
+    uint32_t consumed = typeEnd - type;
+
     // Iterate over parameters
     bool typeHasCharset = false;
     uint32_t paramStart = flatStr.FindChar(';', typeEnd - start);
@@ -843,6 +846,7 @@ net_ParseMediaType(const nsACString &aMediaTypeStr,
                 charsetParamEnd = curParamEnd;
             }
 
+            consumed = curParamEnd;
             curParamStart = curParamEnd + 1;
         } while (curParamStart < flatStr.Length());
     }
@@ -872,8 +876,10 @@ net_ParseMediaType(const nsACString &aMediaTypeStr,
     // some servers give junk after the charset parameter, which may
     // include a comma, so this check makes us a bit more tolerant.
 
-    if (type != typeEnd && strncmp(type, "*/*", typeEnd - type) != 0 &&
-        memchr(type, '/', typeEnd - type) != nullptr) {
+    if (type != typeEnd &&
+        memchr(type, '/', typeEnd - type) != nullptr &&
+        (aStrict ? (net_FindCharNotInSet(start + consumed, end, HTTP_LWS) == end) :
+                   (strncmp(type, "*/*", typeEnd - type) != 0))) {
         // Common case here is that aContentType is empty
         bool eq = !aContentType.IsEmpty() &&
             aContentType.Equals(Substring(type, typeEnd),
@@ -980,13 +986,59 @@ net_ParseContentType(const nsACString &aHeaderStr,
         net_ParseMediaType(Substring(flatStr, curTypeStart,
                                      curTypeEnd - curTypeStart),
                            aContentType, aContentCharset, curTypeStart,
-                           aHadCharset, aCharsetStart, aCharsetEnd);
+                           aHadCharset, aCharsetStart, aCharsetEnd, false);
 
         // And let's move on to the next media-type
         curTypeStart = curTypeEnd + 1;
     } while (curTypeStart < flatStr.Length());
 }
 
+void
+net_ParseRequestContentType(const nsACString &aHeaderStr,
+                            nsACString       &aContentType,
+                            nsACString       &aContentCharset,
+                            bool             *aHadCharset)
+{
+    //
+    // Augmented BNF (from RFC 7231 section 3.1.1.1):
+    //
+    //   media-type   = type "/" subtype *( OWS ";" OWS parameter )
+    //   type         = token
+    //   subtype      = token
+    //   parameter    = token "=" ( token / quoted-string )
+    //
+    // Examples:
+    //
+    //   text/html
+    //   text/html; charset=ISO-8859-1
+    //   text/html; charset="ISO-8859-1"
+    //   application/octet-stream
+    //
+
+    aContentType.Truncate();
+    aContentCharset.Truncate();
+    *aHadCharset = false;
+    const nsCString& flatStr = PromiseFlatCString(aHeaderStr);
+
+    // At this point curTypeEnd points to the spot where the media-type
+    // starting at curTypeEnd ends.  Time to parse that!
+    nsAutoCString contentType, contentCharset;
+    bool hadCharset = false;
+    int32_t dummy1, dummy2;
+    uint32_t typeEnd = net_FindMediaDelimiter(flatStr, 0, ',');
+    if (typeEnd != flatStr.Length()) {
+        // We have some stuff left at the end, so this is not a valid
+        // request Content-Type header.
+        return;
+    }
+    net_ParseMediaType(flatStr, contentType, contentCharset, 0,
+                       &hadCharset, &dummy1, &dummy2, true);
+
+    aContentType = contentType;
+    aContentCharset = contentCharset;
+    *aHadCharset = hadCharset;
+}
+
 bool
 net_IsValidHostName(const nsCSubstring &host)
 {
diff --git a/netwerk/base/nsURLHelper.h b/netwerk/base/nsURLHelper.h
index 816a3c5..21e17be 100644
--- a/netwerk/base/nsURLHelper.h
+++ b/netwerk/base/nsURLHelper.h
@@ -172,11 +172,27 @@ char * net_RFindCharNotInSet(const char *str, const char *end, const char *set);
  * specified), aHadCharset is set to false.  Otherwise, it's set to
  * true.  Note that aContentCharset can be empty even if aHadCharset
  * is true.
+ *
+ * This parsing is suitable for HTTP request.  Use net_ParseContentType
+ * for parsing this header in HTTP responses.
+ */
+void net_ParseRequestContentType(const nsACString &aHeaderStr,
+                                 nsACString       &aContentType,
+                                 nsACString       &aContentCharset,
+                                 bool*          aHadCharset);
+
+/**
+ * Parses a content-type header and returns the content type and
+ * charset (if any).  aCharset is not modified if no charset is
+ * specified in anywhere in aHeaderStr.  In that case (no charset
+ * specified), aHadCharset is set to false.  Otherwise, it's set to
+ * true.  Note that aContentCharset can be empty even if aHadCharset
+ * is true.
  */
 void net_ParseContentType(const nsACString &aHeaderStr,
-                                      nsACString       &aContentType,
-                                      nsACString       &aContentCharset,
-                                      bool*          aHadCharset);
+                          nsACString       &aContentType,
+                          nsACString       &aContentCharset,
+                          bool*          aHadCharset);
 /**
  * As above, but also returns the start and end indexes for the charset
  * parameter in aHeaderStr.  These are indices for the entire parameter, NOT
@@ -187,11 +203,11 @@ void net_ParseContentType(const nsACString &aHeaderStr,
  * *aCharsetStart is nonnegative; this corresponds to charset="".
  */
 void net_ParseContentType(const nsACString &aHeaderStr,
-                                      nsACString       &aContentType,
-                                      nsACString       &aContentCharset,
-                                      bool             *aHadCharset,
-                                      int32_t          *aCharsetStart,
-                                      int32_t          *aCharsetEnd);
+                          nsACString       &aContentType,
+                          nsACString       &aContentCharset,
+                          bool             *aHadCharset,
+                          int32_t          *aCharsetStart,
+                          int32_t          *aCharsetEnd);
 
 /* inline versions */
 
-- 
2.5.0