golang/go

x/sys/unix: IoctlGetInt broken on 64-bit big-endian platforms

Open

#60,429 建立於 2023年5月25日

在 GitHub 查看
 (5 留言) (0 反應) (0 負責人)Go (19,008 fork)batch import
NeedsFixcompiler/runtimehelp wanted

倉庫指標

Star
 (133,883 star)
PR 合併指標
 (30 天內沒有已合併 PR)

描述

What version of Go are you using (go version)?

What operating system and processor architecture are you using (go env)?

GOARCH=s390x
GOOS=linux

(using QEMU on an amd64 host)

What did you do?

package main

import (
	"fmt"
	"os"

	"golang.org/x/sys/unix"
)

func main() {
	tty, err := os.OpenFile("/dev/tty", os.O_RDWR, 0)
	if err != nil {
		panic(err)
	}
	pgid, err := unix.IoctlGetInt(int(tty.Fd()), unix.TIOCGPGRP)
	fmt.Println(pgid, unix.Getpgrp())
}

What did you expect to see?

Same number twice, as on amd64:

$ go run pgrp.go
101981 101981

What did you see instead?

$ GOARCH=s390x go run pgrp.go
438060894388224 101994

The first number is 101994<<32. I believe this happens because IoctlGetInt passes a pointer to a Go int to the system call:

func IoctlGetInt(fd int, req uint) (int, error) {
        var value int
        err := ioctlPtr(fd, req, unsafe.Pointer(&value))
        return value, err
}

The ioctl system call expects a pointer to a C int. Passing a Go int means it stores the pgid in the upper 32 bits.

Note that IoctlSetPointerInt passes a pointer to an int32:

func IoctlSetPointerInt(fd int, req uint, value int) error {
        v := int32(value)
        return ioctlPtr(fd, req, unsafe.Pointer(&v))
}

貢獻者指南