Skip to content

Commit aad1815

Browse files
authored
Improvement desc for P.NAM.05 && P.NAM.07 && P.UNS.MEM.04 (#114)
* V 0.3 * V0.3: modify README * update Version to 0.3 * add code example for P.SEC.01 * modify P.SEC.01 * 3.30 review * update * update to 1.0 beta * fixed for P.NAM.01 * Improvement desc for P.NAM.05 && P.NAM.07 && P.UNS.MEM.04
1 parent ca815e5 commit aad1815

File tree

3 files changed

+31
-27
lines changed

3 files changed

+31
-27
lines changed

src/safe-guides/code_style/naming/P.NAM.05.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ impl S {
6060
}
6161

6262
// set_前缀是可以的
63-
pub fn set_first(&mut self, f: First) -> &mut First {
63+
pub fn set_first(&mut self, f: First) {
6464
self.first = f;
6565
}
6666
}

src/safe-guides/code_style/naming/P.NAM.07.md

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,7 @@ type Sized = u16;
1212

1313
fn main() {
1414
// 不符合:try 为保留关键字
15-
// 如果必须要用,使用`r#`前缀可以使用它,但要尽力避免
16-
let r#try = 1;
15+
let try = 1;
1716
}
1817
```
1918

@@ -27,4 +26,28 @@ fn main() {
2726
// 符合
2827
let tried = 1;
2928
}
29+
```
30+
31+
**【例外】**
32+
33+
在一些特定场合,比如对接遗留数据库中的字段和Rust关键字冲突:
34+
35+
```rust
36+
37+
struct SomeTable{
38+
// 使用 `r#`+type 来解决这种问题
39+
r#type: String
40+
}
41+
42+
```
43+
44+
或者当序列化为 json 或 proto 时,存在成员为关键字,则可以通过相关库提供的功能来使用:
45+
46+
```rust
47+
pub struct UserRepr {
48+
// ...
49+
#[serde(rename="self")]
50+
pub self_: Option<String>,
51+
// ...
52+
}
3053
```

src/safe-guides/coding_practice/unsafe_rust/mem/P.UNS.MEM.04.md

Lines changed: 5 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -2,37 +2,18 @@
22

33
**【描述】**
44

5-
以 Linux 系统为例,在 **glibc**(/usr/lib/libc.so) 等知名 C 语言库中,
5+
以 Linux 系统为例,在 **glibc**(/usr/lib/libc.so) 等知名 C 语言库中,很多 API 会既提供不可重入版本和**可重入(reentrant)**版本,例如 ctime 和 ctime_r 这对系统调用。可重入版本的函数命名一般带 **_r** 的后缀,*_r* 也就是单词可重入 reentrant 的缩写。
66

7-
很多 API 会既提供不可重入版本和**可重入(reentrant)**版本,例如 ctime 和 ctime_r 这对系统调用
7+
> libc 中不可重入函数的执行过程一般是将函数的输出写到动态库的某个 static 命令内,然后再返回指向该 static 变量的指针返回给调用方,因此是一种「有状态」的函数,多线程环境下可能有**线程安全问题**
88
9-
可重入版本的函数命名一般带 **_r** 的后缀,*_r* 也就是单词可重入 reentrant 的缩写。
10-
11-
libc 中不可重入函数的执行过程一般是将函数的输出写到动态库的某个 static 命令内,然后再返回指向该 static 变量的指针返回给调用方,因此是一种「有状态」的函数,多线程环境下可能有**线程安全问题**
12-
13-
例如线程 A 正在将 glibc 动态库的 gmtime 数据逐个复制回来,结果复制到一半线程 B 调用 gmtime 把后半部分的 gmtime 输出数据给更新掉了,导致线程 A 得到的数据有误。
14-
15-
而无重入版本例如 libc::localtime_r 会比 libc::localtime 多一个入参叫 result,
16-
17-
允许调用方进程的内存空间内分配内存,再将调用方进程的可变指针传入到 glibc 中让 glibc 修改可变指针指向的数据。
18-
19-
应当通过工具搜索动态库的函数符号查找可重入版本的函数,或者通过 man 文档查询自己所用函数有没有可重入的版本。
20-
21-
```
22-
[w@ww repos]$ nm -D /usr/lib/libc.so.6 | grep "_r@"
23-
00000000000bb030 W asctime_r@@GLIBC_2.2.5
24-
00000000000bb100 T ctime_r@@GLIBC_2.2.5
25-
0000000000040a30 T drand48_r@@GLIBC_2.2.5
26-
```
27-
28-
使用不可重入函数的危害例如 P.UNS.MEM.02 和 P.UNS.MEM.03 规范的反例中的 sqlite3_libversion() 会导致开发人员带来很大的心智负担,需要人工 code review 确保没有线程安全和内存安全问题,因此必须尽量使用可重入版本的函数。
9+
使用不可重入函数的风险会导致开发人员带来很大的心智负担,需要耗费人力进行代码安全评审确保没有线程安全和内存安全问题,因此必须尽量使用可重入版本的函数。
2910

3011
**【反例】**
3112

3213
`ctime`, `gmtime`,` localtime`, `gethostbyname`
3314

3415
**【正例】**
3516

36-
`chrono` 库中用 `libc::localtime_r` 获取本地时间而不用 `libc::localtime`
17+
`chrono` 库中用 `libc::localtime_r` 获取本地时间而不用 `libc::localtime`
3718

38-
`ctime_r`, `gmtime_r`,` localtime_r`, `gethostbyname_r`
19+
还有诸如 `ctime_r`, `gmtime_r`,` localtime_r`, `gethostbyname_r`等。

0 commit comments

Comments
 (0)