mirror of https://github.com/golang/go.git
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.
|
// 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
|
// 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.
|
// useful in the response, even though there *is* a response.
|
||||||
var buf [1500]byte
|
const bufSize = 1500
|
||||||
s, err := syscall.BytePtrFromString(hostname)
|
buf := (*_C_uchar)(_C_malloc(bufSize))
|
||||||
if err != nil {
|
defer _C_free(unsafe.Pointer(buf))
|
||||||
return nil, err
|
s := _C_CString(hostname)
|
||||||
}
|
defer _C_FreeCString(s)
|
||||||
size, err := _C_res_nsearch(&state, (*_C_char)(unsafe.Pointer(s)), class, rtype, (*_C_uchar)(unsafe.Pointer(&buf[0])), len(buf))
|
size, err := _C_res_nsearch(&state, s, class, rtype, buf, bufSize)
|
||||||
if size <= 0 {
|
if size <= 0 || size > bufSize {
|
||||||
return nil, errors.New("res_nsearch failure")
|
return nil, errors.New("res_nsearch failure")
|
||||||
}
|
}
|
||||||
var p dnsmessage.Parser
|
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
|
return nil, err
|
||||||
}
|
}
|
||||||
p.SkipAllQuestions()
|
p.SkipAllQuestions()
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,7 @@ package net
|
||||||
#include <netdb.h>
|
#include <netdb.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
// If nothing else defined EAI_OVERFLOW, make sure it has a value.
|
// If nothing else defined EAI_OVERFLOW, make sure it has a value.
|
||||||
#ifndef EAI_OVERFLOW
|
#ifndef EAI_OVERFLOW
|
||||||
|
|
@ -20,6 +21,7 @@ package net
|
||||||
#endif
|
#endif
|
||||||
*/
|
*/
|
||||||
import "C"
|
import "C"
|
||||||
|
import "unsafe"
|
||||||
|
|
||||||
const (
|
const (
|
||||||
_C_AF_INET = C.AF_INET
|
_C_AF_INET = C.AF_INET
|
||||||
|
|
@ -46,6 +48,10 @@ type (
|
||||||
)
|
)
|
||||||
|
|
||||||
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_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 }
|
func _C_ai_canonname(ai *_C_struct_addrinfo) **_C_char { return &ai.ai_canonname }
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@ package net
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"internal/syscall/unix"
|
"internal/syscall/unix"
|
||||||
|
"runtime"
|
||||||
"syscall"
|
"syscall"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
)
|
)
|
||||||
|
|
@ -41,6 +42,22 @@ func _C_GoString(p *_C_char) string {
|
||||||
return unix.GoString(p)
|
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_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_canonname(ai *_C_struct_addrinfo) **_C_char { return &ai.Canonname }
|
||||||
func _C_ai_family(ai *_C_struct_addrinfo) *_C_int { return &ai.Family }
|
func _C_ai_family(ai *_C_struct_addrinfo) *_C_int { return &ai.Family }
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue