com.kdmanalytics.toif.adaptor.SplintAdaptor.java Source code

Java tutorial

Introduction

Here is the source code for com.kdmanalytics.toif.adaptor.SplintAdaptor.java

Source

package com.kdmanalytics.toif.adaptor;

/*******************************************************************************
 * Copyright (c) 2016 KDM Analytics, Inc. All rights reserved. This program and
 * the accompanying materials are made available under the terms of the Open
 * Source Initiative OSI - Open Software License v3.0 which accompanies this
 * distribution, and is available at
 * http://www.opensource.org/licenses/osl-3.0.php/
 ******************************************************************************/
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Scanner;

import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringEscapeUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.kdmanalytics.toif.common.exception.ToifException;
import com.kdmanalytics.toif.framework.files.IFileResolver;
import com.kdmanalytics.toif.framework.toolAdaptor.AbstractAdaptor;
import com.kdmanalytics.toif.framework.toolAdaptor.AdaptorOptions;
import com.kdmanalytics.toif.framework.toolAdaptor.Language;
import com.kdmanalytics.toif.framework.utils.FindingCreator;
import com.kdmanalytics.toif.framework.xmlElements.entities.Element;

public class SplintAdaptor extends AbstractAdaptor {

    /**
     * the logger.
     */
    private static final Logger LOG = LoggerFactory.getLogger(SplintAdaptor.class);

    private File tmpFile = null;

    /**
     * By default we expect the executable to be in path
     */
    private String execPath = "splint";

    /**
     * return this adaptors name
     */
    /*
     * (non-Javadoc)
     * 
     * @see com.kdmanalytics.toif.framework.toolAdaptor.AbstractAdaptor#getAdaptorName ()
     */
    @Override
    public String getAdaptorName() {
        return "Splint";
    }

    /**
     * return the adaptors description.
     */
    /*
     * (non-Javadoc)
     * 
     * @see com.kdmanalytics.toif.framework.toolAdaptor.AbstractAdaptor# getAdaptorDescription()
     */
    @Override
    public String getAdaptorDescription() {
        return "Splint is a tool for statically checking C programs for security vulnerabilities and common programming mistakes. With minimal effort, splint can be used as a better lint. If additional effort is invested adding annotations to programs, splint can perform stronger checks than can be done by any standard lint.";
    }

    /**
     * Create the commands to run the tool.
     */
    @Override
    public String[] runToolCommands(AdaptorOptions options, String[] otherOpts) {
        // this is where the output of the tool is going to be written in order
        // for us to collect it.

        // File tmpdir = new
        // File(options.getOutputDirectory(),options.getInputFile().getName()+"."+getGeneratorName());
        // tmpdir.mkdirs();
        tmpFile = new File(options.getOutputDirectory(),
                options.getInputFile().getName() + "." + getGeneratorName());

        // tmpFile.deleteOnExit();
        // the required commands to run the tool.
        String execPath = this.execPath;
        if (options.getExecutablePath() != null)
            execPath = options.getExecutablePath().getAbsolutePath();
        final String[] commands = { execPath, options.getInputFile().toString(), "+csv", tmpFile.getPath(),
                "+csvoverwrite" };

        String[] allCommands = (String[]) ArrayUtils.addAll(commands, otherOpts);

        return allCommands;
    }

    public static void writeToFile(String sb) throws IOException {
        File tempDir = new File(System.getProperty("java.io.tmpdir"));
        File tempFile = new File(tempDir, "toifLog");
        FileWriter fileWriter = new FileWriter(tempFile, true);
        BufferedWriter bw = new BufferedWriter(fileWriter);
        bw.write(sb);
        bw.close();
    }

    @Override
    public ArrayList<Element> parse(File process, AdaptorOptions options, IFileResolver resolver,
            boolean[] validLines, boolean unknownCWE) throws ToifException {
        com.kdmanalytics.toif.framework.xmlElements.entities.File file = resolver.getDefaultFile();
        // new finding creator
        final FindingCreator creator = new FindingCreator(getProperties(), getAdaptorName(), unknownCWE);

        Scanner scanner = null;
        try {
            scanner = new Scanner(new FileInputStream(process));
            // read from the csv file.
            while (scanner.hasNextLine()) {
                final String csvLine = scanner.nextLine();

                final String[] csvElements = csvLine.split(",");

                // Check if line is valid for parsing
                if (csvElements.length <= 2)
                    continue;

                if ("preproc".equals(csvElements[2])) {
                    continue;
                }
                // the first line of these csv files have the information of
                // what the values are. We dont need this.
                if ("Warning".equals(csvElements[0])) {
                    continue;
                }

                if (csvElements.length < 8) {
                    continue;
                }

                // continue if not same file.
                String csvFileName = new File(csvElements[4]).getName();
                String inputFileName = new File(file.getPath()).getName();
                if (!csvFileName.endsWith(inputFileName)) {
                    continue;
                }

                // get the weakness description
                String msg = csvElements[7];
                if (msg.startsWith("\"")) {
                    msg = msg.substring(1, msg.length());
                }
                if (msg.endsWith("\"")) {
                    msg = msg.substring(0, msg.length() - 1);
                }

                if (msg.trim().startsWith("Parse Error")) {
                    try {
                        writeToFile("splint: " + msg + "\n");
                    } catch (IOException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                    continue;
                }

                // get the weakness id.
                final String id = csvElements[2];
                // get the linenumber of the weakness.
                final Integer lineNumber = Integer.valueOf(csvElements[5]);
                // this tool has no offset.
                final Integer offset = null;
                // get the position of the weakness.
                final Integer position = Integer.valueOf(csvElements[6]);

                // if there is a dataElement, use it.
                String dataElement = null;
                if (msg.split(":").length == 2) {
                    dataElement = msg.split(":")[1].trim();
                }

                // if there are valid lines
                if (validLines != null) {
                    if (lineNumber > 0) {
                        // return if the line number is greater than the array
                        // size.
                        if (lineNumber < validLines.length) {
                            if (validLines[lineNumber]) {
                                // pass the required information to the finding
                                // creator.
                                creator.create(StringEscapeUtils.unescapeHtml4(msg), id, lineNumber, offset,
                                        position, file, dataElement, null);
                            } else {
                                try {
                                    FindingCreator.writeToFile("Splint: Not a valid line (uncompiled) "
                                            + file.getPath() + ":" + lineNumber + "\n");
                                } catch (IOException e) {
                                    // TODO Auto-generated catch block
                                    e.printStackTrace();
                                }
                            }
                        }
                    }

                } else {
                    // pass the required information to the finding creator.
                    creator.create(StringEscapeUtils.unescapeHtml4(msg), id, lineNumber, offset, position, file,
                            dataElement, null);
                }

                // // pass the required information to the finding creator.
                // creator.create(StringEscapeUtils.unescapeHtml4(msg), id,
                // lineNumber, offset, position, file, dataElement, null);
                //
                //
                // // if there are valid lines
                // if (validLines != null)
                // {
                // // return if the line number is greater than the array size.
                // if (lineNumber < validLines.length)
                // {
                // if (validLines[lineNumber])
                // {
                // // create the finding.
                // creator.create(StringEscapeUtils.unescapeHtml4(msg), id,
                // lineNumber, offset, position, file, dataElement, null);
                // }
                // }
                //
                // }

            }

            // delete the file we made in the tmp directory.
            // tmpFile.delete();
        } catch (final FileNotFoundException e) {
            final String msg = "The tools output file could not be found. \"" + tmpFile.getAbsolutePath() + '"';
            LOG.error(msg, e);
            throw new ToifException(msg, e);
        } finally {
            if (scanner != null)
                scanner.close();
        }

        // return the elements from the finding creator.
        return creator.getElements();
    }

    /*
     * (non-Javadoc)
     * 
     * @see com.kdmanalytics.toif.framework.toolAdaptor.AbstractAdaptor# getAdaptorVendorAddress()
     */
    @Override
    public String getAdaptorVendorAddress() {
        return "3730 Richmond Rd, Suite 204, Ottawa, ON, K2H 5B9";
    }

    /*
     * (non-Javadoc)
     * 
     * @see com.kdmanalytics.toif.framework.toolAdaptor.AbstractAdaptor# getAdaptorVendorDescription()
     */
    @Override
    public String getAdaptorVendorDescription() {
        return "KDM Analytics is a security assurance company providing products and services for threat risk assessment and management, due diligence assessments, and information and data assurance. Leveraging our decades of experience in static analysis, reverse engineering and formal methods, we have created breakthrough products for the automated and systematic investigation of code, data and networks.";
    }

    /*
     * (non-Javadoc)
     * 
     * @see com.kdmanalytics.toif.framework.toolAdaptor.AbstractAdaptor# getAdaptorVendorEmail()
     */
    @Override
    public String getAdaptorVendorEmail() {
        return "adam@kdmanalytics.com";
    }

    /*
     * (non-Javadoc)
     * 
     * @see com.kdmanalytics.toif.framework.toolAdaptor.AbstractAdaptor# getAdaptorVendorName()
     */
    @Override
    public String getAdaptorVendorName() {
        return "KDM Analytics";
    }

    /*
     * (non-Javadoc)
     * 
     * @see com.kdmanalytics.toif.framework.toolAdaptor.AbstractAdaptor# getAdaptorVendorPhone()
     */
    @Override
    public String getAdaptorVendorPhone() {
        return "613-627-1011";
    }

    /*
     * (non-Javadoc)
     * 
     * @see com.kdmanalytics.toif.framework.toolAdaptor.AbstractAdaptor# getGeneratorDescription()
     */
    @Override
    public String getGeneratorDescription() {
        return "Splint is a tool for statically checking C programs for security vulnerabilities and coding mistakes.";
    }

    /*
     * (non-Javadoc)
     * 
     * @see com.kdmanalytics.toif.framework.toolAdaptor.AbstractAdaptor#getGeneratorName ()
     */
    @Override
    public String getGeneratorName() {
        return "splint";
    }

    /*
     * (non-Javadoc)
     * 
     * @see com.kdmanalytics.toif.framework.toolAdaptor.AbstractAdaptor# getGeneratorVendorAddress()
     */
    @Override
    public String getGeneratorVendorAddress() {
        return "http://www.splint.org";
    }

    /*
     * (non-Javadoc)
     * 
     * @see com.kdmanalytics.toif.framework.toolAdaptor.AbstractAdaptor#
     * getGeneratorVendorDescription()
     */
    @Override
    public String getGeneratorVendorDescription() {
        return "University of Virginia Department of Computer Science";
    }

    /*
     * (non-Javadoc)
     * 
     * @see com.kdmanalytics.toif.framework.toolAdaptor.AbstractAdaptor# getGeneratorVendorEmail()
     */
    @Override
    public String getGeneratorVendorEmail() {
        return "info@splint.org";
    }

    /*
     * (non-Javadoc)
     * 
     * @see com.kdmanalytics.toif.framework.toolAdaptor.AbstractAdaptor# getGeneratorVendorName()
     */
    @Override
    public String getGeneratorVendorName() {
        return "David Evans";
    }

    /*
     * (non-Javadoc)
     * 
     * @see com.kdmanalytics.toif.framework.toolAdaptor.AbstractAdaptor# getGeneratorVendorPhone()
     */
    @Override
    public String getGeneratorVendorPhone() {
        return "";
    }

    /*
     * (non-Javadoc)
     * 
     * @see com.kdmanalytics.toif.framework.toolAdaptor.AbstractAdaptor# getGeneratorVersion()
     */
    @Override
    public String getGeneratorVersion() {
        final String[] commands = { "splint", "-help", "version" };
        ProcessBuilder splint = new ProcessBuilder(commands);
        try {
            Process splintInstance = splint.start();
            InputStream in = splintInstance.getErrorStream();

            BufferedReader br = new BufferedReader(new InputStreamReader(in));

            String strLine;

            while ((strLine = br.readLine()) != null) {
                String[] stringArray = strLine.split(" ");

                if (stringArray[1].trim().equals("3.1.2")) {
                    return stringArray[1].trim();
                } else {
                    System.err.println(getAdaptorName() + ": Generator " + stringArray[1]
                            + " found, only version 3.1.2 has been tested");
                    return stringArray[1].trim();
                }
            }

        } catch (IOException e) {
            e.printStackTrace();
        }

        return "";
    }

    @Override
    public String getRuntoolName() {
        return "splint";
    }

    @Override
    public Language getLanguage() {
        return Language.C;
    }

    @Override
    public boolean acceptsDOptions() {
        return false;
    }

    @Override
    public boolean acceptsIOptions() {
        return true;
    }

}