---
title: "Bun의 Rust 재작성 코드, 기본 Miri 검사에서 Undefined Behavior 의심 사례 발견"
published: 2026-05-15T16:51:25.000Z
canonical: https://jeff.news/article/2761
---
# Bun의 Rust 재작성 코드, 기본 Miri 검사에서 Undefined Behavior 의심 사례 발견

Bun의 Rust 재작성 코드에서 Miri 검사 중 안전한 Rust 코드 경로에서도 Undefined Behavior가 발생할 수 있다는 이슈가 제기됐어. 문제 지점은 원시 포인터로부터 `&[u8]` 슬라이스를 만드는 부분이고, Miri는 이를 dangling reference로 판단했어.

- Bun의 Rust 재작성 코드에서 Miri가 Undefined Behavior를 잡아냈다는 이슈가 올라옴
  - 에러 메시지는 `&[u8]` 타입의 잘못된 값을 만들었다고 보고함
  - 구체적으로는 dangling reference, 즉 이미 유효하지 않거나 provenance가 없는 주소를 참조로 만들었다는 판정임

- 문제가 찍힌 코드는 `unsafe { core::slice::from_raw_parts(ptr as *const u8, self.len()) }` 부분임
  - `from_raw_parts`는 원시 포인터와 길이만 받아서 슬라이스를 만들어주는 저수준 API임
  - Rust 입장에서는 이 포인터가 진짜 유효한 메모리를 가리키는지, 길이만큼 읽어도 되는지 개발자가 보장해야 함

> [!WARNING]
> Rust로 썼다고 자동으로 안전한 게 아님. `unsafe` 블록이 잘못된 참조를 만들면 safe Rust 바깥에서 터진 문제가 safe API 안으로 그대로 들어올 수 있음.

- Miri의 에러는 꽤 직접적임
  - `constructing invalid value of type &[u8]`라고 찍힘
  - 주소 `0x20933[noalloc]`에 provenance가 없다고 나오는데, 쉽게 말하면 Rust가 추적할 수 있는 정상 할당에서 나온 포인터가 아니라는 뜻임
  - 스택 트레이스도 `PathString::slice`에서 시작해 `main`까지 이어짐

- 이 이슈가 찝는 포인트는 “Rust 재작성” 자체보다 `unsafe` 경계 관리임
  - 런타임이나 번들러처럼 성능이 중요한 코드는 원시 포인터, 커스텀 문자열, 버퍼 뷰 같은 저수준 최적화를 자주 건드림
  - 이런 코드에서 safe wrapper를 제공하더라도 내부 불변 조건이 틀리면 겉 API가 안전해 보이는 게 별 의미 없어짐

- 한국 개발자 입장에서도 꽤 현실적인 교훈이 있음
  - Rust 도입을 “메모리 안전성 확보”로만 포장하면 위험함
  - 실제로는 `unsafe` 사용 지점, 포인터 provenance, 슬라이스 생성 조건 같은 부분을 리뷰와 도구로 계속 검증해야 함
  - 특히 기존 C/C++/Zig 스타일 저수준 코드를 Rust로 옮기는 프로젝트라면 Miri를 CI나 최소한 재현 테스트에 붙이는 게 꽤 설득력 있음

---

## 기술 맥락

- 여기서 핵심 선택은 원시 포인터를 `&[u8]` 슬라이스로 바꾸는 방식이에요. Rust의 슬라이스는 단순한 포인터+길이가 아니라, “이 메모리는 읽어도 되고 참조로 다뤄도 된다”는 약속까지 포함하거든요.

- `core::slice::from_raw_parts`를 쓴 이유는 성능이나 내부 데이터 표현 때문일 가능성이 커요. 문자열이나 경로 같은 값을 복사하지 않고 바로 바이트 뷰로 보고 싶을 때 이런 API를 쓰는데, 대신 포인터가 정상 할당에서 왔는지와 길이가 유효한지는 호출자가 책임져야 해요.

- Miri가 중요해지는 이유는 컴파일러가 이런 런타임 조건을 전부 증명해주지 못하기 때문이에요. 코드가 컴파일되고 테스트가 지나가도, 잘못된 참조를 만든 순간 Rust의 안전성 모델에서는 이미 선을 넘은 상태가 될 수 있어요.

- Bun처럼 성능을 강하게 의식하는 프로젝트에서는 `unsafe`를 완전히 없애기 어렵습니다. 그래서 현실적인 포인트는 `unsafe`를 쓰지 말자가 아니라, `unsafe` 주변의 불변 조건을 작게 만들고 Miri 같은 도구로 계속 확인하는 쪽이에요.

## 핵심 포인트

- `core::slice::from_raw_parts` 호출에서 유효하지 않은 `&[u8]` 값이 만들어진 것으로 보고됨
- Miri는 해당 포인터가 provenance 없는 dangling reference라고 지적함
- Rust로 재작성한다고 자동으로 메모리 안전성이 보장되는 건 아니고, `unsafe` 경계 검증이 핵심임

## 인사이트

Bun처럼 런타임/툴체인 레벨 코드를 Rust로 옮길 때 제일 무서운 지점이 딱 여기야. 겉으로는 safe Rust API처럼 보여도 내부 `unsafe`가 잘못되면 안전성 보장은 바로 깨짐.
