Skip to content

Commit

Permalink
fix wasm on go 1.17.2 (#1684)
Browse files Browse the repository at this point in the history
  • Loading branch information
evanw committed Oct 15, 2021
1 parent 344ec46 commit ae754ae
Show file tree
Hide file tree
Showing 3 changed files with 34 additions and 1 deletion.
11 changes: 11 additions & 0 deletions CHANGELOG.md
Expand Up @@ -25,6 +25,17 @@

This behavior can be used to load a module on the file system with the same name as one of node's core modules. For example, `require('fs/')` will load the module `fs` from the file system instead of loading node's core `fs` module. With this release, esbuild will now match node's behavior in this edge case. This means the external modules that are automatically added by `--platform=node` now behave subtly differently than `--external:`, which allows code that relies on this behavior to be bundled correctly.

* Fix WebAssembly builds on Go 1.17.2+ ([#1684](https://github.com/evanw/esbuild/pull/1684))

Go 1.17.2 introduces a change (specifically a [fix for CVE-2021-38297](https://go-review.googlesource.com/c/go/+/354591/)) that causes Go's WebAssembly bootstrap script to throw an error when it's run in situations with many environment variables. One such situation is when the bootstrap script is run inside [GitHub Actions](https://github.com/features/actions). This change was introduced because the bootstrap script writes a copy of the environment variables into WebAssembly memory without any bounds checking, and writing more than 4096 bytes of data ends up writing past the end of the buffer and overwriting who-knows-what. So throwing an error in this situation is an improvement. However, this breaks esbuild which previously (at least seemingly) worked fine.

With this release, esbuild's WebAssembly bootstrap script that calls out to Go's WebAssembly bootstrap script will now delete all environment variables except for the ones that esbuild checks for, of which there are currently only four: `NO_COLOR`, `NODE_PATH`, `npm_config_user_agent`, and `WT_SESSION`. This should avoid a crash when esbuild is built using Go 1.17.2+ and should reduce the likelihood of memory corruption when esbuild is built using Go 1.17.1 or earlier. This release also updates the Go version that esbuild ships with to version 1.17.2. Note that this problem only affects the `esbuild-wasm` package. The `esbuild` package is not affected.

See also:

* https://github.com/golang/go/issues/48797
* https://github.com/golang/go/issues/49011

## 0.13.6

* Emit decorators for `declare` class fields ([#1675](https://github.com/evanw/esbuild/issues/1675))
Expand Down
7 changes: 6 additions & 1 deletion Makefile
Expand Up @@ -44,8 +44,13 @@ no-filepath:
@! grep --color --include '*.go' -r '"path/filepath"' cmd internal pkg || ( \
echo 'error: Use of "path/filepath" is disallowed. See http://golang.org/issue/43768.' && false)

# This uses "env -i" to run in a clean environment with no environment
# variables. It then adds some environment variables back as needed.
# This is a hack to avoid a problem with the WebAssembly support in Go
# 1.17.2, which will crash when run in an environment with over 4096
# bytes of environment variable data such as GitHub Actions.
test-wasm-node: esbuild
PATH="$(shell go env GOROOT)/misc/wasm:$$PATH" GOOS=js GOARCH=wasm go test ./internal/...
env -i $(shell go env) PATH="$(shell go env GOROOT)/misc/wasm:$(PATH)" GOOS=js GOARCH=wasm go test ./internal/...
node scripts/wasm-tests.js

test-wasm-browser: platform-wasm | scripts/browser/node_modules
Expand Down
17 changes: 17 additions & 0 deletions npm/esbuild-wasm/bin/esbuild
Expand Up @@ -80,5 +80,22 @@ fs.read = function () {
return read.apply(this, arguments);
};

// WASM code generated with Go 1.17.2+ will crash when run in a situation with
// many environment variables: https://github.com/golang/go/issues/49011. An
// example of this situation is running a Go-compiled WASM executable in GitHub
// Actions. Work around this by filtering node's copy of environment variables
// down to only include the environment variables that esbuild currently uses.
const esbuildUsedEnvVars = [
'NO_COLOR',
'NODE_PATH',
'npm_config_user_agent',
'WT_SESSION',
]
for (let key in process.env) {
if (esbuildUsedEnvVars.indexOf(key) < 0) {
delete process.env[key]
}
}

const argv = ['node', wasm_exec, esbuild_wasm].concat(process.argv.slice(2));
wrapper(require, require.main, Object.assign(Object.create(process), { argv }), Object.assign(Object.create(WebAssembly), { instantiate }));

0 comments on commit ae754ae

Please sign in to comment.