fix(core): 行尾句读不再让真 token 整串落盘(M243 BEARERDOT)
`Bearer <JWT>.`(行尾一个英文句点)整串原样落盘:句点自己属于 dotted 字符集,
扫描器把它算进 run 后 `split('.')` 多切出一个空段,「每段 ≥8」当场不成立。
M240 实测 old == new == 原文,影响 core 的全部落盘/展示面。
修法不是抬阈值:`shape::split_trailing_punct` 在判定前把末尾句读(`.` `,` `;` `)`)
切出去,`push_dotted` 再把句读原位写回——占位符只吃 token 本体,句子标点一个不丢。
只有 `.` 会进入字符集,其余三个本来就在外面,列全是为了「句读不参与判定」只有一处出处。
`has_dotted_token` 的闸门同步改成看同一份切分结果,否则闸门关着就静默不抹。
判据:`tests/bearerdot.rs` 三组——四种形状(`Bearer <JWT>.` / `… <JWT>. then` /
`<JWT>,` / `(<JWT>)`)必须抹且标点保留;句点结尾的普通文本(`Service.Unavailable.today.`)
必须逐字原样;两个入口在带句读的输入上必须一致。语料 68 文件 / 243 行仍 0 行被改,
JWT/sha256/base64 正例仍被抹。变异自证:把 trim 改回旧行为 → 主判据红(EXIT=101)。
外层两个既有红(diagnose::session / presenter m241 夹具)是 M240 收窄后的口径冲突,
stash 回 main HEAD 可复现,已各 file 一条 finding,不在本轮修。
This commit is contained in:
1 parent
ea108c5fc4
commit
cc90c64b84
4 files changed
+140
-4
No files matched your search
@@ -28,6 +28,15 @@
|
||||
//! base64 的正例全部仍被抹;但有三类形状是「旧行为抹、新行为留」——`=` 边界、填充不计段长、
|
||||
//! 全小写点分串。三条都在 [`shape`] 的「旧行为抹、新行为留」一节里逐条写明理由,
|
||||
//! 前两条是本次要修的误杀,第三条是代价。
|
||||
//!
|
||||
//! # 句读不是 token 本体(M243 BEARERDOT)
|
||||
//!
|
||||
//! `Bearer eyJ….eyJ….c2ln….`(行尾一个英文句点)在 M240 之后仍整串原样落盘:句点自己属于
|
||||
//! dotted 字符集,被算进 run 后 `split('.')` 多切出一个空段,「每段 ≥8」当场不成立。修法同样
|
||||
//! 不是抬阈值——判定前把**末尾**句读切出去([`shape::split_trailing_punct`]),搬运方
|
||||
//! ([`push_dotted`])再把句读原位写回,所以占位符只吃 token 本体,句子标点一个不丢。
|
||||
//! 只削末尾:中间的句点仍是 token 的一部分(JWT 的三段就是靠它切的);`(`、`)`、`,`、`;`
|
||||
//! 本来就在字符集外,一并列进规则是为了「句读不参与判定」这件事只有一个出处。
|
||||
|
||||
use std::borrow::Cow;
|
||||
use std::path::Path;
|
||||
@@ -37,7 +46,8 @@ use serde_json::Value;
|
||||
mod shape;
|
||||
|
||||
use self::shape::{
|
||||
is_dns_host, is_dotted_token, is_dotted_token_char, is_opaque_char, is_path_run, MAX_OPAQUE_RUN,
|
||||
is_dns_host, is_dotted_token, is_dotted_token_char, is_opaque_char, is_path_run,
|
||||
split_trailing_punct, MAX_OPAQUE_RUN,
|
||||
};
|
||||
|
||||
/// access token / session token 的替换标记。
|
||||
@@ -238,7 +248,7 @@ pub fn has_dotted_token(text: &str) -> bool {
|
||||
fn run_has_dotted_token(run: &str) -> bool {
|
||||
match split_authority(run) {
|
||||
Some((_, rest)) => run_has_dotted_token(rest),
|
||||
None => is_dotted_token(run),
|
||||
None => is_dotted_token(split_trailing_punct(run).0),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -270,11 +280,14 @@ fn push_dotted(out: &mut String, run: &str) {
|
||||
push_dotted(out, rest);
|
||||
return;
|
||||
}
|
||||
if is_dotted_token(run) {
|
||||
// 句读不参与判定,但要原位保留:`Bearer <JWT>.` 的句点不许被占位符吃掉。
|
||||
let (body, punct) = split_trailing_punct(run);
|
||||
if is_dotted_token(body) {
|
||||
out.push_str(TOKEN_PLACEHOLDER);
|
||||
} else {
|
||||
out.push_str(run);
|
||||
out.push_str(body);
|
||||
}
|
||||
out.push_str(punct);
|
||||
}
|
||||
|
||||
/// 把 URL 形状的 run 切成(主机名前缀, 路径那半)。路径那半不含分隔用的那个 `/`。
|
||||
|
||||
Reference in new issue
Block a user