From d4b8b0a463bf89814a2d81260881fe345e27aff5 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 8 Apr 2026 10:50:26 +0000 Subject: [PATCH 1/6] test: add unified range_all testcase crate with single lib.rs Agent-Logs-Url: https://github.com/Coursant/RAP/sessions/83e0a875-c638-46d5-9678-c93261e5ef29 Co-authored-by: Coursant <60531642+Coursant@users.noreply.github.com> --- rapx/tests/range/range_all/Cargo.toml | 6 + rapx/tests/range/range_all/src/lib.rs | 285 ++++++++++++++++++++++++++ 2 files changed, 291 insertions(+) create mode 100644 rapx/tests/range/range_all/Cargo.toml create mode 100644 rapx/tests/range/range_all/src/lib.rs diff --git a/rapx/tests/range/range_all/Cargo.toml b/rapx/tests/range/range_all/Cargo.toml new file mode 100644 index 00000000..6c03f73f --- /dev/null +++ b/rapx/tests/range/range_all/Cargo.toml @@ -0,0 +1,6 @@ +[package] +name = "range_all" +version = "0.1.0" +edition = "2021" + +[dependencies] diff --git a/rapx/tests/range/range_all/src/lib.rs b/rapx/tests/range/range_all/src/lib.rs new file mode 100644 index 00000000..93bf6d60 --- /dev/null +++ b/rapx/tests/range/range_all/src/lib.rs @@ -0,0 +1,285 @@ +//! 统一的 range 测试集合(单文件版本)。 +//! +//! 目标: +//! 1. 覆盖 `rapx/tests/range` 目录已有 testcase 的核心测试要求; +//! 2. 将测试点统一组织在一个 `lib.rs`,便于一次性查看与维护; +//! 3. 每个 testcase 使用注释明确“在测试什么”。 + +use std::slice; + +// ============================================================================ +// 一、纯数值计算 / 区间传播 +// ============================================================================ + +/// testcase: 双变量收敛循环(对应 range_1 的核心思想) +/// +/// 测试功能: +/// - 验证循环中多个变量(`i`、`j`、`k`)的联合区间更新; +/// - 验证 while 条件与循环体赋值对区间上下界的持续收紧; +/// - 验证在嵌套循环场景下,分析是否能稳定收敛。 +pub fn numeric_coupled_loop() { + let mut k = 0usize; + while k < 100 { + let mut i = 0usize; + let mut j = k; + while i < j { + i += 1; + j -= 1; + } + k += 1; + } +} + +/// testcase: 跨函数参数传递与返回值区间(对应 range_2) +/// +/// 测试功能: +/// - 验证调用点实参区间是否能正确传入被调函数; +/// - 验证被调函数循环更新后,返回值区间是否能回传给调用点; +/// - 验证 inter-procedural(跨过程)分析路径。 +pub fn interprocedural_ranges() -> usize { + fn foo1(mut k: usize) { + while k < 100 { + k += 1; + } + } + fn foo2(mut k: usize, _c: usize) -> usize { + while k < 100 { + k += 1; + } + k + } + + foo1(42); + foo2(55, 52) +} + +/// testcase: 分支路径约束(对应 range_3) +/// +/// 测试功能: +/// - 验证 if/else 多分支中的路径条件约束; +/// - 验证不同路径上变量更新后,合流点的区间合并行为; +/// - 覆盖“嵌套分支 + 比较条件”的约束推理。 +pub fn path_constraints_branching() { + let x = 1i32; + let mut y = 10i32; + let z = 0i32; + if x < y { + y += 1; + } else { + y -= 1; + if y > z { + y -= 2; + } else { + y += 2; + } + } +} + +/// testcase: 递归路径(对应 range_4) +/// +/// 测试功能: +/// - 验证递归调用中的参数递减关系; +/// - 验证终止分支(`n <= 0`)与递归分支的路径分离; +/// - 覆盖“函数自调用”下的区间稳定性。 +pub fn recursion_countdown(n: i32) -> i32 { + if n <= 0 { + 0 + } else { + recursion_countdown(n - 1) + } +} + +/// testcase: 符号表达式区间(对应 range_symbolic) +/// +/// 测试功能: +/// - 验证分析器对 `x + 1`、`z - y` 这类符号关系的建模; +/// - 验证在“条件恒真(y > x)”场景下,分支可达性与结果区间; +/// - 覆盖 symbolic interval 的表达能力。 +pub fn symbolic_interval_case(x: i32) -> i32 { + let y = x + 1; + let z = y + 1; + if y > x { + z - y + } else { + z - x + } +} + +// ============================================================================ +// 二、数组 / slice 长度与索引范围 +// ============================================================================ + +/// testcase: for + slice.len()(对应 range_array) +/// +/// 测试功能: +/// - 验证由切片构造 `&mut a[1..slice_index]` 推导出的长度; +/// - 验证 `for i in 0..slice.len()` 下 `slice[i]` 的索引范围安全; +/// - 覆盖“切片长度驱动循环上界”的常见模式。 +pub fn slice_len_for_loop() { + let mut a = [0usize; 10]; + let slice_index = 5usize; + let slice = &mut a[1..slice_index]; + for i in 0..slice.len() { + slice[i] = i + 1; + } +} + +/// testcase: while + slice.len() + 非线性更新(对应 range_6) +/// +/// 测试功能: +/// - 验证 while 条件 `i < 2 * len` 对区间的约束; +/// - 覆盖循环体内乘法与条件更新导致的“非线性区间传播”; +/// - 用于观察分析在复杂更新路径下的保守性。 +pub fn slice_len_while_non_linear() { + let pieces = [42usize; 8]; + let slice_index = 8usize; + let slice = &pieces[1..slice_index]; + let len = slice.len(); + let mut i = 0usize; + + while i < 2 * len { + let mut val = slice[i]; + if val > 128 { + val += 1; + i *= 2; + i += 2; + } else { + i *= 21; + } + let _ = val; + } +} + +/// testcase: 双数组与子切片索引(对应 range_array2) +/// +/// 测试功能: +/// - 验证从切片 `x[1..9]` 推导出的合法索引区间; +/// - 验证多数组并行访问中同一循环变量 `i` 的范围复用; +/// - 覆盖“基于切片长度驱动访问原数组”的边界行为。 +pub fn dual_array_slice_indexing() { + let mut x = [0usize; 10]; + let mut y = [0usize; 10]; + let z = &mut x[1..9]; + for i in 0..z.len() { + x[i] += 1; + y[i] += 1; + } +} + +/// testcase: 字符串/字节索引与字符区间(对应 range_5) +/// +/// 测试功能: +/// - 验证 `string.as_bytes()[0]` 的字节索引模式; +/// - 验证 `char_indices` 与分支匹配下的索引切片 `input[..i]` / `input[i+1..]`; +/// - 覆盖“字符分类 + 索引切分”的真实场景。 +pub fn parse_scheme_case(input: &str) -> Option<(String, &str)> { + #[derive(PartialEq, Eq)] + enum Context { + UrlParser, + Setter, + } + + #[inline] + fn starts_with_ascii_alpha(string: &str) -> bool { + matches!(string.as_bytes()[0], b'a'..=b'z' | b'A'..=b'Z') + } + + if input.is_empty() || !starts_with_ascii_alpha(input) { + return None; + } + + for (i, c) in input.char_indices() { + match c { + 'a'..='z' | 'A'..='Z' | '0'..='9' | '+' | '-' | '.' => (), + ':' => return Some((input[..i].to_ascii_lowercase(), &input[i + 1..])), + _ => return None, + } + } + + match Context::UrlParser { + Context::Setter => Some((input.to_ascii_lowercase(), "")), + Context::UrlParser => None, + } +} + +/// testcase: 对齐/重解释切片(对应 range_align) +/// +/// 测试功能: +/// - 验证 `from_raw_parts_mut` 构造后固定区间循环访问(0..20); +/// - 覆盖不安全转换后的索引约束; +/// - 用于观察分析在 unsafe 场景下的区间处理。 +pub fn align_and_reinterpret_slice(a: &mut [u8], b: &[u32; 20]) { + unsafe { + let c = slice::from_raw_parts_mut(a.as_mut_ptr() as *mut u32, 20); + for i in 0..20 { + c[i] ^= b[i]; + } + } +} + +// ============================================================================ +// 三、BCE(Bounds Check Elimination)中 LLVM 难以消除的场景 +// ============================================================================ + +/// testcase: 间接索引(BCE failure) +/// +/// 测试功能: +/// - `idx` 来自 `indices[i]` 的数据依赖; +/// - LLVM 无法静态证明 `data[idx]` 总是安全; +/// - 预期保留边界检查。 +pub fn bce_failure_indirect_indexing(data: &[i32], indices: &[usize]) -> i32 { + let mut sum = 0; + for i in 0..indices.len() { + let idx = indices[i]; + sum += data[idx]; + } + sum +} + +/// testcase: 循环内修改容器长度(BCE failure) +/// +/// 测试功能: +/// - 在循环内 `push` 导致长度可能变化; +/// - 编译器难以复用先前的边界证明; +/// - 预期 `v[i]` 访问难以完全消除检查。 +pub fn bce_failure_mutation_invalidation(v: &mut Vec) { + let len = v.len(); + for i in 0..len { + let val = v[i]; + v.push(val * 2); + } +} + +/// testcase: 复杂步长归纳变量(BCE failure) +/// +/// 测试功能: +/// - `step_by(dynamic_step)` 的动态步长使归纳证明复杂化; +/// - 编译器通常无法稳定证明每次访问都满足边界; +/// - 预期 `slice[i]` 访问常保留检查。 +pub fn bce_failure_complex_induction(slice: &[i32], dynamic_step: usize) -> i32 { + if dynamic_step == 0 { + return 0; + } + let mut sum = 0; + for i in (0..slice.len()).step_by(dynamic_step) { + sum += slice[i]; + } + sum +} + +#[inline(never)] +fn get_opaque_index() -> usize { + 42 +} + +/// testcase: 非内联边界函数返回索引(BCE failure) +/// +/// 测试功能: +/// - 索引来自 `#[inline(never)]` 函数,局部信息不透明; +/// - 调用点难以做跨边界值域推断; +/// - 预期 `slice[idx]` 边界检查被保留。 +pub fn bce_failure_opaque_boundary(slice: &[i32]) -> i32 { + let idx = get_opaque_index(); + slice[idx] +} + From 117a607a1ff336d6274f17edf8af8201c6826bd0 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 8 Apr 2026 10:50:51 +0000 Subject: [PATCH 2/6] test: clean warnings in unified range_all lib Agent-Logs-Url: https://github.com/Coursant/RAP/sessions/83e0a875-c638-46d5-9678-c93261e5ef29 Co-authored-by: Coursant <60531642+Coursant@users.noreply.github.com> --- rapx/tests/range/range_all/Cargo.lock | 7 +++++++ rapx/tests/range/range_all/src/lib.rs | 12 +++++++++--- 2 files changed, 16 insertions(+), 3 deletions(-) create mode 100644 rapx/tests/range/range_all/Cargo.lock diff --git a/rapx/tests/range/range_all/Cargo.lock b/rapx/tests/range/range_all/Cargo.lock new file mode 100644 index 00000000..e118672f --- /dev/null +++ b/rapx/tests/range/range_all/Cargo.lock @@ -0,0 +1,7 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "range_all" +version = "0.1.0" diff --git a/rapx/tests/range/range_all/src/lib.rs b/rapx/tests/range/range_all/src/lib.rs index 93bf6d60..e5c45897 100644 --- a/rapx/tests/range/range_all/src/lib.rs +++ b/rapx/tests/range/range_all/src/lib.rs @@ -73,6 +73,7 @@ pub fn path_constraints_branching() { y += 2; } } + let _ = y; } /// testcase: 递归路径(对应 range_4) @@ -172,7 +173,7 @@ pub fn dual_array_slice_indexing() { /// - 验证 `string.as_bytes()[0]` 的字节索引模式; /// - 验证 `char_indices` 与分支匹配下的索引切片 `input[..i]` / `input[i+1..]`; /// - 覆盖“字符分类 + 索引切分”的真实场景。 -pub fn parse_scheme_case(input: &str) -> Option<(String, &str)> { +pub fn parse_scheme_case(input: &str, context: bool) -> Option<(String, &str)> { #[derive(PartialEq, Eq)] enum Context { UrlParser, @@ -196,7 +197,13 @@ pub fn parse_scheme_case(input: &str) -> Option<(String, &str)> { } } - match Context::UrlParser { + let mode = if context { + Context::Setter + } else { + Context::UrlParser + }; + + match mode { Context::Setter => Some((input.to_ascii_lowercase(), "")), Context::UrlParser => None, } @@ -282,4 +289,3 @@ pub fn bce_failure_opaque_boundary(slice: &[i32]) -> i32 { let idx = get_opaque_index(); slice[idx] } - From 642b4ebb13b0ff2bbd6e2dd1ead82aebf386dff8 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 8 Apr 2026 10:54:37 +0000 Subject: [PATCH 3/6] test: fix review issues in unified range_all cases Agent-Logs-Url: https://github.com/Coursant/RAP/sessions/83e0a875-c638-46d5-9678-c93261e5ef29 Co-authored-by: Coursant <60531642+Coursant@users.noreply.github.com> --- rapx/tests/range/range_all/src/lib.rs | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/rapx/tests/range/range_all/src/lib.rs b/rapx/tests/range/range_all/src/lib.rs index e5c45897..968d55da 100644 --- a/rapx/tests/range/range_all/src/lib.rs +++ b/rapx/tests/range/range_all/src/lib.rs @@ -139,6 +139,9 @@ pub fn slice_len_while_non_linear() { let mut i = 0usize; while i < 2 * len { + if i >= len { + break; + } let mut val = slice[i]; if val > 128 { val += 1; @@ -162,7 +165,7 @@ pub fn dual_array_slice_indexing() { let mut y = [0usize; 10]; let z = &mut x[1..9]; for i in 0..z.len() { - x[i] += 1; + z[i] += 1; y[i] += 1; } } @@ -182,7 +185,7 @@ pub fn parse_scheme_case(input: &str, context: bool) -> Option<(String, &str)> { #[inline] fn starts_with_ascii_alpha(string: &str) -> bool { - matches!(string.as_bytes()[0], b'a'..=b'z' | b'A'..=b'Z') + !string.is_empty() && matches!(string.as_bytes()[0], b'a'..=b'z' | b'A'..=b'Z') } if input.is_empty() || !starts_with_ascii_alpha(input) { @@ -234,6 +237,10 @@ pub fn align_and_reinterpret_slice(a: &mut [u8], b: &[u32; 20]) { /// - `idx` 来自 `indices[i]` 的数据依赖; /// - LLVM 无法静态证明 `data[idx]` 总是安全; /// - 预期保留边界检查。 +/// +/// 前置条件: +/// - `indices` 中的每个元素都必须是 `data` 的合法下标; +/// - 本例关注 BCE 行为,不关注非法输入下的 panic 处理。 pub fn bce_failure_indirect_indexing(data: &[i32], indices: &[usize]) -> i32 { let mut sum = 0; for i in 0..indices.len() { From 122f109e70aa854ffdf0186ca229cfc54eb1cabb Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 8 Apr 2026 11:02:07 +0000 Subject: [PATCH 4/6] docs: convert range_all testcase comments to English Agent-Logs-Url: https://github.com/Coursant/RAP/sessions/f9881dd0-d94d-4ebf-b3f4-a85e90df729b Co-authored-by: Coursant <60531642+Coursant@users.noreply.github.com> --- rapx/tests/range/range_all/src/lib.rs | 162 +++++++++++++------------- 1 file changed, 81 insertions(+), 81 deletions(-) diff --git a/rapx/tests/range/range_all/src/lib.rs b/rapx/tests/range/range_all/src/lib.rs index 968d55da..f0e2460b 100644 --- a/rapx/tests/range/range_all/src/lib.rs +++ b/rapx/tests/range/range_all/src/lib.rs @@ -1,22 +1,22 @@ -//! 统一的 range 测试集合(单文件版本)。 +//! Unified range test collection (single-file version). //! -//! 目标: -//! 1. 覆盖 `rapx/tests/range` 目录已有 testcase 的核心测试要求; -//! 2. 将测试点统一组织在一个 `lib.rs`,便于一次性查看与维护; -//! 3. 每个 testcase 使用注释明确“在测试什么”。 +//! Goals: +//! 1. Cover the core requirements from existing testcases under `rapx/tests/range`; +//! 2. Keep all test points in one `lib.rs` for easier review and maintenance; +//! 3. Use comments on each testcase to state exactly what is being tested. use std::slice; // ============================================================================ -// 一、纯数值计算 / 区间传播 +// 1) Pure numeric computation / interval propagation // ============================================================================ -/// testcase: 双变量收敛循环(对应 range_1 的核心思想) +/// testcase: Coupled-variable convergence loop (from range_1) /// -/// 测试功能: -/// - 验证循环中多个变量(`i`、`j`、`k`)的联合区间更新; -/// - 验证 while 条件与循环体赋值对区间上下界的持续收紧; -/// - 验证在嵌套循环场景下,分析是否能稳定收敛。 +/// Test intent: +/// - Verify joint interval updates for multiple variables (`i`, `j`, `k`) in loops; +/// - Verify that while-conditions and loop-body assignments continuously tighten bounds; +/// - Verify stable convergence behavior under nested loops. pub fn numeric_coupled_loop() { let mut k = 0usize; while k < 100 { @@ -30,12 +30,12 @@ pub fn numeric_coupled_loop() { } } -/// testcase: 跨函数参数传递与返回值区间(对应 range_2) +/// testcase: Cross-function argument/return intervals (from range_2) /// -/// 测试功能: -/// - 验证调用点实参区间是否能正确传入被调函数; -/// - 验证被调函数循环更新后,返回值区间是否能回传给调用点; -/// - 验证 inter-procedural(跨过程)分析路径。 +/// Test intent: +/// - Verify argument intervals are propagated from callsite to callee; +/// - Verify return-value intervals are propagated back after callee-side loop updates; +/// - Cover inter-procedural analysis behavior. pub fn interprocedural_ranges() -> usize { fn foo1(mut k: usize) { while k < 100 { @@ -53,12 +53,12 @@ pub fn interprocedural_ranges() -> usize { foo2(55, 52) } -/// testcase: 分支路径约束(对应 range_3) +/// testcase: Branch path constraints (from range_3) /// -/// 测试功能: -/// - 验证 if/else 多分支中的路径条件约束; -/// - 验证不同路径上变量更新后,合流点的区间合并行为; -/// - 覆盖“嵌套分支 + 比较条件”的约束推理。 +/// Test intent: +/// - Verify path-condition constraints in if/else multi-branch control flow; +/// - Verify interval merge behavior at join points after branch-specific updates; +/// - Cover constraint reasoning with nested branches and comparisons. pub fn path_constraints_branching() { let x = 1i32; let mut y = 10i32; @@ -76,12 +76,12 @@ pub fn path_constraints_branching() { let _ = y; } -/// testcase: 递归路径(对应 range_4) +/// testcase: Recursive path (from range_4) /// -/// 测试功能: -/// - 验证递归调用中的参数递减关系; -/// - 验证终止分支(`n <= 0`)与递归分支的路径分离; -/// - 覆盖“函数自调用”下的区间稳定性。 +/// Test intent: +/// - Verify monotonic parameter decrease across recursive calls; +/// - Verify path separation between base case (`n <= 0`) and recursive case; +/// - Cover interval stability under self-recursive functions. pub fn recursion_countdown(n: i32) -> i32 { if n <= 0 { 0 @@ -90,12 +90,12 @@ pub fn recursion_countdown(n: i32) -> i32 { } } -/// testcase: 符号表达式区间(对应 range_symbolic) +/// testcase: Symbolic-expression intervals (from range_symbolic) /// -/// 测试功能: -/// - 验证分析器对 `x + 1`、`z - y` 这类符号关系的建模; -/// - 验证在“条件恒真(y > x)”场景下,分支可达性与结果区间; -/// - 覆盖 symbolic interval 的表达能力。 +/// Test intent: +/// - Verify modeling of symbolic relations such as `x + 1` and `z - y`; +/// - Verify branch reachability and resulting intervals in an always-true condition (`y > x`); +/// - Cover symbolic interval expressiveness. pub fn symbolic_interval_case(x: i32) -> i32 { let y = x + 1; let z = y + 1; @@ -107,15 +107,15 @@ pub fn symbolic_interval_case(x: i32) -> i32 { } // ============================================================================ -// 二、数组 / slice 长度与索引范围 +// 2) Array/slice length and index ranges // ============================================================================ -/// testcase: for + slice.len()(对应 range_array) +/// testcase: for-loop with slice.len() (from range_array) /// -/// 测试功能: -/// - 验证由切片构造 `&mut a[1..slice_index]` 推导出的长度; -/// - 验证 `for i in 0..slice.len()` 下 `slice[i]` 的索引范围安全; -/// - 覆盖“切片长度驱动循环上界”的常见模式。 +/// Test intent: +/// - Verify inferred slice length from `&mut a[1..slice_index]`; +/// - Verify index safety for `slice[i]` under `for i in 0..slice.len()`; +/// - Cover the common pattern where loop upper-bound is driven by slice length. pub fn slice_len_for_loop() { let mut a = [0usize; 10]; let slice_index = 5usize; @@ -125,12 +125,12 @@ pub fn slice_len_for_loop() { } } -/// testcase: while + slice.len() + 非线性更新(对应 range_6) +/// testcase: while + slice.len() + non-linear updates (from range_6) /// -/// 测试功能: -/// - 验证 while 条件 `i < 2 * len` 对区间的约束; -/// - 覆盖循环体内乘法与条件更新导致的“非线性区间传播”; -/// - 用于观察分析在复杂更新路径下的保守性。 +/// Test intent: +/// - Verify interval constraints from while-condition `i < 2 * len`; +/// - Cover non-linear interval propagation caused by multiplication and conditional updates; +/// - Observe analysis conservativeness under complex update paths. pub fn slice_len_while_non_linear() { let pieces = [42usize; 8]; let slice_index = 8usize; @@ -154,12 +154,12 @@ pub fn slice_len_while_non_linear() { } } -/// testcase: 双数组与子切片索引(对应 range_array2) +/// testcase: Dual-array and subslice indexing (from range_array2) /// -/// 测试功能: -/// - 验证从切片 `x[1..9]` 推导出的合法索引区间; -/// - 验证多数组并行访问中同一循环变量 `i` 的范围复用; -/// - 覆盖“基于切片长度驱动访问原数组”的边界行为。 +/// Test intent: +/// - Verify legal index range inferred from subslice `x[1..9]`; +/// - Verify re-use of the same loop variable range across multiple array accesses; +/// - Cover boundary behavior driven by subslice length. pub fn dual_array_slice_indexing() { let mut x = [0usize; 10]; let mut y = [0usize; 10]; @@ -170,12 +170,12 @@ pub fn dual_array_slice_indexing() { } } -/// testcase: 字符串/字节索引与字符区间(对应 range_5) +/// testcase: String/byte indexing and character ranges (from range_5) /// -/// 测试功能: -/// - 验证 `string.as_bytes()[0]` 的字节索引模式; -/// - 验证 `char_indices` 与分支匹配下的索引切片 `input[..i]` / `input[i+1..]`; -/// - 覆盖“字符分类 + 索引切分”的真实场景。 +/// Test intent: +/// - Verify the byte-indexing pattern `string.as_bytes()[0]`; +/// - Verify slicing with `input[..i]` / `input[i+1..]` under `char_indices` and match branches; +/// - Cover realistic character classification plus index slicing flow. pub fn parse_scheme_case(input: &str, context: bool) -> Option<(String, &str)> { #[derive(PartialEq, Eq)] enum Context { @@ -212,12 +212,12 @@ pub fn parse_scheme_case(input: &str, context: bool) -> Option<(String, &str)> { } } -/// testcase: 对齐/重解释切片(对应 range_align) +/// testcase: Aligned/reinterpreted slice (from range_align) /// -/// 测试功能: -/// - 验证 `from_raw_parts_mut` 构造后固定区间循环访问(0..20); -/// - 覆盖不安全转换后的索引约束; -/// - 用于观察分析在 unsafe 场景下的区间处理。 +/// Test intent: +/// - Verify fixed-range loop access (0..20) after `from_raw_parts_mut`; +/// - Cover index constraints after unsafe reinterpretation; +/// - Observe interval handling in unsafe contexts. pub fn align_and_reinterpret_slice(a: &mut [u8], b: &[u32; 20]) { unsafe { let c = slice::from_raw_parts_mut(a.as_mut_ptr() as *mut u32, 20); @@ -228,19 +228,19 @@ pub fn align_and_reinterpret_slice(a: &mut [u8], b: &[u32; 20]) { } // ============================================================================ -// 三、BCE(Bounds Check Elimination)中 LLVM 难以消除的场景 +// 3) BCE (Bounds Check Elimination) scenarios LLVM usually cannot eliminate // ============================================================================ -/// testcase: 间接索引(BCE failure) +/// testcase: Indirect indexing (BCE failure) /// -/// 测试功能: -/// - `idx` 来自 `indices[i]` 的数据依赖; -/// - LLVM 无法静态证明 `data[idx]` 总是安全; -/// - 预期保留边界检查。 +/// Test intent: +/// - `idx` is data-dependent from `indices[i]`; +/// - LLVM cannot statically prove `data[idx]` is always in-bounds; +/// - Bounds checks are expected to remain. /// -/// 前置条件: -/// - `indices` 中的每个元素都必须是 `data` 的合法下标; -/// - 本例关注 BCE 行为,不关注非法输入下的 panic 处理。 +/// Preconditions: +/// - Every value in `indices` must be a valid index into `data`; +/// - This case focuses on BCE behavior, not panic handling for invalid inputs. pub fn bce_failure_indirect_indexing(data: &[i32], indices: &[usize]) -> i32 { let mut sum = 0; for i in 0..indices.len() { @@ -250,12 +250,12 @@ pub fn bce_failure_indirect_indexing(data: &[i32], indices: &[usize]) -> i32 { sum } -/// testcase: 循环内修改容器长度(BCE failure) +/// testcase: Container-length mutation inside loop (BCE failure) /// -/// 测试功能: -/// - 在循环内 `push` 导致长度可能变化; -/// - 编译器难以复用先前的边界证明; -/// - 预期 `v[i]` 访问难以完全消除检查。 +/// Test intent: +/// - `push` inside the loop may change vector length; +/// - The compiler cannot reliably reuse prior bounds proofs; +/// - `v[i]` checks are expected to be hard to fully eliminate. pub fn bce_failure_mutation_invalidation(v: &mut Vec) { let len = v.len(); for i in 0..len { @@ -264,12 +264,12 @@ pub fn bce_failure_mutation_invalidation(v: &mut Vec) { } } -/// testcase: 复杂步长归纳变量(BCE failure) +/// testcase: Complex-step induction variable (BCE failure) /// -/// 测试功能: -/// - `step_by(dynamic_step)` 的动态步长使归纳证明复杂化; -/// - 编译器通常无法稳定证明每次访问都满足边界; -/// - 预期 `slice[i]` 访问常保留检查。 +/// Test intent: +/// - Dynamic stride in `step_by(dynamic_step)` complicates induction proofs; +/// - The compiler often cannot prove every access is in-bounds; +/// - `slice[i]` checks are expected to remain in many cases. pub fn bce_failure_complex_induction(slice: &[i32], dynamic_step: usize) -> i32 { if dynamic_step == 0 { return 0; @@ -286,12 +286,12 @@ fn get_opaque_index() -> usize { 42 } -/// testcase: 非内联边界函数返回索引(BCE failure) +/// testcase: Index returned from non-inlined boundary function (BCE failure) /// -/// 测试功能: -/// - 索引来自 `#[inline(never)]` 函数,局部信息不透明; -/// - 调用点难以做跨边界值域推断; -/// - 预期 `slice[idx]` 边界检查被保留。 +/// Test intent: +/// - The index comes from a `#[inline(never)]` function, making local context opaque; +/// - Cross-boundary value-range inference is difficult at the callsite; +/// - Bounds checks on `slice[idx]` are expected to remain. pub fn bce_failure_opaque_boundary(slice: &[i32]) -> i32 { let idx = get_opaque_index(); slice[idx] From 3182ce7a0831cea801a73f18892bd521defcdee1 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 8 Apr 2026 11:11:08 +0000 Subject: [PATCH 5/6] refactor: parameterize selected range_all testcase inputs Agent-Logs-Url: https://github.com/Coursant/RAP/sessions/ab84081b-74ec-4903-8394-c79c6a6b3829 Co-authored-by: Coursant <60531642+Coursant@users.noreply.github.com> --- rapx/tests/range/range_all/src/lib.rs | 67 ++++++++++++++------------- 1 file changed, 36 insertions(+), 31 deletions(-) diff --git a/rapx/tests/range/range_all/src/lib.rs b/rapx/tests/range/range_all/src/lib.rs index f0e2460b..2f9b9b7a 100644 --- a/rapx/tests/range/range_all/src/lib.rs +++ b/rapx/tests/range/range_all/src/lib.rs @@ -17,9 +17,9 @@ use std::slice; /// - Verify joint interval updates for multiple variables (`i`, `j`, `k`) in loops; /// - Verify that while-conditions and loop-body assignments continuously tighten bounds; /// - Verify stable convergence behavior under nested loops. -pub fn numeric_coupled_loop() { - let mut k = 0usize; - while k < 100 { +pub fn numeric_coupled_loop(start_k: usize, upper_bound: usize) { + let mut k = start_k; + while k < upper_bound { let mut i = 0usize; let mut j = k; while i < j { @@ -36,21 +36,21 @@ pub fn numeric_coupled_loop() { /// - Verify argument intervals are propagated from callsite to callee; /// - Verify return-value intervals are propagated back after callee-side loop updates; /// - Cover inter-procedural analysis behavior. -pub fn interprocedural_ranges() -> usize { - fn foo1(mut k: usize) { - while k < 100 { +pub fn interprocedural_ranges(foo1_seed: usize, foo2_seed: usize, c: usize, upper_bound: usize) -> usize { + fn foo1(mut k: usize, upper_bound: usize) { + while k < upper_bound { k += 1; } } - fn foo2(mut k: usize, _c: usize) -> usize { - while k < 100 { + fn foo2(mut k: usize, _c: usize, upper_bound: usize) -> usize { + while k < upper_bound { k += 1; } k } - foo1(42); - foo2(55, 52) + foo1(foo1_seed, upper_bound); + foo2(foo2_seed, c, upper_bound) } /// testcase: Branch path constraints (from range_3) @@ -59,10 +59,7 @@ pub fn interprocedural_ranges() -> usize { /// - Verify path-condition constraints in if/else multi-branch control flow; /// - Verify interval merge behavior at join points after branch-specific updates; /// - Cover constraint reasoning with nested branches and comparisons. -pub fn path_constraints_branching() { - let x = 1i32; - let mut y = 10i32; - let z = 0i32; +pub fn path_constraints_branching(x: i32, mut y: i32, z: i32) -> i32 { if x < y { y += 1; } else { @@ -73,7 +70,7 @@ pub fn path_constraints_branching() { y += 2; } } - let _ = y; + y } /// testcase: Recursive path (from range_4) @@ -116,10 +113,11 @@ pub fn symbolic_interval_case(x: i32) -> i32 { /// - Verify inferred slice length from `&mut a[1..slice_index]`; /// - Verify index safety for `slice[i]` under `for i in 0..slice.len()`; /// - Cover the common pattern where loop upper-bound is driven by slice length. -pub fn slice_len_for_loop() { - let mut a = [0usize; 10]; - let slice_index = 5usize; - let slice = &mut a[1..slice_index]; +pub fn slice_len_for_loop(a: &mut [usize; 10], slice_start: usize, slice_end: usize) { + if slice_start >= slice_end || slice_end > a.len() { + return; + } + let slice = &mut a[slice_start..slice_end]; for i in 0..slice.len() { slice[i] = i + 1; } @@ -131,10 +129,11 @@ pub fn slice_len_for_loop() { /// - Verify interval constraints from while-condition `i < 2 * len`; /// - Cover non-linear interval propagation caused by multiplication and conditional updates; /// - Observe analysis conservativeness under complex update paths. -pub fn slice_len_while_non_linear() { - let pieces = [42usize; 8]; - let slice_index = 8usize; - let slice = &pieces[1..slice_index]; +pub fn slice_len_while_non_linear(pieces: &[usize; 8], slice_start: usize, slice_end: usize) { + if slice_start >= slice_end || slice_end > pieces.len() { + return; + } + let slice = &pieces[slice_start..slice_end]; let len = slice.len(); let mut i = 0usize; @@ -160,10 +159,16 @@ pub fn slice_len_while_non_linear() { /// - Verify legal index range inferred from subslice `x[1..9]`; /// - Verify re-use of the same loop variable range across multiple array accesses; /// - Cover boundary behavior driven by subslice length. -pub fn dual_array_slice_indexing() { - let mut x = [0usize; 10]; - let mut y = [0usize; 10]; - let z = &mut x[1..9]; +pub fn dual_array_slice_indexing( + x: &mut [usize; 10], + y: &mut [usize; 10], + slice_start: usize, + slice_end: usize, +) { + if slice_start >= slice_end || slice_end > x.len() { + return; + } + let z = &mut x[slice_start..slice_end]; for i in 0..z.len() { z[i] += 1; y[i] += 1; @@ -282,8 +287,8 @@ pub fn bce_failure_complex_induction(slice: &[i32], dynamic_step: usize) -> i32 } #[inline(never)] -fn get_opaque_index() -> usize { - 42 +fn get_opaque_index(opaque_index: usize) -> usize { + opaque_index } /// testcase: Index returned from non-inlined boundary function (BCE failure) @@ -292,7 +297,7 @@ fn get_opaque_index() -> usize { /// - The index comes from a `#[inline(never)]` function, making local context opaque; /// - Cross-boundary value-range inference is difficult at the callsite; /// - Bounds checks on `slice[idx]` are expected to remain. -pub fn bce_failure_opaque_boundary(slice: &[i32]) -> i32 { - let idx = get_opaque_index(); +pub fn bce_failure_opaque_boundary(slice: &[i32], opaque_index: usize) -> i32 { + let idx = get_opaque_index(opaque_index); slice[idx] } From baf7d37b5b1a5e3e3d6b159c86c3878bcf9506f1 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 8 Apr 2026 11:15:05 +0000 Subject: [PATCH 6/6] fix: align slice range usage and add unsafe precondition guards Agent-Logs-Url: https://github.com/Coursant/RAP/sessions/ab84081b-74ec-4903-8394-c79c6a6b3829 Co-authored-by: Coursant <60531642+Coursant@users.noreply.github.com> --- rapx/tests/range/range_all/src/lib.rs | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/rapx/tests/range/range_all/src/lib.rs b/rapx/tests/range/range_all/src/lib.rs index 2f9b9b7a..bf01d0aa 100644 --- a/rapx/tests/range/range_all/src/lib.rs +++ b/rapx/tests/range/range_all/src/lib.rs @@ -169,9 +169,10 @@ pub fn dual_array_slice_indexing( return; } let z = &mut x[slice_start..slice_end]; + let y_slice = &mut y[slice_start..slice_end]; for i in 0..z.len() { z[i] += 1; - y[i] += 1; + y_slice[i] += 1; } } @@ -224,8 +225,18 @@ pub fn parse_scheme_case(input: &str, context: bool) -> Option<(String, &str)> { /// - Cover index constraints after unsafe reinterpretation; /// - Observe interval handling in unsafe contexts. pub fn align_and_reinterpret_slice(a: &mut [u8], b: &[u32; 20]) { + let required_bytes = 20 * std::mem::size_of::(); + if a.len() < required_bytes { + return; + } + unsafe { - let c = slice::from_raw_parts_mut(a.as_mut_ptr() as *mut u32, 20); + let ptr = a.as_mut_ptr(); + if ptr.align_offset(std::mem::align_of::()) != 0 { + return; + } + + let c = slice::from_raw_parts_mut(ptr as *mut u32, 20); for i in 0..20 { c[i] ^= b[i]; } @@ -297,6 +308,9 @@ fn get_opaque_index(opaque_index: usize) -> usize { /// - The index comes from a `#[inline(never)]` function, making local context opaque; /// - Cross-boundary value-range inference is difficult at the callsite; /// - Bounds checks on `slice[idx]` are expected to remain. +/// +/// Preconditions: +/// - `opaque_index` must be a valid index into `slice`. pub fn bce_failure_opaque_boundary(slice: &[i32], opaque_index: usize) -> i32 { let idx = get_opaque_index(opaque_index); slice[idx]