Skip to content

Commit

Permalink
p2p: fix infinite loop in dnsaddr resolution (#5926)
Browse files Browse the repository at this point in the history
  • Loading branch information
algorandskiy authored Feb 2, 2024
1 parent a8e2254 commit ba8b2cd
Show file tree
Hide file tree
Showing 2 changed files with 46 additions and 0 deletions.
6 changes: 6 additions & 0 deletions network/p2p/dnsaddr/resolve.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,14 @@ func Iterate(initial multiaddr.Multiaddr, controller ResolveController, f func(d
if resolver == nil {
return errors.New("passed controller has no resolvers Iterate")
}
const maxHops = 100
hops := 0
var toResolve = []multiaddr.Multiaddr{initial}
for resolver != nil && len(toResolve) > 0 {
hops++
if hops > maxHops {
return errors.New("max hops reached while resolving dnsaddr " + initial.String())
}
curr := toResolve[0]
maddrs, resolveErr := resolver.Resolve(context.Background(), curr)
if resolveErr != nil {
Expand Down
40 changes: 40 additions & 0 deletions network/p2p/dnsaddr/resolve_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import (
"fmt"
"net"
"testing"
"time"

"github.com/multiformats/go-multiaddr"
madns "github.com/multiformats/go-multiaddr-dns"
Expand Down Expand Up @@ -109,3 +110,42 @@ func TestMultiaddrsFromResolverDnsFailure(t *testing.T) {
assert.Empty(t, maddrs)
assert.ErrorContains(t, err, "always errors")
}

type mockController struct {
}

func (c mockController) Resolver() Resolver {
return selfResolver{}
}

func (c mockController) NextResolver() Resolver {
return nil
}

type selfResolver struct {
}

func (r selfResolver) Resolve(ctx context.Context, maddr multiaddr.Multiaddr) ([]multiaddr.Multiaddr, error) {
return []multiaddr.Multiaddr{maddr}, nil
}

// TestIterate ensures the Iterate() does not hang in infinite loop
// when resolver returns the same dnsaddr
func TestIterate(t *testing.T) {
partitiontest.PartitionTest(t)
t.Parallel()

dnsAddr := "/dnsaddr/foobar.com"
require.True(t, isDnsaddr(multiaddr.StringCast(dnsAddr)))
ma, err := multiaddr.NewMultiaddr(dnsAddr)
require.NoError(t, err)

require.Eventually(t, func() bool {
Iterate(
ma,
mockController{},
func(dnsaddr multiaddr.Multiaddr, entries []multiaddr.Multiaddr) error { return nil },
)
return true
}, 100*time.Millisecond, 50*time.Millisecond)
}

0 comments on commit ba8b2cd

Please sign in to comment.