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

Syscall in getTermSize() corrupts package variable of a different library #38

Open
VoIdemar opened this issue Sep 10, 2021 · 0 comments

Comments

@VoIdemar
Copy link

VoIdemar commented Sep 10, 2021

Hi.

I am developing a CLI application which uses uilive v0.0.4 to output execution statistics to the console at runtime. Everything was fine until I decided to use sniper as a key-value storage for my app. It turned out that one of the sniper package variables got corrupted (changes it's value from 12 to 0) after calling uilive.New(). Without calling uilive.New() sniper works perfectly fine.

I traced the issue down to the IOCTL syscall in getTermSize() function in terminal_size.go:

//...
var sz windowSize

func getTermSize() (int, int) {
       //...
       // `sniper` package variable is fine here
	_, _, _ = syscall.Syscall(syscall.SYS_IOCTL,
		out.Fd(), uintptr(syscall.TIOCGWINSZ), uintptr(unsafe.Pointer(&sz)))
        // `sniper` package variable is reset to 0 
	return int(sz.cols), int(sz.rows)
}Ubuntu 20.04 LTS x64

I am not sure what goes wrong exactly, but it looks like using an unsafe.Pointer to the sz package variable somehow messes up the memory contents. I can't say if any other package variables are affected.

I managed to fix the issue by simply moving package variables from terminal_size.go into the getTermSize() function body, making them local (and they kinda should be local, there are no usages of them outside of terminal_size.go):

// +build !windows

package uilive

import (
	"os"
	"runtime"
	"syscall"
	"unsafe"
)

type windowSize struct {
	rows    uint16
	cols    uint16
}

func getTermSize() (int, int) {
	var (
		out *os.File
		err error
		sz  windowSize
	)
	if runtime.GOOS == "openbsd" {
		out, err = os.OpenFile("/dev/tty", os.O_RDWR, 0)
		if err != nil {
			return 0, 0
		}
	} else {
		out, err = os.OpenFile("/dev/tty", os.O_WRONLY, 0)
		if err != nil {
			return 0, 0
		}
	}
	_, _, _ = syscall.Syscall(syscall.SYS_IOCTL,
		out.Fd(), uintptr(syscall.TIOCGWINSZ), uintptr(unsafe.Pointer(&sz)))
	return int(sz.cols), int(sz.rows)
}

What do you think? Please help me out.

Env specs:

OS Ubuntu 20.04 LTS x64
Kernel 5.7.7-050707-generic
Go 1.15.7

PR: #39

P.S.: big thanks for the library, it's awesome :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant