A method for detecting defects in unsafe code snippets in the Rust programming language

By using hybrid analysis techniques of HIR and MIR in the Rust programming language, UNSAFE code fragments are identified, solving the problem of inaccurate UNSAFE code scope and improving code security and quality.

CN116089302BActive Publication Date: 2026-05-29NORTHEASTERN UNIV CHINA

Patent Information

Authority / Receiving Office
CN · China
Patent Type
Patents(China)
Current Assignee / Owner
NORTHEASTERN UNIV CHINA
Filing Date
2023-02-21
Publication Date
2026-05-29

AI Technical Summary

Technical Problem

The scope of UNSAFE code snippets in the Rust programming language is not precise enough, making it difficult for developers to accurately mark unsafe functions or methods, increasing the difficulty of code review and causing security risks.

Method used

By using hybrid analysis techniques of HIR and MIR, the UNSAFE code snippets are identified through the rustc_lint module. Combined with data flow analysis and fuzz testing techniques, unsafe operations are accurately located and reported.

Benefits of technology

It improves the accuracy of the scope of UNSAFE code snippets, helping developers identify and correct secure code, reduce security risks, and improve code quality.

✦ Generated by Eureka AI based on patent content.

Smart Images

  • Figure HDA0004088151070000011
    Figure HDA0004088151070000011
  • Figure HDA0004088151070000012
    Figure HDA0004088151070000012
  • Figure HDA0004088151070000013
    Figure HDA0004088151070000013
Patent Text Reader

Abstract

The application designs a detection method for the defect of the UNSAFE code segment in the Rust programming language, first, based on the rustc_lint module, whether the expression in the program language is contained in the unsafe block written by the developer is judged by using HIR; the structure of the expression is analyzed by using HIR; then, the unsafe operation is analyzed and identified by using MIR; finally, the safe expression or statement in the unsafe block written by the developer is reported; the data flow analysis technology for the function parameter is proposed, the alias propagation chain of the function parameter is found out; it is the key technology required for judging whether the function or method is marked with the unsafe keyword, and the target function is tested by combining the fuzz test technology to judge whether the function must be marked with the unsafe keyword.
Need to check novelty before this filing date? Find Prior Art

Description

Technical Field

[0001] This invention belongs to the field of programming languages, specifically relating to a method for detecting defects in UNSAFE code snippets in the Rust programming language. Background Technology

[0002] Software engineers use the `unsafe` keyword in less than 30% of Rust libraries, but because Unsafe Rust is hidden somewhere in the library call chain, more than half of the Rust compilers cannot perform full static checking. Therefore, for better and safer use of Rust, `unsafe` should be used with caution, and the scope of `unsafe` blocks should be as small, self-contained as possible (well-encapsulated and used only within the package).

[0003] Currently, the compiler primarily identifies five specific operations (dereferencing raw pointers, calling unsafe functions or methods, accessing or modifying mutable static variables, implementing an unsafe trait, and accessing union fields). If developers use these five operations in their code, they must use the `unsafe` modifier; otherwise, an error will be reported. Furthermore, the Rust programming language does not have a mandatory constraint on whether functions or methods are marked as `unsafe`.

[0004] The compiler only warns of five operations that must be marked with the `unsafe` flag, thus sometimes developers cannot precisely define the scope of `unsafe`. Furthermore, whether a function or method is marked as `unsafe` is entirely up to the developer; there is no mandatory requirement. Through research on related issues on GitHub, two key problems were identified regarding unsafe Rust:

[0005] First, the scope of `unsafe` is not precise enough. This means that developers may mark the scope of `unsafe` as too broad, or, for convenience, include safe Rust code. Developers can easily include safe code during coding, making the scope of `unsafe` inaccurate and increasing the difficulty of later code reviews. Figure 1This code snippet serves as a proof-of-concept (PoC) example to demonstrate this type of case. It's one of many instances of the first type of problem. The developer changed the first four lines to the last two. Here, `load()` is a safe function in the developer's project, and `stopBaker()` is an unsafe function from a third-party library. It's clear that the scope of the developer's unsafe block is imprecise. Developers easily include safe code during the coding process, making the scope of unsafe blocks less precise and increasing the difficulty of later code reviews. Clearly defined unsafe blocks make it easier to trace the root cause of problems when they occur.

[0006] Secondly, there are no hard and fast rules regarding whether functions or methods should be marked as unsafe. This has led some developers to fail to mark functions or methods that should be marked as unsafe, and to mark functions or methods that don't need to be marked as unsafe, creating security vulnerabilities for the Rust community. Therefore, it is necessary to develop corresponding algorithms to address these two shortcomings regarding unsafe code snippets, reduce security risks for the Rust programming language community, and make software projects developed using Rust more secure. Summary of the Invention

[0007] To address the shortcomings of existing technologies, this invention designs a method for detecting UNSAFE code snippets in the Rust programming language. It uses HIR (Hardware Inference) to quickly collect code regions of interest (unsafe code snippets written by developers), utilizes structural information in HIR to identify statement structures, and then uses MIR (Mandatory Inference) to infer code semantics and identify truly unsafe operations.

[0008] A method for detecting UNSAFE code snippets in the Rust programming language, specifically including the following:

[0009] Step 1: Based on the rustc_lint module, use HIR to determine whether an expression in the programming language is contained in an unsafe block written by the developer; HIR stands for High-Level Intermediate Representation.

[0010] Rust's source code is first analyzed by lexical analysis to generate an Abstract Syntax Tree (AST), which desugars the source code written by the developers. Then, a Hierarchical Representation (HIR) is generated through a query system. After type checking and removal of the unsafe keyword, it is again generated through a query system to generate an Intermediate Representation (MIR). Then, borrow checks and code optimizations are performed, and finally, it is transformed into an LLVM IR.

[0011] HIR contains structural information of the code; the node containing the current expression is found sequentially through HIR. If the type of the node is expression and the type of the expression is block, it is determined whether the block is an unsafe block written by the developer. If it is, it means that the current expression is contained in an unsafe block written by the developer, and the next step of processing is continued; otherwise, the next expression is evaluated.

[0012] Step 2: Use HIR to parse the structure of the expression;

[0013] Rust has a total of 32 types of expressions. The expression types are divided into two main categories: one type does not contain blocks and the other type contains blocks. Furthermore, blocks, statements, and expressions can be recursively nested into each other to any depth.

[0014] An expression of type block has a structure of an array of statements and an expression that is the return value of the block. Therefore, for an expression of type block, there are two cases: if the block only contains expr, it is analyzed directly; if it contains stmt, the structure of each stmt is further parsed and the expression contained therein is analyzed using the same processing method as above.

[0015] Step 3: Use MIR analysis to identify unsafe operations;

[0016] Step 3.1: Identify the operation of dereferencing the raw pointer;

[0017] First, check if the expression is a unary operation (!x, *x, -x) and determine if it is a dereference (*x). Obtain the type check information of the expression through rustc_mir_build to determine if it is an unsafe pointer. If it is, skip the statement containing the expression and continue to process other expressions in the same way.

[0018] Step 3.2: Identify whether an unsafe function or method is being called;

[0019] Check if the expression is a function call or method call. Obtain the type check information of the expression through rustc_mir_build, get the function or method def_id, and then query the function or method signature in TyCtxt to determine if it calls an unsafe function or method. If it does, skip the statement containing the expression and continue to process other expressions in the same way.

[0020] Step 3.3: Identify operations that access mutable static variables;

[0021] For variables of a custom type, the type of the variable is obtained through rustc_mir_build, and the def_id of the type is obtained. It is then determined whether the variable is a mutable static variable. If it is, the statement containing the expression is skipped, and the same processing is performed on other expressions.

[0022] Step 4: Report any security expressions or statements in the unsafeblock written by the developer;

[0023] After the analysis in steps 1-3, safe expressions are reported on a statement-by-statement basis, and if the right side of a statement is unsafe, the left side of the statement is reported.

[0024] If the entire block is safe, report the entire block.

[0025] For conditional statements such as if / match / while, which do not involve complex nested expressions, reports are generated directly.

[0026] Beneficial technical effects of the present invention:

[0027] Compared to existing technologies, this invention can print warnings to allow developers to discover as many safe expressions or statements as possible within their own unsafe blocks (without needing the `unsafe` modifier). Therefore, developers can manually inspect flawed code snippets, make corrections, and finally recompile the entire project using this tool to verify that the warnings have been eliminated. This invention is used to detect issues with the accuracy of unsafe block ranges in real-world (GitHub) Rust crates and to report repositories with inaccurate unsafe block ranges. Attached Figure Description

[0028] Figure 1 Code snippets with inaccurate UNSAFE RUST range in embodiments of the present invention;

[0029] Figure 2 The present invention provides an overall architecture diagram of a method for detecting UNSAFE code snippets in the Rust programming language;

[0030] Figure 3 A comparison chart showing the effect of the test report and the developer's corrected code in this embodiment of the invention. Detailed Implementation

[0031] The present invention will be further described below with reference to the accompanying drawings and embodiments;

[0032] The implementation of this invention relies on the rustc_lint module, a module specifically designed to implement various code quality inspection and analysis processes (Lint passes). Lint is a type of static code analysis tool, originally from the C language. Lint tools typically check for potential problems and errors in code. In addition to identifying errors, Lint tools also have certain fix / refactor suggest and auto-fix capabilities. Introducing Lint tools into a project can effectively reduce errors and improve overall project quality. Furthermore, for a programming language, Lint tools are often a prerequisite for the development of other tools, such as error messages in IDE plugins and pipeline checks in CI. The implementation relies on the rustc_lint module and is carried out in the later stages of compilation. Because it involves the analysis of various type information and requires various type checking information generated by the compiler, a relatively late execution time is chosen. The LateLintPasstrait provides a series of methods, using check_expr(_,LateContext,_), which can be called on each expression in the source code file. The LateContext structure contains the type checking information required by this invention.

[0033] A method for detecting UNSAFE code snippets in the Rust programming language. Figure 2 The overall framework of the method is outlined. It takes the HIR of each expression as input and outputs warnings about safe expressions or statements (those that need to be removed from the unsafe block), making the scope of the unsafe block as precise as possible. Specifically, it includes the following:

[0034] Step 1: Based on the rustc_lint module, use HIR (High-Level Intermediate Representation) to determine whether an expression in the programming language is contained within an unsafe block written by the developer; the HIR is an inaccurate code snippet for UNSAFE RUST. Figure 1 As shown;

[0035] Rust's source code is first analyzed by lexical analysis to generate an Abstract Syntax Tree (AST), which desugars the source code written by the developers. Then, a Hierarchical Representation (HIR) is generated through a query system. After type checking and removal of the unsafe keyword, it is again generated through a query system to generate an Intermediate Representation (MIR). Then, borrow checks and code optimizations are performed, and finally, it is transformed into an LLVM IR.

[0036] HIR contains structural information of the code; the node containing the current expression is found sequentially through HIR. If the type of the node is expression and the type of the expression is block, it is determined whether the block is an unsafe block written by the developer. If it is, it means that the current expression is contained in an unsafe block written by the developer, and the next step of processing is continued; otherwise, the next expression is evaluated.

[0037] Step 2: Use HIR to parse the structure of the expression;

[0038] Rust has a total of 32 types of expressions, which are divided into two main categories: one category does not contain blocks (such as struct expressions, break expressions, continue expressions, etc.), and the other category contains blocks (such as block expressions, if expressions, match expressions, etc.). Furthermore, blocks, statements, and expressions can be recursively nested into each other to any depth.

[0039] Therefore, if expressions are analyzed directly, those that do not require the `unsafe` keyword should be reported; otherwise, it would lead to redundant reporting, as the same expression may contain multiple expressions. Furthermore, some unconventional code structures will be parsed into other structures in HIR (derived from the source code after desugaring), requiring further code structure analysis for identification. For example, `while` expressions are converted to `loop` and `if` expressions in HIR, and `for` expressions are converted to `loop` and `match` expressions. Expressions within `if`, `match`, and `while` structures (where conditional statements are written) are analyzed directly, as complex nested expressions are rarely used in these conditional statements; if they are safe, they should be reported directly.

[0040] An expression of type block has a structure of an array of statements and an expression that is the return value of the block. Therefore, for an expression of type block, there are two cases: if the block only contains expr, it is analyzed directly; if it contains stmt, the structure of each stmt is further parsed and the expression contained therein is analyzed using the same processing method as above.

[0041] Step 3: Use MIR analysis to identify unsafe operations;

[0042] Step 3.1: Identify the operation of dereferencing the raw pointer;

[0043] First, check if the expression is a unary operation (!x, *x, -x) and determine if it is a dereference (*x). Obtain the type check information of the expression through rustc_mir_build to determine if it is an unsafe pointer. If it is, skip the statement containing the expression and continue to process other expressions in the same way.

[0044] Step 3.2: Identify whether an unsafe function or method is being called;

[0045] Check if the expression is a function call or method call. Obtain the type check information of the expression through rustc_mir_build, get the function or method def_id, and then query the function or method signature in TyCtxt to determine if it calls an unsafe function or method. If it does, skip the statement containing the expression and continue to process other expressions in the same way.

[0046] Step 3.3: Identify operations that access mutable static variables;

[0047] For variables of a custom type, the type of the variable is obtained through rustc_mir_build, and the def_id of the type is obtained. It is then determined whether the variable is a mutable static variable. If it is, the statement containing the expression is skipped, and the same processing is performed on other expressions.

[0048] Step 4: Report any security expressions or statements in the unsafeblock written by the developer;

[0049] After the analysis in steps 1-3, safe expressions are reported on a statement-by-statement basis, and if the right side of a statement is unsafe, the left side of the statement is reported.

[0050] If the entire block is safe, report the entire block.

[0051] For conditional statements like if / match / while, which do not involve complex nested expressions, a report is generated directly. A comparison of the detection report and the developer's corrected code is attached. Figure 3 As shown.

[0052] This invention employs a hybrid analysis technique combining HIR and MIR. It's worth emphasizing that the combined use of multiple IR levels is unconventional, but essential for solving the problem this invention addresses. This technique primarily aims to precisely define the scope of unsafe code segments. First, the unsafe block needs to be located (using HIR), then unsafe operations (using MIR) and the called unsafe functions or methods are identified. Statements requiring the use of the `unsafe` keyword are marked, and the scope is compared to the initial unsafe block scope, making corresponding changes. This invention also proposes a data flow analysis technique for function parameters to identify alias propagation chains. This is a key technique for determining whether a function or method should be marked with the `unsafe` keyword. Combined with fuzz testing, the target function is tested to determine whether the function must be marked with the `unsafe` keyword.

Claims

1. A method for detecting defects in UNSAFE code snippets in the Rust programming language, characterized in that, Specifically, it includes the following: Step 1: Based on the rustc_lint module, use HIR to determine whether an expression in the programming language is contained in an unsafe block written by the developer; Rust's source code is first analyzed by lexical analysis to generate an Abstract Syntax Tree (AST), which desugars the source code written by the developers. Then, a Hierarchical Representation (HIR) is generated through a query system. After type checking and removal of the unsafe keyword, it is again generated through a query system to generate an Intermediate Representation (MIR). Then, borrow checks and code optimizations are performed, and finally, it is transformed into an LLVM IR. HIR contains structural information of the code; the node containing the current expression is found sequentially through HIR. If the type of the node is expression and the type of the expression is block, it is determined whether the block is an unsafe block written by the developer. If it is, it means that the current expression is contained in an unsafe block written by the developer, and the next step of processing is continued; otherwise, the next expression is evaluated. Step 2: Use HIR to parse the structure of the expression; Rust has a total of 32 types of expressions. The expression types are divided into two main categories: one type does not contain blocks and the other type contains blocks. Furthermore, blocks, statements, and expressions can be recursively nested into each other to any depth. An expression of type block has a structure of an array of statements and an expression that is the return value of the block. Therefore, for an expression of type block, there are two cases: if the block only contains expr, it is analyzed directly; if it contains stmt, the structure of each stmt is further parsed; and for the expression contained therein, if the type of the expression is block, it is further analyzed according to the two cases mentioned above. Step 3: Use MIR analysis to identify unsafe operations; Step 3.1: Identify the operation of dereferencing the raw pointer; First, check if the expression is a unary operation !x, *x, or -x, and determine if it is a dereference *x. Then, obtain the type check information of the expression through rustc_mir_build to determine if it is an unsafe pointer. If it is, skip the statement containing the expression and continue to process other expressions in the same way. Step 3.2: Identify whether an unsafe function or method is being called; Check if the expression is a function call or method call. Obtain the type check information of the expression through rustc_mir_build, get the function or method def_id, and then query the function or method signature in TyCtxt to determine if it calls an unsafe function or method. If it does, skip the statement containing the expression and continue to process other expressions in the same way. Step 3.3: Identify operations that access mutable static variables; For variables of a custom type, the type of the variable is obtained through rustc_mir_build, and the def_id of the type is obtained to determine whether it is a mutable static variable; If so, skip the statement containing the expression and continue to process other expressions in the same way; Step 4: Report the security expressions or statements in the unsafeblock written by the developer.

2. The method for detecting defects in UNSAFE code snippets in the Rust programming language according to claim 1, characterized in that, The HIR mentioned in step 1 is a high-level intermediate representation.

3. The method for detecting UNSAFE code snippets in the Rust programming language according to claim 1, characterized in that, Step 4: After the analysis in steps 1-3, report the safe expressions on a statement-by-statement basis, and report the left side of the statement if the right side of the statement is unsafe.

4. The method for detecting UNSAFE code snippets in the Rust programming language according to claim 3, characterized in that, If the entire block is safe, report the entire block; for conditional statements such as if / match / while, which do not involve complex nested expressions, report directly.