diff --git a/documentation/advanced-features/debugging-with-dlv.md b/documentation/advanced-features/debugging-with-dlv.md index 4a20ee86de..382105684e 100644 --- a/documentation/advanced-features/debugging-with-dlv.md +++ b/documentation/advanced-features/debugging-with-dlv.md @@ -1,4 +1,4 @@ -# Debugger +# Debugging Tips - [Debugger](#debugger) - [Debug a particular function](#debug-a-particular-function) @@ -80,3 +80,31 @@ VSCode equivalent configuration is: ] ``` + +## Debug `helpers.js` + +Develop a function: + +``` +node -e " +function IP(dot) { + var d = dot.split('.'); + return ((((((+d[0]) * 256) + (+d[1])) * 256) + (+d[2])) * 256) + (+d[3]); +} +console.log(IP('135.181.247.240')); +" +``` + +Debug a function within helpers.js: + +``` +$ node -e " +const fs = require('fs'); +const vm = require('vm'); +const code = fs.readFileSync('/Users/tlimoncelli/gitthings/dnscontrol/pkg/js/helpers.js', 'utf8'); +const sandbox = {}; +vm.createContext(sandbox); +vm.runInContext(code, sandbox); +console.log(vm.runInContext(\" IP('135.181.247.240') \", sandbox)); +" +``` diff --git a/pkg/js/parse_tests/004-ips.js b/pkg/js/parse_tests/004-ips.js index 31928185db..a917398b1c 100644 --- a/pkg/js/parse_tests/004-ips.js +++ b/pkg/js/parse_tests/004-ips.js @@ -7,4 +7,7 @@ D("foo.com", REG, DnsProvider(CF, 0), A("@", BASE), A("p1", BASE + 1), A("p255", BASE + 255), + + // An IP address with the highest bit set, to catch uint/int bugs. + A("yyy", IP("190.2.3.4")) ); diff --git a/pkg/js/parse_tests/004-ips.json b/pkg/js/parse_tests/004-ips.json index c9cb6874e4..5bc0ce2f9d 100644 --- a/pkg/js/parse_tests/004-ips.json +++ b/pkg/js/parse_tests/004-ips.json @@ -47,6 +47,18 @@ "ttl": 300, "type": "A", "typenum": 1 + }, + { + "comparablev3": "190.2.3.4", + "filepos": "[line:12:5]", + "name": "yyy", + "name_unicode": "yyy", + "rdata": { + "Addr": "190.2.3.4" + }, + "ttl": 300, + "type": "A", + "typenum": 1 } ], "registrar": "Third-Party", diff --git a/pkg/js/parse_tests/004-ips/foo.com.zone b/pkg/js/parse_tests/004-ips/foo.com.zone index 0c73c238d1..895342170d 100644 --- a/pkg/js/parse_tests/004-ips/foo.com.zone +++ b/pkg/js/parse_tests/004-ips/foo.com.zone @@ -2,3 +2,4 @@ $TTL 300 @ IN A 1.2.3.4 p1 IN A 1.2.3.5 p255 IN A 1.2.4.3 +yyy IN A 190.2.3.4 diff --git a/pkg/mustbe/ip.go b/pkg/mustbe/ip.go index 60ce29c606..b87119a979 100644 --- a/pkg/mustbe/ip.go +++ b/pkg/mustbe/ip.go @@ -9,16 +9,14 @@ import ( func IPv4(a any) (netip.Addr, error) { switch v := a.(type) { case float64: - i := int32(v) - a := (i >> 24) % 256 - b := (i >> 16) % 256 - c := (i >> 8) % 256 - d := i % 256 + // IP addresses expressed as a number (e.g. via the IP() helper in + // dnsconfig.js) range from 0 to 4294967295 (2^32-1) + i := uint32(v) x := netip.AddrFrom4([4]byte{ - byte(a), - byte(b), - byte(c), - byte(d), + byte(i >> 24), // NB(tlim): byte() silently truncates the upper bits. + byte(i >> 16), + byte(i >> 8), + byte(i), }) return x, nil case string: diff --git a/pkg/mustbe/ip_test.go b/pkg/mustbe/ip_test.go index 2426973104..1490d31662 100644 --- a/pkg/mustbe/ip_test.go +++ b/pkg/mustbe/ip_test.go @@ -45,6 +45,11 @@ func TestIPv4_Parse(t *testing.T) { {"a", "1.2.3.4", netip.MustParseAddr("1.2.3.4")}, {"b", float64((2 << 24) + (3 << 16) + (4 << 8) + 5), netip.MustParseAddr("2.3.4.5")}, {"c", netip.MustParseAddr("3.4.5.6"), netip.MustParseAddr("3.4.5.6")}, + // Regression test for https://github.com/DNSControl/dnscontrol/issues/4825: + // addresses with a first octet >= 128 produce a number greater than + // math.MaxInt32, which used to overflow when converted via int32. + {"d", float64((135 << 24) + (181 << 16) + (247 << 8) + 240), netip.MustParseAddr("135.181.247.240")}, + {"e", float64((255 << 24) + (255 << 16) + (255 << 8) + 255), netip.MustParseAddr("255.255.255.255")}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) {