go 有办法调用基础库 golang.org/x/crypto 的私有结构和方法吗?
开源项目 github.com/trzsz/trzsz-ssh 想支持 ssh ControlMaster 的功能。
go 基础库 golang.org/x/crypto 有个 PR go-review.googlesource.com/c/crypto/+/383374 还没合入。
有办法在不 fork 基础库 golang.org/x/crypto 的情况下,优雅地在自己的项目实现这个 PR 的逻辑吗?
import "golang.org/x/crypto/ssh"
func NewControlClientConn(c net.Conn) (ssh.Conn, <-chan ssh.NewChannel, <-chan *ssh.Request, error) {
conn := &ssh.connection{ ■ undefined: ssh.connection
sshConn: ssh.sshConn{conn: c}, ■ undefined: ssh.sshConn
}
var err error
if conn.transport, err = handshakeControlProxy(c); err != nil {
return nil, nil, nil, fmt.Errorf("ssh: control proxy handshake failed; %v", err)
}
conn.mux = ssh.newMux(conn.transport) ■ undefined: ssh.newMux
return conn, conn.mux.incomingChannels, conn.mux.incomingRequests, nil
}
handshakeControlProxy 这个函数很好办,直接从 PR 中复制出来就行了。
问题:上面的 ssh.connection、ssh.sshConn 和 ssh.newMux 依赖很深,发现很难直接 copy 出来。
用 go:linkname 把私有函数链出来; unsafe 读写私有结构
unsafe 能引用私有结构吗?具体怎么做?
chatGPT ?
你问问看?
V2EX 不允许 gpt 回答的,会 ban 账号的。
可以看 github.com/dolthub/maphash 这玩意的实现,其实就是自己整个和私有结构体一模一样的,然后把指针映射到自己的结构体上
#1 link 要在 golang.org/x/crypto 里面写其实可以用 go 汇编,可以直接根据包名﹒变量名引用(这个不安全)
不需要的,外面写一个相同定义的函数 link 原函数就行了//go:linkname func1 pkg.func1func func1(a string) string记得 import _ "unsafe"
现在要调用的函数是func newMux(p packetConn) mux问题是 packetConn 和 mux 都是私有的,怎么用 go:linkname 定义呢?type packetConn interface { // Encrypt and send a packet of data to the remote peer. writePacket(packet []byte) error // Read a packet from the connection. The read is blocking, // i.e. if error is nil, then the returned byte slice is // always non-empty. readPacket() ([]byte, error) // Close closes the write-side of the connection. Close() error}type mux struct { conn packetConn chanList chanList incomingChannels chan NewChannel globalSentMu sync.Mutex globalResponses chan interface{} incomingRequests chan Request errCond *sync.Cond err error}
#8 你这反了,你看 runtime now github.com/golang/go/blob/master/src/runtime/timestub.go#L14连接到 time now ,linkname 是写在 runtime 而不是 time
最好别拿 linkname 搞,升级 go 版本的时候容易炸。还是乖乖开个 fork 吧
汇编可以参考这个 github.com/golang/go/blob/master/src/sync/atomic/asm.s#L10
fork golang.org/x/crypto 也不好啊。
Go 创始人说:最好的方法就是复制
#14 反对他。我只是要加一点点功能,我可没有能力和精力去维护那么大一个库。
可以算偏移量直接读写; 或者定义一个相同结构的 struct, unsafe 强转 (我不清楚是否安全)
#10 ,linkname 在哪边写都是可以的
可以复制, 毕竟标准库里为了解决循环引用 也搞了很多复制
用 unsafe.Pointer
+ 偏移量 可以做到
packetConn 是个 interface 吧,直接拷贝出来就是了,
mux ,骚一点就是。。//go:linkname newMux golang.org/x/crypto/ssh.newMuxfunc newMux(p packetConn) muxtype mux struct { conn packetConn _ [40]byte incomingChannels chan ssh.NewChannel globalSentMu sync.Mutex globalResponses chan interface{} incomingRequests chan ssh.Request errCond *sync.Cond err error}
接口可以//go:linkname SendRequest golang.org/x/crypto/ssh.(mux).SendRequestfunc SendRequest(mux mux, name string, wantReply bool, payload []byte) (bool, []byte, error)func (c *connection) SendRequest(name string, wantReply bool, payload []byte) (bool, []byte, error) { return SendRequest(c.mux, name, wantReply, payload)}不过整体也不是很优雅就是了,兼容性很差
我觉得最优雅的办法就是 fork 。fork 完 release 个新版本,等 ssh 真的支持你想要的,再发布个新版本换回原来的
但是这样 go 版本更新的时候你可以显式的 review 改了什么,用 linkname 炸的无声无息,stacktrace 都没有那种
下面这个网站罗列了,几乎所有的关于HTML 5 在各种主流浏览器上的安全问题,这些安全问题很有可能将会是黑客攻击你的网上的敲门砖,他们几乎都和Javascript都有关系,你就…
如题,各位有经验没?取取经 多谢各位热心老哥发言,晚点下班我整理一下追加在这个回复下面,给后来的小伙伴做参考。 毕业这三年颈椎和腰椎太疼了,不看医生不行了,挺不住了 三院是…
大佬们,我哭了,一直搞的后端,现在前端不够人,我也得上。结果很难受,自己学个前端一直半途而废,创建好初始项目后,修改了两下,发现效果没到自己的理想,就 ai ,ai 改了之后,…