Skip to content

Commit f404080

Browse files
committed
context: prevent creation of invalid contexts
This commit makes it impossible to create derived contexts with nil parents. Previously it was possible to create derived contexts with nil parents, and invalid contexts could propagate through the program. Eventually this could cause a panic downstream, which is difficult to trace back to the source of the error.
1 parent 2e918c3 commit f404080

File tree

2 files changed

+24
-0
lines changed

2 files changed

+24
-0
lines changed

src/context/context.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -230,6 +230,9 @@ type CancelFunc func()
230230
// Canceling this context releases resources associated with it, so code should
231231
// call cancel as soon as the operations running in this Context complete.
232232
func WithCancel(parent Context) (ctx Context, cancel CancelFunc) {
233+
if parent == nil {
234+
panic("cannot create context from nil parent.")
235+
}
233236
c := newCancelCtx(parent)
234237
propagateCancel(parent, &c)
235238
return &c, func() { c.cancel(true, Canceled) }
@@ -425,6 +428,9 @@ func (c *cancelCtx) cancel(removeFromParent bool, err error) {
425428
// Canceling this context releases resources associated with it, so code should
426429
// call cancel as soon as the operations running in this Context complete.
427430
func WithDeadline(parent Context, d time.Time) (Context, CancelFunc) {
431+
if parent == nil {
432+
panic("cannot create context from nil parent.")
433+
}
428434
if cur, ok := parent.Deadline(); ok && cur.Before(d) {
429435
// The current deadline is already sooner than the new one.
430436
return WithCancel(parent)
@@ -511,6 +517,9 @@ func WithTimeout(parent Context, timeout time.Duration) (Context, CancelFunc) {
511517
// struct{}. Alternatively, exported context key variables' static
512518
// type should be a pointer or interface.
513519
func WithValue(parent Context, key, val interface{}) Context {
520+
if parent == nil {
521+
panic("cannot create context from nil parent.")
522+
}
514523
if key == nil {
515524
panic("nil key")
516525
}

src/context/context_test.go

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -667,6 +667,21 @@ func XTestWithValueChecksKey(t testingT) {
667667
}
668668
}
669669

670+
func TestInvalidDerivedFail(t testingT) {
671+
panicVal := recoveredValue(func() { WithCancel(nil) })
672+
if panicVal == nil {
673+
t.Error("expected panic")
674+
}
675+
panicVal := recoveredValue(func() { WithDeadline(nil, time.Second) })
676+
if panicVal == nil {
677+
t.Error("expected panic")
678+
}
679+
panicVal := recoveredValue(func() { WithValue(nil, "foo", "bar") })
680+
if panicVal == nil {
681+
t.Error("expected panic")
682+
}
683+
}
684+
670685
func recoveredValue(fn func()) (v interface{}) {
671686
defer func() { v = recover() }()
672687
fn()

0 commit comments

Comments
 (0)