Chapter 2: Extraction of Object Graph
2.1 Extracting a Runtime Architecture
2.1.3 Code vs Runtime Structure
A diagram that shows methods, classes and packages represents the code structure and is easier to extract than a diagram that represents the runtime structure. A code structure diagram shows how the code of the program is organized rather than a view of the program at runtime and is unsuitable for ARA. Examples of code structure diagrams are class diagram and call graph, while an example of a runtime structure diagram is the object diagram [123]. Next, I give examples of security constraints that can be written on each diagram and discuss advantages and limitations.
Class diagram. In a class diagram, a node represents a class with field and method signatures (Fig.2.3). A common relation in a class diagram is inheritance. With inheritance, a class diagram shows the responsibility of an object divided into multiple classes. For example, the method onCreate is partially implemented by EActivity, while the default responsibilities are implemented by the base class Activity (Fig.2.1). A class diagram also shows only one class but different instances of the same class can serve different conceptual purposes.
Figure 2.3: Class diagram of CryptoApp extracted using ObjectAid [95].
straints, they would be unable to assign different security properties to different instances of the same class. They may also be misled by multiple classes that correspond to the same instance, since they can assign different security properties to classes in an inheritance hi- erarchy. In CryptoApp, the client code DBase uses two instances of type Service, one for encryption and one for decryption (Fig.2.4). In turn, each instance of Service uses its own instance of Cipher. While a class diagram shows one box for the class Service and one for the class Cipher, the architects needs to distinguish between different instances of these classes and identify the instance that decrypts information and returns confidential informa- tion in clear text, which is not to be disclosed into an untrusted sink such as a temporary file.
Call graph. In a call graph, a node represents a method declaration and an edge indicates that the source method invokes the destination method. At runtime, the same method can be used in different contexts. Distinguishing between contexts allows architects to avoid false positives. The code fragments in Figure 2.4 show the implementation of the class Service, where the method run sends the text to an object of type Cipher, which transforms the text and sends the result to the client. Depending on the receiver of the method, i.e., the object in the context of which the method is invoked, the method run encrypts or decrypts data.
1 class DBase {
2 Service eService = new Service("ENCRYPT"); 3 Service dService = new Service("DECRYPT");
4 File encrypt(File src) {
5 File dst = new File(src.getName());
6 String mydata = getBytesFromFile(src);
7 String dd = dService.run(mydata);
8 String eData = eService.run(dd);
9 PrintWriter pw = new PrintWriter(dst);
10 pw.println(eData); 11 } 12 } 13 class Service { 14 Cipher cipher; 15 Service(String cType) {
16 cipher = new Cipher(cType);
17 }
18 String run(String text) {
19 return cipher.doFinal(text);
20 }
21 }
22 class Cipher { ... }
Figure 2.4: CryptoApp: Code fragments continued from Fig. 2.1.
Call graph constraints. The architects need to ensure that only encrypted data can flow into a temporary file. Assigning security properties may be possible using method declarations such that the architects can select methods that return confidential information (sources), and methods that disclose information (sinks). However, a call graph does not allow architects to write constraints in terms of dataflow communication.
Architects may use other representations such as a System Dependence Graph (SDG), which has both control and data flow edges [126]. The constraint then checks if a SDG contains a path from a source to a sink. Selecting a method declaration as a source or sink can be however imprecise when the method returns both confidential and non-confidential information, as it is the case for the method run of class Service. Section 7.1.2 (page 152) discusses SDG and other program representations in more detail.
Manually drawn object diagram. One diagram of object-oriented programs that rep- resents runtime structure is an object diagram [123]. An object diagram shows multiple instances of the same class and shows points-to relations between objects. For example, it
receipts:HashMap<String,CryptoReceipt> size = 3 e1:Entry<String,CryptoReceipt> e2:Entry<String,CryptoReceipt> e3:Entry<String,CryptoReceipt> k1:String id=“LV90210” value1:CryptoReceipt ciphertext=“86F6…” k2:String id=“LR60210” value2:CryptoReceipt ciphertext=“F32D…” k3:String id=“RV40210” value3:CryptoReceipt ciphertext=“A1E0…”
Figure 2.5: Manually drawn object diagram (left) shows too many instances that have the same conceptual purpose. An abstract object graph (right) merges such instances into canonical abstract objects.
shows two instances of Service and the field declaration Cipher c in the class Service corresponds to a points-to relation from eService:Service to an object of type Cipher. It is not clear only from a field declaration in the code if multiple objects of type Service share the same object of type Cipher, or if multiple objects of type Cipher exist. The object diagram clarifies this situation and shows two objects of type Cipher, one for each object of type Service. One disadvantage of an object diagram is that it also shows multiple instances of the same class that serve the same conceptual purpose. For an object of type HashMap, an object diagram shows for example three objects of type Entry that each refers to a key and a value. In the general case, however, the object diagram can have an unbounded number of objects and edges. Consider for example a server that maps a password with an access token. As the server runs indefinitely, it creates an unbounded number of entries in the map. Object diagram constraints. If architects were to use an object diagram to write con- straints, they would be able to distinguish between different instances of the same class, and reason about the presence and the absence of communication. There might be, however, too many instances on such a diagram that serve the same conceptual purpose (Fig. 2.5). Architects would need to apply the same constraint on many similar instances.
runtime object runtime edge abstract object abstract edge refers to abstract domain …
Figure 2.6: An object graph is sound if there is a mapping from any runtime object graph to the abstract graph. If two runtime edges have the same source and destination (runtime objects), but refer to two runtime objects that have distinct representatives in the abstract graph, then the runtime edges have two distinct representative abstract edges in the abstract graph.