第一节 Welcome to CS 110L
视频:
- YouTube:https://www.youtube.com/watch?v=j7AQrtLevUE&feature=youtu.be
- B站中字:https://www.bilibili.com/video/BV1Ra411A7kN
Slides:https://reberhardt.com/cs110l/spring-2020/slides/lecture-01.pdf
笔记
1.为什么使用Rust

2.为什么不是用C/C++?
安全问题:
例子程序:https://www.tutorialspoint.com/convert-a-string-to-uppercase-in-c

看了一下,程序的作用是把字符串转成大写,明显gets存在缓冲区溢出。在编译的时候,编译器也提醒了。
➜ 01 git:(main) ✗ ./a.out
Enter a string:ashdasihdddddddddddddddddddddddddddddddddddddddddddddddddddddddd
String in Upper Case = ASHDASIHDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD%
➜ 01 git:(main) ✗ ./a.out
Enter a string:GgaudiasSSSSSSSSSASUGDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
*** stack smashing detected ***: terminated
[1] 18336 abort ./a.out
很明显,C/C++的内存安全的问题很严重,这其实也是众所周知的,老师还提到一篇论文,关于汽车攻击面的。
论文:http://www.autosec.org/pubs/cars-usenixsec2011.pdf
YouTube解读: https://www.youtube.com/watch?v=bHfOziIwXic
还提到Chrome OS中的一个 one byte overflow and symlinks,DNS库的一个字节的溢出
链接: https://googleprojectzero.blogspot.com/2016/12/chrome-os-exploit-one-byte-overflow-and.html
然后老师讨论缓冲区溢出的问题,举了一个例子:
char buffer[128];
int bytesToCopy = packet.length;
if (bytesToCopy < 128) {
strncpy(buffer, packet.data, bytesToCopy);
}
看起来是有边界检查的,也使用了带有长度的strncpy函数。但是其实strncpy也是有问题的,容易产生空字符结尾错误和其他的问题。
但是这里的问题,其实是整数转换的问题。

C/C++的内存安全问题,也有很多人搞了一些工具来检查。主要是动态分析和静态分析,动态分析需要预测输入,静态分析主要是错误非常多。
比如: valgrind
我用valgrind来跑convert程序,看看会出什么样的结果
➜ 01 git:(main) ✗ valgrind --tool=memcheck --leak-check=full ./conver
==2022== Memcheck, a memory error detector
==2022== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==2022== Using Valgrind-3.16.1 and LibVEX; rerun with -h for copyright info
==2022== Command: ./conver
==2022==
Enter a string:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
*** stack smashing detected ***: terminated
==2022==
==2022== Process terminating with default action of signal 6 (SIGABRT)
==2022== at 0x489C18B: raise (raise.c:51)
==2022== by 0x487B858: abort (abort.c:79)
==2022== by 0x48E63ED: __libc_message (libc_fatal.c:155)
==2022== by 0x4988B49: __fortify_fail (fortify_fail.c:26)
==2022== by 0x4988B15: __stack_chk_fail (stack_chk_fail.c:24)
==2022== by 0x109245: main (convert.c:22)
String in Upper Case = AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==2022==
==2022== HEAP SUMMARY:
==2022== in use at exit: 0 bytes in 0 blocks
==2022== total heap usage: 2 allocs, 2 frees, 2,048 bytes allocated
==2022==
==2022== All heap blocks were freed -- no leaks are possible
==2022==
==2022== For lists of detected and suppressed errors, rerun with: -s
==2022== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
[1] 2022 abort valgrind --tool=memcheck --leak-check=full ./conver
其实valgrind检查不了这种缓冲区溢出的漏洞。
3.为什么不是用其他有GC的语言?
GC 有性能问题,垃圾一般都是丢在你家里,收集垃圾的需要敲你的门来收集垃圾。
- 代价昂贵
- 具有破坏性
- 存在非确定性
- 排除了手动优化的可能

需要程序都需要高性能,比如
- 用户界面程序
- 游戏
- 自动驾驶
- 支付处理
- 高频交易
4.预习
找bug,链接: https://web.stanford.edu/class/cs110l/lecture-notes/lecture-02/
解答:
程序如下
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
// There are at least 7 bugs relating to memory on this snippet.
// Find them all!
// Vec is short for "vector", a common term for a resizable array.
// For simplicity, our vector type can only hold ints.
typedef struct {
int* data; // Pointer to our array on the heap
int length; // How many elements are in our array
int capacity; // How many elements our array can hold
} Vec;
Vec* vec_new() {
Vec vec;
vec.data = NULL;
vec.length = 0;
vec.capacity = 0;
return &vec;
}
void vec_push(Vec* vec, int n) {
if (vec->length == vec->capacity) {
int new_capacity = vec->capacity * 2;
int* new_data = (int*) malloc(new_capacity);
assert(new_data != NULL);
for (int i = 0; i < vec->length; ++i) {
new_data[i] = vec->data[i];
}
vec->data = new_data;
vec->capacity = new_capacity;
}
vec->data[vec->length] = n;
++vec->length;
}
void vec_free(Vec* vec) {
free(vec);
free(vec->data);
}
void main() {
Vec* vec = vec_new();
vec_push(vec, 107);
int* n = &vec->data[0];
vec_push(vec, 110);
printf("%d\n", *n);
free(vec->data);
vec_free(vec);
}
运行:
[1] 4278 segmentation fault ./pre
直接段错误
7处错误:
- 在vec_new中,创建了一个局部变量vec,并返回了&vec
- vec.data 应该是vec->data = NULL
- vec_push中不要使用assert
- vec_push中vec->length没有检查,而且可以设置为unsigned
- free(vec->data)错误
- vec_free中应该先free(vec->data)
- vec_push 中 ++vec->length错误
第一周的作业

作业链接: