Commit Graph

313 Commits

Author SHA1 Message Date
Krzysztof Wolicki
45c77931c2 Change deprecated b.host to b.graph.host in tests and Zig's build.zig 2024-06-13 10:49:06 -04:00
Ryan Liptak
76fb2b685b std: Convert deprecated aliases to compile errors and fix usages
Deprecated aliases that are now compile errors:

- `std.fs.MAX_PATH_BYTES` (renamed to `std.fs.max_path_bytes`)
- `std.mem.tokenize` (split into `tokenizeAny`, `tokenizeSequence`, `tokenizeScalar`)
- `std.mem.split` (split into `splitSequence`, `splitAny`, `splitScalar`)
- `std.mem.splitBackwards` (split into `splitBackwardsSequence`, `splitBackwardsAny`, `splitBackwardsScalar`)
- `std.unicode`
  + `utf16leToUtf8Alloc`, `utf16leToUtf8AllocZ`, `utf16leToUtf8`, `fmtUtf16le` (all renamed to have capitalized `Le`)
  + `utf8ToUtf16LeWithNull` (renamed to `utf8ToUtf16LeAllocZ`)
- `std.zig.CrossTarget` (moved to `std.Target.Query`)

Deprecated `lib/std/std.zig` decls were deleted instead of made a `@compileError` because the `refAllDecls` in the test block would trigger the `@compileError`. The deleted top-level `std` namespaces are:

- `std.rand` (renamed to `std.Random`)
- `std.TailQueue` (renamed to `std.DoublyLinkedList`)
- `std.ChildProcess` (renamed/moved to `std.process.Child`)

This is not exhaustive. Deprecated aliases that I didn't touch:
  + `std.io.*`
  + `std.Build.*`
  + `std.builtin.Mode`
  + `std.zig.c_translation.CIntLiteralRadix`
  + anything in `src/`
2024-06-13 10:18:59 -04:00
Michael Dusan
2cd536d7e8 libcxx: fix building when -fsingle-threaded
* Skip building libcxx mt-only source files when single-threaded.
* This change is required for llvm18 libcxx.
* Add standalone test to link a trivial:
    - mt-executable with libcxx
    - st-executable with libcxx
2024-06-08 15:34:19 -04:00
MrDmitry
84d1580873 Report error on missing values for addConfigHeader 2024-06-08 15:18:56 -04:00
Andrew Kelley
a5e4fe5487 std.Build.Step.Run: account for new environment variable
Introduces `disable_zig_progress` which prevents the build runner from
assigning the child process a progress node.

This is needed for the empty_env test which requires the environment to
be completely empty.
2024-05-27 20:56:49 -07:00
Andrew Kelley
f97c2f28fd update the codebase for the new std.Progress API 2024-05-27 20:56:48 -07:00
Andrew Kelley
f47824f24d std: restructure child process namespace 2024-05-26 09:31:55 -07:00
Jakub Konka
6f117dbca4 test/standalone: fix iOS smoke test 2024-05-13 08:55:27 +02:00
Jacob Young
d9b00ee4ba standalone: support relative cache path 2024-05-08 19:37:03 -07:00
Jacob Young
dee9f82f69 Run: add output directory arguments
This allows running commands that take an output directory argument. The
main thing that was needed for this feature was generated file subpaths,
to allow access to the files in a generated directory. Additionally, a
minor change was required to so that the correct directory is created
for output directory args.
2024-05-05 15:58:08 -04:00
Jacob Young
e3424332d3 Build: cleanup
* `doc/langref` formatting
 * upgrade `.{ .path = "..." }` to `b.path("...")`
 * avoid using arguments named `self`
 * make `Build.Step.Id` usage more consistent
 * add `Build.pathResolve`
 * use `pathJoin` and `pathResolve` everywhere
 * make sure `Build.LazyPath.getPath2` returns an absolute path
2024-05-05 09:42:51 -04:00
Ryan Liptak
b86c4bde64 Rename Dir.writeFile2 -> Dir.writeFile and update all callsites
writeFile was deprecated in favor of writeFile2 in f645022d16. This commit renames writeFile2 to writeFile and makes writeFile2 a compile error.
2024-05-03 13:29:22 -07:00
Ryan Liptak
ea9d817a90 Build system: Allow specifying Win32 resource include paths using LazyPath
Adds an `include_paths` field to RcSourceFile that takes a slice of LazyPaths. The paths are resolved and subsequently appended to the -rcflags as `/I <resolved path>`.

This fixes an accidental regression from https://github.com/ziglang/zig/pull/19174. Before that PR, all Win32 resource compilation would inherit the CC flags (via `addCCArgs`), which included things like include directories. After that PR, though, that is no longer the case.

However, this commit intentionally does not restore the previous behavior (inheriting the C include paths). Instead, each .rc file will need to have its include paths specified directly and the include paths only apply to one particular resource script. This allows more fine-grained control and has less potentially surprising behavior (at the cost of some convenience).

Closes #19605
2024-05-02 22:08:00 -07:00
Andrew Kelley
9d64332a59
Merge pull request #19698 from squeek502/windows-batbadbut
std.process.Child: Mitigate arbitrary command execution vulnerability on Windows (BatBadBut)
2024-04-24 13:49:43 -07:00
Ryan Liptak
422464d540 std.process.Child: Mitigate arbitrary command execution vulnerability on Windows (BatBadBut)
> Note: This first part is mostly a rephrasing of https://flatt.tech/research/posts/batbadbut-you-cant-securely-execute-commands-on-windows/
> See that article for more details

On Windows, it is possible to execute `.bat`/`.cmd` scripts via CreateProcessW. When this happens, `CreateProcessW` will (under-the-hood) spawn a `cmd.exe` process with the path to the script and the args like so:

    cmd.exe /c script.bat arg1 arg2

This is a problem because:

- `cmd.exe` has its own, separate, parsing/escaping rules for arguments
- Environment variables in arguments will be expanded before the `cmd.exe` parsing rules are applied

Together, this means that (1) maliciously constructed arguments can lead to arbitrary command execution via the APIs in `std.process.Child` and (2) escaping according to the rules of `cmd.exe` is not enough on its own.

A basic example argv field that reproduces the vulnerability (this will erroneously spawn `calc.exe`):

    .argv = &.{ "test.bat", "\"&calc.exe" },

And one that takes advantage of environment variable expansion to still spawn calc.exe even if the args are properly escaped for `cmd.exe`:

    .argv = &.{ "test.bat", "%CMDCMDLINE:~-1%&calc.exe" },

(note: if these spawned e.g. `test.exe` instead of `test.bat`, they wouldn't be vulnerable; it's only `.bat`/`.cmd` scripts that are vulnerable since they go through `cmd.exe`)

Zig allows passing `.bat`/`.cmd` scripts as `argv[0]` via `std.process.Child`, so the Zig API is affected by this vulnerability. Note also that Zig will search `PATH` for `.bat`/`.cmd` scripts, so spawning something like `foo` may end up executing `foo.bat` somewhere in the PATH (the PATH searching of Zig matches the behavior of cmd.exe).

> Side note to keep in mind: On Windows, the extension is significant in terms of how Windows will try to execute the command. If the extension is not `.bat`/`.cmd`, we know that it will not attempt to be executed as a `.bat`/`.cmd` script (and vice versa). This means that we can just look at the extension to know if we are trying to execute a `.bat`/`.cmd` script.

---

This general class of problem has been documented before in 2011 here:

https://learn.microsoft.com/en-us/archive/blogs/twistylittlepassagesallalike/everyone-quotes-command-line-arguments-the-wrong-way

and the course of action it suggests for escaping when executing .bat/.cmd files is:

- Escape first using the non-cmd.exe rules
- Then escape all cmd.exe 'metacharacters' (`(`, `)`, `%`, `!`, `^`, `"`, `<`, `>`, `&`, and `|`) with `^`

However, escaping with ^ on its own is insufficient because it does not stop cmd.exe from expanding environment variables. For example:

```
args.bat %PATH%
```

escaped with ^ (and wrapped in quotes that are also escaped), it *will* stop cmd.exe from expanding `%PATH%`:

```
> args.bat ^"^%PATH^%^"
"%PATH%"
```

but it will still try to expand `%PATH^%`:

```
set PATH^^=123
> args.bat ^"^%PATH^%^"
"123"
```

The goal is to stop *all* environment variable expansion, so this won't work.

Another problem with the ^ approach is that it does not seem to allow all possible command lines to round trip through cmd.exe (as far as I can tell at least).

One known example:

```
args.bat ^"\^"key^=value\^"^"
```

where args.bat is:

```
@echo %1 %2 %3 %4 %5 %6 %7 %8 %9
```

will print

```
"\"key value\""
```

(it will turn the `=` into a space for an unknown reason; other minor variations do roundtrip, e.g. `\^"key^=value\^"`, `^"key^=value^"`, so it's unclear what's going on)

It may actually be possible to escape with ^ such that every possible command line round trips correctly, but it's probably not worth the effort to figure it out, since the suggested mitigation for BatBadBut has better roundtripping and leads to less garbled command lines overall.

---

Ultimately, the mitigation used here is the same as the one suggested in:

https://flatt.tech/research/posts/batbadbut-you-cant-securely-execute-commands-on-windows/

The mitigation steps are reproduced here, noted with one deviation that Zig makes (following Rust's lead):

1. Replace percent sign (%) with %%cd:~,%.
2. Replace the backslash (\) in front of the double quote (") with two backslashes (\\).
3. Replace the double quote (") with two double quotes ("").
4. ~~Remove newline characters (\n).~~
  - Instead, `\n`, `\r`, and NUL are disallowed and will trigger `error.InvalidBatchScriptArg` if they are found in `argv`. These three characters do not roundtrip through a `.bat` file and therefore are of dubious/no use. It's unclear to me if `\n` in particular is relevant to the BatBadBut vulnerability (I wasn't able to find a reproduction with \n and the post doesn't mention anything about it except in the suggested mitigation steps); it just seems to act as a 'end of arguments' marker and therefore anything after the `\n` is lost (and same with NUL). `\r` seems to be stripped from the command line arguments when passed through a `.bat`/`.cmd`, so that is also disallowed to ensure that `argv` can always fully roundtrip through `.bat`/`.cmd`.
5. Enclose the argument with double quotes (").

The escaped command line is then run as something like:

    cmd.exe /d /e:ON /v:OFF /c "foo.bat arg1 arg2"

Note: Previously, we would pass `foo.bat arg1 arg2` as the command line and the path to `foo.bat` as the app name and let CreateProcessW handle the `cmd.exe` spawning for us, but because we need to pass `/e:ON` and `/v:OFF` to cmd.exe to ensure the mitigation is effective, that is no longer tenable. Instead, we now get the full path to `cmd.exe` and use that as the app name when executing `.bat`/`.cmd` files.

---

A standalone test has also been added that tests two things:

1. Known reproductions of the vulnerability are tested to ensure that they do not reproduce the vulnerability
2. Randomly generated command line arguments roundtrip when passed to a `.bat` file and then are passed from the `.bat` file to a `.exe`. This fuzz test is as thorough as possible--it tests that things like arbitrary Unicode codepoints and unpaired surrogates roundtrip successfully.

Note: In order for the `CreateProcessW` -> `.bat` -> `.exe` roundtripping to succeed, the .exe must split the arguments using the post-2008 C runtime argv splitting implementation, see https://github.com/ziglang/zig/pull/19655 for details on when that change was made in Zig.
2024-04-23 03:21:51 -07:00
Meghan Denny
1b4ea80654
do more robust import
Co-authored-by: Carl Åstholm <carl@astholm.se>
2024-04-18 11:24:42 -07:00
Meghan Denny
0820aa4a46 std: fix and add test for Build.dependencyFromBuildZig 2024-04-18 03:07:44 -07:00
Andrew Kelley
b78b2689ed
Merge pull request #19655 from squeek502/windows-argv-post-2008
ArgIteratorWindows: Match post-2008 C runtime rather than `CommandLineToArgvW`
2024-04-15 15:28:33 -07:00
Ryan Liptak
cffe1999c6 windows_argv standalone test: Only test against MSVC if it's available 2024-04-15 02:09:48 -07:00
Ryan Liptak
f4c4c04f1c ArgIteratorWindows: Match post-2008 C runtime rather than CommandLineToArgvW
On Windows, the command line arguments of a program are a single WTF-16 encoded string and it's up to the program to split it into an array of strings. In C/C++, the entry point of the C runtime takes care of splitting the command line and passing argc/argv to the main function.

https://github.com/ziglang/zig/pull/18309 updated ArgIteratorWindows to match the behavior of CommandLineToArgvW, but it turns out that CommandLineToArgvW's behavior does not match the behavior of the C runtime post-2008. In 2008, the C runtime argv splitting changed how it handles consecutive double quotes within a quoted argument (it's now considered an escaped quote, e.g. `"foo""bar"` post-2008 would get parsed into `foo"bar`), and the rules around argv[0] were also changed.

This commit makes ArgIteratorWindows match the behavior of the post-2008 C runtime, and adds a standalone test that verifies the behavior matches both the MSVC and MinGW argv splitting exactly in all cases (it checks that randomly generated command line strings get split the same way).

The motivation here is roughly the same as when the same change was made in Rust (https://github.com/rust-lang/rust/pull/87580), that is (paraphrased):

- Consistent behavior between Zig and modern C/C++ programs
- Allows users to escape double quotes in a way that can be more straightforward

Additionally, the suggested mitigation for BatBadBut (https://flatt.tech/research/posts/batbadbut-you-cant-securely-execute-commands-on-windows/) relies on the post-2008 argv splitting behavior for roundtripping of the arguments given to `cmd.exe`. Note: it's not necessary for the suggested mitigation to work, but it is necessary for the suggested escaping to be parsed back into the intended argv by ArgIteratorWindows after being run through a `.bat` file.
2024-04-15 02:09:48 -07:00
Andrew Kelley
b30ad74908 remove deprecated LazyPath.path union tag 2024-04-11 14:02:47 -07:00
Andrew Kelley
7fb5a0b18b introduce std.Build.path; deprecate LazyPath.relative
This adds the *std.Build owner to LazyPath so that lazy paths returned
from a dependency can be used in the application without friction or
footguns.

closes #19313
2024-04-10 15:02:20 -07:00
Carl Åstholm
33b8fdb6bc Turn "simple" standalone test cases into a package 2024-04-07 16:05:54 -07:00
Carl Åstholm
c3ecc6972e Don't add standalone test cases until we've built stage3 2024-04-07 16:05:54 -07:00
Carl Åstholm
d6ecfa7025 Move "simple" standalone test cases to a new directory 2024-04-07 16:05:54 -07:00
Carl Åstholm
3ed221f149 Promote standalone test cases to packages
This is a prerequisite for removing `b.anonymousDependency()`, but
having compiler tests dogfood package management might be a good idea
in general.
2024-04-07 16:05:53 -07:00
Carl Åstholm
eee5400b7d Account for dependency boundaries when duping headers
This is a temporary workaround that can be revered if/when 'path'
lazy paths are updated to encode which build root they are relative to.
2024-04-07 15:34:47 +02:00
Carl Åstholm
d99e44a157 Document added/updated functions
Also renames `addHeaders` to `addHeadersDirectory` for clarity.
2024-04-07 15:34:47 +02:00
Carl Åstholm
5af4e91e00 Oops, forgot to dupe installations in installLibraryHeaders
Added test coverage for `installLibraryHeaders`
2024-04-07 15:34:47 +02:00
Carl Åstholm
7b1a6a93a4 Fix install_headers test on macOS (and possibly Linux) 2024-04-07 15:34:47 +02:00
Carl Åstholm
27c8f895eb Add standalone tests for Compile.installHeaders
Co-authored-by: Abhinav Gupta <mail@abhinavg.net>
2024-04-07 15:34:47 +02:00
Jacob Young
eb723a4070 Update uses of @fieldParentPtr to use RLS 2024-03-30 20:50:48 -04:00
Jacob Young
e409afb79b Update uses of @fieldParentPtr to pass a pointer type 2024-03-30 20:50:48 -04:00
Ryan Liptak
bad9efbcc1 Add standalone test for all possible MinGW exe entry points 2024-03-27 10:06:06 +00:00
Andrew Kelley
8c94950c24 fix compilation failures found by CI 2024-03-19 16:18:18 -07:00
Ahmed
5c8eda36d6 chore: Fix some typos 2024-03-14 19:43:24 +02:00
Carl Åstholm
44cd59a3ba Move big enum tests to a standalone test case 2024-03-12 00:53:09 +01:00
Tristan Ross
9d70d614ae
std.builtin: make link mode fields lowercase 2024-03-11 07:09:10 -07:00
Ryan Liptak
80508b98c2 Update deprecated std.unicode function usages 2024-02-24 14:04:59 -08:00
Andrew Kelley
483b63d301 std.http: migrate remaining test/standalone/http.zig to std lib
These tests were not being actually run. Now they are run along with
testing the standard library.
2024-02-23 02:37:11 -07:00
Andrew Kelley
abde76a808 std.http.Server: handle expect: 100-continue requests
The API automatically handles these requests as expected. After
receiveHead(), the server has a chance to notice the expectation and do
something about it. If it does not, then the Server implementation will
handle it by sending the continuation header when the read stream is
created.

Both respond() and respondStreaming() send the continuation header as
part of discarding the request body, only if the read stream has not
already been created.
2024-02-23 02:37:11 -07:00
Andrew Kelley
380916c0f8 std.http.Server.Request.Respond: support all transfer encodings
Before I mistakenly thought that missing content-length meant zero when
it actually means to stream until the connection is closed.

Now the respond() function accepts transfer_encoding which can be left
as default (use content.len for content-length), set to none which makes
it omit the content-length, or chunked, which makes it format the
response as a chunked transfer even though the server has the entire
contents already buffered.

The echo-content tests are moved from test/standalone/http.zig to the
standard library where they are actually run.
2024-02-23 02:37:11 -07:00
Andrew Kelley
51451341bf update standalone http test file to new API 2024-02-23 02:37:11 -07:00
Andrew Kelley
6129ecd4fe std.net, std.http: simplify 2024-02-23 02:37:11 -07:00
Andrew Kelley
743a0c966d std.http.Client: remove bad decisions from fetch()
* "storage" is a better name than "strategy".
* The most flexible memory-based storage API is appending to an
  ArrayList.
* HTTP method should default to POST if there is a payload.
* Avoid storing unnecessary data in the FetchResult
* Avoid the need for a deinit() method in the FetchResult

The decisions that this logic made about how to handle files is beyond
repair:
- fail to use sendfile() on a plain connection
- redundant stat
- does not handle arbitrary streams
So, file-based response storage is no longer supported. Users should use
the lower-level open() API which allows avoiding these pitfalls.
2024-02-23 02:37:11 -07:00
Andrew Kelley
d574875f00 Revert "std.http: remove 'done' flag"
This reverts commit 42be972a72c86b32ad8403d082ab42763c6facec.

Using a bit to distinguish between headers and trailers is fine. It was
just named and documented poorly.
2024-02-23 02:37:11 -07:00
Andrew Kelley
3d61890d24 std: convert http trailers test to unit test
making it no longer dead code. it is currently failing.
2024-02-23 02:37:11 -07:00
Andrew Kelley
4d401e6159 std.http: remove Headers API
I originally removed these in 402f967ed5.
I allowed them to be added back in #15299 because they were smuggled in
alongside a bug fix, however, I wasn't kidding when I said that I wanted
to take the design of std.http in a different direction than using this
data structure.

Instead, some headers are provided via explicit field names populated
while parsing the HTTP request/response, and some are provided via
new fields that support passing extra, arbitrary headers.

This resulted in simplification of logic in many places, as well as
elimination of the possibility of failure in many places. There is
less deinitialization code happening now.

Furthermore, it made it no longer necessary to clone the headers data
structure in order to handle redirects.

http_proxy and https_proxy fields are now pointers since it is common
for them to be unpopulated.

loadDefaultProxies is changed into initDefaultProxies to communicate
that it does not actually load anything from disk or from the network.
The function now is leaky; the API user must pass an already
instantiated arena allocator. Removes the need to deinitialize proxies.

Before, proxies stored arbitrary sets of headers. Now they only store
the authorization value.

Removed the duplicated code between https_proxy and http_proxy. Finally,
parsing failures of the environment variables result in errors being
emitted rather than silently ignoring the proxy.

error.CompressionNotSupported is renamed to
error.CompressionUnsupported, matching the naming convention from all
the other errors in the same set.

Removed documentation comments that were redundant with field and type
names.

Disabling zstd decompression in the server for now; see #18937.

I found some apparently dead code in src/Package/Fetch/git.zig. I want
to check with Ian about this.

I discovered that test/standalone/http.zig is dead code, it is only
being compiled but not being run. Furthermore it hangs at the end if you
run it manually. The previous commits in this branch were written under
the assumption that this test was being run with
`zig build test-standalone`.
2024-02-23 02:37:11 -07:00
Andrew Kelley
50e2a5f673 std.http: remove 'done' flag
This is a state machine that already has a `state` field. No need to
additionally store "done" - it just makes things unnecessarily
complicated and buggy.
2024-02-23 02:37:11 -07:00
Veikka Tuominen
220d3264c9 std: make options a struct instance instead of a namespace 2024-02-01 15:22:36 +02:00