Skip to content

Commit 4d3fde9

Browse files
committed
fix GetServers csv parser robustness for c-ares CSV output
1 parent fedc05d commit 4d3fde9

1 file changed

Lines changed: 32 additions & 4 deletions

File tree

src/cares_wrap.cc

Lines changed: 32 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2163,29 +2163,57 @@ void GetServers(const FunctionCallbackInfo<Value>& args) {
21632163
std::string entry = servers_str.substr(pos, comma - pos);
21642164
pos = comma + 1;
21652165

2166+
// Trim whitespace just in case c-ares somehow adds it
2167+
size_t first = entry.find_first_not_of(" \t\r\n");
2168+
if (first == std::string::npos) continue;
2169+
size_t last = entry.find_last_not_of(" \t\r\n");
2170+
entry = entry.substr(first, (last - first + 1));
2171+
if (entry.empty()) continue;
2172+
21662173
std::string host;
21672174
int port = 53; // default DNS port
21682175

2169-
if (!entry.empty() && entry[0] == '[') {
2176+
if (entry[0] == '[') {
21702177
/* IPv6: [host]:port or [host] */
21712178
auto bracket_end = entry.find(']');
21722179
if (bracket_end != std::string::npos) {
21732180
host = entry.substr(1, bracket_end - 1);
21742181
if (bracket_end + 1 < entry.size() && entry[bracket_end + 1] == ':') {
2175-
port = std::stoi(entry.substr(bracket_end + 2));
2182+
try {
2183+
port = std::stoi(entry.substr(bracket_end + 2));
2184+
} catch (...) { /* ignore */
2185+
}
21762186
}
2187+
} else {
2188+
host = entry; // fallback if malformed
21772189
}
21782190
} else {
21792191
/* IPv4: host:port or just host */
21802192
auto colon = entry.rfind(':');
2181-
if (colon != std::string::npos) {
2193+
/* ensure colon isn't part of an IPv6 address accidentally output without
2194+
* brackets */
2195+
auto first_colon = entry.find(':');
2196+
if (colon != std::string::npos && colon == first_colon) {
21822197
host = entry.substr(0, colon);
2183-
port = std::stoi(entry.substr(colon + 1));
2198+
try {
2199+
port = std::stoi(entry.substr(colon + 1));
2200+
} catch (...) { /* ignore */
2201+
}
21842202
} else {
2203+
/* no port, or IPv6 addr without brackets */
21852204
host = entry;
21862205
}
21872206
}
21882207

2208+
// Node.js expects IPv6 scope IDs to be preserved (if they were generated).
2209+
// The previous implementation dropped them since uv_inet_ntop ignores scope
2210+
// IDs. To match the previous strict behavior perfectly, we strip scope IDs
2211+
// (e.g. %lo0).
2212+
auto pct = host.find('%');
2213+
if (pct != std::string::npos) {
2214+
host = host.substr(0, pct);
2215+
}
2216+
21892217
Local<Value> ret[] = {OneByteString(env->isolate(), host.c_str()),
21902218
Integer::New(env->isolate(), port)};
21912219

0 commit comments

Comments
 (0)