Java knowledge base reference

This document describes Java Path knowledge base entries used for both tuning analysis results for existing checkers and creating your own Java Path checkers. Whether tuning Java Path checkers or creating new ones, annotating your source in knowledge base files is the critical component of both activities.

The knowledge base entries are listed alphabetically, with the annotations (indicated with "@") appearing at the top. Some entries may be more applicable to creating checkers than tuning them, or the other way around.

About the Java knowledge base syntax

The Java knowledge base specification is like annotated Java code. The knowledge base syntax:

  • uses Java syntax, with some extensions, to describe method signatures.
  • supports package declarations, as well as imports, to avoid writing the fully qualified names.
  • uses Java annotations to describe the knowledge base record types and their properties.

The Java knowledge base file is a text file with the extension .jkb.

Java Path knowledge base entries

Annotation placement

In the Java knowledge base file, you copy the method signature and 'mark' it up using the appropriate annotation to 'educate' the checker about data elements you want it to take into consideration during analysis. This is the case whether you are tuning existing checkers or creating your own.

Annotation placement in relation to the method signature is important because it describes what part of the method call becomes the source, sink, or check.

If it is placed before the method, the sink, *source or check requires ("this") or ("return") to be specified to identify the method owner or its return value.

If placed before a parameter, then the parameter is identified as the source, sink or check.

For the @Bind annotation, which is used exclusively for tuning existing checkers, its placement can determine whether the Binding applies only to the declaration of the method or all methods declared in the class.

There is an exception for the source when identified as the return value.

@Bind

@Bind is a tuning annotation. @Bind is used to add additional sources, sinks or checks to existing checkers. This allows you to extend or tune pre-defined checkers, such as adding a custom source or check to NPE.RET.

You do not need @Bind when you create your own Java Path checkers because binding is handled automatically in the checker's configuration (checkers.xml file).

One signature or class can be preceded by multiple @Bind annotations.

@Bind ties the method declaration to the specified checker. You can bind:

  • each method declaration to the same checker
  • each method declaration to a different checker
  • all the method declarations of a class to one checker
public class Validation {
@Bind("SV.XSS.REF")  
   public static boolean isValid(@CheckTrue String s);  

@Bind("SV.XSS.DB")
   public static boolean isInvalid(@CheckFalse String s); 
}

In the above, each method (isValid and isInvalid) is bound to a different checker.

If you place @Bind before the class declaration, then all methods in the class would be bound to the checker that you specified. See the example below:

@Bind("SV.XSS.REF")
public class Validation {
   public static boolean isValid(@CheckTrue String s); 
   public static boolean isInvalid(@CheckFalse String s); 
}

Binding the declaration of a method to a specific checker

This example shows how to bind the declaration of a method to the NPE.RET checker.

public class DirContext {
@Bind("NPE.RET") @Source("return") public NamingEnumeration<SearchResult> search(Name name, String filter, SearchControls cons)
throws NamingException;

@Bind("NPE.RET") @Source("return") public NamingEnumeration<SearchResult> search(String name, String filter, SearchControls cons)
throws NamingException;

}

Binding all methods declared in the class to a specific checker

This example shows how to bind the declaration of the class to the NPE.RET checker:

@Bind("NPE.RET")
public class DirContext {
   @Source("return") public NamingEnumeration<SearchResult> search(Name name, String filter, SearchControls cons)
throws NamingException;
 
   @Source("return") public NamingEnumeration<SearchResult> search(String name, String filter, SearchControls cons)
throws NamingException;

}

All of the methods (search(Name name, String filter, SearchControls cons) and search(String name, String filter, SearchControls cons)) will now be bound to NPE.RET .

@BindAll

Like @Bind, @BindAll is a tuning annotation. @BindAll binds all method declarations to a specific checker and is used if you have more than one class or package in your knowledge base file. @BindAll should be placed before the first package declaration. For example:

@BindAll("SV.XSS.REF")
package com.klocwork.jdefects.checkers.dfa.binding_walkthrough;

public class Validation {
   public static boolean isValid(@CheckTrue String s);  
   public static boolean isInvalid(@CheckFalse String s);  
}

public class Validation2 {
   public static boolean isValid(@CheckTrue String s); 
   public static boolean isInvalid(@CheckFalse String s);  
} 
Multiple @BindAll annotations can be used.

Example 2: Binding all methods in all classes in all packages

@BindAll("NPE.RET")

package aaa.bbb.ccc;
public class ABC {
@Source("return") public a();

@Source("return") public b();
}

package aaa.bbb.ddd;

public class DEF {
   @Source("return") public x();

   @Source("return") public y();
}

Now all the methods (a, b, x, y) will be bound to NPE.RET.

@Check

@Check describes a method that checks the data that came from the source. We consider the data to be valid or safe after the check, so its usage (even in the sink method) would not be considered as an issue. A check is used most often when tuning analysis (with a knowledge base) to reduce the detection of false positives rather than when creating your own checkers.

You can also specify a field as a Check value.

See the examples below.

@Check("this"): The check is the object itself

@Check("this") public NamingEnumeration<SearchResult> search(Name name, String filter, SearchControls cons)
throws NamingException;

You can also specify the sink as the object with @Check("class"):

@Check("class") public NamingEnumeration<SearchResult> search(Name name, String filter, SearchControls cons)
throws NamingException;

@Check("return"): The check is the returned value:

@Check("return") public NamingEnumeration<SearchResult> search(Name name, String filter, SearchControls cons)
throws NamingException;

@Check("parameter_name"): The check is the parameter:

@Check("filter") public NamingEnumeration<SearchResult> search(Name name, String filter, SearchControls cons)
throws NamingException;

You can also point to the parameter itself:

public NamingEnumeration<SearchResult> search(Name name, @Check String filter, SearchControls cons)
throws NamingException;

(@Check *)--Check any parameter:

public NamingEnumeration<SearchResult> search(@Check *)
throws NamingException;

The (*) wildcard can be used to identify 'any parameter' with these annotations as well: @Source, @Sink, @CheckTrue, @CheckFalse, @In, and @Out.

@CheckFalse

@CheckFalse returns a method that works as a 'check' if the method returned 'false'. For example:

@CheckFalse("s") public boolean contains(String s);

This can also be expressed as:

public boolean contains(@CheckFalse String s);

Typically, @CheckFalse is used most often when tuning analysis (with a knowledge base) to reduce the detection of false positives rather than when creating your own checkers.

You can also specify a field as a checkfalse value.

@CheckerParam

@CheckerParam configures a checker to use user-specified strings. Only certain checkers can be configured with this option (for example, SV.SENSITIVE.DATA).

Example 1

@CheckerParam("SV.SENSITIVE.DATA", "name,dob,ssn")

Multiple @CheckerParam annotations can be used for a checker.

Example 2

@CheckerParam(“SV.SENSITIVE.DATA”, “creditCardNumer,ccn,cvv2”)
@CheckerParam(“SV.SENSITIVE.DATA”, “socialSecurityNumber,ssn,datOfBirth,dob”)
@CheckerParam(“SV.SENSITIVE.DATA”, “password,passwd,pwd,pw”)

@CheckTrue

@CheckTrue returns a method that works as a "check" if the method returned "true". For example, the equals method is a check for tainted data, if it returns true:

@CheckTrue("o") public boolean equals( Object o);

This can also be expressed as:

public boolean equals(@CheckTrue Object o);

Typically, @CheckTrue is used most often when tuning analysis (with a knowledge base) to reduce the detection of false positives than when creating your own checkers.

You can also specify a field as a CheckTrue value.

@Exit

@Exit states that once a method is called, any further analysis should be stopped. A typical 'Exit' method is System.exit(int code) or void halt(int status) from java.lang.Runtime. For example:

class System {
   @Exit void exit(int status);
}

@In

@In is used for method parameters participating in the @Prop entry.

@Out

@Out is used for method parameters participating in the @Prop entry.

@Prop

@Prop describes a method that extends the set of data elements being tracked. A prop takes some data which came from source and copies it. After a call to a prop, both the original data that came from the source and the data copied by the prop would be considered dangerous. A code issue would be reported if any of this data were used in a sink method.

For prop records, you need to specify the incoming tainted data as well as the target that would be tainted after the prop call. All prop records therefore have two values: "in" stands for the tainted data that would be propagated to "out".

For method parameters participating in the prop entry, you can use the @In and @Out annotations for the parameters, instead of specifying them directly in the @Prop annotation.

You can also use wildcards along with @In and @Out.

You can also specify a field as a Prop value.

Example 1

package java.lang;

import java.util.Iterator;

@Bind("MY.ERROR")
public interface Iterable<T> {
   @Prop(in="this", out="return") Iterator<T> iterator();

}

In the above example, "in" is the object owning the iterator method and "out" is the return value. If the iterable element is tainted, then all of its sub-elements are tainted as well.

Consider the following examples, which mean the same and are fully replaceable with each other:

Example 2

import java.util.*;

@Bind("MY.ERROR")
public interface Map<K,V> {
   @Prop(in="key", out="value") V put(K key, V value);
}

In the above example, a key is being mapped to a value. If the key is tainted, then the value is also tainted.

Example 3

import java.util.*;

@Bind("MY.ERROR")
public interface Map<K,V> {
   @Prop(in="key") V put(K key, @Out V value);
}

Example 4

import java.util.*;

@Bind("MY.ERROR")
public interface Map<K,V> {
   @Prop V put(@In K key, @Out V value);

@Sink

@Sink describes a call that uses potentially dangerous data that came from the source, converting the potential for an issue into an actual code issue. Sinks are specified in the same way as sources, but with the @Sink annotation.

Typically, you use a source (and a sink) more often when creating your own checkers than when tuning existing checkers to find more errors than originally detected.

You can also specify a field as a Sink value.

See the examples below.

@Sink("this")--The sink is the object itself

@Sink("this") public NamingEnumeration<SearchResult> search(Name name, String filter, SearchControls cons)
throws NamingException;

The above can also be expressed without "this", provided that the @Sink annotation has no parameters and is placed before the method signature:

@Sink public NamingEnumeration<SearchResult> search(Name name, String filter, SearchControls cons)
throws NamingException;

You can also specify the sink as the object with @Sink("class"):

@Sink("class") public NamingEnumeration<SearchResult> search(Name name, String filter, SearchControls cons)
throws NamingException;

You can also specify a field as a Source value.

@Sink("return")--The sink is the returned value:

@Sink("return") public NamingEnumeration<SearchResult> search(Name name, String filter, SearchControls cons)
throws NamingException;

@Sink("parameter_name")--The sink is the parameter:

@Sink("filter") public NamingEnumeration<SearchResult> search(Name name, String filter, SearchControls cons)
throws NamingException;

You can also point to the parameter itself:

public NamingEnumeration<SearchResult> search(Name name, @Sink String filter, SearchControls cons)
throws NamingException;

(@Sink *)--The sink as any parameter:

public NamingEnumeration<SearchResult> search(@Sink *)
throws NamingException;

The (*) wildcard can be used to identify 'any parameter' with these annotations as well: @Source, @Check, @CheckTrue, @CheckFalse, @In, and @Out.

@Source

@Source describes a call that produces tainted data, which can lead to a specific type of code issue if the tainted data is used by another method (the sink). Typically, you use a source (and a sink) more often when creating your own checkers than when tuning existing checkers to find more errors than originally detected.

For example, a call to method get(Key) from java.util .Map will return null if the Key is unknown. Thus, the method get is the source for the NPE checker.

Another example of a source is the method getParameter for the HttpServletRequest, which can return tainted data. If the data is used for an SQL query, Klocwork would report the SV.SQL issue.

See the examples below.

@Source("this")--The source is the object itself

@Source("this") public NamingEnumeration<SearchResult> search(Name name, String filter, SearchControls cons)
throws NamingException;

@Source("return")--The source is the returned value:

@Source("return") public NamingEnumeration<SearchResult> search(Name name, String filter, SearchControls cons)
throws NamingException;

The example above indicates the return value of "search" method as the source.

The source as the returned value is the most frequently-used type of @Source annotation. If you use @Source without any parameters before the method signature, it is the same as @Source("return"). You can specify the same as above with just @Source, as in:

@Source public NamingEnumeration<SearchResult> search(Name name, String filter, SearchControls cons)
throws NamingException;

@Source("parameter_name")--The source is the parameter:

@Source("filter") public NamingEnumeration<SearchResult> search(Name name, String filter, SearchControls cons)
throws NamingException;

You can also point to the parameter itself:

public NamingEnumeration<SearchResult> search(Name name, @Source String filter, SearchControls cons)
throws NamingException;

(@Source *)--The source as any parameter:

public NamingEnumeration<SearchResult> search(@Source *)
throws NamingException;

The (*) wildcard can be used to identify any parameter with these annotations as well: @Sink, @Check, @CheckTrue, @CheckFalse, @In, and @Out.

@Suppress

@Suppress turns off specific sources and sinks in existing checkers for the purposes of tuning. You use it when your test analysis produces too much "noise" from one or more sources and/or sinks.

@Suppress is used in the same ways as the @Source and @Sink annotations.

Suppress source examples

@Suppress("this")--Suppress spoiling of the owner's methods

@Suppress("this") public NamingEnumeration<SearchResult> search(Name name, String filter, SearchControls cons)
throws NamingException;

@Suppress("return")--Suppress the return value

@Suppress("return") public NamingEnumeration<SearchResult> search(Name name, String filter, SearchControls cons)
throws NamingException;

Or you can express it this way:

@Suppress public NamingEnumeration<SearchResult> search(Name name, String filter, SearchControls cons)
throws NamingException;

@Suppress("parameter_name")--Suppress spoiling of a parameter

@Suppress("filter") public NamingEnumeration<SearchResult> search(Name name, String filter, SearchControls cons)
throws NamingException;

Or you can point to the parameter itself:

public NamingEnumeration<SearchResult> search(Name name, @Suppress String filter, SearchControls cons)
throws NamingException;

Interprocedural analysis

You can suppress sources that appeared as a result of interprocedural analysis.

For example, we have a source:

@Source public String foo() throws NamingException;

And a code snippet:

public String bar() {
   if (checkEnv()) {
      return foo();
   }
   return "";
}

The method bar() would be considered as source, as well as foo(), since it returns the result of foo() under certain conditions. If checkEnv() guarantees that calling foo() is safe, we can suppress the source for bar() like this:

@Suppress public String bar();

Suppress sink example

Let's say we do not want to issue the SV.LOG_FORGING warning if unchecked user input is passed to org.apache.log4j.Logger.debug method.

package org.apache.log4j;

@Bind("SV.IL.DEV")
class Logger {
   public void debug(@Suppress java.lang.Object message);
}

@Verbose

@Verbose allows you to get more feedback from the engine regarding the provided Java knowledge base.

Use @Verbose to get information from the engine during your testing phase to make sure that what you described in your Java knowledge base (JKB) is the description of the methods and types and classes that actually exist in your code.

By default, the engine does not issue any warnings when data types or method names in the JKB are different from what's in the code. @Verbose turns this reporting feature on.

Place @Verbose at the top of the file. Once you are satisfied with the results, remove this annotation from your checker's knowledge base.

See the example below:

@Verbose
package com.klocwork.test;

class A {
   @Source String a();
}

@Wipe

Use @Wipe to mark only one aspect (alias or element) of the tracked data to be safe or valid. @Wipe works in a similar way to @Check, but unlike @Check, @Wipe is used to "check" only one item from the set of variables being tracked. (If a prop was applied to the tainted data, more than one variable is tracked).

Consider this example for the SV.XSS issue:

void doGet(HttpServletRequest req, HttpServletReponse res) {
   String val = req.getParameter("name");  // Source: val
   ByteArrayOutputStream baos = new ByteArrayOutputStream();
   baos.write(val);  // Prop: baos
   baos.reset();    // baos is purged, but val is still dangerous
   res.getWriter.write(baos);  // no defect here
   res.getWriter.write(val);  // defect should be reported here
}

In the example above val is a tainted string. baos is tainted after val is written into it, since ByteArrayOutputStream.write(...) is a prop. reset() clears baos but it cannot be described as @Check, since @Check states that both val and baos are fine, which will lead to a false negative at line res.getWriter.write(val);.

The solution in the above situation is to use @Wipe in order to mark only baos as the clean variable. This prevents a false positive at res.getWriter.write(baos); and reports a true positive at res.getWriter.write(val);.

Describing @Wipe is the same as for @Check, so the JKB would be:

package java.io;

class ByteArrayOutputStream {
   @Wipe("this") void reset();
}

Fields

You can specify fields as a value for a: Source, Sink, Prop, Check, CheckFalse or CheckTrue.

Examples

Let's say you want to specify that the field called "fld" of the value returned by a method 'mthd' is the source value. In that case we can write:

class Cls {
   @Source("return.fld") Object mthd();
}

If you want to say the same about the field "fld" of the owner of the method write:

class Cls {
   @Source("this.fld") Object mthd();
}

This syntax can also be used with parameters, as in the following example:

class Cls {
   @Source("paramName.fld") Object mthd(Object paramName);
}

The same is applicable to other record types.

public class String {
   @Prop(in="this.value", out="return.length") char[] toCharArray();
}

Multi-sectional knowledge bases

You can specify only one package declaration for a Java source file, and you cannot override imports after the imports block is finished. This works well for highly modular Java source code, but it does not fit well the purposes of the knowledge base, where sometimes you want to specify the knowledge base for a whole project or library.

You can use more than one package declaration in a .jkb file. These package declarations split the .jkb file into multiple sections with independent package and import declarations.

Example

package java.util;

import java.util.*;

interface Entry<K,V> {
   @Source("return") K getKey();
}

package java.io; // Here starts another section

import java.net.URI;
import java.net.URL;

public class File {
   @Source("return") int getPrefixLength();
}

import javax.swing.*; // Here starts another section

class About {
   @Source("return") JFrame getFrame();
}

To describe the classes which are not in any package, use "package;"

@BindAll("ERROR")

class AKB {
void a(@Sink String s);
}

package java.lang;

public class String {
   @Source("return") java.lang.String trim();
}

package;

class BKB {
void b(@Sink String s);
}

Nested classes

Nested classes can be used to describe the knowledge base, if needed. For example:

public class SampleNested {
   private static class Validation {
      public static void verify(@Check final Object o) throws Exception;
   }
}

Wildcards

Wildcards can be used to replace:

  • method return types
  • method parameters

A wildcard used in conjunction with an annotation knowledge base record (@Source, @Sink, @Check, @CheckTrue, @CheckFalse , @In, and @Out ) means that these records are applicable to any parameters.