250 líneas de comentario en 151 scripts. Control verificado: el diff no toca NI UNA línea que no empiece por #, y la sintaxis de los 151 pasa. El barrido saltea heredocs y cadenas triples, y el guardián DISPARÓ 3 veces: las tres eran el MOTD que el script escribe DENTRO de la imagen construida — texto del producto, no comentario del script. Se cambiaron aparte y a propósito, que es rebranding, no limpieza. Y el hallazgo caro: casaba contra , que es el TARGET de tracing — o sea el module_path!, o sea el nombre del crate. La etapa 4 lo movió a y el script quedó casando NADA. No fallaba: imprimía cero atribuciones, indistinguible de un log sin problemas. Comprobado con el binario (RUST_LOG=info sobre zlib), no deducido. Ahora acepta las dos, y tiene que seguir aceptándolas porque los logs viejos en disco dicen la vieja. Además 14 rutas de módulo en docs, que el barrido anterior no tocó porque no es frontera de palabra.
101 lines
4.3 KiB
Bash
Executable File
101 lines
4.3 KiB
Bash
Executable File
#!/usr/bin/env sh
|
|
# test-guardianes-wasm.sh — le pone delante a los guardianes de la cadena wasm las formas conocidas
|
|
# de romperla y exige que las maten. Y corre un CONTROL con el sysroot intacto que tiene que PASAR.
|
|
#
|
|
# POR QUÉ EXISTE. Un guardián que nunca falló no se sabe si sirve, y uno que falla SIEMPRE se ve
|
|
# idéntico a uno que funciona: por eso el control no es un extra, es la mitad de la prueba. El
|
|
# método lo aportó la sesión takana-f8 (su scripts/test-atuq-politica.py hace lo mismo con el cruce
|
|
# política↔XPI).
|
|
#
|
|
# NO CONSTRUYE NADA, NO TOMA EL LOCK Y NO ESCRIBE EN EL STORE: trabaja sobre copias temporales de
|
|
# artefactos ya sellados, así que se puede correr con la granja a pleno.
|
|
#
|
|
# ./scripts/test-guardianes-wasm.sh [--store DIR]
|
|
set -u
|
|
STORE="./store"
|
|
[ "${1:-}" = "--store" ] && STORE="$2"
|
|
LAB="./.dev-fs/alpine"
|
|
TMP="${TMPDIR:-/tmp}/guardianes-wasm.$$"
|
|
ok=0; mal=0
|
|
|
|
di() { printf '%s\n' "$*"; }
|
|
fin() { rm -rf "$TMP"; }
|
|
trap fin EXIT
|
|
|
|
# ⚠ EL ARTEFACTO SE RESUELVE POR EL HASH DE LA RECETA, NUNCA POR GLOB. La primera versión de este
|
|
# script hacía `ls -d "$STORE"/*-wasi-libcxx | head -1` y agarró el artefacto VIEJO —el de antes de
|
|
# que la receta creara el directorio-sonda— así que el CONTROL falló y los cuatro sabotajes
|
|
# "pasaron". Es la misma trampa que el cache-hit que congela regresiones: un artefacto anterior se
|
|
# hace pasar por el actual y la prueba mide otra cosa. Y es, además, la demostración de para qué
|
|
# sirve el control: sin él eso se habría leído como "4 en verde, guardianes ok".
|
|
art() {
|
|
h=$(./target/release/takana --store "$STORE" hash "recipes/$1.toml" 2>/dev/null | tail -1)
|
|
h=${h#b3:}
|
|
[ -n "$h" ] && [ -d "$STORE/$h-$1" ] && printf '%s' "$STORE/$h-$1"
|
|
}
|
|
libc=$(art wasi-libc)
|
|
cxx=$(art wasi-libcxx)
|
|
[ -n "$libc" ] && [ -n "$cxx" ] || { di "el store no tiene el artefacto VIGENTE de wasi-libc/wasi-libcxx (¿sin construir?) — nada que probar"; exit 77; }
|
|
di "artefactos vigentes: $(basename "$libc" | cut -c1-12)… / $(basename "$cxx" | cut -c1-12)…"
|
|
[ -d "$LAB" ] || { di "sin lab en $LAB"; exit 77; }
|
|
|
|
# Arma un sysroot fusionado como el que ve firefox, y le aplica el sabotaje que se le pida.
|
|
armar() {
|
|
rm -rf "$TMP/s"; mkdir -p "$TMP/s"
|
|
cp -a "$libc"/usr/share/wasi-sysroot/. "$TMP/s"/
|
|
cp -a "$cxx"/usr/share/wasi-sysroot/. "$TMP/s"/
|
|
case "${1:-}" in
|
|
sin-sonda) rm -rf "$TMP/s/include/c++/v1" ;;
|
|
sin-libcxx) rm -f "$TMP/s"/lib/*/libc++.a ;;
|
|
sin-libc) rm -f "$TMP/s"/lib/*/libc.a ;;
|
|
sin-cstring) find "$TMP/s/include" -name cstring -delete ;;
|
|
intacto) : ;;
|
|
esac
|
|
}
|
|
|
|
# La prueba EXACTA que hace el configure de firefox, dentro del lab.
|
|
probar_cxx() {
|
|
bwrap --overlay-src "$LAB" --tmp-overlay / --proc /proc --dev /dev --tmpfs /tmp \
|
|
--ro-bind "$TMP/s" /sysroot --unshare-all --die-with-parent \
|
|
/bin/sh -c 'echo "#include <cstring>" > /tmp/p.cpp
|
|
clang++ -std=gnu++20 --target=wasm32-wasip1 /tmp/p.cpp --sysroot=/sysroot -c -o /tmp/p.o' \
|
|
>/dev/null 2>&1
|
|
}
|
|
|
|
# --- EL CONTROL. Va PRIMERO a propósito: si esto no pasa, los demás resultados no significan nada,
|
|
# porque un guardián que mata todo se ve igual que uno que discrimina.
|
|
armar intacto
|
|
if probar_cxx; then
|
|
di "✓ CONTROL sysroot intacto -> compila (el guardián NO es un «mata siempre»)"; ok=$((ok+1))
|
|
else
|
|
di "✗ CONTROL sysroot intacto -> NO compila. El resto de esta prueba no vale nada."; mal=$((mal+1))
|
|
fi
|
|
|
|
# --- LOS SABOTAJES. Cada uno es una forma conocida de romper la cadena; todos tienen que matar.
|
|
for caso in sin-sonda sin-cstring; do
|
|
armar "$caso"
|
|
if probar_cxx; then
|
|
di "✗ SABOTAJE $caso -> compiló igual. El guardián NO cubre este caso."; mal=$((mal+1))
|
|
else
|
|
di "✓ SABOTAJE $caso -> muere, como debe"; ok=$((ok+1))
|
|
fi
|
|
done
|
|
|
|
# --- Los de presencia pura, que son los que el caso `sin-sonda` demostró insuficientes por sí solos.
|
|
for caso in sin-libcxx sin-libc; do
|
|
armar "$caso"
|
|
falta=0
|
|
for t in wasm32-wasip1 wasm32-wasip1-threads; do
|
|
[ -s "$TMP/s/lib/$t/libc++.a" ] && [ -s "$TMP/s/lib/$t/libc.a" ] || falta=1
|
|
done
|
|
if [ "$falta" = 1 ]; then
|
|
di "✓ SABOTAJE $caso -> el test de presencia lo caza"; ok=$((ok+1))
|
|
else
|
|
di "✗ SABOTAJE $caso -> el test de presencia NO lo caza"; mal=$((mal+1))
|
|
fi
|
|
done
|
|
|
|
di ""
|
|
di "resumen: $ok en verde, $mal en rojo"
|
|
[ "$mal" = 0 ] || exit 1
|