Merge pull request #3181 from tree-sitter/handle-wasm-oom

When loading languages via WASM, gracefully handle memory errors and leaks in external scanners
This commit is contained in:
Max Brunsfeld 2024-03-18 13:15:06 -07:00 committed by GitHub
commit 09b18fad5b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
13 changed files with 1895 additions and 2463 deletions

View file

@ -2,27 +2,33 @@
set -e
# Remove quotes, add leading underscores, remove newlines, remove trailing comma.
# Remove quotes and commas
EXPORTED_FUNCTIONS=$( \
cat lib/src/wasm/stdlib-symbols.txt | \
sed -e 's/"//g' | \
sed -e 's/^/_/g' | \
tr -d '\n"' | \
sed -e 's/,$//' \
tr -d ',"' \
)
emcc \
-o stdlib.wasm \
-Os \
--no-entry \
-s MAIN_MODULE=2 \
-s "EXPORTED_FUNCTIONS=${EXPORTED_FUNCTIONS}" \
-s 'ALLOW_MEMORY_GROWTH' \
-s 'TOTAL_MEMORY=4MB' \
-fvisibility=hidden \
-fno-exceptions \
-xc \
/dev/null
EXPORT_FLAGS=""
for function in ${EXPORTED_FUNCTIONS}; do
EXPORT_FLAGS+=" -Wl,--export=${function}"
done
target/wasi-sdk-21.0/bin/clang-17 \
-o stdlib.wasm \
-Os \
-fPIC \
-Wl,--no-entry \
-Wl,--stack-first \
-Wl,-z -Wl,stack-size=65536 \
-Wl,--import-undefined \
-Wl,--import-memory \
-Wl,--import-table \
-Wl,--strip-debug \
-Wl,--export=reset_heap \
-Wl,--export=__wasm_call_ctors \
-Wl,--export=__stack_pointer \
${EXPORT_FLAGS} \
lib/src/wasm/stdlib.c
xxd -C -i stdlib.wasm > lib/src/wasm/wasm-stdlib.h
mv stdlib.wasm target/

View file

@ -12,7 +12,7 @@ OPTIONS
-h Print this message
-a Compile C code with the Clang static analyzer
-a Compile C code with the Clang address sanitizer
-e Run only the corpus tests whose name contain the given string
@ -41,9 +41,17 @@ while getopts "adDghl:e:s:i:" option; do
exit
;;
a)
export RUSTFLAGS="-Z sanitizer=address"
# Specify a `--target` explicitly. For some reason, this is required for
# address sanitizer support.
export CFLAGS="-fsanitize=undefined,address"
# When the Tree-sitter C library is compiled with the address sanitizer, the address sanitizer
# runtime library needs to be linked into the final test executable. When using Xcode clang,
# the Rust linker doesn't know where to find that library, so we need to specify linker flags directly.
runtime_dir=$(cc -print-runtime-dir)
if [[ $runtime_dir == */Xcode.app/* ]]; then
export RUSTFLAGS="-C link-arg=-L${runtime_dir} -C link-arg=-lclang_rt.asan_osx_dynamic -C link-arg=-Wl,-rpath,${runtime_dir}"
fi
# Specify a `--target` explicitly. This is required for address sanitizer support.
toolchain=$(rustup show active-toolchain)
toolchain_regex='(stable|beta|nightly)-([_a-z0-9-]+).*'
if [[ $toolchain =~ $toolchain_regex ]]; then
@ -52,7 +60,8 @@ while getopts "adDghl:e:s:i:" option; do
else
echo "Failed to parse toolchain '${toolchain}'"
fi
test_flags="${test_flags} --target ${current_target}"
test_flags+=" --target ${current_target}"
;;
e)
export TREE_SITTER_EXAMPLE=${OPTARG}