Skip to content

runtime: should bad addresses panic? #7277

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
robpike opened this issue Feb 6, 2014 · 8 comments
Closed

runtime: should bad addresses panic? #7277

robpike opened this issue Feb 6, 2014 · 8 comments
Milestone

Comments

@robpike
Copy link
Contributor

robpike commented Feb 6, 2014

Consider this program:

package main

import (
    "fmt"
    "unsafe"
)

func main() {
    probe(0)
    probe(4096-8)
    probe(4096)
    probe(8192)
}

func probe(p uintptr) {
    defer func() {
        fmt.Println(recover())
    }()
    fmt.Printf("probe %x\n", p)
    b := (*byte)(unsafe.Pointer(p))
    *b = 1
}

also at the playground at http://play.golang.org/p/5P0zvSIVVp

In the playground, it prints:

probe 0
runtime error: invalid memory address or nil pointer dereference
probe ff8
runtime error: invalid memory address or nil pointer dereference
probe 1000
runtime error: invalid memory address or nil pointer dereference
probe 2000
runtime error: invalid memory address or nil pointer dereference

On my Mac amd64 machine, it prints:

probe 0
runtime error: invalid memory address or nil pointer dereference
probe ff8
runtime error: invalid memory address or nil pointer dereference
probe 1000
unexpected fault address 0x1000
fatal error: fault
[signal 0xa code=0x2 addr=0x1000 pc=0x2134]
...

There's code in the standard runtime that turns a probe of lowest 4K of memory into a
"nil pointer" panic, but any other bad address causes an uncatchable
runtime.throw and program death. I propose that we make all invalid address errors
panics, so they can be recovered from the way they seem to work in the playground. This
would allow programs running dodgy code (say, code compiled on the fly) to protect
themselves from unexpected exits.

At the very least, the playground and the main repo should behave consistently. Marking
for Go 1.3 because this is complicated some tool development unnecessarily.

Opening the floor for debate.
@minux
Copy link
Member

minux commented Feb 6, 2014

Comment 1:

Yes, this will be useful.
The only problem I can think of is that what if it's caused by corrupted runtime
state? Recovering from it might just trigger another fault later.

@minux
Copy link
Member

minux commented Feb 6, 2014

Comment 2:

Also, if we do this change, I'd like to define a specific type in the runtime package
for this panic, so that I don't need to parse the string to get the address (and
possibly also includes the thread context, e.g. registers).

@dvyukov
Copy link
Member

dvyukov commented Feb 6, 2014

Comment 3:

If this is the only motivating example, then I propose to do nothing.
Unsafe is, well, unsafe. If you are writing to random addresses, it can lead to
arbitrary consequences, we can not reliably panic in all such cases.
I second the concern about runtime corruption. Whenever we saw such crash, it was a
serious corruption of runtime, continuing in such case makes no sense and dangerous.
Also think of a malicious code that probes system data structures.
If you want to execute untrusted code, you need to do it in a separate process. It has
1000 and 1 way to crash the process (or do something worse). Then simplest way it to
start a goroutine that panics, or allocate all memory, etc, etc.

@minux
Copy link
Member

minux commented Feb 6, 2014

Comment 4:

Russ once provided another example:
the pure Go linker will want try to mmap(2) the object files instead of reading
and loading them to memory, but in case of IO errors or concurrent file writes,
reading the mmapped the content might trigger SIGBUS (or SIGSEGV).
so it's better to be able to catch them. (I'd think we categorize the SIGBUS/SIGSEGV
into runtime errors and user errors, and only let the user catch the latter one.
The problem is how we categorize them.

@robpike
Copy link
Contributor Author

robpike commented Feb 6, 2014

Comment 5:

On-the-fly compilation was just an example. What really bothers me here is the two
inconsistencies: inconsistency between the playground and the standard library, and
between one set of addresses and another.

@dvyukov
Copy link
Member

dvyukov commented Feb 7, 2014

Comment 6:

I don't know why playground is different, I do not mind if it's changed.
Regarding set of addresses, there is a 3rd set of addresses that we can not fix:
http://play.golang.org/p/QrXsFggzKW
But all this relates only to unsafe, which can lead to arbitrary results anyway.

@robpike
Copy link
Contributor Author

robpike commented Feb 21, 2014

Comment 7:

Issue closed http://golang.org/cl/66590044

@robpike
Copy link
Contributor Author

robpike commented Feb 21, 2014

Comment 8:

The inconsistency in the runtimes is because on NaCl the faulting address is not
available.

Status changed to Fixed.

@rsc rsc added this to the Go1.3 milestone Apr 14, 2015
@golang golang locked and limited conversation to collaborators Jun 25, 2016
This issue was closed.
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

5 participants