Skip to content

Commit a018006

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

1 file changed

Lines changed: 28 additions & 4 deletions

File tree

src/cares_wrap.cc

Lines changed: 28 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2163,29 +2163,53 @@ 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 */ }
21762185
}
2186+
} else {
2187+
host = entry; // fallback if malformed
21772188
}
21782189
} else {
21792190
/* IPv4: host:port or just host */
21802191
auto colon = entry.rfind(':');
2181-
if (colon != std::string::npos) {
2192+
/* ensure colon isn't part of an IPv6 address accidentally output without brackets */
2193+
auto first_colon = entry.find(':');
2194+
if (colon != std::string::npos && colon == first_colon) {
21822195
host = entry.substr(0, colon);
2183-
port = std::stoi(entry.substr(colon + 1));
2196+
try {
2197+
port = std::stoi(entry.substr(colon + 1));
2198+
} catch (...) { /* ignore */ }
21842199
} else {
2200+
/* no port, or IPv6 addr without brackets */
21852201
host = entry;
21862202
}
21872203
}
21882204

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

0 commit comments

Comments
 (0)