661 words
3 minutes
prevent_Crashes_Overflow_UB_Invalid_memory_access

link#


These patterns prevent crashes, overflow, UB, or invalid memory access.#

  • In systems programming (C, C++, Rust, Zig, kernel code, compilers, parsers, allocators, etc.), there are several very common defensive patterns like

0. Your pattern in context#

  • Your code uses these patterns:
patternwhere
clampmin(count)
pointer + lenStringView
check before movechop_left
check before subtractchop_right
slice instead pointerRust version
defensive programmingwhole code
  • This is exactly the style used in:
    • Zig std
    • Rust std
    • LLVM
    • Linux kernel
    • SQLite
    • Redis
    • game engines

00. Core rule of systems programming#

  • Most common rules:
never trust input
never exceed length
never underflow
never overflow
never move pointer blindly
always clamp
always check
  • These patterns appear everywhere in low-level code.
절대 신뢰할 수 없는 입력
길이를 초과하지 않음
절대로 흐르지 않음
절대 넘치지 않음
포인터를 맹목적으로 움직이지 않기
항상 클램프
항상 확인
  • clamp
  • In computer science, clamping, or clipping is the process of limiting a value to a range between a minimum and a maximum value. Unlike wrapping, Clamping moves a value to the nearest boundary if it is outside the allowed range.
    • 컴퓨터 과학에서 클램핑 또는 클리핑은 값을 최소 값과 최대 값 사이의 범위로 제한하는 프로세스입니다. 래핑과 달리 클램핑은 허용 범위를 벗어난 경우 값을 가장 가까운 경계로 이동합니다.
  • https://en.wikipedia.org/wiki/Clamp_(function)

1. Clamp pattern (min / max)#

  • Pattern
// main.c
if (n > len)
    n = len;
  • Rust:
let n = n.min(len);
  • Meaning:

Never exceed bounds

  • Used in:

    • string slicing
    • buffer writing
    • reading files
    • network packets
    • parsers
  • Example:

fn read(buf: &mut [u8], n: usize) {
    let n = n.min(buf.len());
}

2. Clamp to range (min + max)#

  • Pattern:
// main.rs
x = x.clamp(min, max);
  • Same as:
// main.c
if (x < min) x = min;
if (x > max) x = max;
  • Example:
// main.rs
let volume = volume.clamp(0, 100);
  • Used in:
    • graphics
    • audio
    • physics
    • UI
    • game engines

3. Check before pointer move#

  • Very common in C.
// main.c
if (ptr + n <= end)
    ptr += n;
  • Rust equivalent:
// main.rs
if n <= slice.len() {
    slice = &slice[n..];
}
  • Meaning:

Never move pointer past end

  • Used in:
    • parsers
    • lexers
    • binary readers
    • networking

4. Length + pointer pair pattern#

  • Used in your example.
pointer + length
  • C:
// main.c
char *data;
size_t len;
  • Rust:
&[u8]
&str
  • Used in:

    • string_view
    • slices
    • buffers
    • kernel code
    • compilers
  • Example:

struct View<'a> {
    data: &'a [u8],
    len: usize,
}

5. Check before subtract#

  • Pattern:
// main.c
if (n > len)
    n = len;

len -= n;
// main.rs
let n = n.min(len);
len -= n;
  • Meaning:

Never underflow

  • Why?
    • Because unsigned:
// main.c
size_t len = 5;
len -= 10;  
  • Result:
huge number (underflow)
  • Very dangerous.

  • Used in:

    • allocators
    • containers
    • string_view
    • ring buffers

6. Null / empty check pattern#

  • C:
// main.c
if (ptr == NULL)
    return;
  • Rust
if slice.is_empty() {
    return;
}
  • Meaning:

Handle empty case first

  • Used everywhere.

7. Early return pattern#

  • Very common in kernel / Rust / C.
// main.rs
if n == 0 {
    return;
}
  • or
// main.c
if (!ptr)
    return;
  • Meaning:

Exit early to keep code safe

  • Used in:
    • OS kernels
    • drivers
    • parsers
    • allocators

8. Saturating arithmetic pattern#

  • Rust:
// main.rs
x = x.saturating_add(y);
x = x.saturating_sub(y);
  • Meaning:

Never overflow

  • Example:
// main.rs
let x: u8 = 250;
let y = x.saturating_add(10); // 255, not overflow
  • Used in:

    • embedded
    • kernel
    • graphics
    • DSP
  • C equivalent:

// main.c
if (x > MAX - y)
    x = MAX;
else
    x += y;

9. Checked arithmetic pattern#

  • Rust:
// main.rs
x.checked_add(y)
  • Returns Option.

  • Used when overflow must be detected.

  • Example:

// main.rs
if let Some(v) = x.checked_add(y) {
    x = v;
}
  • Used in:
    • crypto
    • big integers
    • parsers
    • compilers

10. Slice instead of pointer math (Rust pattern)#

  • C:
// main.c
ptr += n;
len -= n;
  • Rust:
// main.rs
slice = &slice[n..];
  • Safer.

  • Used everywhere in Rust std.

11. Defensive copy length pattern#

  • C:
// main.c
memcpy(dst, src, min(dst_size, src_size));
  • Rust:
// main.rs
let n = dst.len().min(src.len());
dst[..n].copy_from_slice(&src[..n]);
  • Used in:
    • networking
    • kernel
    • file IO
    • serialization

12. Bounds check before index#

  • C:
// main.c
if (i < len)
    x = arr[i];
  • Rust:
// main.rs
if let Some(x) = arr.get(i) {
}
  • Used everywhere.

13. Sentinel / end pointer pattern#

  • C parsers use this:
// main.c
while (ptr < end)
  • Rust:
// main.rs
while !slice.is_empty()
  • Used in:
    • compilers
    • lexers
    • JSON parsers
    • HTTP parsers
prevent_Crashes_Overflow_UB_Invalid_memory_access
https://younghakim7.github.io/blog/posts/prevent_crashes_overflow_ub_invalid_memory_access/
Author
YoungHa
Published at
2026-03-20