Skip to content

🐛 [Bug]: nil pointer dereference for (fiber.Ctx).Value #4061

@Vovcharaa

Description

@Vovcharaa

Bug Description

When sending streaming response with object that was created from minio.GetObject with fiber.Ctx context it tries to access ctx.Value but is hit with nil pointer dereference.

How to Reproduce

Steps to reproduce the behavior:

  1. Use minio.GetObject to get io.ReadCloser implementation while using fiber.Ctx as context.Context
  2. Send it in response as body stream
  3. Observe error
panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x2 addr=0x0 pc=0x10538ec84]

goroutine 210 [running]:
github.com/valyala/fasthttp.(*RequestCtx).UserValue(...)
        /Users/vovchara/go/pkg/mod/github.com/valyala/fasthttp@v1.69.0/server.go:773
github.com/gofiber/fiber/v3.(*DefaultCtx).Value(0x1400004bc88?, {0x1065adb00?, 0x107199b20?})
        /Users/vovchara/go/pkg/mod/github.com/gofiber/fiber/v3@v3.0.0/ctx.go:595 +0x24
context.value({0x107ab7d48?, 0x140006ae008?}, {0x1065adb00, 0x107199b20})
        /opt/homebrew/Cellar/go/1.25.7_1/libexec/src/context/context.go:803 +0x230
context.(*cancelCtx).Value(0x140000242c8?, {0x1065adb00?, 0x107199b20?})
        /opt/homebrew/Cellar/go/1.25.7_1/libexec/src/context/context.go:445 +0x6c
net/http/httptrace.ContextClientTrace(...)
        /opt/homebrew/Cellar/go/1.25.7_1/libexec/src/net/http/httptrace/trace.go:25
net/http.(*Transport).roundTrip(0x140000be000, 0x14000334a00)
        /opt/homebrew/Cellar/go/1.25.7_1/libexec/src/net/http/transport.go:585 +0xa4
net/http.(*Transport).RoundTrip(0x14000024498?, 0x10676bd60?)
        /opt/homebrew/Cellar/go/1.25.7_1/libexec/src/net/http/roundtrip.go:33 +0x20
net/http.send(0x14000334a00, {0x10676bd60, 0x140000be000}, {0x1051a24e8?, 0x8?, 0x0?})
        /opt/homebrew/Cellar/go/1.25.7_1/libexec/src/net/http/client.go:259 +0x478
net/http.(*Client).send(0x14000386900, 0x14000334a00, {0x14000024718?, 0x104f199f0?, 0x0?})
        /opt/homebrew/Cellar/go/1.25.7_1/libexec/src/net/http/client.go:180 +0x88
net/http.(*Client).do(0x14000386900, 0x14000334a00)
        /opt/homebrew/Cellar/go/1.25.7_1/libexec/src/net/http/client.go:729 +0x710
net/http.(*Client).Do(...)
        /opt/homebrew/Cellar/go/1.25.7_1/libexec/src/net/http/client.go:587
github.com/minio/minio-go/v7.(*Client).do(0x140004da1e0, 0x14000334a00)
        /Users/vovchara/go/pkg/mod/github.com/minio/minio-go/v7@v7.0.98/api.go:606 +0x64
github.com/minio/minio-go/v7.(*Client).executeMethod-range1(0x148?)
        /Users/vovchara/go/pkg/mod/github.com/minio/minio-go/v7@v7.0.98/api.go:717 +0x124
github.com/minio/minio-go/v7.(*Client).executeMethod.(*Client).newRetryTimer.func3(...)
        /Users/vovchara/go/pkg/mod/github.com/minio/minio-go/v7@v7.0.98/retry.go:84
github.com/minio/minio-go/v7.(*Client).executeMethod(0x140004da1e0, {0x106776570, 0x1400046a050}, {0x105bde51d, 0x3}, {0x0, {0x140003920dd, 0x19}, {0x1400039229a, 0x26}, ...})
        /Users/vovchara/go/pkg/mod/github.com/minio/minio-go/v7@v7.0.98/api.go:691 +0x5dc
github.com/minio/minio-go/v7.(*Client).getObject(_, {_, _}, {_, _}, {_, _}, {0x14000398690, 0x0, {0x0, ...}, ...})
        /Users/vovchara/go/pkg/mod/github.com/minio/minio-go/v7@v7.0.98/api-get-object.go:675 +0x148
github.com/minio/minio-go/v7.(*Client).GetObject.func1()
        /Users/vovchara/go/pkg/mod/github.com/minio/minio-go/v7@v7.0.98/api-get-object.go:204 +0x2a0
created by github.com/minio/minio-go/v7.(*Client).GetObject in goroutine 168
        /Users/vovchara/go/pkg/mod/github.com/minio/minio-go/v7@v7.0.98/api-get-object.go:70 +0x270
Process Exit with Code: 2

Expected Behavior

Body can be streamed in response like it is in fiber v2

Fiber Version

v3.0.0

Code Snippet (optional)

package main

import (
	"context"
	"log"
	"strings"

	"github.com/gofiber/fiber/v3"
	"github.com/minio/minio-go/v7"
	"github.com/minio/minio-go/v7/pkg/credentials"
)

func main() {
	minioClient, err := minio.New("localhost:4566", &minio.Options{
		Creds:  credentials.NewStaticV4("minioadmin", "minioadmin", ""),
		Secure: false,
	})
	if err != nil {
		log.Fatal(err)
	}

	app := fiber.New()
	minioClient.MakeBucket(context.Background(), "mybucket", minio.MakeBucketOptions{})
	minioClient.PutObject(context.Background(), "mybucket", "myfile.txt", strings.NewReader("hello"), 5, minio.PutObjectOptions{})

	app.Get("/broken", func(c fiber.Ctx) error {
		obj, err := minioClient.GetObject(c, "mybucket", "myfile.txt", minio.GetObjectOptions{})
		if err != nil {
			return err
		}
		stat, err := obj.Stat()
		if err != nil {
			return err
		}
		c.Response().StreamBody = true
		return c.SendStream(obj, int(stat.Size))
	})

	log.Fatal(app.Listen(":3000"))
}

Checklist:

  • I agree to follow Fiber's Code of Conduct.
  • I have checked for existing issues that describe my problem prior to opening this one.
  • I understand that improperly formatted bug reports may be closed without explanation.

Metadata

Metadata

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions