summaryrefslogtreecommitdiffstats
path: root/src/tools/clippy/src/docs/uninit_vec.txt
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/tools/clippy/src/docs/uninit_vec.txt41
1 files changed, 41 insertions, 0 deletions
diff --git a/src/tools/clippy/src/docs/uninit_vec.txt b/src/tools/clippy/src/docs/uninit_vec.txt
new file mode 100644
index 000000000..cd50afe78
--- /dev/null
+++ b/src/tools/clippy/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