Skip to content

Commit

Permalink
Reject non-IPv4 hostnames that end in numbers.
Browse files Browse the repository at this point in the history
  • Loading branch information
F3n67u committed Jun 3, 2022
1 parent 5b6f280 commit 9d8ddc1
Show file tree
Hide file tree
Showing 3 changed files with 39 additions and 12 deletions.
45 changes: 36 additions & 9 deletions src/node_url.cc
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#include "node_errors.h"
#include "node_external_reference.h"
#include "node_i18n.h"
#include "util.h"
#include "util-inl.h"

#include <cmath>
Expand Down Expand Up @@ -58,7 +59,7 @@ class URLHost {
public:
~URLHost();

void ParseIPv4Host(const char* input, size_t length, bool* is_ipv4);
void ParseIPv4Host(const char* input, size_t length);
void ParseIPv6Host(const char* input, size_t length);
void ParseOpaqueHost(const char* input, size_t length);
void ParseHost(const char* input,
Expand Down Expand Up @@ -401,9 +402,37 @@ int64_t ParseNumber(const char* start, const char* end) {
return strtoll(start, nullptr, R);
}

void URLHost::ParseIPv4Host(const char* input, size_t length, bool* is_ipv4) {
// https://url.spec.whatwg.org/#ends-in-a-number-checker
bool EndsInANumber(std::string& str) {
std::vector<std::string> parts = SplitString(str, '.', false);
if (parts.size() == 0)
return false;

if (parts.back() == "") {
if (parts.size() == 1)
return false;
parts.pop_back();
}

const std::string& last = parts.back();

if (last == "")
return false;

int64_t num = ParseNumber(last.c_str(), last.c_str() + last.size());
if (num >= 0)
return true;

if (last.find_first_not_of("0123456789") == std::string::npos) {
return true;
}

return false;
}


void URLHost::ParseIPv4Host(const char* input, size_t length) {
CHECK_EQ(type_, HostType::H_FAILED);
*is_ipv4 = false;
const char* pointer = input;
const char* mark = input;
const char* end = pointer + length;
Expand Down Expand Up @@ -436,7 +465,6 @@ void URLHost::ParseIPv4Host(const char* input, size_t length, bool* is_ipv4) {
pointer++;
}
CHECK_GT(parts, 0);
*is_ipv4 = true;

// If any but the last item in numbers is greater than 255, return failure.
// If the last item in numbers is greater than or equal to
Expand Down Expand Up @@ -508,11 +536,10 @@ void URLHost::ParseHost(const char* input,
}
}

// Check to see if it's an IPv4 IP address
bool is_ipv4;
ParseIPv4Host(decoded.c_str(), decoded.length(), &is_ipv4);
if (is_ipv4)
return;
// If domain ends in a number, then return the result of IPv4 parsing domain
if (EndsInANumber(decoded)) {
return ParseIPv4Host(decoded.c_str(), decoded.length());
}

// If the unicode flag is set, run the result through punycode ToUnicode
if (unicode && !ToUnicode(decoded, &decoded))
Expand Down
4 changes: 2 additions & 2 deletions src/util.cc
Original file line number Diff line number Diff line change
Expand Up @@ -164,15 +164,15 @@ std::string GetHumanReadableProcessName() {
return SPrintF("%s[%d]", GetProcessTitle("Node.js"), uv_os_getpid());
}

std::vector<std::string> SplitString(const std::string& in, char delim) {
std::vector<std::string> SplitString(const std::string& in, char delim, bool skipEmpty) {
std::vector<std::string> out;
if (in.empty())
return out;
std::istringstream in_stream(in);
while (in_stream.good()) {
std::string item;
std::getline(in_stream, item, delim);
if (item.empty()) continue;
if (item.empty() && skipEmpty) continue;
out.emplace_back(std::move(item));
}
return out;
Expand Down
2 changes: 1 addition & 1 deletion src/util.h
Original file line number Diff line number Diff line change
Expand Up @@ -645,7 +645,7 @@ struct FunctionDeleter {
template <typename T, void (*function)(T*)>
using DeleteFnPtr = typename FunctionDeleter<T, function>::Pointer;

std::vector<std::string> SplitString(const std::string& in, char delim);
std::vector<std::string> SplitString(const std::string& in, char delim, bool skipEmpty = true);

inline v8::MaybeLocal<v8::Value> ToV8Value(v8::Local<v8::Context> context,
std::string_view str,
Expand Down

0 comments on commit 9d8ddc1

Please sign in to comment.