Checker Framework Tutorial - Validating User Input - Command Line

# Checker Framework Tutorial

## Previous Getting Started

## Validating User Input

This part of the tutorial shows how the Checker Framework can detect and help correct missing input validation.

##### Outline

1. The RegexExample program
2. Run the example with an invalid regular expression
3. Run the Regex Checker to see how it could have prevented the runtime error
4. Validate the user input
5. Run the Regex Checker to verify that the error is corrected
6. Run the example with an invalid regular expression to see the warning

#### 1. The RegexExample program

If you have not already done so, download the source files for the tutorial.

The RegexExample.java program is called with two arguments: a regular expression and a string. The program prints the text from the string that matches the first capturing group in the regular expression.
Compile the program:

    $ javac RegexExample.java

#### 2. Run the RegexExample program

Run the program with a valid regular expression and a matching string:

    $ java RegexExample '[01]?\d-([0123]?\d)-\d{4}+' '01-24-2013'
    Group 1: 24

Run the program with an invalid regular expression and any string:

    $ java RegexExample '[01]?[\d-[0123]?\d-\d{4}+' '01-24-2013'
    Exception in thread "main" java.util.regex.PatternSyntaxException: Unclosed character class near index 24
    [01]?[d-[0123]?d-d{4}+
                         ^
            at java.util.regex.Pattern.error(Pattern.java:1924)
            at java.util.regex.Pattern.clazz(Pattern.java:2493)
            at java.util.regex.Pattern.sequence(Pattern.java:2030)
            at java.util.regex.Pattern.expr(Pattern.java:1964)
            at java.util.regex.Pattern.compile(Pattern.java:1665)
            at java.util.regex.Pattern.<init>(Pattern.java:1337)
            at java.util.regex.Pattern.compile(Pattern.java:1022)
            at RegexExample.main(RegexExample.java:13)

Good programming style dictates that the user should not see a stack trace, even if the user supplies invalid output.

#### 3. Run the Regex Checker

The Regex Checker prevents, at compile time, use of syntactically invalid regular expressions and access of invalid capturing groups. In other words, it prevents you from writing code that would throw certain exceptions at run time. Next run the Regex Checker to see how it could have spotted this issue at compile time.

    $ javacheck -processor org.checkerframework.checker.regex.RegexChecker RegexExample.java
    RegexExample.java:13: error: [argument] incompatible types in argument.
            Pattern pat = Pattern.compile(regex);
                                          ^
      found   : String
      required: @Regex String
    1 errors

The "incompatible types" warning indicates that variable `regex` is not of type `@Regex String` which is required for strings passed to `Pattern.compile()`.

#### 4. Fix the Code

The right way to fix the problems is for the code to issue a user-friendly message at run time. It should verify the user input using the `RegexUtil.isRegex(String, int)` method. If the string is not a valid regular expression, it should print an error message and halt. If it is a valid regular expression, perform as before.

You need to make two changes to `RegexExample.java` to correctly handle invalid user input. At the top of the file, add

    import org.checkerframework.checker.regex.RegexUtil;

After variable `regex` is defined but before it is used (that is, before `Pattern pat = Pattern.compile(regex);`), add

        if (!RegexUtil.isRegex(regex, 1)) {
            System.out.println("Input is not a regular expression \"" + regex
                + "\": " + RegexUtil.regexException(regex).getMessage());
            System.exit(1);
        }

#### 5. Re-run the Regex Checker

    $ javacheck -processor org.checkerframework.checker.regex.RegexChecker RegexExample.java

There should be no warnings. This shows that the code will not throw a PatternSyntaxException at compile time.

#### 6. Run the Example

Run the program as before (but adding `checker-qual.jar` to the classpath) to verify that the program prints a user-friendly warning.

    $ java -cp ".:$CHECKERFRAMEWORK/checker/dist/checker-qual.jar" RegexExample '[01]?[\d-\([0123]?\d\)-\d{4}+' '01-24-2013'
    Input is not a regular expression "[01]?[d-([0123]?d)-d{4}+": Illegal character range near index 24

For a full discussion of the Regex Checker, please see the Regex Checker chapter of the Checker Framework manual.

## Next, try Finding a Security Error, a complex example using the Tainting Checker.