Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit b5154bd

Browse files
committed
runtime: add argc/argv null safety for all Unix platforms
This change extends null-safety checks to handle argc/argv absence across all Unix platforms for shared library builds. When running as c-archive or c-shared on non-glibc systems, argv may be nil since DT_INIT_ARRAY constructors don't receive arguments per ELF specification. Only glibc provides argc/argv as a non-standard extension. Added universal null checks in sysargs() for: - Linux: Handles standards-compliant libc implementations - Darwin/macOS: Prevents crashes when using c-shared builds - FreeBSD/NetBSD/OpenBSD/DragonFly: BSD libc follows ELF spec strictly - Solaris: Standards-compliant libc implementation Prevents SIGSEGV crashes while maintaining full backward compatibility with glibc systems.
1 parent 647a854 commit b5154bd

File tree

7 files changed

+63
-12
lines changed

7 files changed

+63
-12
lines changed

‎src/runtime/os3_solaris.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -600,6 +600,12 @@ func osyield() {
600600
var executablePath string
601601

602602
func sysargs(argc int32, argv **byte) {
603+
// Check for nil argv to handle c-shared/c-archive libraries
604+
// where DT_INIT_ARRAY doesn't pass arguments according to ELF specification
605+
if argv == nil || argc < 0 || (islibrary || isarchive) {
606+
return
607+
}
608+
603609
n := argc + 1
604610

605611
// skip over argv, envp to get to auxv

‎src/runtime/os_darwin.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -458,6 +458,12 @@ func validSIGPROF(mp *m, c *sigctxt) bool {
458458
var executablePath string
459459

460460
func sysargs(argc int32, argv **byte) {
461+
// Check for nil argv to handle c-shared/c-archive libraries
462+
// where DT_INIT_ARRAY doesn't pass arguments according to ELF specification
463+
if argv == nil || argc < 0 || (islibrary || isarchive) {
464+
return
465+
}
466+
461467
// skip over argv, envv and the first string will be the path
462468
n := argc + 1
463469
for argv_index(argv, n) != nil {

‎src/runtime/os_dragonfly.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -295,6 +295,12 @@ func validSIGPROF(mp *m, c *sigctxt) bool {
295295
}
296296

297297
func sysargs(argc int32, argv **byte) {
298+
// Check for nil argv to handle c-shared/c-archive libraries
299+
// where DT_INIT_ARRAY doesn't pass arguments according to ELF specification
300+
if argv == nil || argc < 0 || (islibrary || isarchive) {
301+
return
302+
}
303+
298304
n := argc + 1
299305

300306
// skip over argv, envp to get to auxv

‎src/runtime/os_freebsd.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -403,6 +403,12 @@ func validSIGPROF(mp *m, c *sigctxt) bool {
403403
}
404404

405405
func sysargs(argc int32, argv **byte) {
406+
// Check for nil argv to handle c-shared/c-archive libraries
407+
// where DT_INIT_ARRAY doesn't pass arguments according to ELF specification
408+
if argv == nil || argc < 0 || (islibrary || isarchive) {
409+
return
410+
}
411+
406412
n := argc + 1
407413

408414
// skip over argv, envp to get to auxv

‎src/runtime/os_linux.go

Lines changed: 17 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -238,22 +238,27 @@ func mincore(addr unsafe.Pointer, n uintptr, dst *byte) int32
238238
var auxvreadbuf [128]uintptr
239239

240240
func sysargs(argc int32, argv **byte) {
241-
n := argc + 1
241+
// On non-glibc systems, argc/argv are not passed to shared library constructors.
242+
// The ELF specification for DT_INIT_ARRAY does not require passing arguments.
243+
// Skip the argv-based auxv parsing when argv is invalid.
244+
if argv != nil && argc >= 0 && !(islibrary || isarchive) {
245+
n := argc + 1
246+
247+
// skip over argv, envp to get to auxv
248+
for argv_index(argv, n) != nil {
249+
n++
250+
}
242251

243-
// skip over argv, envp to get to auxv
244-
for argv_index(argv, n) != nil {
252+
// skip NULL separator
245253
n++
246-
}
247-
248-
// skip NULL separator
249-
n++
250254

251-
// now argv+n is auxv
252-
auxvp := (*[1 << 28]uintptr)(add(unsafe.Pointer(argv), uintptr(n)*goarch.PtrSize))
255+
// now argv+n is auxv
256+
auxvp := (*[1 << 28]uintptr)(add(unsafe.Pointer(argv), uintptr(n)*goarch.PtrSize))
253257

254-
if pairs := sysauxv(auxvp[:]); pairs != 0 {
255-
auxv = auxvp[: pairs*2 : pairs*2]
256-
return
258+
if pairs := sysauxv(auxvp[:]); pairs != 0 {
259+
auxv = auxvp[: pairs*2 : pairs*2]
260+
return
261+
}
257262
}
258263
// In some situations we don't get a loader-provided
259264
// auxv, such as when loaded as a library on Android.

‎src/runtime/os_netbsd.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -388,6 +388,12 @@ func validSIGPROF(mp *m, c *sigctxt) bool {
388388
}
389389

390390
func sysargs(argc int32, argv **byte) {
391+
// Check for nil argv to handle c-shared/c-archive libraries
392+
// where DT_INIT_ARRAY doesn't pass arguments according to ELF specification
393+
if argv == nil || argc < 0 || (islibrary || isarchive) {
394+
return
395+
}
396+
391397
n := argc + 1
392398

393399
// skip over argv, envp to get to auxv

‎src/runtime/runtime1.go

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,13 @@ func goargs() {
7474
if GOOS == "windows" {
7575
return
7676
}
77+
// When running as c-archive or c-shared on non-glibc systems,
78+
// argv may be nil since DT_INIT_ARRAY doesn't pass arguments per ELF spec.
79+
if argv == nil || (islibrary || isarchive) {
80+
// Initialize argslice to empty slice for consistency
81+
argslice = make([]string, 0)
82+
return
83+
}
7784
argslice = make([]string, argc)
7885
for i := int32(0); i < argc; i++ {
7986
argslice[i] = gostringnocopy(argv_index(argv, i))
@@ -84,6 +91,15 @@ func goenvs_unix() {
8491
// TODO(austin): ppc64 in dynamic linking mode doesn't
8592
// guarantee env[] will immediately follow argv. Might cause
8693
// problems.
94+
95+
// When running as c-archive or c-shared on non-glibc systems,
96+
// argv may be nil since DT_INIT_ARRAY doesn't pass arguments per ELF spec.
97+
if argv == nil || (islibrary || isarchive) {
98+
// Initialize envs to empty slice to avoid "getenv before env init"
99+
envs = make([]string, 0)
100+
return
101+
}
102+
87103
n := int32(0)
88104
for argv_index(argv, argc+1+n) != nil {
89105
n++

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /