结论:wasm blocker 分析器现在与 manifest 输入校验一致拒绝缺少 note 或字段数量异常的坏行,并在 blocker self-check 中覆盖该负向路径;未扩展 smoke 功能。
235 lines
12 KiB
Bash
Executable File
235 lines
12 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
set -euo pipefail
|
|
|
|
cd "$(dirname "$0")"
|
|
|
|
# LinuxCNC source basis: this guardrail locks the blocker categories reported
|
|
# by analyze-linuxcnc-wasm-blockers.sh for the RS274/WASM manifest. The locked
|
|
# groups cover LinuxCNC Python/Boost.Python module bindings, tooldata mmap,
|
|
# dlopen use, and native filesystem calls found in src/emc/rs274ngc and
|
|
# src/emc/tooldata.
|
|
manifest=${1:-linuxcnc-rs274-wasm-source-files.txt}
|
|
self_checks=${CNC_SIM_WASM_BLOCKERS_SELF_CHECKS:-0}
|
|
if [[ "$self_checks" != "0" && "$self_checks" != "1" ]]; then
|
|
echo "CNC_SIM_WASM_BLOCKERS_SELF_CHECKS must be 0 or 1: $self_checks" >&2
|
|
exit 1
|
|
fi
|
|
linuxcnc_root=${LINUXCNC_ROOT:-../linuxcnc}
|
|
cache_dir=${CNC_SIM_WASM_BLOCKERS_CACHE_DIR-${CNC_SIM_PREFLIGHT_CACHE_DIR:-build/wasm-blocker-cache}}
|
|
if [[ -z "$cache_dir" ]]; then
|
|
echo "CNC_SIM_WASM_BLOCKERS_CACHE_DIR must not be empty" >&2
|
|
exit 1
|
|
fi
|
|
if [[ "$cache_dir" =~ [[:space:]] ]]; then
|
|
echo "CNC_SIM_WASM_BLOCKERS_CACHE_DIR must not contain whitespace: $cache_dir" >&2
|
|
exit 1
|
|
fi
|
|
mkdir -p "$cache_dir"
|
|
cache_dir=$(cd "$cache_dir" && pwd)
|
|
if [[ "$cache_dir" == "/" ]]; then
|
|
echo "CNC_SIM_WASM_BLOCKERS_CACHE_DIR must not be the filesystem root" >&2
|
|
exit 1
|
|
fi
|
|
LINUXCNC_ROOT="$linuxcnc_root" ./check-linuxcnc-inputs-cached.sh --cache-dir "$cache_dir/preflight" "$manifest"
|
|
manifest=$(cd "$(dirname "$manifest")" && pwd)/$(basename "$manifest")
|
|
linuxcnc_root=$(cd "$linuxcnc_root" && pwd)
|
|
|
|
if [[ "$self_checks" == "1" ]]; then
|
|
|
|
missing_manifest=${TMPDIR:-/tmp}/cnc_sim_missing_wasm_blocker_manifest.txt
|
|
missing_manifest_log=$(mktemp "${TMPDIR:-/tmp}/cnc_sim_missing_wasm_blocker_manifest.XXXXXX.log")
|
|
missing_root_log=$(mktemp "${TMPDIR:-/tmp}/cnc_sim_wasm_blocker_missing_root.XXXXXX.log")
|
|
missing_source_manifest=$(mktemp "${TMPDIR:-/tmp}/cnc_sim_missing_wasm_blocker_manifest_source.XXXXXX.txt")
|
|
missing_source_log=$(mktemp "${TMPDIR:-/tmp}/cnc_sim_missing_wasm_blocker_manifest_source.XXXXXX.log")
|
|
duplicate_manifest=$(mktemp "${TMPDIR:-/tmp}/cnc_sim_duplicate_wasm_blocker_manifest.XXXXXX.txt")
|
|
duplicate_manifest_log=$(mktemp "${TMPDIR:-/tmp}/cnc_sim_duplicate_wasm_blocker_manifest.XXXXXX.log")
|
|
bad_line_manifest=$(mktemp "${TMPDIR:-/tmp}/cnc_sim_bad_wasm_blocker_manifest_line.XXXXXX.txt")
|
|
bad_line_log=$(mktemp "${TMPDIR:-/tmp}/cnc_sim_bad_wasm_blocker_manifest_line.XXXXXX.log")
|
|
missing_replacement_manifest=$(mktemp "${TMPDIR:-/tmp}/cnc_sim_missing_wasm_blocked_replacement.XXXXXX.txt")
|
|
missing_replacement_log=$(mktemp "${TMPDIR:-/tmp}/cnc_sim_missing_wasm_blocked_replacement.XXXXXX.log")
|
|
trap 'rm -f "$missing_manifest" "$missing_manifest_log" "$missing_root_log" "$missing_source_manifest" "$missing_source_log" "$duplicate_manifest" "$duplicate_manifest_log" "$bad_line_manifest" "$bad_line_log" "$missing_replacement_manifest" "$missing_replacement_log"' EXIT
|
|
if ! awk '
|
|
/^trap '\''rm -f "\$missing_manifest" "\$missing_manifest_log" "\$missing_root_log" "\$missing_source_manifest" "\$missing_source_log" "\$duplicate_manifest" "\$duplicate_manifest_log" "\$bad_line_manifest" "\$bad_line_log" "\$missing_replacement_manifest" "\$missing_replacement_log"'\'' EXIT$/ { found_trap = 1 }
|
|
END { exit !found_trap }
|
|
' test-linuxcnc-wasm-blockers.sh; then
|
|
echo "wasm blocker scan cleanup trap no longer covers fixed blocker temporaries" >&2
|
|
exit 1
|
|
fi
|
|
if awk '/^rm -f "\$missing_source_manifest" "\$missing_source_log"$/{ found = 1 } END { exit !found }' test-linuxcnc-wasm-blockers.sh >/dev/null; then
|
|
echo "wasm blocker scan still relies on manual cleanup for missing-source temporaries" >&2
|
|
exit 1
|
|
fi
|
|
|
|
rm -f "$missing_manifest"
|
|
if ./analyze-linuxcnc-wasm-blockers.sh "$missing_manifest" >"$missing_manifest_log" 2>&1; then
|
|
echo "wasm blocker analyzer accepted missing manifest: $missing_manifest" >&2
|
|
exit 1
|
|
fi
|
|
if ! grep -F "missing manifest: $missing_manifest" "$missing_manifest_log" >/dev/null; then
|
|
echo "wasm blocker analyzer did not report missing manifest clearly" >&2
|
|
sed -n '1,20p' "$missing_manifest_log" >&2
|
|
exit 1
|
|
fi
|
|
|
|
missing_root=/tmp/does-not-exist-linuxcnc
|
|
if LINUXCNC_ROOT="$missing_root" ./analyze-linuxcnc-wasm-blockers.sh "$manifest" >"$missing_root_log" 2>&1; then
|
|
echo "wasm blocker analyzer accepted missing LinuxCNC root" >&2
|
|
exit 1
|
|
fi
|
|
if ! grep -F "missing LinuxCNC root: $missing_root" "$missing_root_log" >/dev/null; then
|
|
echo "wasm blocker analyzer did not report missing LinuxCNC root clearly" >&2
|
|
sed -n '1,20p' "$missing_root_log" >&2
|
|
exit 1
|
|
fi
|
|
|
|
printf 'blocked:src/emc/tooldata/does_not_exist.cc:test missing blocked source\n' >"$missing_source_manifest"
|
|
if ./analyze-linuxcnc-wasm-blockers.sh "$missing_source_manifest" >"$missing_source_log" 2>&1; then
|
|
echo "wasm blocker analyzer accepted missing manifest source" >&2
|
|
exit 1
|
|
fi
|
|
if ! grep -F "missing manifest source: src/emc/tooldata/does_not_exist.cc" "$missing_source_log" >/dev/null; then
|
|
echo "wasm blocker analyzer did not report missing manifest source clearly" >&2
|
|
sed -n '1,20p' "$missing_source_log" >&2
|
|
exit 1
|
|
fi
|
|
|
|
cat >"$duplicate_manifest" <<'EOF'
|
|
core:src/emc/rs274ngc/interp_arc.cc:duplicate core entry
|
|
core:src/emc/rs274ngc/interp_arc.cc:duplicate core entry
|
|
blocked:src/emc/tooldata/tooldata_mmap.cc:blocked entry
|
|
EOF
|
|
if ./analyze-linuxcnc-wasm-blockers.sh "$duplicate_manifest" >"$duplicate_manifest_log" 2>&1; then
|
|
echo "wasm blocker analyzer accepted duplicate manifest source" >&2
|
|
exit 1
|
|
fi
|
|
if ! grep -F "duplicate manifest source: src/emc/rs274ngc/interp_arc.cc" "$duplicate_manifest_log" >/dev/null; then
|
|
echo "wasm blocker analyzer did not report duplicate manifest source clearly" >&2
|
|
sed -n '1,20p' "$duplicate_manifest_log" >&2
|
|
exit 1
|
|
fi
|
|
|
|
printf 'core:src/emc/rs274ngc/interp_arc.cc\n' >"$bad_line_manifest"
|
|
if ./analyze-linuxcnc-wasm-blockers.sh "$bad_line_manifest" >"$bad_line_log" 2>&1; then
|
|
echo "wasm blocker analyzer accepted bad manifest line" >&2
|
|
exit 1
|
|
fi
|
|
if ! grep -F "bad manifest line 1: core:src/emc/rs274ngc/interp_arc.cc" "$bad_line_log" >/dev/null; then
|
|
echo "wasm blocker analyzer did not report bad manifest line clearly" >&2
|
|
sed -n '1,20p' "$bad_line_log" >&2
|
|
exit 1
|
|
fi
|
|
|
|
cat >"$missing_replacement_manifest" <<'EOF'
|
|
core:src/emc/rs274ngc/interp_arc.cc:core entry
|
|
blocked:src/emc/tooldata/tooldata_db.cc:blocked entry without wasm replacement
|
|
EOF
|
|
if ./analyze-linuxcnc-wasm-blockers.sh "$missing_replacement_manifest" >"$missing_replacement_log" 2>&1; then
|
|
echo "wasm blocker analyzer accepted blocked source without replacement mapping" >&2
|
|
exit 1
|
|
fi
|
|
if ! grep -F "missing blocked replacement mapping: src/emc/tooldata/tooldata_db.cc" "$missing_replacement_log" >/dev/null; then
|
|
echo "wasm blocker analyzer did not report missing replacement mapping clearly" >&2
|
|
sed -n '1,20p' "$missing_replacement_log" >&2
|
|
exit 1
|
|
fi
|
|
|
|
fi
|
|
|
|
manifest_key=$(printf '%s' "$manifest" | sha256sum | awk '{ print $1 }')
|
|
exec 8>"$cache_dir/wasm-blockers.lock"
|
|
flock 8
|
|
cache_signature="$cache_dir/wasm-blockers.${manifest_key}.signature"
|
|
cache_output="$cache_dir/wasm-blockers.${manifest_key}.out"
|
|
next_signature="$cache_signature.next"
|
|
write_manifest_source_stats() {
|
|
local group path note source_path
|
|
while IFS=: read -r group path note; do
|
|
case "$group" in
|
|
""|\#*)
|
|
continue
|
|
;;
|
|
esac
|
|
[[ -z "${path:-}" ]] && continue
|
|
source_path="$linuxcnc_root/$path"
|
|
[[ -f "$source_path" ]] || return 1
|
|
stat -c 'SOURCE=%n:%s:%y' "$source_path"
|
|
done < "$manifest"
|
|
}
|
|
write_shim_source_hashes() {
|
|
local shim_source
|
|
while IFS= read -r shim_source; do
|
|
[[ -n "$shim_source" ]] || continue
|
|
[[ -f "$shim_source" ]] || return 1
|
|
sha256sum "$shim_source"
|
|
done < <(./list-linuxcnc-wasm-safe-shims.sh)
|
|
}
|
|
{
|
|
printf 'BLOCKER_SCRIPT='
|
|
sha256sum test-linuxcnc-wasm-blockers.sh
|
|
printf 'ANALYZER='
|
|
sha256sum analyze-linuxcnc-wasm-blockers.sh
|
|
printf 'SHIM_LISTER='
|
|
sha256sum list-linuxcnc-wasm-safe-shims.sh
|
|
printf 'MANIFEST_PATH=%s\n' "$manifest"
|
|
printf 'MANIFEST='
|
|
sha256sum "$manifest"
|
|
printf 'LINUXCNC_ROOT=%s\n' "$linuxcnc_root"
|
|
write_manifest_source_stats
|
|
write_shim_source_hashes
|
|
} > "$next_signature"
|
|
if [[ -f "$cache_signature" && -f "$cache_output" ]] && cmp -s "$cache_signature" "$next_signature"; then
|
|
output=$(cat "$cache_output")
|
|
rm -f "$next_signature"
|
|
else
|
|
output=$(CNC_SIM_PREFLIGHT_CACHE_DIR="$cache_dir/preflight" LINUXCNC_ROOT="$linuxcnc_root" ./analyze-linuxcnc-wasm-blockers.sh "$manifest")
|
|
printf '%s\n' "$output" > "$cache_output"
|
|
mv "$next_signature" "$cache_signature"
|
|
fi
|
|
|
|
grep -F "[manifest]" <<<"$output" >/dev/null
|
|
grep -F "core=26" <<<"$(sed -n '/^\[manifest\]/,/^$/p' <<<"$output")" >/dev/null
|
|
grep -F "blocked=9" <<<"$(sed -n '/^\[manifest\]/,/^$/p' <<<"$output")" >/dev/null
|
|
grep -F "[python]" <<<"$output" >/dev/null
|
|
grep -F "src/emc/rs274ngc/canonmodule.cc" <<<"$(sed -n '/^\[python\]/,/^$/p' <<<"$output")" >/dev/null
|
|
grep -F "src/emc/rs274ngc/gcodemodule.cc" <<<"$(sed -n '/^\[python\]/,/^$/p' <<<"$output")" >/dev/null
|
|
grep -F "src/emc/rs274ngc/interpmodule.cc" <<<"$(sed -n '/^\[python\]/,/^$/p' <<<"$output")" >/dev/null
|
|
grep -F "src/emc/rs274ngc/pyarrays.cc" <<<"$(sed -n '/^\[python\]/,/^$/p' <<<"$output")" >/dev/null
|
|
grep -F "src/emc/rs274ngc/pyparamclass.cc" <<<"$(sed -n '/^\[python\]/,/^$/p' <<<"$output")" >/dev/null
|
|
grep -F "[dlopen]" <<<"$output" >/dev/null
|
|
grep -F "(none)" <<<"$(sed -n '/^\[dlopen\]/,/^$/p' <<<"$output")" >/dev/null
|
|
grep -F "[tooldata]" <<<"$output" >/dev/null
|
|
grep -F "src/emc/tooldata/tooldata_mmap.cc" <<<"$output" >/dev/null
|
|
grep -F "[tooldata-users]" <<<"$output" >/dev/null
|
|
grep -F "(none)" <<<"$(sed -n '/^\[tooldata-users\]/,/^$/p' <<<"$output")" >/dev/null
|
|
grep -F "[native-backend]" <<<"$output" >/dev/null
|
|
grep -F "src/emc/tooldata/tooldata_mmap.cc" <<<"$(sed -n '/^\[native-backend\]/,/^$/p' <<<"$output")" >/dev/null
|
|
grep -F "[native-fs]" <<<"$output" >/dev/null
|
|
grep -F "src/emc/tooldata/tooldata_mmap.cc" <<<"$(sed -n '/^\[native-fs\]/,/^$/p' <<<"$output")" >/dev/null
|
|
grep -F "[blocked-replacements]" <<<"$output" >/dev/null
|
|
grep -F "src/emc/tooldata/tooldata_mmap.cc -> core/wasm_shims/tooldata/tooldata_mmap_backend.cc" \
|
|
<<<"$(sed -n '/^\[blocked-replacements\]/,/^$/p' <<<"$output")" >/dev/null
|
|
grep -F "src/emc/rs274ngc/canonmodule.cc -> core/wasm_shims/linuxcnc_runtime_shim.cc" \
|
|
<<<"$(sed -n '/^\[blocked-replacements\]/,/^$/p' <<<"$output")" >/dev/null
|
|
grep -F "src/emc/rs274ngc/interpmodule.cc -> core/wasm_shims/linuxcnc_runtime_shim.cc" \
|
|
<<<"$(sed -n '/^\[blocked-replacements\]/,/^$/p' <<<"$output")" >/dev/null
|
|
grep -F "src/emc/rs274ngc/pyarrays.cc -> core/wasm_shims/python_c_api_shim.cc" \
|
|
<<<"$(sed -n '/^\[blocked-replacements\]/,/^$/p' <<<"$output")" >/dev/null
|
|
grep -F "src/emc/rs274ngc/pyparamclass.cc -> core/wasm_shims/python_c_api_shim.cc" \
|
|
<<<"$(sed -n '/^\[blocked-replacements\]/,/^$/p' <<<"$output")" >/dev/null
|
|
grep -F 'blocked replacement is not in wasm shim build set' analyze-linuxcnc-wasm-blockers.sh >/dev/null
|
|
grep -F 'wasm_safe_shim_in_build "$replacement"' analyze-linuxcnc-wasm-blockers.sh >/dev/null
|
|
grep -F 'shim_source_output=$(./list-linuxcnc-wasm-safe-shims.sh)' analyze-linuxcnc-wasm-blockers.sh >/dev/null
|
|
grep -F "[core-python-shimmed]" <<<"$output" >/dev/null
|
|
grep -F "src/emc/rs274ngc/interp_python.cc" <<<"$(sed -n '/^\[core-python-shimmed\]/,/^$/p' <<<"$output")" >/dev/null
|
|
grep -F "src/emc/rs274ngc/rs274ngc_pre.cc" <<<"$(sed -n '/^\[core-python-shimmed\]/,/^$/p' <<<"$output")" >/dev/null
|
|
grep -F "[core-dlopen-shimmed]" <<<"$output" >/dev/null
|
|
grep -F "src/emc/rs274ngc/interp_base.cc" <<<"$(sed -n '/^\[core-dlopen-shimmed\]/,/^$/p' <<<"$output")" >/dev/null
|
|
grep -F "[core-tooldata-shimmed]" <<<"$output" >/dev/null
|
|
grep -F "src/emc/tooldata/tooldata_common.cc" <<<"$(sed -n '/^\[core-tooldata-shimmed\]/,/^$/p' <<<"$output")" >/dev/null
|
|
grep -F "[core-tooldata-users-shimmed]" <<<"$output" >/dev/null
|
|
grep -F "src/emc/rs274ngc/interp_find.cc" <<<"$(sed -n '/^\[core-tooldata-users-shimmed\]/,/^$/p' <<<"$output")" >/dev/null
|
|
grep -F "[core-native-fs-shimmed]" <<<"$output" >/dev/null
|
|
grep -F "src/emc/rs274ngc/interp_o_word.cc" <<<"$(sed -n '/^\[core-native-fs-shimmed\]/,/^$/p' <<<"$output")" >/dev/null
|
|
|
|
echo "linuxcnc wasm blocker scan passed"
|