Skip to content

Comments

Fix nil pointer dereference when sending to binary channel type alias#1715

Merged
traefiker merged 2 commits intotraefik:masterfrom
pk910:pk910/fix-binary-channel-panic
Feb 9, 2026
Merged

Fix nil pointer dereference when sending to binary channel type alias#1715
traefiker merged 2 commits intotraefik:masterfrom
pk910:pk910/fix-binary-channel-panic

Conversation

@pk910
Copy link
Contributor

@pk910 pk910 commented Feb 6, 2026

Description

When sending a value to a channel that is a type alias defined in a binary package, yaegi panics with a nil pointer dereference.

This PR was created with AI assistance (Claude) as I hit this issue in a downstream project using yaegi.
The fix and tests have been reviewed and verified for correctness and functionality by myself.

Root Cause

In the send function (interp/run.go), the code directly accesses c0.typ.val to get the channel element type:

value1 := genDestValue(c0.typ.val, c1)

For source-defined channels (category chanT), .val contains the element type. But for binary channel type aliases (category valueT), .val is nil - the element type is only available via reflection in .rtype.

Fix

Use the existing elem() method which correctly handles both cases:

value1 := genDestValue(c0.typ.elem(), c1)

The elem() method (in type.go) already handles this properly:

func (t *itype) elem() *itype {
    if t.cat == valueT {
        return valueTOf(t.rtype.Elem())  // Binary types: create from reflect
    }
    return t.val  // Source types: use existing itype with all metadata
}

This is a one-line fix that fixes binary channel type aliases by using reflection to get the element type

Test Results

Test Without Fix With Fix
TestSendToSourceDefinedChannel PASS PASS
TestSendToSourceDefinedChannelTypeAlias PASS PASS
TestSendToBinaryChannelTypeAlias FAIL PASS

Minimal Reproduction

mypkg/mypkg.go

package mypkg

// IntChan is a channel type alias
type IntChan chan int

// NewIntChan creates a new IntChan
func NewIntChan() IntChan {
    return make(IntChan, 1)
}

symbols.go

package main

import (
    "reflect"
    "yaegi-repro/mypkg"
)

var Symbols = map[string]map[string]reflect.Value{}

func init() {
    Symbols["yaegi-repro/mypkg/mypkg"] = map[string]reflect.Value{
        "IntChan":    reflect.ValueOf((*mypkg.IntChan)(nil)),
        "NewIntChan": reflect.ValueOf(mypkg.NewIntChan),
    }
}

main.go

package main

import (
    "fmt"
    "log"
    "github.com/traefik/yaegi/interp"
)

func main() {
    i := interp.New(interp.Options{})
    if err := i.Use(Symbols); err != nil {
        log.Fatal(err)
    }

    code := `
package main

import "yaegi-repro/mypkg"

func main() {
    ch := mypkg.NewIntChan()
    ch <- 42  // This line panics without the fix
    val := <-ch
    println("Received:", val)
}
`
    _, err := i.Eval(code)
    if err != nil {
        log.Fatal(err)
    }
    fmt.Println("Success!")
}

Results

Without fix:

panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x128 pc=0x...]

goroutine 1 [running]:
github.com/traefik/yaegi/interp.(*itype).refType(0x0?, ...)
    .../interp/type.go:2065 +0x7a
github.com/traefik/yaegi/interp.(*itype).TypeOf(...)
    .../interp/type.go:2223
github.com/traefik/yaegi/interp.genDestValue(0x0, ...)
    .../interp/value.go:157 +0x25
github.com/traefik/yaegi/interp.send(...)
    .../interp/run.go:3766 +0x...

With fix:

Received: 42
Success!

@CLAassistant
Copy link

CLAassistant commented Feb 6, 2026

CLA assistant check
All committers have signed the CLA.

Copy link
Collaborator

@mvertes mvertes left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The fix is correct. The test case needs to be adjusted to avoid confusion with standard library test package.

@pk910
Copy link
Contributor Author

pk910 commented Feb 8, 2026

Heya @mvertes
Thanks for your review :)
I've updated the test accordingly.

Copy link
Collaborator

@mvertes mvertes left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good to me

@mvertes mvertes added this to the v0.16.x milestone Feb 9, 2026
@traefiker
Copy link
Contributor

🚫 the mergeable state is "blocked"

@traefiker traefiker merged commit fcb76d1 into traefik:master Feb 9, 2026
13 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/core bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants