Translating C code into safe Rust is an effective way to ensure its memory safety. Compared to rule-based translation which produces Rust code that remains largely unsafe, LLM-based methods can generate more idiomatic and safer Rust code because LLMs have been trained on vast amount of human-written idiomatic code. Although promising, existing LLM-based methods still struggle with project-level C-to-Rust translation. They typically partition a C project into smaller units (\eg{} functions) based on call graphs and translate them bottom-up to resolve program dependencies. However, this bottom-up, unit-by-unit paradigm often fails to translate pointers due to the lack of a global perspective on their usage. To address this problem, we propose a novel C-Rust Pointer Knowledge Graph (KG) that enriches a code-dependency graph with two types of pointer semantics: (i) pointer-usage information which record global behaviors such as points-to flows and map lower-level struct usage to higher-level units; and (ii) Rust-oriented annotations which encode ownership, mutability, nullability, and lifetime. Synthesizing the \kg{} with LLMs, we further propose \ourtool{}, which implements a project-level C-to-Rust translation technique. In \ourtool{}, the \kg{} provides LLMs with comprehensive pointer semantics from a global perspective, thus guiding LLMs towards generating safe and idiomatic Rust code from a given C project. Our experiments show that \ourtool{} reduces unsafe usages in translated Rust by 99.9\% compared to both rule-based translation and traditional LLM-based rewriting, while achieving an average 29.3\% higher functional correctness than those fuzzing-enhanced LLM methods.
- 논문 ID: 2510.10956
- 제목: Project-Level C-to-Rust Translation via Synergistic Integration of Knowledge Graphs and Large Language Models
- 저자: Zhiqiang Yuan, Wenjun Mao, Zhuo Chen, Xiyue Shang, Chong Wang, Yiling Lou, Xin Peng
- 분류: cs.SE (소프트웨어 공학), cs.AI (인공지능)
- 발표 시간: 2025년 10월 13일
- 논문 링크: https://arxiv.org/abs/2510.10956
C 코드를 안전한 Rust 코드로 번역하는 것은 메모리 안전성을 보장하는 효과적인 방법이다. 많은 양의 안전하지 않은 코드를 생성하는 규칙 기반 번역 방법과 비교하여, 대규모 언어 모델(LLM) 기반 방법은 더욱 관용적이고 안전한 Rust 코드를 생성할 수 있다. 그러나 기존 LLM 방법은 프로젝트 수준의 C-to-Rust 번역에서 여전히 어려움을 겪고 있으며, 특히 포인터 처리 시 전역적 관점이 부족하다. 이 문제를 해결하기 위해 본 논문은 새로운 C-Rust 포인터 지식 그래프(KG)를 제안하며, 이는 두 가지 포인터 의미론으로 코드 의존성 그래프를 풍부하게 한다: (1) 전역 동작을 기록하는 포인터 사용 정보; (2) 소유권, 가변성, 널 가능성 및 생명주기를 인코딩하는 Rust 지향 주석. 이 지식 그래프를 기반으로 프로젝트 수준의 C-to-Rust 번역을 구현하는 PTRMAPPER 기술을 제안한다. 실험 결과 PTRMAPPER는 규칙 기반 및 기존 LLM 방법과 비교하여 안전하지 않은 코드 사용을 99.9% 감소시켰으며, 기능 정확성에서 평균 29.3% 향상되었다.
C 언어는 운영 체제, 임베디드 시스템 및 성능 중심 애플리케이션에 광범위하게 적용되지만, 수동 메모리 관리 및 직접 포인터 조작은 버퍼 오버플로우, 메모리 누수 등의 보안 취약점을 초래한다. Rust는 현대적 대안으로서 C 언어의 성능을 유지하면서 메모리 안전성을 보장한다. 따라서 레거시 C 코드를 자동으로 Rust로 번역하는 것이 시급한 요구사항이다.
- 규칙 기반 방법: 사전 정의된 규칙에 의존하며, 생성된 Rust 코드는 unsafe 블록, 원시 포인터 및 외부 함수 호출을 많이 사용하여 여전히 보안 위험이 존재한다
- 기존 LLM 방법: 상향식 단위 번역 패러다임을 채택하여 전역 포인터 사용 관점이 부족하며, 포인터 번역에서 정의-사용 충돌이 자주 발생한다
C와 Rust는 포인터 사용에서 근본적인 차이가 있다:
- C 언어: 포인터가 매우 유연하며, 정의 시 타입만 지정하고 사용 시 자유롭게 읽기/쓰기 수정이 가능하다
- Rust 언어: 포인터 사용이 엄격하게 제한되며, 정의 시 소유권, 가변성 및 생명주기를 명시적으로 지정해야 하고, 사용 시 차용 검사기 규칙을 엄격히 준수해야 한다
- 새로운 C-Rust 포인터 지식 그래프(KG) 제안: 프로젝트 수준 컨텍스트에서 코드 단위 의존성, 포인터 사용 정보 및 Rust 지향 주석을 포괄적으로 모델링할 수 있다
- PTRMAPPER 프로젝트 수준 번역 기술 설계: C-Rust 포인터 KG를 LLM과 협력하여 C 프로젝트를 안전하고 관용적인 Rust 코드로 번역한다
- 현저한 성능 향상 달성: 더욱 관용적이고 안전하며 정확성이 높은 Rust 코드를 생성한다
- 포괄적인 실험 검증 제공: 소거 실험을 통해 포인터 사용 정보 및 Rust 지향 주석이 번역 성능 향상에 미치는 중요성을 입증한다
주어진 C 프로젝트를 기능적으로 동등하고 메모리 안전하며 관용적인 Rust 프로젝트로 자동 번역한다. 입력은 C 소스 코드 파일 집합이고, 출력은 컴파일 및 실행 가능한 Rust 프로젝트이다.
PTRMAPPER는 세 가지 주요 단계로 구성된다:
지식 그래프 스키마 설계:
- 코드 의존성 그래프: 코드 단위(함수, 구조체, 열거형 등) 간의 의존성 관계를 설명한다
- 포인터 사용 정보: 프로젝트 수준 포인터 동작을 포착하며, 다음을 포함한다:
- 엔티티: Param(매개변수), Value(반환값), Member(멤버), Pointer(포인터) 등
- 관계: derivesFrom(파생 관계), mayAlias/noAlias(별칭 관계), pointsTo(지시 관계) 등
- Rust 지향 주석: 소유권, 가변성, 널 가능성, 생명주기 등의 의미론을 포함한다
구축 프로세스:
- 코드 의존성 그래프 추출: 정적 분석을 사용하여 코드 단위 및 의존성 관계를 추출한다
- 포인터 사용 정보 추출: 컨텍스트 민감하고 필드 민감한 분석 전략을 채택한다
- Rust 지향 주석 추출: 사전 정의된 규칙을 기반으로 포인터 생명주기를 분석하고 해당 의미론에 주석을 단다
번역 단위 식별 및 정렬:
- Tarjan 알고리즘을 사용하여 강연결 요소(SCC) 감지
- 각 SCC를 독립적인 번역 단위로 취급
- 위상 정렬을 통해 상향식 번역 순서를 결정한다
포인터 의미론 추출:
각 번역 단위에 대해 KG에서 해당 포인터 의미론 지식을 추출하여 <엔티티1, 관계, 엔티티2> 삼중항 형식으로 LLM에 제공한다.
증분 번역 및 검증:
- 번역 단위, 포인터 의미론 지식 및 이미 번역된 Rust 컨텍스트를 번역 프롬프트에 통합한다
- 각 번역 단위가 생성된 후 즉시 Rust 프로젝트에 통합되고 컴파일 검증된다
- 오류 발생 시 오류 수정 메커니즘을 트리거한다
Rust 버전의 포인터 KG를 활용하여 LLM에 프로젝트 수준 의미론 컨텍스트를 제공한다:
- 의존성 관계는 오류 관련 코드 단위를 정확히 식별하는 데 도움이 된다
- Rust 지향 주석은 효과적인 수정을 위한 정확한 프로그램 의미론 지침을 제공한다
- 전역 포인터 의미론 모델링: 프로젝트 수준 포인터 사용 정보 및 Rust 특정 의미론을 지식 그래프에 처음으로 통합한다
- 협력적 번역 패러다임: 지식 그래프의 전역 관점과 LLM의 생성 능력을 결합한다
- 증분 검증 메커니즘: 오류를 적시에 발견하고 수정하여 오류 누적을 방지한다
- 지능형 오류 수정: 컴파일러 오류 정보만이 아닌 KG의 의미론 정보를 기반으로 한다
CROWN 데이터셋의 16개 실제 C 프로젝트를 사용하며, 코드 라인 수는 154에서 14,829까지 다양하며, 다음을 포함한다:
- avl, buffer, genann, quadtree, rgba, urlparser 등 소형 프로젝트
- bzip2, heman, lodepng 등 대형 프로젝트
기능 동등성을 평가하기 위해 단위 테스트를 수동으로 구축하여 81.4%-97.7%의 라인 커버리지와 92.9%-100.0%의 함수 커버리지를 달성했다.
관용성 평가:
- Lint Alert Count: Rust-Clippy를 사용하여 관용적이지 않은 코드 경고 수를 계산한다
- Unsafe Usage Count: Cargo-geiger를 사용하여 unsafe 코드 사용 횟수를 계산한다
정확성 평가:
- Compiled: 컴파일 성공한 함수의 비율
- Equiv.: 단위 테스트를 통과한 함수의 비율
- 관용성 비교: CROWN(규칙 기반), PR2(LLM 재작성)
- 정확성 비교: FLOURINE(퍼징 테스트 강화 LLM 방법)
- 소거 실험: PTRTRANSPS, PTRTRANSPU, PTRTRANSRA, PTRTRANSEC 등 변형
- LLM: ChatGPT-4o, temperature=0
- 정적 분석: Clang, Doxygen, SVF 프레임워크
- 오류 수정: 최대 5회 반복
- 컴파일 검증: cargo check
관용성 현저히 향상:
- CROWN 대비: Lint 경고 94.9% 감소(6,802→349), unsafe 사용 99.9% 감소(141,866→85)
- PR2 대비: Lint 경고 91.8% 감소(4,272→349), unsafe 사용 99.9% 감소(134,185→85)
정확성 대폭 개선:
- FLOURINE 대비: 컴파일 성공률 28.4% 향상(98.3% vs 69.9%), 기능 동등성 29.3% 향상(81.6% vs 52.3%)
- 소형 프로젝트(avl, rgba, ht, bst)는 100% 기능 동등성 달성
소거 실험은 각 구성 요소의 중요성을 검증했다:
- 포인터 의미론 없음(PTRTRANSPS): 동등성이 81.6%에서 59.5%로 감소, 22.1% 하락
- 포인터 사용 정보만(PTRTRANSRA): 완전한 버전보다 성능 저하
- Rust 주석만(PTRTRANSPU): 동일하게 성능 저하
- 오류 수정 없음(PTRTRANSEC): 동등성이 81.6%에서 50.8%로 감소, 30.8% 하락
PTRMAPPER는 다양한 복잡도에서 안정적인 성능을 보인다:
- 코드 라인 수: 복잡도 증가에 따라 성능이 안정적이며, FLOURINE은 급격히 하락한다
- 의존성 관계: 의존성 수[16,44)일 때 동등성 57.1%, FLOURINE은 0%
- 포인터 수: 포인터 수[20,50)일 때 동등성 50.0%, FLOURINE은 0%
Quadtree 프로젝트를 예로 들어 PTRMAPPER가 복잡한 차용 충돌을 해결하는 방법을 보여준다:
tree 매개변수가 불변 차용 &Quadtree이어야 함을 식별한다root를 가변 차용 &mut QuadtreeNode로 분리한다key_free를 독립적인 매개변수로 추출하여 차용 충돌을 회피한다- 소유권 의미론을 올바르게 처리한다
- 규칙 기반 방법: Corrode, C2RUST 등으로 많은 양의 unsafe 코드를 생성한다
- LLM 기반 방법: SPECTRA, FLOURINE 등으로 전역 관점이 부족하다
- 단위 번역 방법: SYZYGY 등으로 포인터 의미론 손실 문제가 있다
- 프로젝트 수준 포인터 의미론을 처음으로 체계적으로 모델링한다
- 정적 분석과 LLM 생성을 결합한 협력적 방법이다
- 안전성과 정확성을 현저히 향상시킨다
- C-Rust 포인터 지식 그래프는 프로젝트 수준 번역에서 포인터 의미론 손실 문제를 효과적으로 해결한다
- 정적 분석과 LLM의 협력적 통합은 번역 품질을 현저히 향상시킨다
- 증분 검증 및 지능형 오류 수정 메커니즘은 번역 신뢰성을 보장한다
- 구축 오버헤드: 지식 그래프 구축에 추가 정적 분석 시간이 필요하다
- 규칙 의존성: Rust 주석 추출이 사전 정의된 규칙에 의존하여 커버리지가 불완전할 수 있다
- 프로젝트 규모: 초대형 프로젝트의 확장성이 검증 대기 중이다
- 수동 개입: 복잡한 경우 여전히 소량의 수동 조정이 필요할 수 있다
- 지식 그래프 구축 효율성 최적화
- 더 많은 프로그래밍 언어 쌍으로 확장
- 더 많은 프로그램 분석 기술 통합
- 자동화 수준 향상
- 높은 혁신성: 지식 그래프와 LLM을 코드 번역에 처음으로 결합하여 기존 방법의 근본 문제를 해결한다
- 체계적 방법론: 문제 분석에서 솔루션 설계까지 완전하며 기술 경로가 명확하다
- 충분한 실험: 16개 실제 프로젝트, 다양한 비교 방법, 상세한 소거 실험
- 현저한 효과: 안전성, 관용성, 정확성 세 가지 차원에서 모두 현저한 향상을 달성한다
- 높은 실용 가치: 실제 공학 문제를 해결하며 매우 강한 응용 전망이 있다
- 확장성 문제: 정적 분석의 계산 복잡도가 초대형 프로젝트에서의 적용을 제한할 수 있다
- 규칙 완전성: Rust 주석 추출 규칙이 모든 경계 사례를 커버하지 못할 수 있다
- 평가 한계: 주로 중소형 프로젝트에서 검증되었으며 대형 프로젝트의 성능은 추가 검증이 필요하다
- 의존성 품질: 방법 효과가 정적 분석의 정확성에 크게 의존한다
- 학술 기여: 코드 번역 분야에 새로운 연구 패러다임을 제공하며 프로그램 분석과 생성형 AI를 결합한다
- 공학 가치: C-to-Rust 마이그레이션을 위한 실용적 도구를 제공하여 소프트웨어 안전성 향상에 기여한다
- 기술 영감: 지식 그래프 기반 LLM 지도 방식을 다른 코드 생성 작업으로 확대할 수 있다
- 레거시 시스템 마이그레이션: C 코드베이스를 Rust로 마이그레이션해야 하는 프로젝트에 적합하다
- 안전 중심 애플리케이션: 메모리 안전성 요구사항이 높은 시스템 개발에 적합하다
- 자동화 도구: IDE 또는 CI/CD 파이프라인에 통합될 수 있다
- 교육 훈련: 개발자가 Rust의 메모리 안전 개념을 학습하는 데 도움이 된다
논문은 76편의 관련 문헌을 인용하며, 코드 번역, 프로그램 분석, 대규모 언어 모델 등 여러 분야의 중요한 연구를 포함하여 연구에 견고한 이론적 기초를 제공한다.
종합 평가: 이는 고품질의 소프트웨어 공학 연구 논문으로, 지식 그래프와 대규모 언어 모델을 혁신적으로 결합하여 C-to-Rust 번역의 핵심 문제를 해결한다. 방법 설계가 합리적이고 실험 검증이 충분하며 결과가 설득력 있다. 일부 한계가 있지만 코드 번역 분야에 새로운 연구 방향을 개척했으며 중요한 학술 가치와 실용적 의의를 가진다.