★★★ 收 pi 30ee8ff2: ⑧b **不只是"规格错",它有真实假绿** —— 调用者判定依赖 strip ⇒ source 行里的 ${VAR#…} 被当注释截断 ⇒ **调用者身份丢失** ⇒ 该文件的裸赋值连查都不查(实测 rc=0、调用者数仍 3、三条不变量全过);已改用**词首注释规则**修掉,并把 ⑧b 拆出 **⑧c(可闭,已闭)**
★★ (A) pi 报的假绿(我复现,逐字一致):
`deploy/redeploy-nc.sh`:
. "${REPO#/home}/deploy/lib/env-defaults.sh"
AGENTMAIL_REQUIRE="z" ← 真违规
⇒ 真 strip(`s/#.*$//`)把它截成 `. "${REPO` ⇒ **不再提及 env-defaults.sh**
⇒ 该文件**静默退出调用者集合** ⇒ 裸赋值**不被查** ⇒ rc=**0**,
仍报"3 个调用者,裸赋值 0 处"(z 被漏)
现实形态同样命中(pi 报、我复现): `. "$(dirname "${BASH_SOURCE[0]#/x}")/lib/env-defaults.sh"` ⇒ rc=0
★ 而**三条不变量全过**(首尾探针 / 行号算术 / 逐行局部不变量):
删的首字符**确实**是 `#`、stripped 也**确实**是 raw 的前缀 ⇒ ⑧a 那套形状检查**看不见它**
★ 触发形态本仓已在用(`${VAR#…}`/`${VAR##…}`/`${VAR%…}`):
prune-deploy-artifacts.sh:66、recount-relay-counts.sh:161-165、install.sh:768 等
★ (B) 修法: ① 调用者判定改用**词首注释规则** `sed 's/\(^\|[[:space:]]\)#.*$//'`
—— shell 的真实规则(`#` 只在**词首**才是注释)⇒ 参数展开/引号内的 `#` **不再**被截断
★ 我先试过"用 raw 原文",**它引入假红**(实测):
`. other.sh # 注释里提到 env-defaults.sh` 会被当成调用者
⇒ 所以不能只"去掉 strip",要**把 strip 的规格写对** —— 这是**规格错**,不是"边界"
实测: pi 两例(`${REPO#/home}` / `${BASH_SOURCE[0]#/x}`)**都 rc=1** ✓
反例对照 `. other.sh # 提到 env-defaults.sh` **仍不算调用者**(rc=0、调用者数 3)✓
三个真实调用者全认出、判据自己不误入集合 ✓
★ (C) ⑧b 拆两半(本轮第三格记法):
⑧c **调用者判定**(判"哪一行是 source 行"只用到**行首形态**,与注释后缀无关)⇒ **可闭,已闭**
⑧b **注释语义本身**(strip 对**行内** `${V#x}`/引号内 `#` 的截断会不会让**违规行自己**
不再匹配 `AM_SCAN_RE`)⇒ **真边界**。残余实测: `AGENTMAIL_REQUIRE#="z"` ⇒ strip 成
`AGENTMAIL_REQUIRE` ⇒ 不再匹配 ⇒ rc=0(但该行**本就不是合法赋值**,落在射程边缘);
合法形态 `AGENTMAIL_REQUIRE="${V#x}"` ⇒ 截断后仍匹配 ⇒ rc=1 ✓ 不漏
⇒ ★★★ 记法: **"耦合"本身会被误报成"边界"** —— 我原说"⑧b 是语义边界",
其实里面**掺着一处没必要的耦合**(调用者判定顺手复用了 strip)。
判法: 申报边界前问 **"这个信息真的只能由被检对象给出吗,还是我顺手复用了它?"**
⇒ ⑧a 是"换错观察对象"、⑧c 是"**多余的依赖**" —— 两次都把可闭的说成了边界
★ 回归: 12 向变异矩阵全 rc=1;干净基线 rc=0;criteria-hygiene **10/10** 绿
This commit is contained in:
@ -90,17 +90,42 @@ _scan_text() { _scan_stripped "$(strip_text "$1")"; }
|
||||
callers=""
|
||||
for f in $(find deploy -name '*.sh' -type f | sort); do
|
||||
[ "$f" = "$LIB_REL" ] && continue # 定义点不是调用点(见射程)
|
||||
body="$(strip_text "$(cat "$f")")"
|
||||
case "$body" in
|
||||
# ★★★ 调用者判定**不看 strip 后的文本**(pi `30ee8ff2` 实测的**假绿**,我复现并采纳):
|
||||
# 若 source 行里含 `${VAR#…}` 这类**参数展开**(`#` 不是注释),`strip_text` 会
|
||||
# 从那个 `#` 起把整行截断 ⇒ 行内**不再提及** `env-defaults.sh` ⇒ 该文件**静默退出调用者集合**
|
||||
# ⇒ 它的裸赋值**根本不被查**(连进都没进集合)⇒ **假绿**。实测(`d3c74ec` 的树上):
|
||||
# `deploy/redeploy-nc.sh`:
|
||||
# . "${REPO#/home}/deploy/lib/env-defaults.sh"
|
||||
# AGENTMAIL_REQUIRE="z" ← 真违规
|
||||
# ⇒ rc=**0**,仍报"3 个调用者,裸赋值 0 处"(z 被漏)
|
||||
# 对照: 把 source 行换成 `. "$REPO/deploy/lib/env-defaults.sh"` ⇒ rc=**1** ✓
|
||||
# ★ 而**三条不变量全过**(首尾探针 / 行号算术 / 逐行局部不变量)—— 因为删的首字符
|
||||
# **确实**是 `#`、stripped 也**确实**是 raw 的前缀 ⇒ ⑧a 那套"形状"检查**看不见它**。
|
||||
# ⇒ 修法: 调用者判定改用**词首注释规则**(shell 的真实规则: `#` 只在**词首**才是注释)。
|
||||
# ★ 不能用"raw 原文"了事: 我实测过 raw 版会把
|
||||
# `. other.sh # 注释里提到 env-defaults.sh`
|
||||
# 当成调用者 ⇒ **假红**(安全方向,但仍是错的)。
|
||||
# 也不能用 `strip_text`(它是 `s/#.*$//`,正是被 pi 抓到的那个错)。
|
||||
# ⇒ 用 `_caller_strip`: 只在 `#` 位于**行首或空白之后**时才截断 ⇒
|
||||
# `${REPO#/home}` / `${BASH_SOURCE[0]#/x}` / `X="a#b"` **都不被截断** ✓
|
||||
# 而 `foo.sh # 提到 env-defaults.sh` **被截断**(不误判,无假红)✓
|
||||
# 整行注释 `# . env-defaults.sh` ⇒ 截成空 ⇒ 不匹配 ✓
|
||||
# ★ 这不是"换一个实现",是**把注释的规格写对**: 原 `s/#.*$//` 把
|
||||
# "参数展开/引号内的 `#`"也当成了注释 —— 那是**规格错**,不是"边界"。
|
||||
# ⚠️ 射程(本处**只**修调用者判定这一半): 正式违规扫描仍走 `strip_text`
|
||||
# (`s/#.*$//`)⇒ 若某**违规行**本身含 `${VAR#…}` 且截断后不再匹配 `AM_SCAN_RE`,
|
||||
# 那仍会漏(属 ⑧b 的**语义**半,真边界)—— 本处**不**声称那半已闭。
|
||||
_ftext="$(sed 's/\(^\|[[:space:]]\)#.*$//' "$f")"
|
||||
case "$_ftext" in
|
||||
*env-defaults.sh*)
|
||||
# 无管道匹配:`grep` 读文件而非读管道 ⇒ 不会因 SIGPIPE 造出不稳定的 rc。
|
||||
if grep -qE '^[[:space:]]*(\.|source)[[:space:]].*env-defaults\.sh' <<< "$body"; then
|
||||
# 无管道匹配(`<<<` here-string):不会因 SIGPIPE 造出不稳定的 rc。
|
||||
if grep -qE '^[[:space:]]*(\.|source)[[:space:]].*env-defaults\.sh' <<< "$_ftext"; then
|
||||
callers="$callers $f"
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
done
|
||||
unset body
|
||||
unset _ftext
|
||||
# shellcheck disable=SC2086
|
||||
set -- $callers
|
||||
n_callers=$#
|
||||
@ -385,4 +410,29 @@ exit 0
|
||||
# ★ 我上轮就是**拿语义的循环性去论证形状那半也不可闭**,于是**多申报了一个边界**。
|
||||
# ⚠️ 与 ⑤ 的关系: ⑤ 也是"我把可闭的误判成边界"(拿"同一次观察的后退"当理由)——
|
||||
# ⑧a 与 ⑤ 是**同一类错误**(论证里的"循环/后退"其实不成立),⑧b 才与 ⑥⑦ 同级。
|
||||
# ⑧c ★★★ **⑧b 还要再拆一半**(pi `30ee8ff2` 实测的**假绿**,我复现后已修 —— 见 ① 调用者判定):
|
||||
# pi 指出 ⑧b 不只是"规格本身错"(无害),它有一条**真实可达的假绿**:
|
||||
# 当"不该当注释的 `#`"出现在**唯一那处 `env-defaults.sh` 提及之前**时,
|
||||
# 整行 strip 后**不再提及** env-defaults.sh ⇒ **调用者身份丢失** ⇒ 该文件被跳过
|
||||
# ⇒ 它的裸赋值**连查都不查**(不是漏判,是**根本没进集合**)⇒ **假绿**。
|
||||
# 实测(`d3c74ec` 的树上,我复现): `deploy/redeploy-nc.sh`
|
||||
# `. "${REPO#/home}/deploy/lib/env-defaults.sh"` + `AGENTMAIL_REQUIRE="z"` ⇒ rc=**0**
|
||||
# 现实形态同样命中: `. "$(dirname "${BASH_SOURCE[0]#/x}")/lib/env-defaults.sh"` ⇒ rc=**0**
|
||||
# ★ 而**三条不变量全过**(首尾探针/行号算术/逐行局部不变量)—— 因为删的首字符
|
||||
# **确实**是 `#`、stripped 也**确实**是前缀 ⇒ ⑧a 那套"形状"检查**看不见它**。
|
||||
# ⇒ ★ 已修(① 调用者判定改用**词首注释规则** `s/\(^\|[[:space:]]\)#.*$//`):
|
||||
# 参数展开 `#` / 引号内 `#` **不再**被当注释 ⇒ 调用者不再丢失 ⇒ 上面两例都 rc=**1** ✓
|
||||
# 且**不引入假红**: `foo.sh # 注释里提到 env-defaults.sh` **仍不算调用者** ✓
|
||||
# ⇒ ★★ 于是 ⑧b 拆两半:
|
||||
# ⑧c **调用者判定**(判"哪一行是 source 行"只用到**行首形态**,与注释后缀无关)
|
||||
# ⇒ **可闭**(已闭)—— 我原先把"strip 的实现"与"调用者判定"**耦合**在一起
|
||||
# ⑧b **注释语义本身**(strip 对**行内**`${V#x}` / 引号内 `#` 的截断会不会
|
||||
# 让**违规行自己**不再匹配 `AM_SCAN_RE`)⇒ **真边界**
|
||||
# 实测残余: `AGENTMAIL_REQUIRE#="z"` 被 strip 成 `AGENTMAIL_REQUIRE` ⇒ 不再匹配 ⇒ rc=0
|
||||
# (但这行**本来就不是合法赋值** ⇒ 落在射程边缘;合法形态 `AGENTMAIL_REQUIRE="${V#x}"`
|
||||
# 截断后仍是 `AGENTMAIL_REQUIRE="${V` ⇒ **仍匹配** ⇒ rc=1 ✓ 不漏)
|
||||
# ⇒ ★★★ 记法(本轮第三格): **"耦合"本身会被误报成"边界"** ——
|
||||
# 我原来说"⑧b 是语义边界",其实里面**掺着一处没必要的耦合**(调用者判定依赖 strip)。
|
||||
# 判法: 申报边界前问一句 **"这个信息真的只能由被检对象给出吗,还是我顺手复用了它?"**
|
||||
# ⇒ ⑧a 是"换错观察对象"、⑧c 是"**多余的依赖**" —— 两次都把可闭的说成了边界。
|
||||
# ══════════════════════════════════════════════════════════════════════════════
|
||||
|
||||
Reference in New Issue
Block a user