about summary refs log tree commit diff
path: root/src/docs/uninit_vec.txt
diff options
context:
space:
mode:
authorPhilipp Krones <hello@philkrones.com>2022-09-09 13:36:26 +0200
committerPhilipp Krones <hello@philkrones.com>2022-09-09 13:36:26 +0200
commit98bf99e2f8cf8b357d63a67ce67d5fc5ceef8b3c (patch)
tree9737ff22b257f29282e7538d9ecb264451a3c1c0 /src/docs/uninit_vec.txt
parent854f751b263dfac06dc3f635f8a9f92b8bc51da6 (diff)
Merge commit 'b52fb5234cd7c11ecfae51897a6f7fa52e8777fc' into clippyup
Diffstat (limited to 'src/docs/uninit_vec.txt')
-rw-r--r--src/docs/uninit_vec.txt41
1 files changed, 41 insertions, 0 deletions
diff --git a/src/docs/uninit_vec.txt b/src/docs/uninit_vec.txt
new file mode 100644
index 00000000000..cd50afe78f6
--- /dev/null
+++ b/src/docs/uninit_vec.txt
@@ -0,0 +1,41 @@
+### What it does
+Checks for `set_len()` call that creates `Vec` with uninitialized elements.
+This is commonly caused by calling `set_len()` right after allocating or
+reserving a buffer with `new()`, `default()`, `with_capacity()`, or `reserve()`.
+
+### Why is this bad?
+It creates a `Vec` with uninitialized data, which leads to
+undefined behavior with most safe operations. Notably, uninitialized
+`Vec<u8>` must not be used with generic `Read`.
+
+Moreover, calling `set_len()` on a `Vec` created with `new()` or `default()`
+creates out-of-bound values that lead to heap memory corruption when used.
+
+### Known Problems
+This lint only checks directly adjacent statements.
+
+### Example
+```
+let mut vec: Vec<u8> = Vec::with_capacity(1000);
+unsafe { vec.set_len(1000); }
+reader.read(&mut vec); // undefined behavior!
+```
+
+### How to fix?
+1. Use an initialized buffer:
+   ```rust,ignore
+   let mut vec: Vec<u8> = vec![0; 1000];
+   reader.read(&mut vec);
+   ```
+2. Wrap the content in `MaybeUninit`:
+   ```rust,ignore
+   let mut vec: Vec<MaybeUninit<T>> = Vec::with_capacity(1000);
+   vec.set_len(1000);  // `MaybeUninit` can be uninitialized
+   ```
+3. If you are on 1.60.0 or later, `Vec::spare_capacity_mut()` is available:
+   ```rust,ignore
+   let mut vec: Vec<u8> = Vec::with_capacity(1000);
+   let remaining = vec.spare_capacity_mut();  // `&mut [MaybeUninit<u8>]`
+   // perform initialization with `remaining`
+   vec.set_len(...);  // Safe to call `set_len()` on initialized part
+   ```
\ No newline at end of file