Method for performing a dynamic memory safety analysis of a program containing specific sentences

By preprocessing and statically analyzing the C language source code, generating a symbol table and abstract syntax tree, and performing targeted instrumentation, the problem of existing tools handling uncommon specific statements is solved, achieving stronger memory safety dynamic analysis and correct compilation.

CN116126705BActive Publication Date: 2026-02-24NANJING UNIV OF AERONAUTICS & ASTRONAUTICS
View PDF 0 Cites 0 Cited by

Patent Information

Application Number
CN202310017945.3
Authority / Receiving Office
CN · China
Patent Type
Patents(China)
Current Assignee / Owner
Filing Date
2023-01-06
Publication Date
2026-02-24
Estimated Expiration
2043-01-06

AI Technical Summary

Technical Problem

Existing memory safety dynamic analysis tools struggle to correctly handle uncommon specific statements when dealing with complex C language projects, leading to instrumentation failures or the instrumented program failing to compile correctly.

Method used

By selecting the source code to be instrumented, preprocessing and static analysis are performed to generate a symbol table and abstract syntax tree. The nodes are traversed to perform instrumentation, including the definition and initialization of pointer variables and structure variables, function calls, etc. An executable file is generated and memory error detection is performed to report the error location.

Benefits of technology

It enables stronger dynamic memory safety analysis of programs containing specific statements, avoiding instrumentation failures and program compilation errors, and improving instrumentation capabilities.

✦ Generated by Eureka AI based on patent content.

Smart Images

  • Figure CN116126705B_ABST
    Figure CN116126705B_ABST
Patent Text Reader

Abstract

The application relates to a method for performing memory safety dynamic analysis on a program containing specific sentences. The method comprises the following steps: selecting a project directory or a single source code file to be instrumented; preprocessing the source code, replacing macro calls with the content in the macro definition, and commenting out the original macro call; generating a symbol table and an abstract syntax tree of the source code by using a compiler; traversing all nodes in the abstract syntax tree, performing static analysis on the source code, and modifying the source code for sentences that cannot be processed, and then re-instrumenting the source code; traversing all nodes in the abstract syntax tree, performing different instrumentations on the source code according to different node types, compiling the instrumented project directory or file by using a compiler, generating an executable file on a target system, and running the executable file, performing memory error detection on the program containing specific sentences, and reporting the position of the source code corresponding to the error. The method avoids the problems of instrumentation failure and the failure of correctly compiling the program after instrumentation.
Need to check novelty before this filing date? Find Prior Art

Description

Technical Field

[0001] This application relates to the field of computer software technology, and in particular to a method for dynamic memory safety analysis of programs containing specific statements. Background Technology

[0002] C is widely used in system software and embedded software development due to its precise memory control and extremely fast execution speed. However, C does not provide a memory safety detection mechanism. Using pointers can lead to memory errors such as buffer overflows, multiple frees, and memory leaks, which can cause fatal damage such as system crashes or internal data corruption. Memory errors are divided into two categories: spatial memory errors and temporal memory errors. Spatial memory errors include: buffer overflows, array out-of-bounds errors, uninitialized pointers, using NULL pointers, and forcibly casting and then dereferencing arbitrary integer data. Temporal memory errors include dangling stack pointers, dangling heap pointers, multiple frees, intermediate frees, using the `free` function to release off-heap memory, and memory leaks.

[0003] In related technologies, there are many memory safety dynamic analysis tools to detect memory errors. However, due to the complex language structure of C, dynamic analysis tools often cannot correctly handle some uncommon specific statements when analyzing some large and complex projects, resulting in instrumentation failure or the instrumented program being unable to be compiled correctly. Summary of the Invention

[0004] Therefore, it is necessary to provide a method for dynamic memory safety analysis of programs containing specific statements that can correctly handle some uncommon specific statements and avoid instrumentation failures or the inability of the instrumented program to be compiled correctly, in order to address the above-mentioned technical problems.

[0005] A method for dynamic memory safety analysis of a program containing specific statements, the method comprising:

[0006] Select the project directory or a single source code file of the source code to be instrumented;

[0007] The source code is preprocessed by commenting out file inclusion directives, macro definition directives, and source code included by file inclusion directives, replacing macro calls with the content in the macro definition, and commenting out the original macro calls.

[0008] The compiler is used to generate the symbol table and abstract syntax tree of the source code;

[0009] Traverse all nodes in the abstract syntax tree, perform static analysis on the source code, and for statements that cannot be processed, prompt the user to modify the source code and then re-insert the source code.

[0010] Traverse all nodes in the abstract syntax tree and perform different instrumentation on the source code according to different node types, including: instrumenting definition and initialization statements of pointer variables and structure variables, assignment statements of pointer variables and structure variables, function call statements, pointer dereference statements, array subscript access statements, and structure member access statements;

[0011] The instrumented project directory or files are compiled using a compiler to generate an executable file for the target system;

[0012] The executable file is deployed to the target system and run. When the executable file runs to the replaced or inserted code segment, memory error detection is performed on the program containing the specific statement, and the location of the source code corresponding to the error is reported.

[0013] In one embodiment, when the macro call has a string parameter and the string contains the comment terminator "* / ", a space character is inserted between "*" and " / ".

[0014] In one embodiment, static analysis of the variable-size array declarations in the source code includes:

[0015] The algorithm iterates through all function definitions in the abstract syntax tree. Upon entering each function definition, it sets the variable `inserted_goto`, which indicates whether a `goto` statement has been inserted, to 0. Then, it iterates through the statements in the function body. If the statement is a compound statement, conditional statement, or loop statement, it sets the variable `inserted_goto` to 1. If the statement is a variable-size array declaration and the value of the variable `inserted_goto` is 1, it prompts the user to modify the source code and then re-inserts the source code.

[0016] In one embodiment, during the process of instrumenting the source code differently according to different node types, the wrapper function name adopts a custom prefix PREFIX, and the data structure definition and interface function definition adopt the prefix _PREFIX.

[0017] In one embodiment, during the process of instrumenting the source code according to different node types, if a variable PREFIXret_val needs to be inserted in the wrapper function to store the function's return value, the type of this variable is the function's return value type, and the const modifier in the type is removed.

[0018] In one embodiment, during the process of instrumenting the source code differently according to different node types, if the node is a conditional operator, the conditional operator is treated as a variable parameter function call containing actual parameters.

[0019] In one embodiment, during the process of instrumenting the source code differently according to different node types, if the node is a call to the function sscanf, a wrapper function for the function sscanf is inserted before the function containing the function call.

[0020] The above-described method for dynamic memory safety analysis of programs containing specific statements involves: selecting the project directory or a single source code file of the source code to be instrumented; preprocessing the source code by commenting out file inclusion directives, macro definition directives, and inserting source code included by file inclusion directives; replacing macro calls with the content of macro definitions and commenting out the original macro calls; using a compiler to generate a symbol table and abstract syntax tree for the source code; traversing all nodes in the abstract syntax tree; performing static analysis on the source code; for statements that cannot be processed, prompting the user to modify the source code; and then re-inserting the source code; traversing the abstract syntax tree... The syntax tree analyzes all nodes and instrumentes the source code differently based on the node type, including: instrumenting definition and initialization statements of pointer variables and structure variables, assignment statements of pointer variables and structure variables, function call statements, pointer dereference statements, array subscript access statements, and structure member access statements; compiling the instrumented project directory or files with a compiler to generate an executable file for the target system; deploying the executable file to the target system and running it; when the executable file runs to the replaced or inserted code segment, performing memory error detection on the program containing the specific statement and reporting the location of the source code corresponding to the error. Therefore, it can perform dynamic memory safety analysis on programs containing specific statements, possessing stronger instrumentation capabilities than existing dynamic analysis tools, and avoiding problems such as instrumentation failure or the inability to compile the instrumented program correctly. Attached Figure Description

[0021] Figure 1 This is a flowchart illustrating a method for dynamically analyzing the memory safety of a program containing specific statements, as shown in one embodiment. Detailed Implementation

[0022] To make the objectives, technical solutions, and advantages of this application clearer, the following detailed description is provided in conjunction with the accompanying drawings and embodiments. It should be understood that the specific embodiments described herein are merely illustrative and not intended to limit the scope of this application.

[0023] In one embodiment, such as Figure 1 As shown, a method for dynamic memory safety analysis of a program containing specific statements is provided. Taking the application of this method to a terminal as an example, the method includes the following steps:

[0024] Step S220: Select the project directory or a single source code file of the source code to be instrumented.

[0025] Step S240: Preprocess the source code by commenting out file inclusion directives, macro definition directives, and source code included by file inclusion directives, replacing macro calls with the content in the macro definition, and commenting out the original macro calls.

[0026] In one embodiment, when a macro call has a string parameter and the string contains the comment terminator "* / ", a space character is inserted between "*" and " / ".

[0027] It should be understood that if the original macro call has a string parameter, and the string contains the comment terminator "* / ", then inserting a space character between "*" and " / " can break its comment terminator structure.

[0028] Step S260: Use a compiler to generate a symbol table and abstract syntax tree for the source code.

[0029] Step S280: Traverse all nodes in the abstract syntax tree, perform static analysis on the source code, and for statements that cannot be processed, prompt the user to modify the source code and then re-insert the source code.

[0030] In one embodiment, static analysis of the variable-size array declaration in the source code includes:

[0031] The algorithm iterates through all function definitions in the abstract syntax tree. Upon entering each function definition, it sets the variable `inserted_goto`, which indicates whether a `goto` statement has been inserted, to 0. Then, it iterates through the statements in the function body. If the statement is a compound statement, conditional statement, or loop statement, it sets the variable `inserted_goto` to 1. If the statement is a variable-size array declaration and the value of the variable `inserted_goto` is 1, it prompts the user to modify the source code and then re-inserts the source code.

[0032] It should be understood that when traversing all function definitions in the abstract syntax tree, upon entering each function definition, the variable `inserted_goto`, which indicates whether a `goto` statement has been inserted, is set to 0. Then, the statements in its function body are traversed sequentially. If the statement is a compound statement, conditional statement, or loop statement, it means that a `goto` statement will be inserted to jump to the pointer metadata deletion statement, so the variable `inserted_goto` is set to 1. If the statement is a variable-size array declaration and the value of the variable `inserted_goto` is 1, it means that the array declaration will cause the compiler to fail to compile the instrumented code correctly. Therefore, the user needs to be prompted to modify the source code and then the source code is re-inserted.

[0033] Step S300: Traverse all nodes in the abstract syntax tree and perform different instrumentation on the source code according to different node types, including: instrumenting definition and initialization statements of pointer variables and structure variables, assignment statements of pointer variables and structure variables, function call statements, pointer dereference statements, array subscript access statements, and structure member access statements.

[0034] It should be understood that instrumenting the definition and initialization statements of pointer variables and structure variables aims to create pointer metadata at runtime; instrumenting the assignment statements of pointer variables and structure variables aims to update pointer metadata at runtime; instrumenting function call statements aims to pass pointer metadata of parameters and return values ​​at runtime; and instrumenting pointer dereferencing, array subscript access, and structure member access statements aims to use pointer metadata to check for memory access errors.

[0035] In one embodiment, during the different instrumentation processes of the source code based on different node types, the wrapper function name adopts a custom prefix PREFIX, and the data structure definition and interface function definition adopt the prefix _PREFIX.

[0036] It should be understood that when instrumenting, wrapper function names use the custom prefix PREFIX, while data structure definitions and interface function definitions use the prefix _PREFIX, which is an underscore added before the custom prefix PREFIX, thus avoiding name conflicts between identifiers and wrapper function names.

[0037] In one embodiment, during the process of instrumenting the source code according to different node types, if a variable PREFIXret_val needs to be inserted in the wrapper function to store the function's return value, the type of this variable is the function's return value type, and the const modifier in the type is removed.

[0038] It should be understood that when inserting a wrapper function, if you need to insert a variable PREFIXret_val to store the function's return value, its type should be the function's return value type. However, the const modifier in the type should be removed so that the value of the variable PREFIXret_val can be modified in the wrapper function.

[0039] In one embodiment, during the different instrumentation processes of the source code based on different node types, if the node is a conditional operator, the conditional operator is treated as a variadic function call containing actual parameters.

[0040] In one example, if the node is a conditional operator, such as: cond? TE(t_kpe): FE(f_kpe), where cond represents the Boolean conditional expression in the conditional operator, TE(t_kpe) and FE(f_kpe) represent the truth and false expressions respectively (i.e., the expressions that return as the operator's values ​​when the Boolean conditional expression evaluates to true and false, respectively), TE(t_kpe) represents the expression containing the expression t_kpe, and FE(f_kpe) represents the expression containing the expression f_kpe. t_kpe and f_kpe are the core pointer expressions in their respective expressions. This conditional operator can be viewed as a variadic function call containing three actual parameters: cond, TE(t_kpe), and FE(f_kpe). Therefore, this node can be replaced with the following expression:

[0041] PREFIXcond_expr_ID(_PREFIXpmd_tbl_create(&ret),

[0042] cond? _PREFIXpmd_tbl_lookup(&t_kpe):NULL,

[0043] cond? NULL:_PREFIXpmd_tbl_lookup(&f_kpe),

[0044] cond? 1:0,cond? TE(t_kpe):FE(f_kpe));

[0045] Here, the function PREFIXcond_expr_ID is the wrapper function for the conditional operator, the variable ret is the variable that stores the return value of the conditional operator, the function _PREFIXpmd_tbl_create creates pointer metadata for the pointer variable in the parameter, and the function _PREFIXpmd_tbl_lookup looks up the pointer metadata of the parameter. Then, the definition of the wrapper function is inserted before the function containing the conditional operator:

[0046] T PREFIXcond_expr_ID(_PREFIXpmd*ret_pmd,

[0047] _PREFIXpmd*T_pmd,_PREFIXpmd*F_pmd,int cond,T result){

[0048] if(cond)_PREFIXpmd_cp_pmd(ret_pmd,T_pmd);

[0049] else_PREFIXpmd_cp_pmd(ret_pmd,F_pmd);

[0050] _PREFIXpmd_free_null_ptr(T_pmd);

[0051] _PREFIXpmd_free_null_ptr(F_pmd);

[0052] return result;

[0053] }

[0054] Here, type T is the return value type of the conditional operator, type _PREFIXpmd is the pointer metadata type, the function _PREFIXpmd_cp_pmd copies the pointer metadata in the second parameter to the pointer metadata in the first parameter, and the function _PREFIXpmd_free_null_ptr releases the pointer metadata in the parameter.

[0055] In one embodiment, during the different instrumentation processes of the source code based on different node types, if the node is a call to the function sscanf, a wrapper function for the function sscanf is inserted before the function containing the function call.

[0056] In one example, if a node is a call to the function sscanf, such as: sscanf(a1(kpe1),a2(kpe2),va1(vkpe1),…,vam(vkpem)), where the actual parameters a1(kpe1), a2(kpe2), va1(vkpe1)~vam(vkpem) represent expressions containing the core pointer expressions kpe1, kpe2, vkpe1~vkpem respectively, then the wrapper function of the function sscanf, "int PREFIXsscanf_ID(const char*pbuffer,const char*pformat,T1vp1,...,Tm vpm)", is inserted before the function containing the function call. Within the function body of this wrapper function, an `is_string` array is first declared to store whether the variable arguments are used as character arrays. Then, the format string `pformat` is analyzed. If any conversion rule in `pformat` is "%s" or "%[", it means the variable argument corresponding to that conversion rule is being used as a character array, so the corresponding element in the `is_string` array is set to 1. If any conversion rule in the format string `pformat` is not "%s" or "%[", but rather "%d", etc., then the corresponding element in the `is_string` array is set to 0. Then, the function `sscanf(pbuffer, pformat, vp1, ..., vpm)` is called. Finally, the elements in the `is_string` array are traversed. If the value of the i-th element (1 ≤ i ≤ m) is 1, then the pointer metadata corresponding to the parameter `vpi` and the string length in `vpi` are checked to determine if a memory error has occurred.

[0057] Step S320: Compile the instrumented project directory or files using a compiler to generate an executable file for the target system.

[0058] Step S340: Deploy the executable file to the target system and run it. When the executable file runs to the replaced or inserted code segment, perform memory error detection on the program containing the specific statement and report the location of the source code corresponding to the error.

[0059] Memory error detection for programs containing specific statements can include processing the following specific statements: macro calls with string parameters and the strings containing comment terminators, variable-size array declarations, functions that return constant variables, conditional operators, and calls to the function sscanf, etc.

[0060] The aforementioned method for dynamic memory safety analysis of programs containing specific statements involves: selecting the project directory or a single source code file to be instrumented; preprocessing the source code by commenting out file inclusion directives, macro definition directives, and inserting source code included by file inclusion directives; replacing macro calls with the content of macro definitions and commenting out the original macro calls; generating a symbol table and abstract syntax tree (AST) for the source code using a compiler; traversing all nodes in the AST and performing static analysis on the source code; for statements that cannot be processed, prompting the user to modify the source code and then re-inserting the source code; and traversing the AST... The system instrumentes all nodes and performs different instrumentations on the source code based on different node types. This includes instrumenting definitions and initialization statements of pointer and structure variables, assignment statements of pointer and structure variables, function call statements, pointer dereference statements, array subscript access statements, and structure member access statements. The instrumented project directory or files are then compiled using a compiler to generate an executable file for the target system. The executable file is deployed to the target system and run. When the executable file reaches the replaced or inserted code segment, memory error detection is performed on the program containing the specific statement, and the location of the corresponding source code is reported. Therefore, it can perform dynamic memory safety analysis on programs containing specific statements, offering stronger instrumentation capabilities than existing dynamic analysis tools and avoiding problems such as instrumentation failures or the inability to compile the instrumented program correctly.

[0061] It should be understood that, although Figure 1 The steps in the flowchart are shown sequentially as indicated by the arrows, but these steps are not necessarily executed in the order indicated by the arrows. Unless otherwise specified herein, there is no strict order in which these steps are executed, and they can be performed in other orders. Figure 1 At least some of the steps in the process may include multiple sub-steps or multiple stages. These sub-steps or stages are not necessarily completed at the same time, but can be executed at different times. The execution order of these sub-steps or stages is not necessarily sequential, but can be executed in turn or alternately with other steps or at least some of the sub-steps or stages of other steps.

[0062] The technical features of the above embodiments can be combined in any way. For the sake of brevity, not all possible combinations of the technical features in the above embodiments are described. However, as long as there is no contradiction in the combination of these technical features, they should be considered to be within the scope of this specification.

[0063] The embodiments described above are merely illustrative of several implementation methods of this application, and while the descriptions are relatively specific and detailed, they should not be construed as limiting the scope of the invention patent. It should be noted that those skilled in the art can make various modifications and improvements without departing from the concept of this application, and these all fall within the protection scope of this application. Therefore, the protection scope of this patent application should be determined by the appended claims.

Claims

1. A method for dynamic memory safety analysis of a program containing specific statements, characterized in that, The method includes: Select the project directory or a single source code file of the source code to be instrumented; The source code is preprocessed by commenting out file inclusion directives, macro definition directives, and source code included by file inclusion directives, replacing macro calls with the content in the macro definition, and commenting out the original macro calls. The compiler is used to generate the symbol table and abstract syntax tree of the source code; Traverse all nodes in the abstract syntax tree, perform static analysis on the source code, and for statements that cannot be processed, prompt the user to modify the source code and then re-insert the modified source code. Traverse all nodes in the abstract syntax tree and perform different instrumentation on the source code according to different node types, including: instrumenting definition and initialization statements of pointer variables and structure variables, assignment statements of pointer variables and structure variables, function call statements, pointer dereference statements, array subscript access statements, and structure member access statements; The instrumented project directory or files are compiled using a compiler to generate an executable file for the target system; The executable file is deployed to the target system and run. When the executable file runs to the replaced or inserted code segment, memory error detection is performed on the program containing the specific statement, and the location of the source code corresponding to the error is reported.

2. The method according to claim 1, characterized in that, If the macro call has a string parameter and the string contains the comment terminator "* / ", insert a space character between "*" and " / ".

3. The method according to claim 1, characterized in that, The static analysis of the variable-size array declarations in the source code includes: The algorithm iterates through all function definitions in the abstract syntax tree. Upon entering each function definition, it sets the variable `inserted_goto`, which indicates whether a `goto` statement has been inserted, to 0. Then, it iterates through the statements in the function body of the entered function definition. If the statement is a compound statement, conditional statement, or loop statement, it sets the variable `inserted_goto` to 1. If the statement is a variable-size array declaration and the value of the variable `inserted_goto` is 1, it prompts the user to modify the source code and then re-inserts the source code.

4. The method according to claim 1, characterized in that, In the process of instrumenting the source code according to different node types, the wrapper function name adopts the custom prefix PREFIX, and the data structure definition and interface function definition adopt the prefix _PREFIX.

5. The method according to claim 1, characterized in that, In the process of instrumenting the source code according to different node types, when a variable PREFIXret_val needs to be inserted in the wrapper function to store the function's return value, the type of the variable PREFIXret_val is the function's return value type, and the const modifier in the type is removed.

6. The method according to claim 1, characterized in that, In the process of instrumenting the source code according to different node types, if the node is a conditional operator, the conditional operator is regarded as a variable parameter function call containing actual parameters.

7. The method according to claim 1, characterized in that, In the process of instrumenting the source code according to different node types, if the node is a call to the function sscanf, a wrapper function for the function sscanf is inserted before the function where the function call is located.