Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion demo/crash/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,13 @@ bin/gf demo/crash/<文件名>; echo "exit=$?"
已在 devel/0142.md 修复,修复验证完成后移除。
- `h02-which-public-integer.scm`(which 传入非字符串 abort)
已在 devel/0143.md 修复,修复验证完成后移除。
- `c09-g_rename-integer.scm`(g_rename 传入非字符串段错误)
已在 devel/0144.md 修复,修复验证完成后移除。

## 已确认的崩溃点

| 文件 | 触发代码 | 信号 | 根因 |
|---|---|---|---|
| c09-g_rename-integer.scm | `(g_rename 1 2)` | SIGSEGV | `liii_os.cpp` 的 `f_rename` 对两个参数都未做类型检查,垃圾指针传入 `std::filesystem::rename` |
| c11-g_listdir-integer.scm | `(g_listdir 99)` | SIGABRT | `liii_os.cpp` 的 `f_listdir` 未检查参数类型,`s7_string()` 得到空指针后构造 `std::string` 抛 `std::logic_error` |
| f03-base64-encode-oob-length.scm | `(g_bytevector-base64-encode (make-bytevector 4 65) 1073741824)` | SIGSEGV | `liii_base64.cpp` 的长度参数不校验是否超过 bytevector 实际大小,编码循环按声明长度越界读取 1GB |

Expand Down
1 change: 0 additions & 1 deletion demo/crash/c09-g_rename-integer.scm

This file was deleted.

47 changes: 47 additions & 0 deletions devel/0144.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
# [0144] 修复 g_rename 传入非字符串参数导致 gf 段错误的问题

## 任务相关的代码文件
- src/liii_os.cpp
- tests/liii/os/rename-test.scm
- demo/crash/README.md

## 如何测试
```bash
xmake b goldfish
bin/gf tests/liii/os/rename-test.scm
```

预期:测试输出 `12 correct, 0 failed`。

## 2026-09-08 C++ 层为 g_rename 增加参数类型检查

### What

1. `src/liii_os.cpp` 的 `f_rename` 入口处为 `src`(第 1 参数)与
`dst`(第 2 参数)增加类型守卫:不是 string 时抛出
`(liii error)` 约定的 `type-error`。
2. `tests/liii/os/rename-test.scm` 增加 3 个 C 层入口参数类型回归测试
(`(g_rename 1 2)`、`(g_rename "src" 2)`、`(g_rename 1 "dst")`)。
3. 崩溃片段 `demo/crash/c09-g_rename-integer.scm`
(`(g_rename 1 2)`)修复验证完成后移除。
4. 按 review 意见,错误类型由 s7 内建的 `wrong-type-arg` 调整为
`(liii error)` 约定的 `type-error`,测试断言同步更新。

### Why

`bin/gf demo/crash/c09-g_rename-integer.scm`(即 `(g_rename 1 2)`)会让
进程段错误(SIGSEGV, exit 139)。根因在 C++ 层:`f_rename` 直接
`s7_string(s7_car(args))` / `s7_string(s7_cadr(args))`,对非字符串对象
等同于把对象强转为字符串 cell 解引用,垃圾指针传入
`std::filesystem::rename` 后触发段错误。

`(liii os)` 公开包装 `rename` 已有 `string?` 检查,但根环境直接调用
`g_rename` 的代码不受保护。按 0142/0143 的模式,防御放在 C++ 层。

修复前运行新测试会直接段错误(TDD 红灯),修复后 12/12 通过。

### How

与 devel/0142.md 相同的模式:C++ 入口先 `s7_is_string` 检查,非字符串抛出
`(liii error)` 约定的 `type-error`(`string_type_error` 辅助函数,经
`s7_error` 实现),可用 `(catch 'type-error ...)` 捕获。
18 changes: 16 additions & 2 deletions src/liii_os.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,12 @@ string_vector_to_s7_vector (s7_scheme* sc, vector<string> v) {
return ret;
}

// 抛出 (liii error) 约定的 type-error,irritant 为出错的参数
inline s7_pointer
string_type_error (s7_scheme* sc, const char* msg, s7_pointer arg) {
return s7_error (sc, s7_make_symbol (sc, "type-error"), s7_list (sc, 2, s7_make_string (sc, msg), arg));
}

static s7_pointer
f_os_arch (s7_scheme* sc, s7_pointer args) {
return s7_make_string (sc, TB_ARCH_STRING);
Expand Down Expand Up @@ -263,8 +269,16 @@ glue_remove_file (s7_scheme* sc) {

static s7_pointer
f_rename (s7_scheme* sc, s7_pointer args) {
const char* src= s7_string (s7_car (args));
const char* dst= s7_string (s7_cadr (args));
s7_pointer src_arg= s7_car (args);
if (!s7_is_string (src_arg)) {
return string_type_error (sc, "rename: src must be a string", src_arg);
}
s7_pointer dst_arg= s7_cadr (args);
if (!s7_is_string (dst_arg)) {
return string_type_error (sc, "rename: dst must be a string", dst_arg);
}
const char* src= s7_string (src_arg);
const char* dst= s7_string (dst_arg);
try {
fs::rename (src, dst);
return s7_make_boolean (sc, true);
Expand Down
8 changes: 8 additions & 0 deletions tests/liii/os/rename-test.scm
Original file line number Diff line number Diff line change
Expand Up @@ -109,3 +109,11 @@


(check-report)


;; ; C 层入口 g_rename 参数类型测试(type-error 为 (liii error) 约定)
;; src/dst 必须是 string?,C++ 层需要类型守卫,
;; 避免把非字符串对象当作 C 字符串指针导致段错误 (devel/0144.md)
(check-catch 'type-error (g_rename 1 2))
(check-catch 'type-error (g_rename "src" 2))
(check-catch 'type-error (g_rename 1 "dst"))
Loading