mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-09 19:35:51 +00:00
Bug 504014 - Enforce RFC 3986 syntax for IPv6 literals
This commit is contained in:
parent
4610476ed2
commit
60e90c98b0
@ -37,6 +37,8 @@
|
|||||||
*
|
*
|
||||||
* ***** END LICENSE BLOCK ***** */
|
* ***** END LICENSE BLOCK ***** */
|
||||||
|
|
||||||
|
#include "mozilla/RangedPtr.h"
|
||||||
|
|
||||||
#include "nsURLHelper.h"
|
#include "nsURLHelper.h"
|
||||||
#include "nsReadableUtils.h"
|
#include "nsReadableUtils.h"
|
||||||
#include "nsIServiceManager.h"
|
#include "nsIServiceManager.h"
|
||||||
@ -53,6 +55,8 @@
|
|||||||
#include "prprf.h"
|
#include "prprf.h"
|
||||||
#include "prnetdb.h"
|
#include "prnetdb.h"
|
||||||
|
|
||||||
|
using namespace mozilla;
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
// Init/Shutdown
|
// Init/Shutdown
|
||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
@ -990,3 +994,94 @@ net_IsValidHostName(const nsCSubstring &host)
|
|||||||
PRNetAddr addr;
|
PRNetAddr addr;
|
||||||
return PR_StringToNetAddr(strhost.get(), &addr) == PR_SUCCESS;
|
return PR_StringToNetAddr(strhost.get(), &addr) == PR_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PRBool
|
||||||
|
net_IsValidIPv4Addr(const char *addr, PRInt32 addrLen)
|
||||||
|
{
|
||||||
|
RangedPtr<const char> p(addr, addrLen);
|
||||||
|
|
||||||
|
PRInt32 octet = -1; // means no digit yet
|
||||||
|
PRInt32 dotCount = 0; // number of dots in the address
|
||||||
|
|
||||||
|
for (; addrLen; ++p, --addrLen) {
|
||||||
|
if (*p == '.') {
|
||||||
|
dotCount++;
|
||||||
|
if (octet == -1) {
|
||||||
|
// invalid octet
|
||||||
|
return PR_FALSE;
|
||||||
|
}
|
||||||
|
octet = -1;
|
||||||
|
} else if (*p >= '0' && *p <='9') {
|
||||||
|
if (octet == 0) {
|
||||||
|
// leading 0 is not allowed
|
||||||
|
return PR_FALSE;
|
||||||
|
} else if (octet == -1) {
|
||||||
|
octet = *p - '0';
|
||||||
|
} else {
|
||||||
|
octet *= 10;
|
||||||
|
octet += *p - '0';
|
||||||
|
if (octet > 255)
|
||||||
|
return PR_FALSE;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// invalid character
|
||||||
|
return PR_FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (dotCount == 3 && octet != -1);
|
||||||
|
}
|
||||||
|
|
||||||
|
PRBool
|
||||||
|
net_IsValidIPv6Addr(const char *addr, PRInt32 addrLen)
|
||||||
|
{
|
||||||
|
RangedPtr<const char> p(addr, addrLen);
|
||||||
|
|
||||||
|
PRInt32 digits = 0; // number of digits in current block
|
||||||
|
PRInt32 colons = 0; // number of colons in a row during parsing
|
||||||
|
PRInt32 blocks = 0; // number of hexadecimal blocks
|
||||||
|
PRBool haveZeros = PR_FALSE; // true if double colon is present in the address
|
||||||
|
|
||||||
|
for (; addrLen; ++p, --addrLen) {
|
||||||
|
if (*p == ':') {
|
||||||
|
if (colons == 0) {
|
||||||
|
if (digits != 0) {
|
||||||
|
digits = 0;
|
||||||
|
blocks++;
|
||||||
|
}
|
||||||
|
} else if (colons == 1) {
|
||||||
|
if (haveZeros)
|
||||||
|
return PR_FALSE; // only one occurrence is allowed
|
||||||
|
haveZeros = PR_TRUE;
|
||||||
|
} else {
|
||||||
|
// too many colons in a row
|
||||||
|
return PR_FALSE;
|
||||||
|
}
|
||||||
|
colons++;
|
||||||
|
} else if ((*p >= '0' && *p <= '9') || (*p >= 'a' && *p <= 'f') ||
|
||||||
|
(*p >= 'A' && *p <= 'F')) {
|
||||||
|
if (colons == 1 && blocks == 0) // starts with a single colon
|
||||||
|
return PR_FALSE;
|
||||||
|
if (digits == 4) // too many digits
|
||||||
|
return PR_FALSE;
|
||||||
|
colons = 0;
|
||||||
|
digits++;
|
||||||
|
} else if (*p == '.') {
|
||||||
|
// check valid IPv4 from the beginning of the last block
|
||||||
|
if (!net_IsValidIPv4Addr(p.get() - digits, addrLen + digits))
|
||||||
|
return PR_FALSE;
|
||||||
|
return (haveZeros && blocks < 6) || (!haveZeros && blocks == 6);
|
||||||
|
} else {
|
||||||
|
// invalid character
|
||||||
|
return PR_FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (colons == 1) // ends with a single colon
|
||||||
|
return PR_FALSE;
|
||||||
|
|
||||||
|
if (digits) // there is a block at the end
|
||||||
|
blocks++;
|
||||||
|
|
||||||
|
return (haveZeros && blocks < 8) || (!haveZeros && blocks == 8);
|
||||||
|
}
|
||||||
|
@ -248,4 +248,14 @@ inline char *net_RFindCharNotInSet(const char *str, const char *set)
|
|||||||
*/
|
*/
|
||||||
NS_HIDDEN_(PRBool) net_IsValidHostName(const nsCSubstring &host);
|
NS_HIDDEN_(PRBool) net_IsValidHostName(const nsCSubstring &host);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks whether the IPv4 address is valid according to RFC 3986 section 3.2.2.
|
||||||
|
*/
|
||||||
|
NS_HIDDEN_(PRBool) net_IsValidIPv4Addr(const char *addr, PRInt32 addrLen);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks whether the IPv6 address is valid according to RFC 3986 section 3.2.2.
|
||||||
|
*/
|
||||||
|
NS_HIDDEN_(PRBool) net_IsValidIPv6Addr(const char *addr, PRInt32 addrLen);
|
||||||
|
|
||||||
#endif // !nsURLHelper_h__
|
#endif // !nsURLHelper_h__
|
||||||
|
@ -641,6 +641,13 @@ nsAuthURLParser::ParseServerInfo(const char *serverinfo, PRInt32 serverinfoLen,
|
|||||||
if (port)
|
if (port)
|
||||||
*port = -1;
|
*port = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// In case of IPv6 address check its validity
|
||||||
|
if (*hostnameLen > 1 && *(serverinfo + *hostnamePos) == '[' &&
|
||||||
|
*(serverinfo + *hostnamePos + *hostnameLen - 1) == ']' &&
|
||||||
|
!net_IsValidIPv6Addr(serverinfo + *hostnamePos + 1, *hostnameLen - 2))
|
||||||
|
return NS_ERROR_MALFORMED_URI;
|
||||||
|
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
73
netwerk/test/unit/test_bug504014.js
Normal file
73
netwerk/test/unit/test_bug504014.js
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
const Cc = Components.classes;
|
||||||
|
const Ci = Components.interfaces;
|
||||||
|
const Cr = Components.results;
|
||||||
|
|
||||||
|
var valid_URIs = [ "http://[::]/",
|
||||||
|
"http://[::1]/",
|
||||||
|
"http://[1::]/",
|
||||||
|
"http://[::]/",
|
||||||
|
"http://[::1]/",
|
||||||
|
"http://[1::]/",
|
||||||
|
"http://[1:2:3:4:5:6:7::]/",
|
||||||
|
"http://[::1:2:3:4:5:6:7]/",
|
||||||
|
"http://[1:2:a:B:c:D:e:F]/",
|
||||||
|
"http://[1::8]/",
|
||||||
|
"http://[1:2::8]/",
|
||||||
|
"http://[0000:0123:4567:89AB:CDEF:abcd:ef00:0000]/",
|
||||||
|
"http://[::192.168.1.1]/",
|
||||||
|
"http://[1::0.0.0.0]/",
|
||||||
|
"http://[1:2::255.255.255.255]/",
|
||||||
|
"http://[1:2:3::255.255.255.255]/",
|
||||||
|
"http://[1:2:3:4::255.255.255.255]/",
|
||||||
|
"http://[1:2:3:4:5::255.255.255.255]/",
|
||||||
|
"http://[1:2:3:4:5:6:255.255.255.255]/"];
|
||||||
|
|
||||||
|
var invalid_URIs = [ "http://[1]/",
|
||||||
|
"http://[192.168.1.1]/",
|
||||||
|
"http://[:::]/",
|
||||||
|
"http://[:::1]/",
|
||||||
|
"http://[1:::]/",
|
||||||
|
"http://[::1::]/",
|
||||||
|
"http://[1:2:3:4:5:6:7:]/",
|
||||||
|
"http://[:2:3:4:5:6:7:8]/",
|
||||||
|
"http://[1:2:3:4:5:6:7:8:]/",
|
||||||
|
"http://[:1:2:3:4:5:6:7:8]/",
|
||||||
|
"http://[1:2:3:4:5:6:7:8::]/",
|
||||||
|
"http://[::1:2:3:4:5:6:7:8]/",
|
||||||
|
"http://[1:2:3:4:5:6:7]/",
|
||||||
|
"http://[1:2:3:4:5:6:7:8:9]/",
|
||||||
|
"http://[00001:2:3:4:5:6:7:8]/",
|
||||||
|
"http://[0001:2:3:4:5:6:7:89abc]/",
|
||||||
|
"http://[A:b:C:d:E:f:G:h]/",
|
||||||
|
"http://[::192.168.1]/",
|
||||||
|
"http://[::192.168.1.]/",
|
||||||
|
"http://[::.168.1.1]/",
|
||||||
|
"http://[::192..1.1]/",
|
||||||
|
"http://[::0192.168.1.1]/",
|
||||||
|
"http://[::256.255.255.255]/",
|
||||||
|
"http://[::1x.255.255.255]/",
|
||||||
|
"http://[::192.4294967464.1.1]/",
|
||||||
|
"http://[1:2:3:4:5:6::255.255.255.255]/",
|
||||||
|
"http://[1:2:3:4:5:6:7:255.255.255.255]/"];
|
||||||
|
|
||||||
|
function run_test() {
|
||||||
|
var ios = Cc["@mozilla.org/network/io-service;1"].
|
||||||
|
getService(Ci.nsIIOService);
|
||||||
|
|
||||||
|
for (var i=0 ; i<valid_URIs.length ; i++) {
|
||||||
|
try {
|
||||||
|
var uri = ios.newURI(valid_URIs[i], null, null);
|
||||||
|
} catch (e) {
|
||||||
|
do_throw("cannot create URI:" + valid_URIs[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (var i=0 ; i<invalid_URIs.length ; i++) {
|
||||||
|
try {
|
||||||
|
var uri = ios.newURI(invalid_URIs[i], null, null);
|
||||||
|
do_throw("should throw: " + invalid_URIs[i]);
|
||||||
|
} catch (e) {
|
||||||
|
do_check_eq(e.result, Cr.NS_ERROR_MALFORMED_URI);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -45,6 +45,7 @@ tail =
|
|||||||
[test_bug482601.js]
|
[test_bug482601.js]
|
||||||
[test_bug484684.js]
|
[test_bug484684.js]
|
||||||
[test_bug490095.js]
|
[test_bug490095.js]
|
||||||
|
[test_bug504014.js]
|
||||||
[test_bug510359.js]
|
[test_bug510359.js]
|
||||||
[test_bug515583.js]
|
[test_bug515583.js]
|
||||||
[test_bug528292.js]
|
[test_bug528292.js]
|
||||||
|
Loading…
Reference in New Issue
Block a user