Code testing method and device, electronic equipment and readable storage medium
Through static analysis, the execution path of code tests is determined and the input file is selectively mutated, which solves the redundant testing problem caused by random input in the existing technology, and improves the efficiency of code tests and the ability to discover deep vulnerabilities.
Patent Information
- Application Number
- CN202510459740.X
- Authority / Receiving Office
- CN · China
- Patent Type
- Applications(China)
- Current Assignee / Owner
- Filing Date
- 2025-04-11
- Publication Date
- 2025-08-19
AI Technical Summary
In the prior art, code testing methods send a large amount of random or semi-random input data to the tested program, resulting in the generation of redundant test cases, affecting the performance and efficiency of the test tools, making it difficult to effectively discover deep vulnerabilities.
By performing static analysis of the source program, determine all paths from the entry point to the target code block, selectively mutate the initial input file, set the detection function and test it in the target program, to ensure that the input file can overwrite the execution path of the target code block.
It improves the efficiency of code testing, increases the probability of deep vulnerabilities in the program, reduces invalid input, and improves the effectiveness of the test.
Smart Images

Figure CN120509035A_ABST
Abstract
Description
Technical Field
[0001] The present application relates to the field of computer technology, and in particular to a code testing method, device, electronic device, and readable storage medium. Background Art
[0002] Code testing is a method of discovering software vulnerabilities by providing unexpected inputs to the target system and monitoring abnormal results. The core idea is to inject invalid data, unexpected data, or random data as input into the program under test and monitor program anomalies such as crashes, built-in code assertion errors, potential memory leaks, log anomalies, etc. to test the program under test.
[0003] Existing techniques discover potential vulnerabilities by sending large amounts of random or semi-random input data to the program under test and monitoring its execution status. This approach can result in the generation of numerous redundant test cases, impacting the performance and efficiency of testing tools and making it difficult to effectively discover deeper vulnerabilities in the program under test.
[0004] Application Contents
[0005] The embodiments of the present application provide a code testing method, device, electronic device, and readable storage medium, which can improve code testing efficiency.
[0006] In a first aspect, an embodiment of the present application discloses a code testing method, the method comprising:
[0007] Performing static analysis on the source program to determine all paths from the entry point to the target code block;
[0008] selectively mutating the initial input file according to all the paths to obtain a target input file;
[0009] Setting a detection function in the source program to obtain a target program;
[0010] The target input files are sequentially input into the target program for testing to obtain the test results corresponding to the source program.
[0011] In a second aspect, an embodiment of the present application discloses a code testing device, the device comprising:
[0012] The analysis module is used to perform static analysis on the source program and determine all paths from the entry point to the target code block;
[0013] a mutation module, configured to selectively mutate the initial input file according to all the paths to obtain a target input file;
[0014] A generation module, configured to set a detection function in the source program to obtain a target program;
[0015] The test module is used to input the target input files into the target program in sequence for testing, and obtain the test results corresponding to the source program.
[0016] In a third aspect, an embodiment of the present application discloses an electronic device, characterized in that the electronic device includes a processor, a memory, a communication interface and a communication bus, and the processor, the memory and the communication interface communicate with each other through the communication bus; the memory is used to store executable instructions, and the executable instructions enable the processor to execute the aforementioned code testing method.
[0017] In a fourth aspect, an embodiment of the present application discloses a readable storage medium, characterized in that a program or instruction is stored on the readable storage medium, and the program or instruction implements the aforementioned code testing method when executed by a processor.
[0018] The embodiments of the present application include the following advantages:
[0019] For each target code block, determine the entire path from the source program's entry point to the target code block; selectively mutate the initial input file based on the entire path to obtain the target input file; set a detection function in the source program to obtain the target program; and sequentially input the target input files into the target program for testing. This application obtains the execution path of the target code block in advance, guiding the initial input file, including the test case, to selectively mutate, rather than randomly and blindly mutate. This increases the probability that the mutated input file will cause the program to crash or trigger a new path, thereby improving the efficiency of code testing. BRIEF DESCRIPTION OF THE DRAWINGS
[0020] In order to more clearly illustrate the technical solutions of the embodiments of the present application, the following briefly introduces the drawings required for use in the description of the embodiments of the present application. Obviously, the drawings described below are only some embodiments of the present application. For ordinary technicians in this field, other drawings can be obtained based on these drawings without any creative work.
[0021] Figure 1 This is a flowchart of the steps of an embodiment of a code testing method of the present application;
[0022] Figure 2 This is a structural block diagram of a code testing device of the present application;
[0023] Figure 3 This is a structural block diagram of an electronic device provided as an example in this application. DETAILED DESCRIPTION
[0024] The following will be combined with the accompanying drawings in the embodiments of this application to clearly and completely describe the technical solutions in the embodiments of this application. Obviously, the described embodiments are part of the embodiments of this application, not all of them. Based on the embodiments in this application, all other embodiments obtained by ordinary technicians in this field without making creative efforts are within the scope of protection of this application.
[0025] Method Example
[0026] Reference Figure 1 , shows a flowchart of a code testing method embodiment of the present application, the method may specifically include the following steps:
[0027] Step S101: Perform static analysis on the source program to determine all paths from the entry point to the target code block.
[0028] The code testing method provided in this application can be applied to a test system to test target objects to discover potential problems and vulnerabilities in the target objects. The target objects refer to network devices, application programming interfaces, applications, etc.
[0029] It should be noted that static analysis can be performed on the entire source program, or on portions of the source program. Using program static analysis techniques, target code blocks within the source program are identified. Program static analysis is a computer program debugging method that examines code without executing the program, facilitating understanding of code structure and ensuring compliance with industry standards. Program static analysis techniques may include lexical analysis, syntax analysis, control flow analysis, data flow analysis, interface analysis, pointer analysis, pattern matching, and expression analysis. In embodiments of the present application, a single analysis technique may be used to identify target code blocks within the source program, or multiple static analysis techniques may be combined to identify target code blocks within the source program. Data flow analysis involves tracing the flow of variables and data within the code to detect issues such as uninitialized variables, dead code, and memory leaks. Control flow analysis involves examining possible execution paths within a program to detect branches and loop structures that may cause program exceptions. Interface analysis involves checking the consistency of interfaces between subroutines and functions, including checking the consistency of parameter types, number, dimension, and order. When common variable blocks or global variables are used for data or control transfer between subroutines, their consistency should also be checked. Expression analysis refers to checking for problems such as mismatched brackets, out-of-bounds array references, and division by zero.
[0030] Target code blocks refer to code blocks with logical errors, poor performance, and code blocks that do not comply with coding standards. They also refer to code blocks with security issues such as memory access errors, memory leaks, and undefined behavior.
[0031] As an example, suppose the source program looks like this:
[0032]
[0033] The process of statically analyzing a source program can include tracking the state of variables within the source program, identifying key function calls within the source program, and determining whether the source program contains logic that checks the return values of key functions. Key functions are those that perform important system functions, may return error messages, or involve resource management. For example, the malloc function, used for dynamic memory allocation, returns NULL if the allocation fails. Directly using a pointer without checking the malloc function's return value can result in a null pointer error.
[0034] For example, in the source program in the example, the state of the variable buffer is tracked. The variable buffer is initially NULL. When the conditional branch data! = NULL && size > 0 holds, memory is dynamically allocated, buffer = malloc(...). The return value of the malloc() function may be NULL. The source program is checked for logic that checks the return value of the malloc() function. Clearly, the source program does not check the return value of the malloc() function. If the return value of malloc is NULL in the subsequent program, buffer = NULL. Therefore, executing buffer[i] may result in a null pointer dereference. Therefore, "buffer = (int*)malloc(size*sizeof(int));_" is the first target code block, lacking logic to check the function return value. "buffer[i] = data[i]" is the second target code block, which may result in a null pointer dereference error.
[0035] It is understandable that because different static code analysis methods focus on different code attributes, when analyzing a source program using different static code analysis techniques, the target code blocks identified in the source program may be different. Furthermore, the number of target code blocks in a source program may be single or multiple.
[0036] It should be noted that determining all possible execution paths from the source program's entry point to the target code block refers to identifying all possible execution paths from the source program's entry point to the target code block through program static analysis methods. Each target code block corresponds to at least one path, and each path begins at the source program's entry point and ends at the target code block.
[0037] Specifically, determining the entire path from the entry point of the source program to the target code block may include the following steps:
[0038] Step 11: Build the abstract syntax tree (AST) corresponding to the source program.
[0039] Specifically, the source program is split into lexical units, and the lexical units are organized into AST according to grammatical rules. AST is an abstract representation of the source program, which retains the structure and semantic information of the source program.
[0040] Step 12: Based on AST, construct the control flow graph corresponding to the source program.
[0041] A control flow graph is a directed graph in which nodes represent basic blocks in a source program. A basic block is a sequence of instructions without branches or jumps. Directed edges indicate the transfer of control flow from one basic block to another. A source program is divided into basic blocks and connected by directed edges. A control flow graph is used to represent the basic blocks within each function in the source program and all possible execution paths between basic blocks.
[0042] Step 13: Build a call graph.
[0043] A call graph is a graph that shows the function call relationships within a source program. In a call graph, nodes represent individual functions in the source program, and edges represent the function call relationships. By constructing a call graph, you can determine the call relationships and call hierarchy between functions. A target code block is a portion of code within a function.
[0044] Step 14: Traverse the control flow graph and call graph.
[0045] As can be seen above, a control flow graph represents the paths within each function in a source program, while a call graph represents the calling relationships between functions within the source program. The global call chain in the source program is determined based on the call graph. The internal paths of each function are analyzed based on the control flow graph, and the global path is concatenated. From these paths, all possible paths to the target code block are filtered out. Starting from the source program's entry point, the control flow graph and call graph are traversed to identify all possible paths to the target code block. The program's entry point is typically the main function. This traversal can be implemented using graph traversal algorithms such as depth-first search and breadth-first search.
[0046] As an example, suppose the source program looks like this:
[0047]
[0048]
[0049] Static analysis of the source program reveals that the strcpy() function, which copies strings, does not validate external data. Therefore, "strcpy(buffer, input);" is the target code block. Based on this source program, we construct the corresponding abstract syntax tree and, based on it, generate the control flow graph and call graph for each function.
[0050] The control flow graph of the main function is: main function entry → conditional branch (argc>1?), when the conditional branch is true, it points to the process_input() function; when the conditional branch is false, it points to validate.
[0051] The control flow graph of the process_input function is: process_input function entry → buffer
[64] → conditional branch (input!=NULL); when the conditional branch is true, it points to strcpy; when the conditional branch is false, it is skipped.
[0052] The control flow graph of the validate function is: validate function entry → conditional branch (flag>0); when the conditional branch is true, it points to process_input("test"); when the conditional branch is false, it is skipped.
[0053] The call graph of the source program is: main function entry → conditional branch (argc>1?); when the conditional branch is true, it points to the process_input function; when the conditional branch is false, it points to the validate function, and when flag>0, it points to the process_input function.
[0054] The call graph identifies the calling relationships between functions and determines the direct path from the program entry point to the target code block: main → process_input (when argc > 1); the indirect path: main → validate → process_input (when argc <= 1 and flag > 0). By refining the paths in the control flow graph, we can find that path 1 from the program entry point to the target code block is: main → (argc > 1) → process_input → (input != NULL) → strcpy, and path 2 is: main → (argc <= 1) → validate → (flag > 0) → process_input → (input != NULL) → strcpy.
[0055] It should be noted that after determining all the paths from the entry point of the source program to the target code block, the information of each path node on the path can be saved in a two-dimensional array. Among them, the number of rows in the two-dimensional array represents the number of all paths from the entry point of the source program to the target code block; the number of columns in each row represents the number of path nodes on each path. Path node information refers to the attributes of the path node or the data contained in the path node. The path node information may include the identifier, type, value, location information, etc. of the path node. Based on the abstract syntax tree, the nodes passing from the entry point of the program to the target code block constitute the entire path corresponding to the target code block, and each node on the path is saved in a two-dimensional array. For example, path 1 and path 2 are saved in the two-dimensional array paths,
[0056] Then, paths=[["main", "argc>1", "process_input", "input!=NULL", "strcpy"], ["main", "argc<=1", "validate", "flag>0", "process_input", "input!=NULL", "strcpy"]].
[0057] Among them, ["main", "argc>1", "process_input", "input!=NULL", "strcpy"] represents path 1, and ["main", "argc<=1", "validate", "flag>0", "process_input", "input!=NULL", "strcpy"] represents path 2.
[0058] When storing path node information in a two-dimensional array, the storage form of the path node information in the array can be determined based on the complexity and type of the path node information. The storage form can be an integer, a string, a structure, or other data type.
[0059] It should be noted that after determining all paths from the program entry point to the target code block, each path can be further evaluated to determine the risk level of each path, and the initial input file can be mutated preferentially based on the paths with higher risk levels.
[0060] Specifically, the risk level of each path can be comprehensively determined based on dimensions such as security vulnerabilities and performance issues. Each dimension is assigned a corresponding weight, and a weighted sum is taken based on the weights and scores of each dimension to obtain a total risk score for each path. The total risk score for each path is calculated and divided into three intervals: high, medium, and low risk. For example, a total risk score between 61 and 100 corresponds to a high risk level; a total risk score between 31 and 60 corresponds to a medium risk level; and a total risk score between 0 and 30 corresponds to a low risk level. The score for the security vulnerability dimension can be determined based on factors such as input validation and the number of calls to the target code block. Specifically, unvalidated inputs are more likely to present a security risk than validated inputs; therefore, the score for unvalidated inputs in a path is higher than that for validated inputs. The greater the number of calls to a target code block, the greater the likelihood of program exceptions. Therefore, the greater the number of calls to a target code block in a path, the higher the score. The score for the performance issue dimension can be determined based on factors such as cyclomatic complexity and resource usage.
[0061] For example, the security vulnerability dimension accounts for 70%, and the performance issue dimension accounts for 30%. Path 1 has no input validation, scoring 15; the target code block in Path 1 is called twice, scoring 20; the security vulnerability dimension score is 24.5; the three-level nested loop score is 10, the peak memory usage reaches 80%, scoring 8; the performance issue dimension score is 5.4, and the total risk score is 29.9, placing Path 1 at a low risk level.
[0062] Step S102: selectively mutate the initial input file according to all the paths to obtain a target input file.
[0063] It should be noted that static analysis tools are used to identify risky paths within all paths in the source program. Based on these risky paths, the initial input file is selectively mutated. For example, if the risky path is associated with specific types of input data, the initial input file will be mutated primarily around these data types and structures. For example, if the source program contains an image parsing function, static analysis may reveal that the parse_header() function does not verify the validity of the width and height fields and directly passes them to the malloc() function, potentially triggering a buffer overflow. Therefore, a risky path exists between the program entry point and the malloc() function. Because this risky path primarily relates to the width and height fields, the initial input file is mutated by modifying these fields. For example, the initial input file has width = 1024 and height = 768; in the mutated input file, width = 0xFFFFFFFF and height = 0x00000000. A risky path refers to a series of steps or decision-making processes that could lead to adverse consequences during program execution. Risky paths can include logical error paths, security vulnerability paths, and performance bottleneck paths.
[0064] During code testing, the initial input file refers to any form of data received by the program under test. The data can be text, binary files, network data packets, and other test cases. The format and content of the data depend on the needs and expectations of the program under test. The initial input file can be a specific file created manually or random data generated using an automated tool. There is usually no fixed limit on the number of initial input files, and the program can be code tested based on any number of initial input files. Specifically, if the program under test can receive and process structured files (such as JSON, XML, PDF, etc.), the input file is the corresponding structured file. If the program under test can receive and process binary files (such as image files, video files, etc.), the input file is the corresponding binary file.
[0065] Step S103: Setting a detection function in the source program to obtain a target program.
[0066] It should be noted that the source program refers to a human-readable computer program written in a programming language, which has not been compiled. The target program refers to the machine code that can be directly executed by a computer after the source program has been compiled.
[0067] Setting a detection function in the source program means turning on detection options such as memory errors during the process of compiling the source program to generate an executable program or target program. Specifically, the compiler inserts additional code into the source program during the compilation process to detect memory errors at runtime. Memory errors can include memory leaks, buffer overflows, wild pointer accesses, etc. Different programming languages and development environments provide different ways to turn on memory error detection options. For example, on Windows systems, you can use the memory error detection function that comes with development tools such as Visual Studio. These detection options can usually be enabled in project properties or compilation options.
[0068] After enabling the memory error detection option, compile the source program to generate the target program. Compilation is the process of converting a source program into an executable file or machine code. During the compilation process, the compiler generates the target program based on the source program and the specified compilation options, and simultaneously performs memory error detection on the source program. After compilation is complete, the target program is generated. The target program contains the functionality of the source program as well as additional code for memory error detection. When running the target program, if the target program attempts to perform illegal memory access operations, the additional memory error detection code will catch these exceptions and may provide detailed error information and stack traces to help developers locate and fix the problem.
[0069] Step S104: input the target input files into the target program in sequence for testing, and obtain the test results corresponding to the source program.
[0070] During testing, focus on the target program's test results, including direct output, error messages, and performance. For each target input file, record the target program's output, test results, and any errors or exceptions that occur, so that they can be provided to developers for analysis.
[0071] It should be noted that mutation refers to changing the content of the input file, specifically, changing the bits, bytes, values, etc. in the input file. Mutation is usually random and blind. In the embodiments of the present application, static analysis is used to determine the target code blocks in the source program that may cause program execution exceptions, and the execution path from the source program entry to the target code blocks is determined. Based on the execution path, the input file is modified in a targeted and selective manner.
[0072] As an example, suppose there is a program that parses a binary file as follows:
[0073]
[0074]
[0075] The initial input file is original_data=b"\x01\x00\x10"+b"A"*16, in the initial input file, opcode=0x01,length=0x1000,data="A"*16, and the possible input file after random mutation is mutated_data=b"\x02\xFF\x00"+b"B\x00C". The random mutation in the input file after random mutation is to randomly flip, insert, delete or replace all bytes of the input file, that is, randomly modify the opcode, length and data fields. In an embodiment of the present application, the target code block in the source program is determined to be "memcpy(buffer,data+3,length)" through static analysis, and the execution path to reach the target code block depends on opcode=0x01. Therefore, opcode=0x01 is kept unchanged to ensure that the execution path to reach the target code block is reachable, and only the length field and data field are modified.
[0076] Therefore, most of the input files generated by random mutation may not trigger the target code block, while all input files generated by selective mutation can ensure that the execution path covers the target code block, reduce invalid input, and can cause the program under test to crash or trigger new paths more quickly, thereby improving the efficiency of testing the program under test.
[0077] In an embodiment of the present application, for each target code block, wherein the target code block refers to a code block with logical errors, a code block with poor performance, a code block that does not comply with coding specifications, and a code block with security issues such as memory access errors, memory leaks, and undefined behavior. Determine all paths from the entry point of the source program to the target code block; selectively mutate the initial input file according to all paths to obtain a target input file; set a detection function in the source program to obtain a target program; and input the target input file into the target program in sequence for testing. In an embodiment of the present application, by obtaining the execution path to the target code block in advance, the initial input file is guided to perform selective mutation. Selective mutation refers to selectively modifying part of the content of the initial input file in a targeted manner so that the mutated input file can trigger a crash or exception in the target program more quickly, thereby improving the efficiency of code testing.
[0078] Optionally, selectively mutating the input file according to all the paths to obtain the target input file includes:
[0079] Step 21: insert at least one marker into each path between the entry point of the source program and the target code block to obtain a first program;
[0080] Step 22: selectively mutate the initial input file according to at least two mutation methods to obtain at least two first input files, and determine mutation information corresponding to each of the first input files when a flag in the first program is triggered; the mutation information is used to indicate the mutation location and mutation type in the first input file;
[0081] Step 23: Determine target mutation parameters based on the mutation positions and mutation types corresponding to the at least two first input files;
[0082] Step 24: mutate the initial input file according to the target mutation parameter to obtain the target input file.
[0083] It should be noted that markers can be inserted at key nodes in each path. Key nodes may include: the starting point of the path, the end point of the path, the function entry, the conditional judgment branch, the beginning and end of the loop structure, and the location where data is operated. Performing insertion operations at the location where data is operated can monitor the life cycle and state changes of the data, which helps to discover memory leaks and cross-boundary access issues. Among them, the marker can exist in various forms, and the content of the marker is unique, and is used to monitor and analyze the execution path of the first program, and record the execution status and coverage information of the first program.
[0084] Specifically, a marker can be directly inserted into each path of the source program, and the source program can be compiled to generate the first program. Alternatively, the source program can be converted into an abstract syntax tree, the abstract syntax tree can be instrumented, and the source program can be reconstructed based on the instrumented abstract syntax tree. The reconstructed source program can be mutated to generate the first program.
[0085] Exemplarily, markers are inserted at control flow branches, loops, or function calls to track the execution path triggered by the input file.
[0086]
[0087]
[0088] Add log functions as markers at the program entry points and conditional branches. Log functions are typically used to record program status or events during runtime. During program execution, when input = "A...", the execution path will trigger Marker 1 → Marker 2, while input = "B..." will trigger Marker 1 → Marker 3.
[0089] After converting the source program into an abstract syntax tree, the information for each path node along all paths from the program entry point to the target code block can be stored in a two-dimensional array. After determining which target path nodes to insert markers before, the target path node's target position in the abstract syntax tree is retrieved from the two-dimensional array. The marker is inserted before the target position to form a new marker node, and the marker node information is inserted into the two-dimensional array. The marker content is unique and can be generated based on, for example, the source program name, the length of the path where the marker is located, and the index of the marker node in the two-dimensional array.
[0090] The mutation method refers to the rules for modifying the content of the initial input file. For example, after determining the execution path from the program entry point to the target code block, the field range of the variables in the input file that the execution path depends on is modified. Specifically, methods for selectively mutating the initial input file can include bit flipping, byte flipping, and simple arithmetic. Bit flipping refers to flipping bits one by one, from 1 to 32 bits. Specifically, the variables that depend on the execution path can be flipped bit by bit from the beginning to the end to generate new input samples. Byte flipping is an extension of bit flipping, mainly flipping 8-bit, 16-bit, and 32-bit wide bytes. Simple arithmetic refers to arithmetic operations such as adding or subtracting values in the initial input file, typically incrementing or decrementing bytes, 16-bit, and 32-bit values. The difference between bit flipping and byte flipping lies in the size of the smallest unit of mutation operation. Bit flipping modifies one or more bits in the initial input file, modifying the objects more precisely; byte flipping modifies one or more bytes in the initial input file, modifying the objects more broadly than bit flipping. Simple arithmetic modifies the values in the initial input file. By affecting the size of the values, it can be used to simulate numerical boundary conditions or numerical overflows, and discover boundary condition errors or overflow problems related to numerical values.
[0091] By mutating the initial input file, more different input files for testing can be generated. After the input file is input into the program, the execution process of the program is monitored. In the case where an abnormal input file causes the program to crash, the crash scene is captured, and the processing defects, security holes and other problems of the program can be analyzed and located. By mutating the input file, a large number of different input files can be generated in a short period of time, increasing the probability of triggering boundary conditions in the program, with low cost and high efficiency. In an embodiment of the present application, the target code block in the source program where an exception may occur and the execution path from the program entry to the target code block are first determined, and the initial input file is mutated relatively targeted according to the path to the target code block, rather than a completely random and blind mutation.
[0092] Among them, the mutation position refers to the position in the initial input file where the content changes, and the mutation type refers to the way of modifying the content of the mutation position, such as deletion, addition, flipping, replacement and other operations. It should be noted that the mutation information corresponding to the first input file is used to indicate the mutation of the first input file, specifically including the mutation position and mutation type in the first input file. The target mutation parameter is used to indicate how to mutate the initial input file. Specifically, the mutation positions and mutation types of at least two first input files can be arranged and combined to mutate the initial input file; or after the first input file is input into the first program, the mutation methods corresponding to the first input file can be sorted according to the running status of the first program.
[0093] For example, a mutation method that can cause the first program to execute close to the target code block, trigger the first program to crash, or trigger a new path during the execution of the first program is preferably used to mutate the initial input file to obtain a target input file. For example, the initial input file is "original_data = b"\x01\x00\x10" + b"A" * 16", and there are two first input files, namely "mutated_data1 = b"\x01\xFF\xFF" + b"A" * 16" and "mutated_data2 = b"\x01\x00\x10" + b"B" * 1000". The two first input files are combined and the initial input file is mutated to obtain the target input file "mutated_data3 = b"\x01\xFF\xFF" + b"B" * 1000".
[0094] In an embodiment of the present application, at least one marker is inserted into each path between the entry point of the source program and the target code block; the initial input file is selectively mutated according to at least two mutation methods to obtain at least two first input files; for each first input file, when the first input file triggers a marker in the first program, the mutation information corresponding to the first input file is determined; the mutation information is used to indicate the mutation position and mutation type in the first input file; the initial input file is mutated according to the target mutation parameter to obtain the target input file. First, selective mutation is performed according to the path to the target code block, and then, according to the situation of triggering the marker during the running of the first program after the first selective mutation, the mutation method of the first selective mutation is sorted or combined, and the initial input file is mutated to obtain the final target input file, so that the mutated target input file is more likely to trigger the crash or exception of the target program than the input file obtained by random mutation, thereby improving the efficiency of code testing.
[0095] Optionally, determining target mutation parameters according to the mutation positions and mutation types corresponding to the at least two first input files includes:
[0096] Step 31: Calculate, using an inverse proportional function, a weight of the variation information corresponding to the first input file based on the distance between the first marker triggered by the first input file and the target code block in the source program; the weight is used to indicate the priority corresponding to the variation information; the first marker is the last marker triggered by the first input file before the execution of the first program ends;
[0097] Step 32: Determine the target mutation parameter according to the weight of the mutation information corresponding to the first input file.
[0098] It should be noted that, if the first program successfully completes after the first input file is input into it, the last mark refers to the last mark before the first program completes normally. The last mark can reflect the length of the execution path of the first program. If the first program crashes after the first input file is input into it, the last mark refers to the last mark before the first program triggers the crash. The last mark can be used to locate potential problem areas.
[0099] The distance between the first marker and the target code block can be measured using the following factors: the number of logical steps between the last marker and the target code block, the number of jumps and branches in the control flow between the last marker and the target code block, and the execution time between the last marker and the target code block. It should be understood that when calculating the distance between the last marker and the target code block, the target code block and the last marker are on the same execution path.
[0100] For example, the source program includes the following code:
[0101]
[0102] Static analysis of the source program above determines that "buffer[i] = data[i];" is the target code block, which poses a risk of buffer overflow. The entire path from the program entry to the target code block is obtained, and stubs are inserted at key locations along the path, i.e., markers are inserted, such as branches or loops. The path from the program entry to the target code block is: main → process_data → marker 1 → marker 2 → target code block; MARK(1) and MARK(2) are markers; the path length from marker 1 to the target code block is 2 (marker 1 → marker 2 → target code block); the path length from marker 2 to the target code block is 1 (marker 2 → target code block).
[0103] It should be noted that, when the information of each path node and the information of the marker node are stored in a two-dimensional array, the distance between the first marker and the target code block is determined based on the position of the first marker in the two-dimensional array. Specifically, the index of the first marker in the two-dimensional array contains two dimensions, Ext_vec_index represents the index of the first dimension of the two-dimensional array, and Int_vec_index represents the index of the second dimension of the two-dimensional array. The length of the path where the first marker is located is determined based on the first dimension index corresponding to the first marker. The distance between the first marker and the target code block can be expressed by subtracting the second dimension index corresponding to the first marker from the length of the path where the first marker is located.
[0104] In an embodiment of the present application, the weight of the mutation information corresponding to each first input file is determined based on the distance between the first marker triggered by each first input file and the target code block. The greater the weight, the higher the priority of the mutation information corresponding to the first input file. The initial input file is preferentially mutated based on the mutation information of the first input file with a short distance between the first marker and the target code block to obtain the target input file. Alternatively, the initial input file is simultaneously mutated based on the mutation information corresponding to at least two initial input files with high priority in order of priority to obtain the target input file.
[0105] The distance between the last marker triggered by the first input file and the target code block is negatively correlated with the weight corresponding to the mutation information of the first input file, i.e., the smaller the distance, the greater the weight; the larger the distance, the smaller the weight. Specifically, compared to the calculation methods of exponential functions and polynomial functions, this embodiment uses an inverse proportional function to calculate the weight of the mutation information corresponding to the first input file, which can show an intuitive negative correlation. The inverse proportional function also provides a smooth calculation method, avoiding the explosive growth of weights when the distance is small. The calculation process of using the inverse proportional function to calculate weights is relatively simple, which is suitable for scenarios where high-frequency weight calculation is required during code testing, and can improve calculation efficiency.
[0106] For example, the inverse proportional function is Formula (1), where x is the distance between the first marker and the target code block, y is the weight corresponding to the mutation information corresponding to the first input file, and k is a constant not equal to 0.
[0107]
[0108] Among them, the distance between the first marker and the target code block in the inverse proportional function is the independent variable, and the weight of the mutation information corresponding to the first input file is the dependent variable, and the two correspond one to one and are negatively correlated. The closer the distance between the first marker and the target code block, the greater the weight of the mutation information corresponding to the first input file. The k value is a proportional constant. The larger the k value, the higher the overall weight value of each mutation information, and the smaller the k value, the lower the overall weight value of each mutation information. Usually the default value is k = 1. When the numerical range of the overall distance is large, the weight y of the mutation information of each first input file can be avoided from being too small by increasing the k value. For example, the k value can be adjusted to 10, and the weight of the mutation information of the first input file whose first marker is triggered at a distance x of 10 from the target code is 1.
[0109] For example, assume the program under test parses network protocol data. Static analysis has determined the location of the vulnerable_parser() function, and defined its entry point as a target code block. Assume the control flow of the program under test follows the sequence: main → parse_header (B1) → validate (B2). At basic block B2, there are two branches: one pointing to process_data (B3) → vulnerable_parser (B4); the other to safe_handler (B5). B1, B2, B3, B4, and B5 are basic blocks, respectively. Assume there are two input files, input1 and input2, whose execution paths cover the following basic blocks: input1: B1 → B2 → B5 (does not reach target B4), triggering markers: B1, B2, B5; input2: B1 → B2 → B3 (approaches target B4 but does not reach it), triggering markers: B1, B2, B3. The distance between the last triggered marker and the target code block is determined by the number of markers between them. The last marker triggered by input file input1 is B5, which cannot reach the target code block B4, so the distance is infinite. The last marker triggered by input file input2 is B3, and the distance between it and the target code block B4 is 1. Substituting this into the weight formula, we can see that the weight corresponding to the mutation information of input1 is negligible due to the infinite distance. The weight corresponding to the mutation information of input2 is greater than the weight corresponding to the mutation information of input1.
[0110] In an embodiment of the present application, when a first input file triggers a marker in the first program, an inverse proportional function is used to calculate the weight corresponding to the mutation information of the first input file based on the distance between the last marker triggered by the first input file and the target code block in the source program. A target mutation parameter is determined based on the weight of the mutation information corresponding to each first input file. The mutation method corresponding to the first input file with the most weighted mutation parameter is preferentially used to mutate the initial input file to obtain the target input file. This allows the program to execute closer to the target code block where security vulnerabilities, processing defects, and other issues exist, thereby triggering a crash more quickly and improving code testing efficiency.
[0111] Optionally, mutating the initial input file according to the target mutation parameter to obtain a target input file includes:
[0112] Step 41: Obtain a target array based on the variation position information in each first input file;
[0113] Step 42: Analyze the target array and determine a mutation strategy;
[0114] Step 43: Mutate the initial input file according to the mutation strategy to obtain a target input file.
[0115] It should be noted that the number of mutation positions in the first input file may be one or more; the target array is used to store the mutation position information in each first input file.
[0116] If the length of the target array is N, the mutation strategy can be: sequentially obtain the mutation position information of each first input file in the target array in ascending order of the target array index value; each time the mutation position information of a first input file in the target array is obtained, the corresponding position in the initial input file is mutated according to the mutation position information to obtain a target input file. The mutation strategy can also be: sequentially obtain the mutation position information of n first input files in the target array in ascending order of the target array index value (n>1); each time the mutation position information of n first input files is obtained, the corresponding position in the initial input file is mutated to obtain a target input file; after traversing each element in the target array, n is increased by one, each element in the target array is traversed again, and the initial input file is mutated according to the mutation position information of the n first input files to obtain the target input file, and the cycle is repeated until n=N.
[0117] For example, assuming the initial input file is binary data b"\x01\x02\x03\x04", the target array stores three mutation position information, and the mutation operation is to add 1 to the byte value at the specified position. The target array is defined as follows:
[0118]
[0119] Traverse the target array in index order, mutating only one position in the initial input file at a time to generate an independent target file. Read the mutated position at index 0 and add 1 to the value of byte 0, that is, 0x01→0x02, resulting in the target input file: b"\x02\x02\x03\x04". Three target input files are generated based on the three elements. Traverse the target array in index order, selecting n positions for combined mutation each time. For n = 2, read the mutated position information at indexes 0 and 1 in the initial input file b"\x01\x02\x03\x04" and add 1 to the values at indexes 0 and 1, respectively. That is, add 1 to "\x01\x02" to obtain "\x02\x03". The final target input file is: b"\x02\x03\x03\x04". Repeat this process until n = N.
[0120] In an embodiment of the present application, a target array is obtained based on the mutation position information in each first input file; a mutation strategy is determined based on the target array; and the initial input file is mutated according to the mutation strategy to obtain a target input file. The target input file obtained by mutating the initial input file based on the mutation positions corresponding to the selective mutations is more likely to cause the target program to crash more quickly than an input file obtained through random mutation, thereby improving the efficiency of code testing.
[0121] Optionally, the step of sequentially inputting the target input files into the target program for testing includes:
[0122] Step 51: for each target input file, determine whether the target program crashes or triggers a new path during execution, and record the time interval between the last time the crash or new path was triggered and the current time.
[0123] Step 52: When the time interval reaches a preset threshold, stop testing the target program.
[0124] It should be noted that each target input file can be input into the target program in sequence, and the target program executes each target input file in sequence; or at least two target input files can be input into the target program at the same time, and the target program executes at least two target input files in parallel.
[0125] In an embodiment of the present application, for each target input file, a determination is made as to whether the target program crashes or triggers a new path during execution, and the time interval between the last time a crash or new path was triggered and the current time is recorded. If the time interval reaches a preset threshold, it indicates that the input file covers most possible abnormal situations of the target program, and testing of the target program is stopped. By setting reasonable iteration termination conditions, testing can be stopped promptly after achieving the desired test results, thus avoiding resource waste and improving test efficiency.
[0126] Optionally, for each target input file, determining whether the target program crashes or triggers a new path during execution, and recording the number of executions of the target program, includes:
[0127] Step 61: When the target program crashes or triggers a new path during execution, selectively mutate the target input file according to all the paths to obtain a new target input file;
[0128] Step 62: Input the new target input file into the target program for the next round of testing until the preset conditions are met.
[0129] It should be noted that at the beginning of the test, some input files are selected as initial input files and added to the input queue. Each initial input file in the input queue is mutated based on the path to the target code block to obtain the target input file, which is then fed into the target program. If the target program crashes or triggers a new path during execution, the target input file is added to the input queue, and each target input file in the input queue is mutated based on all paths to obtain the updated target input file. The input queue can be stored in memory, a file system, or a database. For example, an initial input file named input.txt is created with the content "Hello, World!". A portion of the content in the initial input file is mutated to obtain the target input file input_1.txt with the content "Hello, Fuzz!". Input.txt and input_1.txt are added to the input queue. The file system is selected as the storage location, and an input_queue directory is created and stored in this directory.
[0130] If the mutated target input file causes the target program to crash or trigger a new path during execution, the mutated target input file is re-added to the input queue, and the target input file is further mutated while retaining the previous mutation. Both mutations are based on the path to the target code block, but it is understandable that the latter mutation method differs from the former during specific implementation. For example, the former mutation is based on the path to the first target code block, while the latter mutation is based on the path to the next target code block.
[0131] It should be noted that for target input files that do not trigger a crash or a new path, in order to more comprehensively evaluate the stability and security of the target program, the target input files that do not trigger a crash or a new path can be retained in the input queue, waiting for subsequent mutations; or based on requirements such as test resources, the target input files that do not trigger a crash or a new path can be regarded as invalid inputs and deleted from the input queue. Subsequent tests focus on the target input files in the input queue, and more vulnerabilities are discovered through iterative mutation and testing.
[0132] In an embodiment of the present application, when the target program crashes or triggers a new path during execution, the target input file is selectively mutated according to all paths to obtain a new target input file; the new target input file is input into the target program for the next round of testing, and further mutation is made based on the target input file that triggered the crash, which can more easily cause the target program to crash or become abnormal, thereby helping developers locate and fix problems more quickly.
[0133] In summary, the code testing method provided by the embodiments of the present application can, through static analysis methods, pre-identify target code blocks with logical errors and other problems in the source program and determine the execution path corresponding to each target code block. At least one marker is inserted into the execution path, and the initial input file is mutated. The weight corresponding to the mutation is determined based on the distance between the last marker triggered by the first mutated file and the target code block. The initial input file is mutated preferentially according to the mutation method with the largest weight, which can more quickly cause the target program to crash or anomaly, thereby improving the efficiency of code testing. Furthermore, for each target input file, it is determined whether the target program crashes or triggers a new path during execution, and the number of executions of the target program is recorded. If the target program crashes or triggers a new path during execution, the target input file is selectively mutated according to all paths to obtain a new target input file; the new target input file is input into the target program for the next round of testing. Further mutation of the target input file that triggers the crash can more easily trigger the target program to crash, thereby improving the efficiency of code testing. When the time interval reaches a preset threshold, the test of the target program is stopped. By setting reasonable iteration end conditions, the test can be stopped promptly after achieving the expected test results, improving test efficiency.
[0134] Device embodiment
[0135] Reference Figure 2 , shows a structural block diagram of a code testing device of the present application, the device specifically may include:
[0136] Analysis module 210, for performing static analysis on the source program to determine all paths from the entry point to the target code block;
[0137] a mutation module 220 for selectively mutating the initial input file according to all the paths to obtain a target input file;
[0138] A generating module 230 is configured to set a detection function in the source program to obtain a target program;
[0139] The testing module 240 is used to input the target input files into the target program in sequence for testing, and obtain the test results corresponding to the source program.
[0140] Optionally, the first generating module includes:
[0141] an insertion module, configured to insert at least one marker into each path between an entry point of the source program and the target code block, to obtain a first program;
[0142] a first mutation submodule, configured to selectively mutate an initial input file according to at least two mutation methods, and determine mutation information corresponding to the first input file when the first input file triggers a marker in the first program; the mutation information is used to indicate a mutation location and mutation type in the first input file;
[0143] A first determination module is configured to determine a target mutation parameter according to the mutation position and mutation type corresponding to the at least two first input files;
[0144] The second mutation submodule is used to mutate the initial input file according to the target mutation parameter to obtain a target input file.
[0145] Optionally, the first determining module includes:
[0146] a calculation module configured to calculate, when a first input file triggers a marker in the first program, a weight of the variation information corresponding to the first input file based on a distance between the first marker triggered by the first input file and the target code block using an inverse proportional function; the weight being used to indicate a priority corresponding to the variation information; the first marker being the last marker triggered by the first input file before the execution of the first program ends;
[0147] A determining unit is configured to determine the target mutation parameter according to a weight of the mutation information corresponding to the first input file.
[0148] Optionally, the second mutation submodule includes:
[0149] An array generation module, configured to sort the first input files according to the mutation position information corresponding to the first input files to obtain a target array;
[0150] A strategy determination module, configured to analyze the target array and determine a mutation strategy;
[0151] The mutation unit is used to mutate the initial input file according to the mutation strategy to obtain a target input file.
[0152] Optionally, the test module includes:
[0153] a recording module for determining, for each target input file, whether the target program crashes or triggers a new path during execution, and recording the time interval between the last time the crash or new path was triggered and the current time;
[0154] The end module is used to stop testing the target program when the time interval reaches a preset threshold.
[0155] Optionally, the recording module includes:
[0156] An update module, configured to selectively mutate the target input file according to all the paths to obtain a new target input file when the target program crashes or triggers a new path during execution;
[0157] The input module is used to input the new target input file into the target program for the next round of testing until the preset conditions are met.
[0158] In summary, the code testing device provided by the embodiments of the present application can, through a static analysis method, pre-identify target code blocks with logical errors and other problems in the source program and determine the execution path corresponding to each target code block. At least one marker is inserted into the execution path, and the initial input file is mutated. The weight corresponding to the mutation is determined based on the distance between the last marker triggered by the mutated first file and the target code block. The initial input file is mutated preferentially according to the mutation method with the largest weight, which can more quickly cause the target program to crash or fail, thereby improving the efficiency of code testing. Furthermore, for each target input file, it is determined whether the target program crashes or triggers a new path during execution, and the number of executions of the target program is recorded. If the target program crashes or triggers a new path during execution, the target input file is selectively mutated according to all paths to obtain a new target input file. The new target input file is then input into the target program for the next round of testing. Further mutation of the target input file that triggers the crash can more easily trigger the target program to crash, thereby improving the efficiency of code testing. When the time interval reaches a preset threshold, testing of the target program is stopped. By setting reasonable iteration end conditions, testing can be stopped promptly after achieving the expected test results, improving testing efficiency.
[0159] As for the device embodiment, since it is basically similar to the method embodiment, the description is relatively simple, and the relevant parts can be referred to the partial description of the method embodiment.
[0160] The various embodiments in this specification are described in a progressive manner, and each embodiment focuses on the differences from other embodiments. The same or similar parts between the various embodiments can be referenced to each other.
[0161] The code testing device in the embodiment of the present application can be an electronic device, or a component in an electronic device, such as an integrated circuit or a chip. The electronic device can be a terminal, or other devices other than a terminal. Exemplarily, the electronic device can be a GPU BOX, a mobile phone, a tablet computer, a laptop computer, a PDA, a car-mounted electronic device, a mobile Internet device (Mobile Internet Device, MID), an augmented reality (augmented reality, AR) / virtual reality (virtual reality, VR) device, a robot, a wearable device, an ultra-mobile personal computer (ultra-mobile personal computer, UMPC), a netbook or a personal digital assistant (personal digital assistant, PDA), etc., and can also be a server, a network attached storage (Network Attached Storage, NAS), a personal computer (personal computer, PC), a television (television, TV), a teller machine or a self-service machine, etc., and the embodiment of the present application is not specifically limited.
[0162] The code testing device in the embodiment of the present application can be a device having an operating system. The operating system can be an Android operating system, a Linux operating system, a Windows operating system, etc., or other possible operating systems, which are not specifically limited in the embodiment of the present application.
[0163] The code testing device provided in the embodiment of the present application can achieve Figure 1 To avoid repetition, the various processes implemented in the method embodiment are not described here.
[0164] Alternatively, as Figure 3 As shown, an embodiment of the present application also provides an electronic device, including a processor and a memory, wherein the memory stores a program or instruction that can be run on the processor. When the program or instruction is executed by the processor, the various steps of the above-mentioned code testing method embodiment are implemented and the same technical effect can be achieved. To avoid repetition, it will not be repeated here.
[0165] In an embodiment of the present application, a memory may be used to store software programs and various data. The memory may mainly include a first storage area for storing programs or instructions and a second storage area for storing data, wherein the first storage area may store an operating system, an application program or instruction required for at least one function (such as a sound playback function, an image playback function, etc.), etc. In addition, the memory may include a volatile memory or a non-volatile memory, or the memory may include both volatile and non-volatile memories. Among them, the non-volatile memory may be a read-only memory (ROM), a programmable read-only memory (PROM), an erasable programmable read-only memory (EPROM), an electrically erasable programmable read-only memory (EEPROM), or a flash memory. Volatile memory can be random access memory (RAM), static random access memory (SRAM), dynamic random access memory (DRAM), synchronous dynamic random access memory (SDRAM), double data rate synchronous dynamic random access memory (DDRSDRAM), enhanced synchronous dynamic random access memory (ESDRAM), synchronous link dynamic random access memory (SLDRAM) and direct RAM bus random access memory (DRRAM). The memory in the embodiments of the present application includes but is not limited to these and any other suitable types of memory.
[0166] The processor may include one or more processing units; optionally, the processor may integrate an application processor and a modem processor, wherein the application processor primarily handles operations related to the operating system, user interface, and application programs, and the modem processor primarily processes wireless communication signals, such as a baseband processor. It is understood that the modem processor may not be integrated into the processor.
[0167] An embodiment of the present application also provides a readable storage medium, on which a program or instruction is stored. When the program or instruction is executed by a processor, the various processes of the above-mentioned code testing method embodiment are implemented and the same technical effect can be achieved. To avoid repetition, it will not be repeated here.
[0168] The processor is the processor in the electronic device described in the above embodiment. The readable storage medium includes a computer readable storage medium, such as a computer read-only memory (ROM), a random access memory (RAM), a magnetic disk, or an optical disk.
[0169] An embodiment of the present application further provides a chip, which includes a processor and a communication interface, wherein the communication interface is coupled to the processor, and the processor is used to run programs or instructions to implement the various processes of the above-mentioned code testing method embodiment and achieve the same technical effect. To avoid repetition, it will not be repeated here.
[0170] It should be understood that the chip involved in the embodiments of the present application can also be called a system-level chip, a system chip, a chip system or a system-on-chip chip, etc.
[0171] An embodiment of the present application provides a computer program product, which is stored in a storage medium. The program product is executed by at least one processor to implement the various processes of the above-mentioned code testing method embodiment and can achieve the same technical effect. To avoid repetition, it will not be repeated here.
[0172] The embodiments of the present application are described above in conjunction with the accompanying drawings, but the present application is not limited to the above-mentioned specific implementation methods. The above-mentioned specific implementation methods are merely illustrative and not restrictive. Under the guidance of this application, ordinary technicians in this field can also make many forms without departing from the purpose of this application and the scope of protection of the claims, all of which are within the protection of this application.
Claims
1. A code testing method, characterized in that: The method comprises: Perform static analysis on the source program to determine all paths from the entry point to the target code block; selectively mutating the initial input file according to all the paths to obtain a target input file; Setting a detection function in the source program to obtain a target program; The target input files are sequentially input into the target program for testing to obtain the test results corresponding to the source program.
2. The method according to claim 1, characterized in that The selectively mutating the initial input file according to all the paths to obtain the target input file includes: Inserting a plurality of tags into each path included in all the paths to obtain a first program; selectively mutating the initial input file according to at least two mutation methods to obtain at least two first input files, and determining mutation information corresponding to each of the first input files when a flag in the first program is triggered; the mutation information is used to indicate the mutation location and mutation type in the first input file; Determining target mutation parameters according to the mutation positions and mutation types respectively corresponding to the at least two first input files; The initial input file is mutated according to the target mutation parameter to obtain the target input file.
3. The method according to claim 2, characterized in that The determining of target mutation parameters according to the mutation positions and mutation types corresponding to the at least two first input files includes: calculating, using an inverse proportional function, a weight of the variation information corresponding to the first input file based on a distance between a first marker triggered by the first input file and the target code block; the first marker being the last marker triggered by the first input file before the execution of the first program ends; The target mutation parameter is determined according to the weight of the mutation information corresponding to the first input file.
4. The method according to claim 2, characterized in that The mutating the initial input file according to the target mutation parameter to obtain the target input file includes: Obtaining a target array according to the mutation position information corresponding to each first input file; Analyze the target array and determine the mutation strategy; The initial input file is mutated according to the mutation strategy to obtain a target input file.
5. The method according to claim 1, wherein The step of sequentially inputting the target input files into the target program for testing comprises: For each target input file, determine whether the target program crashes or triggers a new path during execution, and record the time interval between the last time the crash or new path was triggered and the current time; When the time interval reaches a preset threshold, the test of the target program is stopped.
6. The method according to claim 5, characterized in that Determining whether the target program crashes or triggers a new path during execution includes: In the event that the target program crashes or triggers a new path during execution, selectively mutating the target input file according to all the paths to obtain a new target input file; The new target input file is input into the target program for the next round of testing until the preset conditions are met.
7. A code testing device, characterized in that: The device comprises: The analysis module is used to perform static analysis on the source program and determine all paths from the entry point to the target code block; a mutation module, configured to selectively mutate the initial input file according to all the paths to obtain a target input file; A generation module, configured to set a detection function in the source program to obtain a target program; The test module is used to input the target input files into the target program in sequence for testing, and obtain the test results corresponding to the source program.
8. The method according to claim 7, characterized in that The mutation module includes: An inserting module, configured to insert at least one marker into each path included in all the paths, to obtain a first program; a first mutation submodule, configured to selectively mutate the initial input file according to at least two mutation methods to obtain at least two first input files, and determine mutation information corresponding to each of the first input files when a flag in the first program is triggered; the mutation information is used to indicate a mutation location and mutation type in the first input file; A first determination module is configured to determine a target mutation parameter according to mutation positions and mutation types corresponding to the at least two first input files; The second mutation submodule is configured to mutate the initial input file according to the target mutation parameter to obtain the target input file.
9. An electronic device, characterized in that: The electronic device includes a processor, a memory, a communication interface and a communication bus, and the processor, the memory and the communication interface communicate with each other via the communication bus; The memory is used to store executable instructions, and the executable instructions enable the processor to execute the code testing method according to any one of claims 1 to 6.
10. A readable storage medium, characterized in that: The readable storage medium stores a program or instruction, and when the program or instruction is executed by a processor, the code testing method according to any one of claims 1 to 6 is implemented.