aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Ashcon Partovi <ashcon@partovi.net> 2023-10-13 17:47:05 -0700
committerGravatar GitHub <noreply@github.com> 2023-10-13 17:47:05 -0700
commit77d7e47019753bacc76306dd9066df25c67c51a9 (patch)
tree40f4b058deb09ffe39f35f06f198f94e98605874
parent1bad64bc5e6fc2757a99dc7529d11c86835300bb (diff)
downloadbun-77d7e47019753bacc76306dd9066df25c67c51a9.tar.gz
bun-77d7e47019753bacc76306dd9066df25c67c51a9.tar.zst
bun-77d7e47019753bacc76306dd9066df25c67c51a9.zip
Fix dns.lookup returning wrong address for family (#6474)
* Fix #6452 * Fix formatting
-rw-r--r--src/bun.js/api/bun/dns_resolver.zig7
-rw-r--r--test/js/bun/dns/resolve-dns.test.ts126
2 files changed, 90 insertions, 43 deletions
diff --git a/src/bun.js/api/bun/dns_resolver.zig b/src/bun.js/api/bun/dns_resolver.zig
index 873cdcddc..3c20f4df7 100644
--- a/src/bun.js/api/bun/dns_resolver.zig
+++ b/src/bun.js/api/bun/dns_resolver.zig
@@ -102,11 +102,12 @@ const LibInfo = struct {
) catch unreachable;
const promise_value = request.head.promise.value();
+ const hints = query.options.toLibC();
const errno = getaddrinfo_async_start_(
&request.backend.libinfo.machport,
name_z.ptr,
null,
- null,
+ if (hints != null) &hints.? else null,
GetAddrInfoRequest.getAddrInfoAsyncCallback,
request,
);
@@ -2475,7 +2476,7 @@ pub const DNSResolver = struct {
return dns_lookup.promise.value();
}
- // var hints_buf = &[_]c_ares.AddrInfo_hints{query.toCAres()};
+ var hints_buf = &[_]c_ares.AddrInfo_hints{query.toCAres()};
var request = GetAddrInfoRequest.init(
cache,
.{
@@ -2491,7 +2492,7 @@ pub const DNSResolver = struct {
channel.getAddrInfo(
query.name,
query.port,
- &.{},
+ hints_buf,
GetAddrInfoRequest,
request,
GetAddrInfoRequest.onCaresComplete,
diff --git a/test/js/bun/dns/resolve-dns.test.ts b/test/js/bun/dns/resolve-dns.test.ts
index 6102b0745..57b3a50c7 100644
--- a/test/js/bun/dns/resolve-dns.test.ts
+++ b/test/js/bun/dns/resolve-dns.test.ts
@@ -1,50 +1,96 @@
import { dns } from "bun";
import { describe, expect, it, test } from "bun:test";
import { withoutAggressiveGC } from "harness";
+import { isIP, isIPv4, isIPv6 } from "node:net";
-describe("dns.lookup", () => {
- const backends = [process.platform === "darwin" ? "system" : undefined, "libc", "c-ares"].filter(x => !!x) as (
- | "system"
- | "libc"
- | "c-ares"
- )[];
- for (let backend of backends) {
- it(backend + " parallell x 10", async () => {
- const promises = [];
- for (let i = 0; i < 10; i++) {
- promises.push(dns.lookup("localhost", { backend }));
- }
- const results = (await Promise.all(promises)).flat();
- withoutAggressiveGC(() => {
- for (let { family, address } of results) {
- if (family === 4) {
- expect(address).toBe("127.0.0.1");
- } else if (family === 6) {
- expect(address).toBe("::1");
- } else {
- throw new Error("Unknown family");
+const backends = ["system", "libc", "c-ares"];
+const validHostnames = ["localhost", "example.com"];
+const invalidHostnames = [`this-should-not-exist-${Math.floor(Math.random() * 99999)}.com`];
+const malformedHostnames = ["", " ", ".", " .", "localhost:80", "this is not a hostname"];
+
+describe("dns", () => {
+ describe.each(backends)("lookup() [backend: %s]", backend => {
+ describe.each(validHostnames)("%s", hostname => {
+ test.each([
+ {
+ options: { backend },
+ address: isIP,
+ },
+ {
+ options: { backend, family: 4 },
+ address: isIPv4,
+ family: 4,
+ },
+ {
+ options: { backend, family: "IPv4" },
+ address: isIPv4,
+ family: 4,
+ },
+ {
+ options: { backend, family: 6 },
+ address: isIPv6,
+ family: 6,
+ },
+ {
+ options: { backend, family: "IPv6" },
+ address: isIPv6,
+ family: 6,
+ },
+ {
+ options: { backend, family: 0 },
+ address: isIP,
+ },
+ {
+ options: { backend, family: "any" },
+ address: isIP,
+ },
+ ])("%j", async ({ options, address: expectedAddress, family: expectedFamily }) => {
+ // @ts-expect-error
+ const result = await dns.lookup(hostname, options);
+ expect(result).toBeArray();
+ expect(result.length).toBeGreaterThan(0);
+ withoutAggressiveGC(() => {
+ for (const { family, address, ttl } of result) {
+ expect(address).toBeString();
+ expect(expectedAddress(address)).toBeTruthy();
+ expect(family).toBeInteger();
+ if (expectedFamily !== undefined) {
+ expect(family).toBe(expectedFamily);
+ }
+ expect(ttl).toBeInteger();
}
- }
+ });
});
});
-
- it(backend + " remote", async () => {
- const [first, second] = await dns.lookup("google.com", { backend });
- console.log(first, second);
- });
- it(backend + " local", async () => {
- const [first, second] = await dns.lookup("localhost", { backend });
- console.log(first, second);
+ test.each(validHostnames)("%s [parallel x 10]", async hostname => {
+ const results = await Promise.all(
+ // @ts-expect-error
+ Array.from({ length: 10 }, () => dns.lookup(hostname, { backend })),
+ );
+ const answers = results.flat();
+ expect(answers).toBeArray();
+ expect(answers.length).toBeGreaterThan(10);
+ withoutAggressiveGC(() => {
+ for (const { family, address, ttl } of answers) {
+ expect(address).toBeString();
+ expect(isIP(address)).toBeTruthy();
+ expect(family).toBeInteger();
+ expect(ttl).toBeInteger();
+ }
+ });
});
-
- it(backend + " failing domain throws an error without taking a very long time", async () => {
- try {
- await dns.lookup("yololololololo1234567.com", { backend });
- throw 42;
- } catch (e: any) {
- expect(typeof e).not.toBe("number");
- expect(e.code).toBe("DNS_ENOTFOUND");
- }
+ test.each(invalidHostnames)("%s", hostname => {
+ // @ts-expect-error
+ expect(dns.lookup(hostname, { backend })).rejects.toMatchObject({
+ code: "DNS_ENOTFOUND",
+ });
});
- }
+ // TODO: causes segfaults
+ // test.each(malformedHostnames)("%s", (hostname) => {
+ // // @ts-expect-error
+ // expect(dns.lookup(hostname, { backend })).rejects.toMatchObject({
+ // code: "DNS_ENOTFOUND",
+ // });
+ // });
+ });
});