Skip to content

Commit

Permalink
Merged Pull Request '#88 feature/ip-parser-respect-end->version/4.5: …
Browse files Browse the repository at this point in the history
…IP parsing function contract improvements.'

* FIX: Treat new line character as IP break.

* REFACT: Do not require terminator to be included in IP string for parsing.

* REFACT: Add `ParseIp_Ipv4_NoOverwrite12` test and comment.
  • Loading branch information
drasmart authored Feb 25, 2025
1 parent 029298b commit 25c8e93
Show file tree
Hide file tree
Showing 3 changed files with 94 additions and 12 deletions.
13 changes: 10 additions & 3 deletions ip.c
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,7 @@ static IpStringSeparatorType getSeparatorCharType(
case ']':
case '/':
case '\0':
case '\n':
return IP_ADDRESS_BREAK_CHAR;
default:
break;
Expand Down Expand Up @@ -207,6 +208,8 @@ static IpType iterateIpAddress(
IpType type,
const parseIterator foundSegment) {

const char * const postEnd = end + 1;

*springCount = 0;
if (*start == '[') {
if (type == IP_TYPE_IPV4) {
Expand All @@ -220,9 +223,13 @@ static IpType iterateIpAddress(

const char *current = start;
const char *nextSegment = current;
for (; current <= end && nextSegment < end; ++current) {
for (; current <= postEnd && nextSegment <= postEnd; ++current) {
char nextChar = 0;
if (current < postEnd) {
nextChar = *current;
}
IpStringSeparatorType separatorType =
getSeparatorCharType(*current, type);
getSeparatorCharType(nextChar, type);
if (!separatorType) {
continue;
}
Expand All @@ -231,7 +238,7 @@ static IpType iterateIpAddress(
}

currentSegmentType = getSegmentTypeWithSeparator(
*current, type, currentSegmentType);
nextChar, type, currentSegmentType);
if (type == IP_TYPE_INVALID) {
type = currentSegmentType;
}
Expand Down
11 changes: 6 additions & 5 deletions ip.h
Original file line number Diff line number Diff line change
Expand Up @@ -74,15 +74,16 @@ typedef struct fiftyone_degrees_ip_address_t {

/**
* Parse a single IP address string.
* Does not modify the last 12 (out of 16) bytes when parsing IPv4.
* @param start of the string containing the IP address to parse
* @param end of the string containing the IP address to parse
* @param address memory to write parsed IP address into
* @param end the last character of the string (with IP address) to be considered for parsing
* @param address memory to write parsed IP address into.
* @return <c>true</c> if address was parsed correctly, <c>false</c> otherwise
*/
EXTERNAL bool fiftyoneDegreesIpAddressParse(
const char * const start,
const char * const end,
fiftyoneDegreesIpAddress * const address);
const char *start,
const char *end,
fiftyoneDegreesIpAddress *address);

/**
* Compare two IP addresses in its binary form
Expand Down
82 changes: 78 additions & 4 deletions tests/IpParserTests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
#include "../fiftyone.h"
#include <memory>

static bool CheckResult(byte* result, byte* expected, uint16_t size) {
static bool CheckResult(byte* result, const byte* expected, uint16_t size) {
bool match = true;
for (uint16_t i = 0; i < size; i++) {
match = match && *result == *expected;
Expand All @@ -35,13 +35,21 @@ static bool CheckResult(byte* result, byte* expected, uint16_t size) {
return match;
}

static std::unique_ptr<IpAddress> parseIpAddressString(const char * const ipString) {
static bool parseIpAddressInPlace(const std::unique_ptr<IpAddress> &ipAddress, const char * const ipString, const size_t length) {
const char * const end = ipString ? ipString + length : nullptr;
return IpAddressParse(ipString, end, ipAddress.get());
}

static std::unique_ptr<IpAddress> parseIpAddressStringOfLength(const char * const ipString, const size_t length) {
std::unique_ptr<IpAddress> ipPtr = std::make_unique<IpAddress>();
const char * const end = ipString ? ipString + strlen(ipString) : nullptr;
const bool parsed = IpAddressParse(ipString, end, ipPtr.get());
const bool parsed =parseIpAddressInPlace(ipPtr, ipString, length);
return parsed ? std::move(ipPtr) : nullptr;
}

static std::unique_ptr<IpAddress> parseIpAddressString(const char * const ipString) {
return parseIpAddressStringOfLength(ipString, ipString ? strlen(ipString) : 0);
}

// ------------------------------------------------------------------------------
// IPv4 tests
// ------------------------------------------------------------------------------
Expand All @@ -60,6 +68,72 @@ TEST(ParseIp, ParseIp_Ipv4_High)
EXPECT_TRUE(CheckResult(result->value, expected, sizeof(expected)))
<< L"Expected result to be '255.255.255.255'";
}
TEST(ParseIp, ParseIp_Ipv4_Endline)
{
const char* ip = "0.0.0.0\n";
auto const result = parseIpAddressString(ip);
byte expected[] = { 0, 0, 0, 0 };
EXPECT_TRUE(result) <<
L"Expected result to be non-NULL.";
EXPECT_TRUE(CheckResult(result->value, expected, sizeof(expected) - 1)) <<
L"Expected result to be '0.0.0.0'";
}
TEST(ParseIp, ParseIp_Ipv4_NoOverwrite12)
{
const char ip[] = "73.79.83.89";
constexpr byte initial[] {
67, 13, 43, 47, 53, 29, 61, 19, 41, 31, 59, 71, 23, 37, 17, 11,
}, expected[] {
73, 79, 83, 89, 53, 29, 61, 19, 41, 31, 59, 71, 23, 37, 17, 11,
};
std::unique_ptr<IpAddress> ipAddress = std::make_unique<IpAddress>();
memcpy(ipAddress->value, initial, sizeof(initial));
const bool parsed = parseIpAddressInPlace(ipAddress, ip, sizeof(ip));
EXPECT_TRUE(parsed) <<
L"Expected result to be non-NULL.";
EXPECT_TRUE(CheckResult(ipAddress->value, expected, sizeof(expected) - 1)) <<
L"Expected result to be '73.79.83.89' with the rest (12 bytes) unchanged.";
}
TEST(ParseIp, ParseIp_Ipv4_Trim0)
{
const char* ip = "192.168.101.217";
auto const result = parseIpAddressStringOfLength(ip, strlen(ip));
byte expected[] = { 192, 168, 101, 217 };
EXPECT_TRUE(result) <<
L"Expected result to be non-NULL.";
EXPECT_TRUE(CheckResult(result->value, expected, sizeof(expected) - 1)) <<
L"Expected result to be '192.168.101.217'";
}
TEST(ParseIp, ParseIp_Ipv4_Trim1)
{
const char* ip = "192.168.101.217";
auto const result = parseIpAddressStringOfLength(ip, strlen(ip) - 1);
byte expected[] = { 192, 168, 101, 217 };
EXPECT_TRUE(result) <<
L"Expected result to be non-NULL.";
EXPECT_TRUE(CheckResult(result->value, expected, sizeof(expected) - 1)) <<
L"Expected result to be '192.168.101.217'";
}
TEST(ParseIp, ParseIp_Ipv4_Trim2)
{
const char* ip = "192.168.101.217";
auto const result = parseIpAddressStringOfLength(ip, strlen(ip) - 2);
byte expected[] = { 192, 168, 101, 21 };
EXPECT_TRUE(result) <<
L"Expected result to be non-NULL.";
EXPECT_TRUE(CheckResult(result->value, expected, sizeof(expected) - 1)) <<
L"Expected result to be '192.168.101.21'";
}
TEST(ParseIp, ParseIp_Ipv4_Trim3)
{
const char* ip = "192.168.101.217";
auto const result = parseIpAddressStringOfLength(ip, strlen(ip) - 3);
byte expected[] = { 192, 168, 101, 2 };
EXPECT_TRUE(result) <<
L"Expected result to be non-NULL.";
EXPECT_TRUE(CheckResult(result->value, expected, sizeof(expected) - 1)) <<
L"Expected result to be '192.168.101.2'";
}
TEST(ParseIp, ParseIp_Ipv4_PortNumber)
{
auto const result = parseIpAddressString("1.2.3.4:80");
Expand Down

0 comments on commit 25c8e93

Please sign in to comment.