mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-01-15 06:20:41 +00:00
Bug 1063281, Part 3: Implement ParseIPv4Address, r=keeler
--HG-- extra : rebase_source : fbafcb7573be8fa83036a8fadbfa74938ab7a4a6
This commit is contained in:
parent
4a2c8b5274
commit
0e87ec98c7
@ -35,6 +35,61 @@
|
||||
|
||||
namespace mozilla { namespace pkix {
|
||||
|
||||
namespace {
|
||||
|
||||
bool
|
||||
ReadIPv4AddressComponent(Reader& input, bool lastComponent,
|
||||
/*out*/ uint8_t& valueOut)
|
||||
{
|
||||
size_t length = 0;
|
||||
unsigned int value = 0; // Must be larger than uint8_t.
|
||||
|
||||
for (;;) {
|
||||
if (input.AtEnd() && lastComponent) {
|
||||
break;
|
||||
}
|
||||
|
||||
uint8_t b;
|
||||
if (input.Read(b) != Success) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (b >= '0' && b <= '9') {
|
||||
if (value == 0 && length > 0) {
|
||||
return false; // Leading zeros are not allowed.
|
||||
}
|
||||
value = (value * 10) + (b - '0');
|
||||
if (value > 255) {
|
||||
return false; // Component's value is too large.
|
||||
}
|
||||
++length;
|
||||
} else if (!lastComponent && b == '.') {
|
||||
break;
|
||||
} else {
|
||||
return false; // Invalid character.
|
||||
}
|
||||
}
|
||||
|
||||
if (length == 0) {
|
||||
return false; // empty components not allowed
|
||||
}
|
||||
|
||||
valueOut = static_cast<uint8_t>(value);
|
||||
return true;
|
||||
}
|
||||
|
||||
} // unnamed namespace
|
||||
|
||||
bool
|
||||
ParseIPv4Address(Input hostname, /*out*/ uint8_t (&out)[4])
|
||||
{
|
||||
Reader input(hostname);
|
||||
return ReadIPv4AddressComponent(input, false, out[0]) &&
|
||||
ReadIPv4AddressComponent(input, false, out[1]) &&
|
||||
ReadIPv4AddressComponent(input, false, out[2]) &&
|
||||
ReadIPv4AddressComponent(input, true, out[3]);
|
||||
}
|
||||
|
||||
bool
|
||||
IsValidDNSName(Input hostname)
|
||||
{
|
||||
|
@ -31,6 +31,7 @@
|
||||
namespace mozilla { namespace pkix {
|
||||
|
||||
bool IsValidDNSName(Input hostname);
|
||||
bool ParseIPv4Address(Input hostname, /*out*/ uint8_t (&out)[4]);
|
||||
|
||||
} } // namespace mozilla::pkix
|
||||
|
||||
@ -237,6 +238,108 @@ static const InputValidity DNSNAMES_VALIDITY_TURKISH_I[] =
|
||||
I("xn--\0xC4\0xB1", false), // latin small letter dotless i, mashup
|
||||
};
|
||||
|
||||
template <unsigned int L>
|
||||
struct IPAddressParams
|
||||
{
|
||||
ByteString input;
|
||||
bool isValid;
|
||||
uint8_t expectedValueIfValid[L];
|
||||
};
|
||||
|
||||
#define IPV4_VALID(str, a, b, c, d) \
|
||||
{ \
|
||||
ByteString(reinterpret_cast<const uint8_t*>(str), sizeof(str) - 1), \
|
||||
true, \
|
||||
{ a, b, c, d } \
|
||||
}
|
||||
|
||||
// The value of expectedValueIfValid must be ignored for invalid IP addresses.
|
||||
// The value { 73, 73, 73, 73 } is used because it is unlikely to result in an
|
||||
// accidental match, unlike { 0, 0, 0, 0 }, which is a value we actually test.
|
||||
#define IPV4_INVALID(str) \
|
||||
{ \
|
||||
ByteString(reinterpret_cast<const uint8_t*>(str), sizeof(str) - 1), \
|
||||
false, \
|
||||
{ 73, 73, 73, 73 } \
|
||||
}
|
||||
|
||||
static const IPAddressParams<4> IPV4_ADDRESSES[] =
|
||||
{
|
||||
IPV4_INVALID(""),
|
||||
IPV4_INVALID("1"),
|
||||
IPV4_INVALID("1.2"),
|
||||
IPV4_INVALID("1.2.3"),
|
||||
IPV4_VALID("1.2.3.4", 1, 2, 3, 4),
|
||||
IPV4_INVALID("1.2.3.4.5"),
|
||||
|
||||
IPV4_INVALID("1.2.3.4a"), // a DNSName!
|
||||
IPV4_INVALID("a.2.3.4"), // not even a DNSName!
|
||||
IPV4_INVALID("1::2"), // IPv6 address
|
||||
|
||||
// Whitespace not allowed
|
||||
IPV4_INVALID(" 1.2.3.4"),
|
||||
IPV4_INVALID("1.2.3.4 "),
|
||||
IPV4_INVALID("1 .2.3.4"),
|
||||
IPV4_INVALID("\n1.2.3.4"),
|
||||
IPV4_INVALID("1.2.3.4\n"),
|
||||
|
||||
// Nulls not allowed
|
||||
IPV4_INVALID("\0"),
|
||||
IPV4_INVALID("\0" "1.2.3.4"),
|
||||
IPV4_INVALID("1.2.3.4\0"),
|
||||
IPV4_INVALID("1.2.3.4\0.5"),
|
||||
|
||||
// Range
|
||||
IPV4_VALID("0.0.0.0", 0, 0, 0, 0),
|
||||
IPV4_VALID("255.255.255.255", 255, 255, 255, 255),
|
||||
IPV4_INVALID("256.0.0.0"),
|
||||
IPV4_INVALID("0.256.0.0"),
|
||||
IPV4_INVALID("0.0.256.0"),
|
||||
IPV4_INVALID("0.0.0.256"),
|
||||
IPV4_INVALID("999.0.0.0"),
|
||||
IPV4_INVALID("9999999999999999999.0.0.0"),
|
||||
|
||||
// All digits allowed
|
||||
IPV4_VALID("0.1.2.3", 0, 1, 2, 3),
|
||||
IPV4_VALID("4.5.6.7", 4, 5, 6, 7),
|
||||
IPV4_VALID("8.9.0.1", 8, 9, 0, 1),
|
||||
|
||||
// Leading zeros not allowed
|
||||
IPV4_INVALID("01.2.3.4"),
|
||||
IPV4_INVALID("001.2.3.4"),
|
||||
IPV4_INVALID("00000000001.2.3.4"),
|
||||
IPV4_INVALID("010.2.3.4"),
|
||||
IPV4_INVALID("1.02.3.4"),
|
||||
IPV4_INVALID("1.2.03.4"),
|
||||
IPV4_INVALID("1.2.3.04"),
|
||||
|
||||
// Empty components
|
||||
IPV4_INVALID(".2.3.4"),
|
||||
IPV4_INVALID("1..3.4"),
|
||||
IPV4_INVALID("1.2..4"),
|
||||
IPV4_INVALID("1.2.3."),
|
||||
|
||||
// Too many components
|
||||
IPV4_INVALID("1.2.3.4.5"),
|
||||
IPV4_INVALID("1.2.3.4.5.6"),
|
||||
IPV4_INVALID("0.1.2.3.4"),
|
||||
IPV4_INVALID("1.2.3.4.0"),
|
||||
|
||||
// Leading/trailing dot
|
||||
IPV4_INVALID(".1.2.3.4"),
|
||||
IPV4_INVALID("1.2.3.4."),
|
||||
|
||||
// Other common forms of IPv4 address
|
||||
// http://en.wikipedia.org/wiki/IPv4#Address_representations
|
||||
IPV4_VALID("192.0.2.235", 192, 0, 2, 235), // dotted decimal (control value)
|
||||
IPV4_INVALID("0xC0.0x00.0x02.0xEB"), // dotted hex
|
||||
IPV4_INVALID("0301.0000.0002.0353"), // dotted octal
|
||||
IPV4_INVALID("0xC00002EB"), // non-dotted hex
|
||||
IPV4_INVALID("3221226219"), // non-dotted decimal
|
||||
IPV4_INVALID("030000001353"), // non-dotted octal
|
||||
IPV4_INVALID("192.0.0002.0xEB"), // mixed
|
||||
};
|
||||
|
||||
class pkixnames_IsValidDNSName
|
||||
: public ::testing::Test
|
||||
, public ::testing::WithParamInterface<InputValidity>
|
||||
@ -259,3 +362,29 @@ INSTANTIATE_TEST_CASE_P(pkixnames_IsValidDNSName,
|
||||
INSTANTIATE_TEST_CASE_P(pkixnames_IsValidDNSName_Turkish_I,
|
||||
pkixnames_IsValidDNSName,
|
||||
testing::ValuesIn(DNSNAMES_VALIDITY_TURKISH_I));
|
||||
|
||||
class pkixnames_ParseIPv4Address
|
||||
: public ::testing::Test
|
||||
, public ::testing::WithParamInterface<IPAddressParams<4>>
|
||||
{
|
||||
};
|
||||
|
||||
TEST_P(pkixnames_ParseIPv4Address, ParseIPv4Address)
|
||||
{
|
||||
const IPAddressParams<4>& param(GetParam());
|
||||
SCOPED_TRACE(param.input.c_str());
|
||||
Input input;
|
||||
ASSERT_EQ(Success, input.Init(param.input.data(),
|
||||
param.input.length()));
|
||||
uint8_t ipAddress[4];
|
||||
ASSERT_EQ(param.isValid, ParseIPv4Address(input, ipAddress));
|
||||
if (param.isValid) {
|
||||
for (size_t i = 0; i < sizeof(ipAddress); ++i) {
|
||||
ASSERT_EQ(param.expectedValueIfValid[i], ipAddress[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(pkixnames_ParseIPv4Address,
|
||||
pkixnames_ParseIPv4Address,
|
||||
testing::ValuesIn(IPV4_ADDRESSES));
|
||||
|
Loading…
x
Reference in New Issue
Block a user