Skip to content

[stdlib] Ignore argc when setting up CommandLine.arguments #74739

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Jul 2, 2024

Conversation

Azoy
Copy link
Contributor

@Azoy Azoy commented Jun 26, 2024

Unfortunately argc and argv are globally accessible and mutable so in some cases these values may be out of sync with each other. This can result in a crash when accessing CommandLine.arguments because if someone stomps on argv and inserts a null within 0 ..< argc but doesn't update argc, we will attempt to read 0 ..< argc number of strings and crash when trying to unwrap one of the c string pointers in the argv array. Lets just ignore argc and manually iterate argv to find argc for ourselves.

Resolves: rdar://130346225 and rdar://129708138

@Azoy Azoy requested a review from al45tair June 26, 2024 17:59
@Azoy Azoy requested a review from a team as a code owner June 26, 2024 17:59
@Azoy
Copy link
Contributor Author

Azoy commented Jun 26, 2024

@swift-ci please smoke test

@Azoy
Copy link
Contributor Author

Azoy commented Jun 27, 2024

@swift-ci please smoke test

@Azoy
Copy link
Contributor Author

Azoy commented Jul 2, 2024

@swift-ci please smoke test Windows

@Azoy Azoy merged commit 906d6e4 into swiftlang:main Jul 2, 2024
3 checks passed
@Azoy Azoy deleted the commandline-argc-ignore branch July 2, 2024 20:41
Azoy added a commit to Azoy/swift that referenced this pull request Jul 2, 2024
[stdlib] Ignore argc when setting up CommandLine.arguments
@grynspan
Copy link
Contributor

Wait, is unsafeArgv actually mutable? It looks read-only to me—so it should be safe to use argc from the C function. (That said, it's also probably fine for us to stop trying to compute it in the first place since we now guarantee a trailing NULL value, which we didn't historically but which C also guarantees.)

@Azoy
Copy link
Contributor Author

Azoy commented Jul 14, 2024

@grynspan not the Swift interface, the actual underlying argc and argv (at least on Darwin)

@grynspan
Copy link
Contributor

Oh, right, the underlying pointer isn't owned by Swift. I wonder if we should change that given the inherent concurrency unsafety of it, or perhaps offer a withUnsafeArgvArgc() function that provides a locally stable pointer and count (suitable for passing to posix_spawn() etc.)

@al45tair
Copy link
Contributor

C99 §5.1.2.2.1 ¶2:

The parameters argc and argv and the strings pointed to by the argv array shall be modifiable by the program, and retain their last-stored values between program startup and program termination.

One thing it doesn't mention is that a traditional use of this on UNIX is the ability to change what ps shows for a process by overwriting the string stored at argv[0], and somewhat more unpleasantly, this often runs off the end of the original string and overwrites subsequent argument storage as well.

@grynspan
Copy link
Contributor

That's required for C, but I'm talking about Swift API. We can do better!

@al45tair
Copy link
Contributor

True, though we need to bear in mind what the underlying situation is, which is why I mention it. Particularly if we're going to try to lazily capture the argument vector, the fact that C code is free to randomly overwrite it as it sees fit is problematic.

@grynspan
Copy link
Contributor

I think the crux of what I'm saying is that our API surface should be as reliable as is practical. I don't know if we can do much about somebody smashing argv before Swift can read off a copy (and, short of adding an ultra-high-priority constructor function in the runtime, we probably can't guarantee it.)

But, assuming that modifying argv is rare in library code, and assuming that the main binary is written in Swift, it's probably then safe to assume that the first time CommandLine is used is as good a time as any to clone the current state of argc and argv into immutable memory, at which point it is safe for us to vend that copy out to Swift code. (If some other thread comes in and smashes argv while we're copying it, well, them's the breaks.)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants