Skip to content

Errors modified via pointer in defers are not wrapped #129

@prashantv

Description

@prashantv

Named returns with defer can modify the return error through indirect assignments, e.g., passing a pointer to the error to a function that modifies it.

Example:

func main() {
	fmt.Printf("%+v\n", getErr())
}

func getErr() (err error) {
	defer func() {
		setErr(&err)
	}()
	return
}

func setErr(err *error) {
	*err = fmt.Errorf("err")
}

errtrace modifies getErr() by adding a wrap before the return:

func getErr() (err error) {
	defer func() {
		setErr(&err)
	}()
	err = errtrace.Wrap(err)
	return
}

However, the defer is not handled, since it's not clear whether the error will be modified by the function.

We could assume that anytime a pointer to the error is referenced, that it's used to modify the error, and add a wrap (though that could end up double-wrapping in the same function).

Another option, if we see named error returns, and defers that reference the named error return, rather than wrap at return time, we can add an additional defer that wraps the error. We may want to add a WrapInto(*error) to make this cleaner, so callers can do defer errtrace.WrapInto(&err)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions