Skip to content

Feat: implement #[precond] #[hazard] and #[option] proc-macros #7

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 18 commits into from
May 23, 2025

Conversation

zjp-CN
Copy link
Member

@zjp-CN zjp-CN commented May 23, 2025

This PR mainly implements safety attribute proc-macros listed in the title

For example, #[precond] will expand to

  • #[doc] which is used to generate rustdoc content
  • #[Safety::inner(Property, kind = "precond", ...)] a registered tool attribute , used in the rustc driver with kind and Property analyzed
#![feature(register_tool)]
#![register_tool(Safety)]

use safety_tool_lib::safety;

#[safety::precond(
    UnReachable,
    memo = "It's undefined behavior to reach code marked with this intrinsic function."
)]

is expanded to

/// It's undefined behavior to reach code marked with this intrinsic function.
#[Safety::inner(
    UnReachable,
    kind = "precond",
    memo = "It's undefined behavior to reach code marked with this intrinsic function."
)]
More examples

#[safety::precond(
    Init(self.ptr, u8, self.len),
    memo = "The ptr must be initialized first!"
)]
#[safety::precond(
    InBound(self.ptr, u8, self.len),
    memo = "The ptr must be within the length."
)]
#[safety::precond(
    ValidNum(self.len*sizeof(u8), [0,isize::MAX]),
    memo = "Slice length can't exceed isize::MAX due to allocation limit."
)]
#[safety::hazard(
    Alias(self.ptr),
    memo = "Make sure don't alias the ptr."
)]

expanded to

/// The ptr must be initialized first!
#[Safety::inner(
    Init(self.ptr, u8, self.len),
    kind = "precond",
    memo = "The ptr must be initialized first!"
)]
/// The ptr must be within the length.
#[Safety::inner(
    InBound(self.ptr, u8, self.len),
    kind = "precond",
    memo = "The ptr must be within the length."
)]
/// Slice length can't exceed isize::MAX due to allocation limit.
#[Safety::inner(
    ValidNum(self.len*sizeof(u8), [0, isize::MAX]),
    kind = "precond",
    memo = "Slice length can't exceed isize::MAX due to allocation limit."
)]
/// Make sure don't alias the ptr.
#[Safety::inner(
    Alias(self.ptr),
    kind = "hazard",
    memo = "Make sure don't alias the ptr."
)]

Implementation details:

  • safety-tool-parser crate is a attribute macro syntax parser, and shared between safety-tool-macro and rustc driver
  • safety-tool-macro crate is a proc-macro lib, used to add #[doc] and #[Safety::inner] attributes for the annotated function
  • safety-tool-lib crate is mainly for public use, especially for another tool like klint
    • the lib crate will contain the analysis routines

NOTE: the registered tool attribute is changed from safety to Safety.

zjp-CN added 18 commits May 23, 2025 07:22
close Artisan-Lab#6

********* "demo" [Rlib] has reached 8 instances *********
(stable mir) "test" ("src/lib.rs:9:1: 9:26") => "#[safety::precond::UnReachable(memo =\n\"It's undefined behavior to reach code ma
rked with this intrinsic function.\")]\n"

(stable mir) "MyStruct::get" ("src/lib.rs:37:5: 37:42") => "#[safety::precond::Init(self.ptr, u8, self.len, memo =\n\"The ptr must
 be initialized first!\")]\n"

(stable mir) "MyStruct::get" ("src/lib.rs:37:5: 37:42") => "#[safety::precond::InBound(self.ptr, u8, self.len, memo =\n\"The ptr m
ust be within the length.\")]\n"

(stable mir) "MyStruct::get" ("src/lib.rs:37:5: 37:42") => "#[safety::precond::ValidNum(self.len*sizeof(u8), [0,isize::MAX], memo
=\n\"Slice length can't exceed isize::MAX due to allocation limit.\")]\n"

(stable mir) "MyStruct::get" ("src/lib.rs:37:5: 37:42") => "#[safety::hazard::Alias(self.ptr, memo = \"Make sure don't alias the p
tr.\")]\n"

********* "demo" [Executable] has reached 18 instances *********
(internal api) "demo::MyStruct::get" ("/home/gh-zjp-CN/tag-std/demo/rustc_driver/tests/basic/src/lib.rs:37:5: 37:42") => "#[safety
::precond::Init(self.ptr, u8, self.len, memo =\n\"The ptr must be initialized first!\")]\n"

(internal api) "demo::MyStruct::get" ("/home/gh-zjp-CN/tag-std/demo/rustc_driver/tests/basic/src/lib.rs:37:5: 37:42") => "#[safety
::precond::InBound(self.ptr, u8, self.len, memo =\n\"The ptr must be within the length.\")]\n"

(internal api) "demo::MyStruct::get" ("/home/gh-zjp-CN/tag-std/demo/rustc_driver/tests/basic/src/lib.rs:37:5: 37:42") => "#[safety
::precond::ValidNum(self.len*sizeof(u8), [0,isize::MAX], memo =\n\"Slice length can't exceed isize::MAX due to allocation limit.\"
)]\n"

(internal api) "demo::MyStruct::get" ("/home/gh-zjp-CN/tag-std/demo/rustc_driver/tests/basic/src/lib.rs:37:5: 37:42") => "#[safety
::hazard::Alias(self.ptr, memo = \"Make sure don't alias the ptr.\")]\n"
\#[safety(
    Init(self.ptr, u8, self.len),
    memo = "reason"
)]
/// This is a single line.
fn single_line() {}
/// Line 1.
/// Line 2.
fn multi_lines() {}
/// Line 1.
/// Line 2.
fn multi_lines2() {}
/// Line 1.
/// Line 2.
/// Line 3.
fn multi_lines3() {}
seems cargo fill this through stdin?

also fixes CARGO_SAFE_TOOL var.
********* "demo" [Rlib] has reached 8 instances *********
"test" ("src/lib.rs:12:1: 12:26")
 => "#[Safety::inner(UnReachable, kind = \"precond\", memo =\n\"It's undefined behavior to reach code marked with this intrinsic function.\")]\n"

"MyStruct::get" ("src/lib.rs:40:5: 40:42")
 => "#[Safety::inner(Init(self.ptr, u8, self.len), kind = \"precond\", memo =\n\"The ptr must be initialized first!\")]\n"

"MyStruct::get" ("src/lib.rs:40:5: 40:42")
 => "#[Safety::inner(InBound(self.ptr, u8, self.len), kind = \"precond\", memo =\n\"The ptr must be within the length.\")]\n"

"MyStruct::get" ("src/lib.rs:40:5: 40:42")
 => "#[Safety::inner(ValidNum(self.len * sizeof(u8), [0, isize :: MAX]), kind =\n\"precond\", memo =\n\"Slice length can't exceed isize::MAX due to allocation limit.\")]\n"

"MyStruct::get" ("src/lib.rs:40:5: 40:42")
 => "#[Safety::inner(Alias(self.ptr), kind = \"hazard\", memo =\n\"Make sure don't alias the ptr.\")]\n"

********* "demo" [Executable] has reached 18 instances *********
"demo::MyStruct::get" ("/home/gh-zjp-CN/tag-std/demo/rustc_driver/tests/basic/src/lib.rs:40:5: 40:42")
 => "#[Safety::inner(Init(self.ptr, u8, self.len), kind = \"precond\", memo =\n\"The ptr must be initialized first!\")]\n"

"demo::MyStruct::get" ("/home/gh-zjp-CN/tag-std/demo/rustc_driver/tests/basic/src/lib.rs:40:5: 40:42")
 => "#[Safety::inner(InBound(self.ptr, u8, self.len), kind = \"precond\", memo =\n\"The ptr must be within the length.\")]\n"

"demo::MyStruct::get" ("/home/gh-zjp-CN/tag-std/demo/rustc_driver/tests/basic/src/lib.rs:40:5: 40:42")
 => "#[Safety::inner(ValidNum(self.len * sizeof(u8), [0, isize :: MAX]), kind =\n\"precond\", memo =\n\"Slice length can't exceed isize::MAX due to allocation limit.\")]\n"

"demo::MyStruct::get" ("/home/gh-zjp-CN/tag-std/demo/rustc_driver/tests/basic/src/lib.rs:40:5: 40:42")
 => "#[Safety::inner(Alias(self.ptr), kind = \"hazard\", memo =\n\"Make sure don't alias the ptr.\")]\n"
@zjp-CN zjp-CN merged commit 2928817 into Artisan-Lab:main May 23, 2025
@zjp-CN zjp-CN deleted the attr-memo branch May 23, 2025 08:33
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Syntax: ::memo doesn't compile due to AST parsing from rustc, even for registered tool
1 participant