Context sensitive pointer analysis method and system based on module perception
By using a module-aware, context-sensitive pointer analysis method, a module depth graph and an object allocation graph are constructed to parse method call statements in modular programming. This solves the problem of incomplete analysis in existing technologies and improves the efficiency and accuracy of pointer analysis.
Patent Information
- Application Number
- CN202410989222.4
- Authority / Receiving Office
- CN · China
- Patent Type
- Applications(China)
- Current Assignee / Owner
- Filing Date
- 2024-07-23
- Publication Date
- 2026-01-23
AI Technical Summary
Existing pointer analysis methods cannot effectively analyze core code in modular programming, resulting in insufficient analysis completeness. Furthermore, context-sensitive pointer analysis methods suffer from reduced analysis efficiency when context information is added.
By using a module-aware context-sensitive pointer analysis method, the relationships between program modules in the package are parsed, a module depth graph and an object allocation graph are constructed, method call statements are parsed and the object allocation graph and module depth graph are updated, and the final pointer set of variables is obtained.
It improves the efficiency and accuracy of pointer analysis, can fully reflect the dynamic behavior of the program, adapts to the characteristics of modular programming, reduces the number of unnecessary analysis contexts, and maintains high-precision analysis results.
Smart Images

Figure CN121387290A_ABST
Abstract
Description
TECHNICAL FIELD
[0001] The present application relates to the field of computer software and theory, in particular to a pointer analysis optimization technique, and more particularly to a context-sensitive pointer analysis method and system based on module awareness. BACKGROUND
[0002] In the field of software engineering, pointer analysis is a static analysis technique used to determine the runtime behavior of pointer variables in a program. This analysis is crucial for understanding the memory usage patterns of a program, optimizing performance, and discovering potential memory leaks and pointer errors. As software systems become more complex, traditional pointer analysis methods face challenges in terms of accuracy and efficiency. Pointer analysis statically computes the set of runtime values (abstract memory addresses) that a pointer variable in a program can point to, i.e., the set of abstract addresses that can be pointed to by variable v (denoted as pts(v)). Typically, abstract addresses are represented using initialization points (instructions that initialize objects, such as new in Java, representing all dynamic object instances initialized by the instruction at runtime). It is a special class of dataflow problem that provides a foundation for a variety of upper-layer applications, such as vulnerability detection, compiler optimization, security analysis, etc. The efficiency and accuracy of these upper-layer applications directly depend on the accuracy of the pointer analysis results. Traditionally, pointer analysis can be divided into unification-based and inclusion-based based on the flow of objects, and Steensgaard algorithm and Andersen algorithm are two classic algorithms based on unification and inclusion, respectively. Andersen algorithm is widely used due to its higher accuracy, and this algorithm has been used to analyze some mainstream languages such as C / C++, Java, etc., and many compilation and analysis frameworks have integrated this algorithm. Determining the pointing set of runtime variables through static analysis is undecidable, and an approximate solution is usually needed by balancing accuracy and efficiency. There have been a large number of related works to optimize the efficiency and accuracy of pointer analysis, and one of the key mechanisms to improve accuracy is context sensitivity. Context-sensitive pointer analysis can make the pointing values of pointer variables different in different call contexts, thereby effectively reducing false positives introduced by infeasible inter-procedural control flow paths, and greatly improving accuracy.
[0003] In the prior art, there are two ways to realize context sensitivity, one is a summary-based way, that is, realizing context sensitivity by summarizing the input-output relationship of a function, which usually constructs a low-precision function call graph in advance, and the second is a tag-based way (also called a clone-based way), which distinguishes different contexts of the same function by attaching different tags to the function. Since most languages support recursive calls, the number of contexts based on tag representation may be infinite, and the k-limiting technique is usually used to limit the number of contexts, that is, the most recent k context elements are selected to represent the context. Object sensitivity is a mainstream context representation method for analyzing object-oriented languages, which uses the initialization point of the received object to represent the context element. For a function m, its context representation is: [O k ,...,O1] where O1 represents the initialization point of the received object of the function m, O i+1 (1≤i≤k-1) is the initialization point of O i , that is, the initialization point of the received object of the function where O i is located.
[0004] In summary, the existing pointer analysis method analyzes part of the core code in modular programming. Due to the introduction of the modular programming mechanism in program development, the existing pointer analysis method cannot analyze some core code, thereby challenging the completeness of pointer analysis. Although the existing context-sensitive pointer analysis method can improve the performance and precision of pointer analysis by constructing a high-precision function call graph, such a method will sacrifice analysis performance with the increase of context information. There is an urgent need to develop a pointer analysis method that can effectively represent context information and ensure analysis efficiency.
[0005] It should be noted that: the background technology is only used to introduce the related information of the present application, so as to help understand the technical scheme of the present application, but it does not mean that the related information must be prior art. In the absence of evidence that the related information has been disclosed before the filing date of the present application, the related information should not be regarded as prior art. SUMMARY
[0006] Therefore, the purpose of the present application is to overcome the defects of the prior art, provide a context pointer analysis method based on module awareness,
[0007] The purpose of the present application is realized by the following technical solutions:
[0008] According to a first aspect of the present application, a module-aware context-sensitive pointer analysis method is provided for resolving the pointing set of a variable in a program package to achieve context-sensitive analysis, the method comprising: step S1, obtaining a program package to be analyzed, which comprises a plurality of program modules; step S2, resolving program module semantics, resolving each program module based on the keywords of each program module in the program package to obtain the access authority between program modules and establish a program module relationship model; step S3, module dynamic semantics analysis, traversing each method call statement in each program module in the program package to be analyzed that calls a service interface, determining whether there is access authority between the program module where the method call statement is located and the program module where the service interface called by the method call statement is located based on the program module relationship model, and if there is access authority, binding all implementation classes of the service interface called by the method call statement or objects created based on the implementation classes to the left variable of the method call statement; step S4, module encapsulation semantics analysis, resolving all statements in the program package to be analyzed and synchronously updating an object allocation graph and a module depth graph during the resolving process, and constructing an initial pointing set of each variable in the program package based on the module depth graph, wherein the object allocation graph is a directed graph describing the object allocation relationship in the program package, the module depth graph is a directed graph containing module depth information extended based on the object allocation graph, and the module depth is the number of edges of the shortest path from a node to a program module boundary node; and step S5, based on the constructed initial pointing set of all variables, re-binding the implementation classes bound to the left variable of the method call statement to all objects contained in the pointing set of the left variable to obtain the final pointing set of each variable.
[0009] Preferably, the pointing set of each variable contains a plurality of combinations, each combination being an object that the variable can point to and a context corresponding to the object, wherein the context includes at most one element.
[0010] Preferably, in the step S4, all statements in the program package are divided into object allocation statements, copy statements, field read statements, field storage statements and method call statements based on the functions implemented by each statement, and the initial pointing set of each variable in the program package is constructed and the object allocation graph and the module depth graph are updated by selecting a corresponding way to resolve according to the statement type.
[0011] Preferably, in the step S4, the object assignment statement is parsed by the following way: judging whether there is access permission between the program module where the object assignment statement is located and the program module accessed by the object assignment statement based on the inter-module relationship model, if there is access permission, executing the following steps: obtaining the context of the program method where the object assignment statement is located and combining it with the assignment object of the object assignment statement to add to the pointing set of the left variable; obtaining the assignment object of the object assignment statement and all the receiving objects of the program method where the object assignment statement is located and updating the object assignment graph and the module depth graph based on them.
[0012] Preferably, in the step S4, the copy statement is parsed by the following way: obtaining the pointing set of the left variable in the copy statement and adding it to the pointing set of the right variable in the copy statement.
[0013] Preferably, in the step S4, the field reading statement is parsed by the following way: obtaining the pointing set of all the fields read by the field reading statement and adding it to the pointing set of the left variable in the field reading statement.
[0014] Preferably, in the step S4, the field storage statement is parsed by the following way: obtaining the pointing set of the right variable of the field storage statement and adding it to the pointing set of the field corresponding to the field storage statement to update the pointing set of the variable.
[0015] Preferably, in the step S4, the method call statement is parsed by the following way: judging whether there is access permission between the program module where the method call statement is located and the program module accessed by the method call statement based on the inter-module relationship model, if there is access permission, executing the following steps: obtaining the object pointed by the right variable of the method call statement; obtaining the module depth of the object based on the module depth graph, if the module depth is 0, taking the object as the context of the program method called by the method call statement, if the module depth is greater than 0 and less than or equal to a preset threshold, obtaining the module boundary node on the shortest path corresponding to the module depth of the object in the module depth graph, taking the object corresponding to the module boundary node as the context of the program method called by the method call statement, if the obtained module depth is greater than the preset threshold, setting the context of the program method as null; combining the object pointed by the right variable and its corresponding context and adding them to the pointing set of the this variable in the method called by the statement; obtaining the pointing set of the actual parameter of the program method input called by the statement and adding it to the pointing set of the formal parameter variable of the called method; obtaining the pointing set of the return value variable of the called method of the statement and adding it to the pointing set of the left variable in the statement; obtaining the receiving object of the statement and all the assignment objects in the method called by the statement and updating the object assignment graph and the module depth graph based on them.
[0016] Preferably, the object allocation graph is updated by: filtering out the allocation objects and the receiving objects that do not have corresponding nodes in the object allocation graph and creating new nodes corresponding to the allocation objects and the receiving objects, and adding edges from each new node of the corresponding allocation objects to each new node of the corresponding receiving objects to update the object allocation graph.
[0017] Preferably, the module depth graph is updated by: after the object allocation graph is updated, adding corresponding nodes and edges in the module depth graph according to the new nodes and edges in the object allocation graph, and updating the module depth information of the module depth graph by: traversing all the receiving objects and the allocation objects in the object allocation type statements or the method call type statements to obtain corresponding nodes in the module depth graph; if the node is a module boundary node, updating the module depth of the node to 0 and updating the module depths of all the successor nodes of the node one by one; if the node is not a module boundary node, obtaining the module depths of all the direct predecessor nodes of the node and filtering out the minimum value from the module depths; if the minimum value plus 1 is less than the module depth of the node or the node is a newly added node, updating the module depth of the node to the minimum value plus 1 and updating the module depths of all the successor nodes of the node based on the updated module depth of the node, otherwise, not updating the module depth of the node.
[0018] According to a second aspect of the present application, a pointer analysis system based on any of the methods of the first aspect of the present application is provided for constructing the pointing set of all the variables in the program package to be analyzed, the system comprising: a module relationship modeling module for parsing the access and dependency relationships between the program modules based on the keywords of the program modules in the program package and establishing a program module relationship model; an encapsulation semantic analysis module for parsing all the statements in the program package to be analyzed and synchronously updating the object allocation graph and the module depth graph during the parsing process, and constructing the initial pointing set of each variable in the program package based on the module depth graph; and a dynamic semantic analysis module for binding all the implementation classes of the service interface called by each method call type statement in the program package or the objects created based on the implementation classes to the left variable of the statement, and re-binding the implementation classes bound to the left variable of the method call statement to all the objects contained in the pointing set of the left variable to obtain the final pointing set of each variable based on the constructed initial pointing set of all the variables.
[0019] According to a third aspect of the present application, a computer program is stored thereon, and the computer program can be executed by a processor to implement the steps of the method of any of claims 1 to 10.
[0020] According to a fourth aspect of the present application, there is provided: one or more processors; and a memory, wherein the memory is configured to store executable instructions; and the one or more processors are configured to implement the steps of the method of any one of claims 1 to 10 by executing the executable instructions.
[0021] Compared with the prior art, the present application has the advantages that:
[0022] In view of the characteristics of dynamic semantics in modular programming, the present application models the dependency and access relationship between modules by parsing the keywords in the modules, and models the SPI by parsing the method call statements of the calling interface, thereby solving the problem of completeness loss caused by the inability of traditional pointer analysis methods to capture such mapping. Secondly, the algorithm is designed to complete the construction and update of the object allocation graph and the module depth graph during the parsing of the statements, thereby effectively improving the efficiency of pointer analysis. Finally, in order to balance the precision and efficiency of context-sensitive pointer analysis, the present application saves the module depth information of the program by constructing a module depth graph, and selects key information to construct the context, thereby not only reducing the number of unnecessary analysis contexts, but also retaining the high precision of the analysis results, thereby significantly improving the efficiency of the analysis process and realizing the analyzability of more complex program structures under limited resources. Based on this dynamic semantics modeling, the adaptability of pointer analysis to the characteristics of modular programming is significantly enhanced, and the analysis results can fully reflect the dynamic behavior of the program. BRIEF DESCRIPTION OF DRAWINGS
[0023] The embodiments of the present application will be further described below with reference to the accompanying drawings, in which:
[0024] Figure 1 A flowchart of a module-aware context-sensitive pointer analysis method according to an embodiment of the present application;
[0025] Figure 2 A pseudo code diagram of an object allocation graph update algorithm according to an embodiment of the present application;
[0026] Figure 3 A pseudo code diagram of a module depth graph update algorithm according to an embodiment of the present application. DETAILED DESCRIPTION
[0027] In order to make the purpose, technical scheme and advantages of the present application clearer, the present application will be further described in detail below through specific embodiments. It should be understood that the specific embodiments described herein are only used to explain the present application and do not limit the present application.
[0028] As mentioned in the background section, due to the introduction of modular programming mechanism in program development, the existing pointer analysis methods analyze part of the core code in modular programming, which seriously affects the completeness of pointer analysis, resulting in the inability of the existing pointer analysis methods to analyze some core code. Although the existing context-sensitive pointer analysis methods can improve the performance and accuracy of pointer analysis by constructing high-precision function call graphs, such methods will greatly increase the number of elements in the context, thereby affecting the performance of pointer analysis.
[0029] The present application proposes a context-sensitive pointer analysis scheme based on module awareness, in which the relationship between modules is parsed through keywords in each program module in the program package, and a module relationship model for judging the access authority between modules is constructed based on the relationship, then the implementation class of the service interface called in the statement is obtained by parsing the method call statement, and the object constructed based on the implementation class is bound to the left variable in the statement, so as to model the modular programming mechanism, finally, each statement in the program package is parsed, and the object allocation graph and the module depth graph are updated during the parsing process, and the key object is selected as the context in the pointing set based on the module depth in the module depth graph.
[0030] Before the embodiments of the present application are specifically introduced, some terms used therein are explained as follows:
[0031] Object classification graph: the object allocation graph (OAG) is a directed graph, which is represented as G=(N, E), wherein N is the node set, and E is the edge set. A node O in the node N represents an object, and an edge O1→O2∈E represents an object allocation relationship, which means that O2 is allocated in a program method, and the receiving object of the program method is O1.
[0032] Program module boundary: it is a set composed of program module boundary objects, wherein the module boundary object is O l ∈MF is the receiving object of the program method m' in a method call statement l:x=a0.f(...), if the program method in which the method call statement is located is m and the program method m' called by the statement is different from the program module, then O l is regarded as an object of a program module boundary.
[0033] Program module depth graph (MDG) is a directed graph, which is represented as G=(<N, D>, E), wherein N and E are the same as in the object allocation graph, and D represents the shortest path length from the program module boundary node to the current node. For <n, d>∈<N, D>, if n is a program module boundary node, then d will be set to 0.
[0034] Service Provider Interface (SPI): Service Provider Interface is a design pattern used to implement a service discovery and loading mechanism in applications that require high scalability and flexibility. The mechanism implements dynamic mapping of interfaces and implementations from service loading, service propagation to service application. According to one embodiment of the present application, a context-sensitive pointer analysis method based on module awareness is proposed, which is used to parse the program package to obtain the pointing set of the variables in the program package to realize context-sensitive analysis, as shown in Figure 1 In order to better understand the present application, each step will be described in detail below in combination with specific embodiments.
[0035] Step S1, obtaining a program package to be analyzed
[0036] According to one embodiment of the present application, the program package to be analyzed includes a plurality of program modules, and a keyword in each program module defines the relationship between the program module and other program modules. For example, the keyword includes requires, exports, opens, uses, provides, transitive, static, requires is used to declare that the current program module needs to depend on other program modules, i.e., the current module can access the package exported by the program module it depends on. Meanwhile, requires can be combined with transitive and static. When requires is combined with transitive (e.g., requires transitive), the combination is used to declare that the current program module needs to depend on other program modules, and any program module depending on the current program module also has the same dependency relationship with the current program module, which avoids the need for each program module to explicitly declare common dependencies. When requires is combined with static (e.g., requires static), the combination is used to declare the dependency relationship at compile time of the current program module, which indicates that the program module does not necessarily need the program module at runtime, which is very advantageous for program modules providing optional functions or depending on program modules used only in specific cases. Exports is used to specify the package in the current program module that is open to access by other program modules. Only the public types (public classes and interfaces) in the specified package can be accessed by other program modules. Exports is also used to declare which program modules the package can be exported to. The package declared with opens has its types and members accessible to other program modules through reflection. Uses is used to specify a service used by a program module, and the service is represented by an interface or abstract class. When a program module declares a service, it indicates that the program module needs the implementation of the service to run without needing to understand the details of the implementation, which realizes the decoupling of service providers and service consumers. When provides is combined with with, the combination is used to specify a specific implementation (i.e., an interface or abstract class) of a service provided by a program module. By declaring a "provides-with" pair, the program module defines the implementation to be used when requesting the service. This allows a service to have multiple implementations, and the program module system can load a specific implementation at compile time or runtime.
[0037] Step S2, program module semantic modeling
[0038] According to one embodiment of the present application, the access and dependency relationships between program modules in a package are parsed based on keywords of the program modules, and a program module relationship model is established based on the parsed relationships, wherein the access and dependency relationships between the program modules include module dependency relationship, package export relationship, reflective access relationship, interface implementation relationship and interface declaration relationship. The above relationships are maintained using specific symbols, and how to use the specific symbols to describe the above five relationships will be described in detail below with examples.
[0039] In the following examples, M represents a program module, P represents a package, T represents a type, and the symbol represents a module dependency relationship, which is used to maintain program modules that a given program module depends on. For example, R(M1) = {M2, M3} indicates that program module M1 depends on M2 and M3. The symbol represents a package export relationship, which is used to maintain packages that a program module can export to another program module. For example, E(M1, M2) = {P1, P2} indicates that program module M1 exposes packages P1 and P2 to M2. The symbol represents a reflective access relationship, which is used to maintain a mapping similar to E to restrict reflective access. For example, O(M1, M2) = {P1, P2} indicates that program module M1 opens packages P1 and P2 to M2, i.e., M2 can access classes in P1 and P2 through reflection. The symbol represents an interface implementation relationship, which maintains a mapping of interfaces to implementations, indicating implementation classes that can be used by a service provider interface (SPI). For example, P(T1) = {T2, T3} indicates that the implementation classes of T1 interface are T2 and T3. The symbol represents an interface declaration relationship, which maintains interface information used by a program module. For example, U(M) = {T1, T2} indicates that interfaces T1 and T2 are used in program module M. It should be understood that the correspondence between the specific symbols and the modules in the above examples is only one of the specific implementations, and the present application does not limit the symbols used and the description form of the relationships between the modules in the relationship model.
[0040] Step S3, module dynamic semantic modeling
[0041] According to one embodiment of the present application, in module dynamic semantic modeling, each method call type statement in a program package to be analyzed is traversed and its validity is judged based on a module relationship model, for each valid method call type statement, all implementation classes of service interfaces used by a program method called by the method call type statement or objects created based on the implementation classes are bound to a left variable of the method call type statement to establish a service implementation mapping model. In a conventional pointer analysis method, when a method call type statement is analyzed, a program modular programming mechanism, i.e., a service provider interface design pattern (SPI), is not considered, the design pattern realizes dynamic mapping of an interface and an implementation from three steps of service loading, service propagation and service application, the present application models the SPI based on the three steps to obtain the service implementation mapping model, solves a problem that a conventional pointer analysis method cannot analyze core code in a program package using a dynamic loading mechanism, and thus enhances comprehensiveness and accuracy of pointer analysis.
[0042] According to one embodiment of the present application, the module dynamic semantic modeling comprises traversing each method call statement of each calling service interface in each program module in the program package to be analyzed, determining whether there is access permission between the program module where the method call statement is located and the program module where the called service interface is located based on the program module relationship model, and if there is access permission, binding all implementation classes of the service interface called by the method call statement or objects created based on the implementation classes to the left variable of the method call statement, wherein the resolution operation can be divided into three categories according to the type of the called program method, including: 1, if the program method is of a service loading type, obtaining the service interface used by the program method, and judging whether the program module where the statement belongs declares the service interface based on the program relationship model, if the service interface is not declared, regarding the statement as an invalid statement, otherwise, obtaining all implementation classes of the service interface and binding them to the left variable of the method call type statement. 2, if the program method is of a service transfer type, obtaining all implementation classes bound to the receiving object of the statement and binding the implementation classes to the left variable of the statement. 3, if the program method is of a service application type, obtaining all implementation classes of the service interface used by the program method and creating objects corresponding to the implementation classes one by one, and then adding the newly created objects to the pointing set of the left variable of the statement. In order to more clearly describe the module dynamic semantic analysis process, the following will be described in combination with the formal expression of the modeling, wherein the meanings of some functions and symbols in the expression are as follows: l:x=y.f(…) represents a method call type statement, O represents an object, T represents an implementation class, m' represents a program method called by the call type statement, Loader, Transfer and Retrieve represent three types of program methods, i.e., service loading, service transfer and service application. typeOf() is used to parse the constant of a certain parameter, dispatch() is used to parse the target call method, Gen() is used to create an instance object according to the type of the implementation class, constOf() represents the constant of a parameter, pts represents a pointing relationship, typeOf() is used to obtain the service interface type corresponding to the constant, and service represents binding the implementation class to the object O.
[0043] According to one embodiment of the present application, first, the object O pointed to by the left variable x of the statement l and the object O0 pointed to by the receiving variable y are obtained, the program method m' is obtained based on the function f and the object O0 using the dispatch() function, the type of the program method m' is judged, and the corresponding mode is adopted according to the type of the program method to perform resolution.
[0044] When the program method is of a service loading type, the statement resolution process can be formalized as the following formula, and the following will explain the resolution process of the program method of the service loading type statement in combination with the formula. First, the kth parameter a of the program method called by the statement l is obtainedk (i.e. service interface parameter), and parses the service interface T corresponding to the parameter, judges whether the service interface T belongs to the interface declared by the module declaration of the statement l based on the interface declaration relationship maintained in the module relationship model, if not, the statement is regarded as invalid, the statement l is skipped and the next method call statement is analyzed, otherwise, based on the interface implementation relationship maintained in the module relationship model, all implementation classes corresponding to the service interface T and all objects pointed to by the left variable x of the statement l are obtained, and the obtained implementation classes are bound to the obtained objects, since the pointing set of the variable is not determined at this time, i.e. the object pointed to by the left variable is unknown, all implementation classes are bound to the left variable first, and after the initial pointing set of all variables is determined, all implementation classes are re-bound to the object pointed to by the left variable.
[0045]
[0046] When the program method is of the service propagation type, the statement parsing process can be formalized as the following formula, and the statement parsing process of the program method of the service propagation type will be explained in combination with the formula, all implementation classes corresponding to the object O0 pointed to by the receiving variable y of the statement l are obtained, and these implementation classes are bound to all objects O pointed to by the left variable x of the statement l, since the pointing set of the variable is not determined at this time, i.e. the object pointed to by the left variable x is unknown, all implementation classes are bound to the left variable x first, and after the pointing set of all variables is determined, all implementation classes are re-bound to the object O pointed to by the left variable x.
[0047]
[0048] When the program method is of the service application type, the statement parsing process can be formalized as the following formula, and the statement parsing process of the program method of the service application type will be explained in combination with the formula, first, all implementation classes corresponding to the object O0 pointed to by the receiving variable y of the statement l are obtained, and objects O corresponding to these implementation classes are created using the Gen() function, and then these objects are added to the pointing set of the left variable x.
[0049]
[0050] Step S4, module encapsulation semantic analysis
[0051] According to one embodiment of the present application, in the module encapsulation semantic analysis step, all statements in the program package to be analyzed are parsed and the object allocation graph and the module depth graph are updated synchronously during the parsing process, and the initial pointing set of each variable in the program package is constructed based on the module depth graph, wherein the object allocation graph is a directed graph describing the object allocation relationship in the program package, the module depth graph is a directed graph containing module depth information extended based on the object allocation graph, and the module depth is the number of edges of the shortest path from a node to a program module boundary node.
[0052] According to one embodiment of the present application, the statement types include five types, as shown in Table 1, which shows the statement formats corresponding to the object allocation type statement, the copy type statement, the field reading type statement, the field storage type statement, and the method call type statement respectively.
[0053] Table 1: Statement type table
[0054]
[0055]
[0056] According to one embodiment of the present application, the object allocation graph is a directed graph representing the allocation relationship between objects, each node of which represents an object, and the edges between the nodes represent the allocation relationship between the objects; and the module depth graph is a directed graph containing module depth information extended based on the object allocation graph, each node of which represents an object and the module depth of the object, and the edges between the nodes represent the allocation relationship between the objects.
[0057] The module encapsulation semantic analysis step will be described in detail below based on the formalized formula corresponding to the parsing mode of each type of statement. First, the functions of the following functions need to be clarified: methodOf(l), which is used to obtain the program method to which a statement belongs, i.e., the program method in which the statement is located; methodCtx(), which is used to obtain the context of a program method; moduleOf(), which is used to obtain the program module to which a class or object belongs; classOf(), which is used to obtain the class in which a method is located; and pts(x, ctx), which represents the pointing set of variable x.
[0058] According to one embodiment of the present application, the parsing mode of the object allocation type statement can be formalized as the following formula, and the parsing step will be described in detail in combination with the formula: first, the program method m to which the statement l: x = new C belongs is obtained, and the program module m to which the current statement belongs is obtained based on the program method m The program module to which the allocated object belongs is obtained Then, the program module m is obtained based on the program module relationship model And the program module access right between the program module and the program module are the same module or program module program module program module program module the program module l (O l , hctx) and then add (O l , hctx) to the pointer set pts(x, ctx) of the left variable x, and finally call the SolveCaller(m, O l ) function with the program method m and the object O l as input parameters to update the object allocation graph, and update the module depth graph based on the updated object allocation graph.
[0059]
[0060] According to an embodiment of the present application, the parsing method of the copy statement can be formalized as the following formula, and the parsing steps will be explained in detail below: first, obtain the program method m to which the statement l: x = y belongs, obtain the context ctx of the program method m, obtain the pointer set pts(y, ctx) of the right variable y and add it to the pointer set of the left variable x.
[0061]
[0062] According to an embodiment of the present application, the parsing method of the field read statement can be formalized as the following formula, and the parsing steps will be explained in detail below: first, obtain the program method m to which the statement l: x = y.f belongs, obtain the context ctx of the program method m, obtain the pointer set pts(y, ctx) of the right variable y under the context ctx and extract all objects pointed to by the right variable y from the pointer set, and then add the pointer sets of the multiple fields contained in these objects to the pointer set of the left variable x, it should be understood that the field here is the attribute contained in a created object in Java, C++ or other object-oriented programming languages.
[0063]
[0064] According to one embodiment of the present application, the parsing manner of the field storage statement can be formalized as the following formula, and the parsing steps will be explained in detail as follows: first, the program method m to which the statement l:x=y.f belongs is obtained, the context ctx of the program method m is obtained, the pointer set pts(y, ctx) of the left variable x under the context ctx is obtained and all objects pointed by the left variable x are extracted from the pointer set pts(y, ctx), the pointer set pts(y, ctx) of the right variable y under the context ctx is obtained and added to the pointer set of the field of each object pointed by the left variable x, and it should be understood that the field herein is the attribute contained in a created object in Java, C++ or other object-oriented programming languages.
[0065]
[0066] According to one embodiment of the present application, the parsing manner of the method call statement can be formalized as the following formula, and the parsing steps will be explained in detail as follows: first, the program method m to which the statement l:x=a0.f(a1) belongs is obtained, the context ctx of the program method m is obtained, the object O0 pointed by the receiving variable a0 under the context ctx and the corresponding context thereof are obtained, the program method m' called by the statement is parsed based on the function dispatch(f, O0) and the program package P in which the service interface T' to which the method belongs is located is obtained, the program module in which the statement is located and the program module in which the method m' called by the statement is located is further parsed based on the program module relationship model, the access authority between the program module and the program module is obtained, and if the access authority exists, the following two conditions need to be met: 1, the program module and the program module are the same module or the program module depends on the program module 2, the program module exposes the program package P. The authority verification before parsing the statement can identify illegal statements, reduce unnecessary parsing steps, and ensure the correctness of the parsing result.
[0067]
[0068] According to one embodiment of the present application, as a formal formula of a method call statement, for a statement with access permission, a context of a program method m' of the statement call is first constructed, and then a pointing set of other parameters is updated. In which, key context information is selected to construct the context of the program method m' by calling a function selectCtx(), and the main function of the function selectCtx() is as follows: the module depth of an object O0 pointed by a receiving variable a0 of the statement under a context ctx is obtained in a module depth graph, and the context of the program method m' is constructed in different ways according to conditions met by the module depth value, including: 1, if the module depth is 0, the object O0 is taken as the context of the program method m'; 2, if the module depth is greater than 0 and less than or equal to a preset threshold, a module boundary node on a shortest path corresponding to the module depth of the receiving object is obtained in the module depth graph, and an object corresponding to the module boundary node is taken as the context of the program method of the statement l:x=a0.f(a1); 3, if the obtained module depth is greater than the preset threshold, the context of the program method m' is set to be empty.
[0069] In order to more clearly describe the process of constructing the context of the program method m' in the method call statement parsing process, the following will be described in detail in combination with examples:
[0070] Example 1:
[0071] If the module depth of the object O0 is 0, the node corresponding to the object O0 in the module depth graph is a module boundary node, and then the object is directly taken as the context of the program method m'.
[0072] Example 2:
[0073] If the module depth of the object O0 is greater than 0 and less than or equal to a preset threshold, the node corresponding to the object O0 in the module depth graph is not a module boundary node, and then a module boundary node on a shortest path corresponding to the object O0 needs to be found. Assuming that the module depth of the object O0 is 3 and the preset threshold is 4, the shortest path from the node corresponding to the object O0 to a module boundary node is (O0, O1, O2, O3), in which O3 is a module boundary node, and then the context of the program method m' is set to be O3.
[0074] Example 3:
[0075] If the module depth of the object O0 is greater than the preset threshold, the context of the program method m' is set to be empty.
[0076] According to one embodiment of the present application, as shown in the formalized formula of the method call statement, the set of pointers of the parameters in the method call statement is updated by: adding the set of pointers of the this variable in the method called by the statement to the combination of the object O0 pointed by the right variable and its corresponding context hctx; obtaining the set of pointers pts(a1, ctx) of the actual parameter a1 of the program method m' input called by the statement and adding it to the set of pointers pts(p m ', ctx') of the formal parameter variable of the called program method; obtaining the set of pointers pts(ret m ', ctx) of the return value variable of the called program method of the statement and adding it to the set of pointers pts(x, ctx) of the left variable in the statement. Finally, the SolveCaller(m, O l ) function is called with the program method m' and the object O0 as input parameters to update the object allocation graph, and the module depth graph is updated based on the updated object allocation graph.
[0077] According to one embodiment of the present application, after parsing the object allocation statement and the method call statement, based on the receiving object and the allocated object obtained in the object allocation type statement or the method call type statement, the allocated object and the receiving object for which there is no corresponding node in the object allocation graph are filtered out from the object allocation graph, and new nodes corresponding to them are created, and edges from each corresponding allocated object new node to each corresponding receiving object new node are added to update the object allocation graph.
[0078] In order to more clearly illustrate the steps of updating the object allocation graph, the following will be described in detail in combination with the pseudo code shown in Figure 2 . Figure 2The pseudo code of the algorithm for updating the object allocation graph is shown, which includes the function SolveCaller(m, O) for updating the object allocation graph called in the object allocation statement, the function SolveCallee(O, m) for updating the object allocation graph called in the method call allocation statement and the function AddEdge(O, O') for adding the edge relationship, wherein the implementation logic of the function SolveCaller(m, O') is that each receiving object O' in the program method m is traversed, the receiving object O' is the parameter object in the program method m, the function AddEdge(O, O') is called again, the node corresponding to each object O or receiving object O' is added in the object graph, and the edge from the object O to each receiving object O' is added. The implementation logic of the function SolveCallee(O, m) is that each allocation object O' in the program method m is traversed, the allocation object O' is the object created in the program method m, the function AddEdge(O, O') is called again, the node corresponding to each object O or allocation object O' is added in the object graph, and the edge from the object O to each receiving object O' is added. The instant algorithm for updating the object allocation graph in the process of statement analysis is adopted in the application, compared with the traditional algorithm, the object allocation graph algorithm needs to be pre-analyzed to obtain the allocation relationship between the objects and then construct the object allocation graph, and the algorithm adopted in the application can effectively improve the pointer analysis efficiency.
[0079] According to one embodiment of the application, the module depth graph is updated after the object allocation graph is updated each time, and the updating steps include: adding the corresponding nodes and edges in the module depth graph according to the newly added nodes and edges in the object allocation graph, and then updating the module depth information of the module depth graph by the following way: traversing all receiving objects and allocation objects corresponding to the nodes in the module depth graph obtained from the object allocation type statement or the method call type statement; if the node is a module boundary node, updating the module depth of the node to 0 and updating the module depths of all successor nodes of the node one by one; if the node is not a module boundary node, obtaining the module depths of all direct predecessor nodes of the node and screening out the minimum value from the module depths; if the minimum value plus 1 is less than the module depth of the node or the node is a newly added node, updating the module depth of the node to the minimum value plus 1 and updating the module depths of all successor nodes of the node based on the updated module depth of the node; otherwise, not updating the module depth of the node.
[0080] According to another embodiment of the present application, the module depth map is directly updated after parsing the object assignment statement and the method call statement, and the updating steps include: filtering the assignment objects and the receiving objects without corresponding nodes from the module depth map based on the assignment objects and the receiving objects obtained from the object assignment type statement or the method call type statement, creating new nodes corresponding to the assignment objects and the receiving objects, and adding edges from each corresponding assignment object to each corresponding receiving object to update the module depth map; and then updating the module depth information of the module depth map by: traversing all the nodes corresponding to the receiving objects and the assignment objects obtained from the object assignment type statement or the method call type statement in the module depth map; if the node is a module boundary node, updating the module depth of the node to 0 and updating the module depths of all the successor nodes of the node one by one; if the node is not a module boundary node, obtaining the module depths of all the direct predecessor nodes of the node and filtering the minimum value from the module depths, if the minimum value plus 1 is less than the module depth of the node or the node is a newly added node, updating the module depth of the node to the minimum value plus 1, and updating the module depths of all the successor nodes of the node based on the updated module depth of the node, otherwise, not updating the module depth of the node.
[0081] In order to more clearly illustrate the updating method of the module depth of the module depth map, the following will be described in detail with reference to the pseudo code shown in the following table. Figure 3 After updating the module depth map structure, Gather-Apply-Scatter (also referred to as GAS model) is performed in lines 2-10. Each of the receiving objects and the assignment objects obtained from the object assignment type statement or the method call type statement is traversed, if the receiving object or the assignment object P is a program module boundary, the module depth of P is set to zero, and when the depth of P changes, the depth is propagated to the successor nodes of P through the function Scatter. Otherwise, the predecessor nodes of P are gathered and the minimum value of the module depths is calculated (lines 13-14). It should be noted that T always returns the given value when taking the minimum value with any given value. Then, the minimum value plus 1 is applied to the object O through the Apply function (lines 16-23), if the target value is less than the original depth, the module depth of the node corresponding to the object O is refreshed. If the module depth of the object O changes, the updated depth is propagated to the successor nodes of the object O (lines 9-10). In the function Scatter (lines 24-27), if the depth of the object O changes, it is recursively propagated to the successor nodes of the object O.
[0082] In step S5, based on the constructed initial pointing set of all the variables, the implementation class bound to the left variable of the method call statement is re-bound to all the objects contained in the pointing set of the left variable to obtain the final pointing set of each variable.
[0083] According to one embodiment of the present application, since the pointing set of the left variable can be unknown during the execution of step S3, the implementation class temporarily bound to the left variable is re-bound to all objects pointed by the left variable after the initial pointing set of all variables is determined at the end of step S4.
[0084] According to one embodiment of the present application, a module-aware context-sensitive pointer analysis system is provided, which comprises: a module relationship modeling module for parsing the access and dependency relationship between each program module in a program package based on the keywords of each program module and establishing a program module relationship model; an encapsulation semantic analysis module for parsing all statements in the program package to be analyzed and synchronously updating the object allocation graph and the module depth graph during the parsing process, and constructing the initial pointing set of each variable in the program package based on the module depth graph; and a dynamic semantic analysis module for binding all implementation classes of the service interface called by each method call type statement in the program package or the objects created based on the implementation classes to the left variable of the statement, and re-binding the implementation classes bound to the left variable of the method call statement to all objects contained in the pointing set of the left variable based on the constructed initial pointing set of all variables to obtain the final pointing set of each variable.
[0085] In order to better understand the beneficial effects of the present application, the inventors designed two experiments to verify the reliability and performance of the module-aware context-sensitive pointer analysis method proposed in the present application, and the beneficial effects of the present application will be illustrated as follows:
[0086] The dacapo test cases are selected to evaluate the present application, and each program in the test cases is regarded as an "automatic module" by the module system to ensure forward compatibility, because these benchmarks are developed before the module system. The "automatic module" implicitly requires all other modules. In the dacapo test cases, jython is excluded because the context insensitivity cannot be extended to it. In addition, three widely used programs (ant, antlr4, checkstyle) are selected, which are migrated from versions before JDK9 to JDK9 or later versions; and four popular programs (jboss, logback, questdb, lombok) are selected, which are developed based on JDK9 or later versions and make full use of the features of the module system. Reliability tests and performance experiments are respectively conducted on the above-mentioned programs as test samples, and the experimental results are shown in Tables 1 and 2.
[0087] Reliability experiment result analysis: Table 1 shows the reliability experiment result, and the data in the analysis table can be obtained: under the context-insensitive analysis, the number of four indicators of other benchmark tests when modeling and not modeling SPI. For lombok, only 16 application methods are analyzed when not modeling SPI, while 841 methods are found after modeling SPI. For questdb, after modeling SPI, 5375 new methods are found compared with the original methods. For logback, the improvement of completeness is not significant, and only 74 new methods are processed. For the other three precision indicators, it can also be concluded that the present application can improve the completeness of pointer analysis by modeling SPI.
[0088] Table 1: Reliability experiment result
[0089]
[0090] Performance experiment result analysis, Table 2 shows the reliability experiment result, wherein the third column shows the time required for three analyses in the benchmark test. Compared with the context-insensitive analysis, for most benchmark tests such as antlr, eclipse, hsqldb, luindex, lusearch, etc., the running speed of the present application is as fast as the context-insensitive analysis. On average, the present application is 1.4 times slower than the context-insensitive analysis for all benchmark tests. For chart and lombok, the present application is 5.4 times and 9.5 times slower than the context-insensitive analysis, respectively, however, object-sensitive with a depth of 1 cannot analyze them under the same time budget. Excluding these two programs, the present application is only 0.6 times slower than the context-insensitive analysis on average. For other programs, the present application achieves acceleration from 1.8 times (questdb) to 5.6 times (eclipse), with an average acceleration of 3.7 times.
[0091] Table 2: Performance experiment result
[0092]
[0093] It should be noted that although the above describes the steps in a certain order, it does not mean that the steps must be performed in the above-mentioned specific order, in fact, some of the steps can be performed concurrently, or even the order is changed, as long as the required function can be realized.
[0094] The present application can be a system, a method and / or a computer program product. The computer program product can include a computer readable storage medium having computer readable program instructions loaded thereon, which are used to enable a processor to implement various aspects of the present application.
[0095] A computer readable storage medium can be, for example, but is not limited to, an electronic, magnetic, optical, electromagnetic, semiconductor, or any other suitable combination of the foregoing. More specific examples (a non-exhaustive list) of the computer readable storage medium include the following: a portable computer diskette, a hard disk, a random access memory (RAM), a read-only memory (ROM), an erasable programmable read-only memory (EPROM or Flash memory), a static random access memory (SRAM), a portable compact disc read-only memory (CD-ROM), a digital versatile disk (DVD), a memory stick, a floppy disk, a mechanically encoded device such as punch-cards or raised structures in a groove having instructions recorded thereon, and any suitable combination of the foregoing. A computer readable storage medium, as used herein, is not to be construed as being transitory signals per se, such as radio waves or other freely propagating electromagnetic waves.
[0096] Having described above several embodiments, now will be described a number of modifications and alternatives. Such description is included to provide for a more complete understanding of the various embodiments and is not intended in any way to limit the scope of possibilities. Many modifications in addition to those described above can be made by one skilled in the relevant art without departing from the scope and spirit of the described embodiments. The scope of the various embodiments disclosed herein cover all technical equivalents that do not depart from the spirit or essential characteristics of the various embodiments. The embodiments illustratively disclosed herein can suitably be practiced in the absence of any element or elements not specifically disclosed herein.
Claims
1. A module-aware, context-sensitive pointer analysis method for parsing packages to obtain the pointer set of variables within the package to achieve context-sensitive analysis, characterized in that, The method comprises: Step S1, obtaining a program package to be analyzed, which comprises a plurality of program modules; Step S2, parsing program module semantics, parsing each program module based on the keywords of each program module in the program package to obtain access permissions between program modules and to establish a program module relationship model based on the access permissions; Step S3, module dynamic semantic analysis, traversing each method call statement in each program module in the program package to be analyzed which calls a service interface, determining whether there is access permission between the program module where the method call statement is located and the program module where the service interface called by the method call statement is located based on the program module relationship model, and if there is access permission, binding all implementation classes of the service interface called by the method call statement or objects created based on the implementation classes to the left variable of the method call statement; Step S4, module encapsulation semantic analysis, parsing all statements in the program package to be analyzed and synchronously updating an object allocation graph and a module depth graph during the parsing process, and constructing an initial pointing set of each variable in the program package based on the module depth graph, wherein the object allocation graph is a directed graph describing the object allocation relationship in the program package, the module depth graph is a directed graph containing module depth information extended based on the object allocation graph, and the module depth is the number of edges of the shortest path from a node to a program module boundary node; Step S5, based on the constructed initial pointing set of all variables, re-binding the implementation classes bound on the left variable of the method call statement to all objects contained in the pointing set of the left variable to obtain the final pointing set of each variable.
2. The method of claim 1, wherein, The pointing set of each variable contains a plurality of combinations, and each combination is an object that the variable can point to and a context corresponding to the object, wherein the context includes at most one element.
3. The method of claim 1, wherein, In the step S4, all statements in the program package are divided into object allocation statements, copy statements, field read statements, field storage statements and method call statements based on the functions implemented by each statement, and the initial pointing set of each variable in the program package is constructed and the object allocation graph and the module depth graph are updated by selecting a corresponding mode for parsing according to the statement type.
4. The method of claim 3, wherein, In the step S4, the object allocation statement is parsed by the following method: determining whether there is access permission between the program module where the object allocation statement is located and the program module accessed by the object allocation statement based on the inter-module relationship model, and if there is access permission, performing the following steps: obtaining the context of the program method where the object allocation statement is located and combining it with the allocation object of the object allocation statement to add to the pointing set of the left variable; obtaining the allocation object of the object allocation statement and all receiving objects of the program method where the object allocation statement is located and updating the object allocation graph and the module depth graph based on the allocation object and the receiving objects.
5. The method of claim 3, wherein, In the step S4, the copy statement is parsed by the following method: obtaining the pointing set of the left variable in the copy statement and adding it to the pointing set of the right variable in the copy statement.
6. The method of claim 3, wherein, In the step S4, the field read statement is parsed by the following method: obtaining the pointing set of all fields read by the field read statement and adding it to the pointing set of the left variable in the field read statement.
7. The method of claim 3, wherein, In the step S4, the field storage statement is parsed by the following way: obtaining the pointing set of the right variable of the field storage statement and adding it to the pointing set of the field corresponding to the field storage statement to update the pointing set of the variable.
8. The method of claim 4, wherein, In the step S4, the method call statement is parsed by the following way: judging whether there is access permission between the program module where the method call statement is located and the program module accessed by the method call statement based on the inter-module relationship model, if there is access permission, the following steps are executed: obtaining the object pointed by the right variable of the method call statement; obtaining the module depth of the object based on the module depth map, if the module depth is 0, taking the object as the context of the program method called by the method call statement, if the module depth is greater than 0 and less than or equal to a preset threshold, obtaining the module boundary node on the shortest path corresponding to the module depth of the object in the module depth map, taking the object corresponding to the module boundary node as the context of the program method called by the method call statement, if the obtained module depth is greater than the preset threshold, setting the context of the program method as empty; adding the object pointed by the right variable and its corresponding context to the pointing set of the this variable in the method called by the statement after combining them; obtaining the pointing set of the actual parameter of the program method input called by the statement and adding it to the pointing set of the formal parameter variable of the called method; obtaining the pointing set of the return value variable of the called method of the statement and adding it to the pointing set of the left variable of the statement; obtaining the receiving object of the statement and all the allocated objects in the method called by the statement and updating the object allocation map and the module depth map based on them.
9. The method of claim 8, wherein, The object allocation map is updated by the following way: based on the receiving objects and the allocated objects obtained in the object allocation type statement or the method call type statement, filtering out the allocated objects and the receiving objects without corresponding nodes in the object allocation map and creating new nodes corresponding to them one by one, and then adding edges from each corresponding allocated object to each corresponding receiving object to update the object allocation map.
10. The method of claim 8, wherein, The module depth map is updated by the following way: after the object allocation map is updated each time, the corresponding nodes and edges are added in the module depth map according to the newly added nodes and edges in the object allocation map, and then the module depth information of the module depth map is updated by the following way: traversing all the receiving objects and the allocated objects obtained in the object allocation type statement or the method call type statement in the module depth map; if the node is a module boundary node, updating the module depth of the node to 0 and updating the module depths of all the successor nodes of the node one by one; if the node is not a module boundary node, obtaining the module depths of all the direct predecessor nodes of the node and filtering out the minimum value from them, if the minimum value plus 1 is less than the module depth of the node or the node is a newly added node, updating the module depth of the node to the minimum value plus 1 and updating the module depths of all the successor nodes of the node based on the updated module depth of the node, otherwise, not updating the module depth of the node.
11. A pointer analysis system for constructing a set of pointers to all variables in a program package to be analyzed, based on the method of any one of claims 1 to 10, characterized in that The system comprises: The module relationship modeling module is configured to parse the access and dependency relationship among the program modules based on the keywords of the program modules in the program package and to establish a program module relationship model based on the parsed access and dependency relationship. The encapsulation semantic analysis module is configured to parse all statements in the program package to be analyzed and to update the object allocation graph and the module depth graph synchronously during the parsing process, and to construct an initial pointing set of each variable in the program package based on the module depth graph. The dynamic semantic analysis module is configured to bind all implementation classes of the service interface called by each method call type statement in the program package or objects created based on the implementation classes to the left variable of the statement, and to re-bind the implementation classes bound to the left variable of the method call statement to all objects contained in the pointing set of the left variable based on the constructed initial pointing set of all variables to obtain a final pointing set of each variable.
12. A computer-readable storage medium, characterized in that, A computer program is stored thereon, and the computer program is executable by a processor to implement the steps of the method in any one of claims 1 to 10.
13. An electronic device, comprising: Comprise: one or more processors; and a memory, wherein the memory is configured to store executable instructions; the one or more processors are configured to implement the steps of the method in any one of claims 1 to 10 via execution of the executable instructions.