[Code challenge] Can Go be rendered unusable?

blov · 2016-05-23 01:42:25 · 562 次点击    
这是一个分享于 2016-05-23 01:42:25 的资源,其中的信息可能已经有所发展或是发生改变。

I've been having some fun with this hilarious CodeGolf stack exchange question. Read the challenge for a full and clear specification. Last year, the user Cat posted this Go answer (which I've edited for simplicity):

package main

func main() {
    const (
        append = iota
        cap; close; complex; copy
        delete
        imag
        len
        make
        new
        panic; print; println
        real
        recover
        bool; byte
        complex64; complex128
        error
        float32; float64
        int; int8; int16; int32; int64
        rune
        string
        uint; uint8; uint16; uint32; uint64; uintptr
        true
        false
        nil
        iota = 0
    )
    // User code goes here
}

From here on, code samples will go under the // User code goes here line unless otherwise indicated.

Imports can only be done at the top of the file, which means we can't access fmt, os.Args, syscall, or flag. We've erased panic, print, and println, which would allow us to affect the output in at least some way.

However, on seeing this answer the thought occurred to me that you don't need to call panic directly. You can just do something to cause a panic. So we can create a primality test based on panicking or not panicking:

n := 37
for i := 2; i < n; i++ {
    if n % i == 0 {
        c := []struct{}{}
        _ = c[1]
    }
}

This will panic if n is composite and output nothing if it is prime. Luckily, we can plug that leak by adding this code to the top of main:

defer func() {
    _ = recover()
}

Now any panics we create will be absorbed.

That is, any panics in the main goroutine! Go's concurrency features allow us to bypass this block again by wrapping the code in a go statement:

go func() {
    n := 37
    for i := 2; i < n; i++ {
        if n % i == 0 {
            c := []struct{}{}
            _ = c[1]
        }
    }
}()
var c chan interface{}
<-c

Now the program deadlocks on primes and panics on non-primes.

So how can this leak be plugged, and Go made unusable? The only thing I could think of was using the runtime package to restrict the number of goroutines, but there appears to be no such facility, so I'm out of ideas.


评论:

tclineks:

deargodwhy

joushou:

Now returns cleanly on success, and panics on failure.

fail := func() {
    go func() {
        _ = []struct{}{}[1]
    }()
    var c chan interface{}
    <-c
}
n := 37
for i := 2; i < n; i++ {
    if n%i == 0 {
        fail()
    }
}
Partageons:

Since you're the only one who's offered any help, I'm getting closer. Here's what I have now: https://play.golang.org/p/9DLXU2gfMC Despite main and the infinite loop goroutine being locked to the two available OS threads, the user can still create a new goroutine and block main to panic within that goroutine.

DeedleFake:

I'm not too clear on a lot of the internals of the runtime, but how about the following:

runtime.GOMAXPROCS(1)
runtime.LockOSThread()
Partageons:

I've tried that. Somehow the user can break out by blocking the main goroutine. https://play.golang.org/p/Gm4QabOFl_

metamatic:

It's hard to beat Smalltalk, where you can simply redefine true to be false and watch everything crash.

brogrammingsins:

What's the point behind this? Why would it ever be useful?

Carpetsmoker:

Code golf are more like puzzles than anything else (i.e. entertainment). Some people seem to enjoy that sort of stuff...

Still better than football :-)

hukiki:

haha this is awesome. I love the JS version of the answer in the original link. Thanks OP.


入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

562 次点击  
加入收藏 微博
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传