mirror of
https://github.com/golang/go
synced 2024-11-16 20:14:48 -07:00
net: pass C string to res_nsearch, in case it stores the pointer
The current code passes a Go pointer to a NUL-terminated C string to the C function res_nsearch (or res_search), but that function may in turn store the pointer into the res_state, which is a violation of the cgo pointer rules and is being detected on the linux-amd64-wsl builder. Allocating the string in C memory is safer and should resolve the cgo pointer check. When using libc/syscall mode, the memory is still allocated Go-side, which could potentially be a problem if we ever add a moving collector. For now it is OK. Fixes #56658. Change-Id: Ibd84a9665be16c71994ddb1eedf09d45a6553a3e Reviewed-on: https://go-review.googlesource.com/c/go/+/448795 Reviewed-by: Ian Lance Taylor <iant@google.com> Reviewed-by: Bryan Mills <bcmills@google.com> Run-TryBot: Russ Cox <rsc@golang.org> TryBot-Bypass: Russ Cox <rsc@golang.org>
This commit is contained in:
parent
a6642e67e1
commit
12ab0ac184
@ -345,17 +345,17 @@ func resSearch(ctx context.Context, hostname string, rtype, class int) ([]dnsmes
|
||||
// giving us no way to find out how big the packet is.
|
||||
// For now, we are willing to take res_search's word that there's nothing
|
||||
// useful in the response, even though there *is* a response.
|
||||
var buf [1500]byte
|
||||
s, err := syscall.BytePtrFromString(hostname)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
size, err := _C_res_nsearch(&state, (*_C_char)(unsafe.Pointer(s)), class, rtype, (*_C_uchar)(unsafe.Pointer(&buf[0])), len(buf))
|
||||
if size <= 0 {
|
||||
const bufSize = 1500
|
||||
buf := (*_C_uchar)(_C_malloc(bufSize))
|
||||
defer _C_free(unsafe.Pointer(buf))
|
||||
s := _C_CString(hostname)
|
||||
defer _C_FreeCString(s)
|
||||
size, err := _C_res_nsearch(&state, s, class, rtype, buf, bufSize)
|
||||
if size <= 0 || size > bufSize {
|
||||
return nil, errors.New("res_nsearch failure")
|
||||
}
|
||||
var p dnsmessage.Parser
|
||||
if _, err := p.Start(buf[:size]); err != nil {
|
||||
if _, err := p.Start(unsafe.Slice((*byte)(unsafe.Pointer(buf)), size)); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
p.SkipAllQuestions()
|
||||
|
@ -13,6 +13,7 @@ package net
|
||||
#include <netdb.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
// If nothing else defined EAI_OVERFLOW, make sure it has a value.
|
||||
#ifndef EAI_OVERFLOW
|
||||
@ -20,6 +21,7 @@ package net
|
||||
#endif
|
||||
*/
|
||||
import "C"
|
||||
import "unsafe"
|
||||
|
||||
const (
|
||||
_C_AF_INET = C.AF_INET
|
||||
@ -45,7 +47,11 @@ type (
|
||||
_C_struct_sockaddr = C.struct_sockaddr
|
||||
)
|
||||
|
||||
func _C_GoString(p *_C_char) string { return C.GoString(p) }
|
||||
func _C_GoString(p *_C_char) string { return C.GoString(p) }
|
||||
func _C_CString(s string) *_C_char { return C.CString(s) }
|
||||
func _C_FreeCString(p *_C_char) { C.free(unsafe.Pointer(p)) }
|
||||
func _C_malloc(n uintptr) unsafe.Pointer { return C.malloc(C.size_t(n)) }
|
||||
func _C_free(p unsafe.Pointer) { C.free(p) }
|
||||
|
||||
func _C_ai_addr(ai *_C_struct_addrinfo) **_C_struct_sockaddr { return &ai.ai_addr }
|
||||
func _C_ai_canonname(ai *_C_struct_addrinfo) **_C_char { return &ai.ai_canonname }
|
||||
|
@ -8,6 +8,7 @@ package net
|
||||
|
||||
import (
|
||||
"internal/syscall/unix"
|
||||
"runtime"
|
||||
"syscall"
|
||||
"unsafe"
|
||||
)
|
||||
@ -41,6 +42,22 @@ func _C_GoString(p *_C_char) string {
|
||||
return unix.GoString(p)
|
||||
}
|
||||
|
||||
func _C_CString(s string) *_C_char {
|
||||
p := make([]byte, len(s)+1)
|
||||
copy(p, s)
|
||||
return &p[0]
|
||||
}
|
||||
|
||||
func _C_FreeCString(p *_C_char) { _C_free(unsafe.Pointer(p)) }
|
||||
func _C_free(p unsafe.Pointer) { runtime.KeepAlive(p) }
|
||||
|
||||
func _C_malloc(n uintptr) unsafe.Pointer {
|
||||
if n <= 0 {
|
||||
n = 1
|
||||
}
|
||||
return unsafe.Pointer(&make([]byte, n)[0])
|
||||
}
|
||||
|
||||
func _C_ai_addr(ai *_C_struct_addrinfo) **_C_struct_sockaddr { return &ai.Addr }
|
||||
func _C_ai_canonname(ai *_C_struct_addrinfo) **_C_char { return &ai.Canonname }
|
||||
func _C_ai_family(ai *_C_struct_addrinfo) *_C_int { return &ai.Family }
|
||||
|
Loading…
Reference in New Issue
Block a user