Skip to content
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

gnovm: inability to catch unused variables at compile time allows for nuisance programs: deviation from Go #3426

Open
odeke-em opened this issue Dec 30, 2024 · 0 comments
Labels
🐞 bug Something isn't working

Comments

@odeke-em
Copy link
Contributor

Description

While doing security analysis and fuzzing for Gno programs that shall be passed into the gnovm to cause it to misbehave, if we look at this invalid Go program yet valid Gno program

package main

func main() {
	const c1 = 1 < 8
	main()
	1
}

Go result

The Go compiler will flag it as https://go.dev/play/p/OUgbMlbefsj

./prog.go:6:2: 1 (untyped int constant) is not used

Gno result

The result will be ran and run out of memory https://play.gno.land/p/Bg71TmlsEfA

runtime: out of memory: cannot allocate16777216-byte block 238815641 in use)
fatal error:out of memory

goroutine gp0x24001c m mp0x114e9e runnin]:
runtime.thro0x23d3a,0x)
       /home/runner/_work/_tool/go/1.22.4/x64/src/runtime/panic.g102 0x fp0x2434e7 sp0x2434e4 pc0x135a0003
runtime.(*mcache).allocLarg0x214010,0xa00000,0x)
       /home/runner/_work/_tool/go/1.22.4/x64/src/runtime/mcache.g23 0x1 fp0x2434ec sp0x2434e7 pc0x11f3001f
runtime.mallocg0xa00000,0x1c1c6,0x)
       /home/runner/_work/_tool/go/1.22.4/x64/src/runtime/malloc.g116 0xa fp0x2434f4 sp0x2434ec pc0x11a500ab
runtime.makeslic0x1c1c6,0x40000,0x40000)
       /home/runner/_work/_tool/go/1.22.4/x64/src/runtime/slice.g10 0x1 fp0x2434f7 sp0x2434f4 pc0x144a0012
github.com/gnolang/gno/gnovm/pkg/gnolang.(*Machine).PushValu..)
       /home/runner/_work/studio/studio/gno/gnovm/pkg/gnolang/machine.g1754
github.com/gnolang/gno/gnovm/pkg/gnolang.(*Machine).doOpEva0x26de48)
       /home/runner/_work/studio/studio/gno/gnovm/pkg/gnolang/op_eval.g32 0x4 fp0x24358d sp0x2434f7 pc0x58570048
github.com/gnolang/gno/gnovm/pkg/gnolang.(*Machine).Ru0x26de48)
       /home/runner/_work/studio/studio/gno/gnovm/pkg/gnolang/machine.g143 0xe fp0x243598 sp0x24358d pc0x572000eb
github.com/gnolang/gno/gnovm/pkg/gnolang.(*Machine).Eva0x26de48,0x4e1d4,0x27b1da)
       /home/runner/_work/studio/studio/gno/gnovm/pkg/gnolang/machine.g88 0x5 fp0x2435af sp0x243598 pc0x5719005f
main.runExp0x26de48,0x104,0x)
       /home/runner/_work/studio/studio/gno/gnovm/cmd/gno/run.g21 0x fp0x2435b7 sp0x2435af pc0x67f30004
main.execRu0x27acc0,0x27b823,0x,0x,0x4e393,0x270b2c)
       /home/runner/_work/studio/studio/gno/gnovm/cmd/gno/run.g13 0x3 fp0x2435d2 sp0x2435b7 pc0x67ee0037
main.newRunCmd.func0x4dba3,0x11ab30,0x27b823,0x,0x)
       /home/runner/_work/studio/studio/gno/gnovm/cmd/gno/run.g3 0x fp0x2435d7 sp0x2435d2 pc0x67ec0002
github.com/gnolang/gno/tm2/pkg/commands.(*Command).Ru0x26d776,0x4dba3,0x11ab30)
       /home/runner/_work/studio/studio/gno/tm2/pkg/commands/command.g25 0x1 fp0x2435df sp0x2435d7 pc0x21ff001a
github.com/gnolang/gno/tm2/pkg/commands.(*Command).Ru0x26d71e,0x4dba3,0x11ab30)
       /home/runner/_work/studio/studio/gno/tm2/pkg/commands/command.g25 0x1 fp0x2435e7 sp0x2435df pc0x21ff0013
github.com/gnolang/gno/tm2/pkg/commands.(*Command).ParseAndRu0x26d71e,0x4dba3,0x11ab30,0x242e09,0x,0x)
       /home/runner/_work/studio/studio/gno/tm2/pkg/commands/command.g14 0x fp0x2435ea sp0x2435e7 pc0x21fc0004
github.com/gnolang/gno/tm2/pkg/commands.(*Command).Execut0x26d71e,0x4dba3,0x11ab30,0x242e09,0x,0x)
       /home/runner/_work/studio/studio/gno/tm2/pkg/commands/command.g11 0x fp0x2435f3 sp0x2435ea pc0x21fb0002
main.mai)
       /home/runner/_work/studio/studio/gno/gnovm/cmd/gno/main.g1 0x fp0x2435f6 sp0x2435f3 pc0x67d00005
runtime.mai)
       /home/runner/_work/_tool/go/1.22.4/x64/src/runtime/proc.g27 0x4 fp0x2435fe sp0x2435f6 pc0x137c0041
runtime.goexi)
       /home/runner/_work/_tool/go/1.22.4/x64/src/runtime/asm_wasm.43 0x fp0x2435fe sp0x2435fe pc0x16200001

goroutine gp0x240038 m=ni force gc (idle]:
runtime.gopar0x3b49b,0x11492c,0x1,0x,0x)
       /home/runner/_work/_tool/go/1.22.4/x64/src/runtime/proc.g40 0x2 fp0x244efb sp0x244ef8 pc0x13820025
runtime.goparkunloc..)
       /home/runner/_work/_tool/go/1.22.4/x64/src/runtime/proc.g408
runtime.forcegchelpe)
       /home/runner/_work/_tool/go/1.22.4/x64/src/runtime/proc.g32 0x1 fp0x244efe sp0x244efb pc0x137f001b
runtime.goexi)
       /home/runner/_work/_tool/go/1.22.4/x64/src/runtime/asm_wasm.43 0x fp0x244efe sp0x244efe pc0x16200001
created byruntime.init. in goroutine1
       /home/runner/_work/_tool/go/1.22.4/x64/src/runtime/proc.g31 0x2

goroutine gp0x240054 m=ni runnabl]:
runtime.gopar0x3b49b,0x1149f0,0x,0x,0x)
       /home/runner/_work/_tool/go/1.22.4/x64/src/runtime/proc.g40 0x2 fp0x244f79 sp0x244f76 pc0x13820025
runtime.goparkunloc..)
       /home/runner/_work/_tool/go/1.22.4/x64/src/runtime/proc.g408
runtime.bgswee0x245400)
       /home/runner/_work/_tool/go/1.22.4/x64/src/runtime/mgcsweep.g27 0x fp0x244f7d sp0x244f79 pc0x128f000c
runtime.gcenable.gowrap)
       /home/runner/_work/_tool/go/1.22.4/x64/src/runtime/mgc.g20 0x fp0x244f7e sp0x244f7d pc0x12140002
runtime.goexi)
       /home/runner/_work/_tool/go/1.22.4/x64/src/runtime/asm_wasm.43 0x fp0x244f7e sp0x244f7e pc0x16200001
created byruntime.gcenabl in goroutine1
       /home/runner/_work/_tool/go/1.22.4/x64/src/runtime/mgc.g20 0x6

goroutine gp0x240070 m=ni runnabl]:
runtime.gopar0x3b49b,0x114bf6,0x,0x,0x)
       /home/runner/_work/_tool/go/1.22.4/x64/src/runtime/proc.g40 0x2 fp0x244ff8 sp0x244ff5 pc0x13820025
runtime.goparkunloc..)
       /home/runner/_work/_tool/go/1.22.4/x64/src/runtime/proc.g408
runtime.(*scavengerState).par0x114bf6)
       /home/runner/_work/_tool/go/1.22.4/x64/src/runtime/mgcscavenge.g42 0x fp0x244ffa sp0x244ff8 pc0x126d000c
runtime.bgscaveng0x245400)
       /home/runner/_work/_tool/go/1.22.4/x64/src/runtime/mgcscavenge.g65 0x fp0x244ffd sp0x244ffa pc0x12720004
runtime.gcenable.gowrap)
       /home/runner/_work/_tool/go/1.22.4/x64/src/runtime/mgc.g20 0x fp0x244ffe sp0x244ffd pc0x12130002
runtime.goexi)
       /home/runner/_work/_tool/go/1.22.4/x64/src/runtime/asm_wasm.43 0x fp0x244ffe sp0x244ffe pc0x16200001
created byruntime.gcenabl in goroutine1
       /home/runner/_work/_tool/go/1.22.4/x64/src/runtime/mgc.g20 0xa

goroutine gp0x24008c m=ni finalizer wai]:
runtime.gopar0x3b471,0x11ab44,0x1,0x,0x)
       /home/runner/_work/_tool/go/1.22.4/x64/src/runtime/proc.g40 0x2 fp0x244e71 sp0x244e6e pc0x13820025
runtime.runfin)
       /home/runner/_work/_tool/go/1.22.4/x64/src/runtime/mfinal.g19 0x1 fp0x244e7e sp0x244e71 pc0x120a001c
runtime.goexi)
       /home/runner/_work/_tool/go/1.22.4/x64/src/runtime/asm_wasm.43 0x fp0x244e7e sp0x244e7e pc0x16200001
created byruntime.createfin in goroutine1
       /home/runner/_work/_tool/go/1.22.4/x64/src/runtime/mfinal.g16 0xc

goroutine gp0x26c950 m=ni GC worker (idle]:
runtime.gopar0x3b474,0x27d010,0x1,0x,0x)
       /home/runner/_work/_tool/go/1.22.4/x64/src/runtime/proc.g40 0x2 fp0x245074 sp0x245072 pc0x13820025
runtime.gcBgMarkWorke)
       /home/runner/_work/_tool/go/1.22.4/x64/src/runtime/mgc.g131 0x1 fp0x24507e sp0x245074 pc0x1227001f
runtime.goexi)
       /home/runner/_work/_tool/go/1.22.4/x64/src/runtime/asm_wasm.43 0x fp0x24507e sp0x24507e pc0x16200001
created byruntime.gcBgMarkStartWorker in goroutine1
       /home/runner/_work/_tool/go/1.22.4/x64/src/runtime/mgc.g123 0x3

Diagnosis

The red herring here is the unused variable which should be reported at compile time as failed, but Gno will accept it and try to run the program. This is a deviation from Go's specification and expectations. We need tests as well to ensure that unused variables aren't left littered.

Kindly cc-ing @thehowl @jaekwon @moul @petar-dambovaliev @veorq

@odeke-em odeke-em added the 🐞 bug Something isn't working label Dec 30, 2024
odeke-em added a commit to odeke-em/gno that referenced this issue Jan 8, 2025
Adds a fuzzer for Transpile, which found bugs:
* gnolang#3425
* gnolang#3426
* partially gnolang#3428

Updates gnolang#3087
odeke-em added a commit to odeke-em/gno that referenced this issue Jan 8, 2025
Adds a fuzzer for Transpile, which found bugs:
* gnolang#3425
* gnolang#3426
* partially gnolang#3428

Updates gnolang#3087
odeke-em added a commit to odeke-em/gno that referenced this issue Jan 8, 2025
Adds a fuzzer for Transpile, which found bugs:
* gnolang#3425
* gnolang#3426
* partially gnolang#3428

Updates gnolang#3087
odeke-em added a commit to odeke-em/gno that referenced this issue Jan 8, 2025
Adds a fuzzer for Transpile, which found bugs:
* gnolang#3425
* gnolang#3426
* partially gnolang#3428

Updates gnolang#3087
n2p5 added a commit that referenced this issue Jan 9, 2025
Adds a fuzzer for Transpile, which found bugs:
* #3425 in which this following Go program crashed the transpiler
```go
package A
import(""//"
""/***/)
```
* #3426 which generated an input that revealed the fact that Gno
deviates from Go by allowing unused variables yet Go's standard is
strict on unused variables like this program
```go
package main

func main() {
	const c1 = 1 < 8
	main()
	1
}
```
which we shouldn't allow
* partially #3428 which revealed the discrepancy in Gno that the
overflow detection is still lacking as the following program is invalid
Go but Gno allowed it to run
```go
package main

func main() {
	const c1 = int8(1) << 8
	println(c1)
}
```
because 1<<8 (256) is higher than the range of int8 for which the
maximum is `(1<<7) - 1 aka 127`

Updates #3087

Co-authored-by: Nathan Toups <[email protected]>
albttx pushed a commit that referenced this issue Jan 10, 2025
Adds a fuzzer for Transpile, which found bugs:
* #3425 in which this following Go program crashed the transpiler
```go
package A
import(""//"
""/***/)
```
* #3426 which generated an input that revealed the fact that Gno
deviates from Go by allowing unused variables yet Go's standard is
strict on unused variables like this program
```go
package main

func main() {
	const c1 = 1 < 8
	main()
	1
}
```
which we shouldn't allow
* partially #3428 which revealed the discrepancy in Gno that the
overflow detection is still lacking as the following program is invalid
Go but Gno allowed it to run
```go
package main

func main() {
	const c1 = int8(1) << 8
	println(c1)
}
```
because 1<<8 (256) is higher than the range of int8 for which the
maximum is `(1<<7) - 1 aka 127`

Updates #3087

Co-authored-by: Nathan Toups <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
🐞 bug Something isn't working
Projects
Status: Triage
Development

No branches or pull requests

1 participant