@@ -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