Pull to refresh

Как я искал зависимости через include файлы на java

Reading time6 min
Views3K
Доброго времени суток. Сегодня расскажу о том как выполнить часть работ по сертификации кода по требованиям РД ФСТЭК(контроль отсутствия недкларированных возможностей). В требованиях по статическому анализу есть требование контроля компиляции файлов или ответить на вопрос все ли файлы компилируются в объектные файлы и есть ли файлы которые не компилируются. Для этого составим списки файлов cpp, c, h. Для этого зайдем в папку с исходниками и выполним команду «find. -iname *.cpp», «find. -iname *.c», «find. -iname *.o» запишем выдачу в файлы «c_cpp_files.txt» и «h_files.txt».

У нас получится файлы со следующим содержимым:

./arch/powerpc/math-emu/fmul.c
./arch/powerpc/math-emu/lfd.c
./arch/powerpc/math-emu/fsqrt.c
./arch/powerpc/math-emu/fsub.c
./arch/powerpc/math-emu/fnmsub.c
./arch/powerpc/math-emu/frsqrte.c
./arch/powerpc/math-emu/mtfsb0.c
...

и соответственно следующее:

./arch/powerpc/include/asm/udbg.h
./arch/powerpc/include/asm/termios.h
./arch/powerpc/include/asm/immap_cpm2.h
./arch/powerpc/include/asm/linkage.h
./arch/powerpc/include/asm/rio.h
./arch/powerpc/include/asm/dma-mapping.h
...


Далее проанализируем какие Include-ы встречаются в каких *.c или *.cpp файлах. Для этого предназначен следующий код:

файл Incl.java:

/*
    включение одного фала
    со строкой и номером линии
*/
public class Incl {
    public String text;
    public int line;
}

файл InclPoints.java:

import java.io.File;
import java.util.List;

public class InclPoints {


    public File headers;
    public List<Point> points;
}

файл Includes.java:

import java.io.File;
import java.util.ArrayList;
import java.util.List;

public class Includes {
    public File file;    // файл в котором найден инклюд
    public List<Incl> incl=new ArrayList<>();  // массив включений
}

файл Point.java:

import java.io.File;

public class Point
{
    public File src;
    public Incl incl;
}

и файл Main.java:

import java.io.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class Main {
    public static File reportFile;
    public static File header_file;
    public static File sources_file;

    public static Map<Integer,File> headers_nouse;
    public static Map<Integer,File> headers_withuse;
    public static int header_nouse_counter;
    public static int header_withuse_counter;
    private static List<InclPoints> incpo_lst;

    //public List<InclPoints> incpo_lst;

    public static void main(String[] args)
    {
            func1(args);
    }


    public static Map<Integer,File> readCodeList(String path_to_code)
    {
        Map<Integer,File> code_files= new TreeMap<>();

        int file_counter=0;
        try (BufferedReader br = new BufferedReader(new FileReader(path_to_code))) {
            String current_source_line;
            while ((current_source_line = br.readLine()) != null) {
                current_source_line=current_source_line.trim();
                code_files.put(file_counter, new File(current_source_line));
                file_counter++;
            }
        }
        catch(IOException ex){

            System.out.println(ex.getMessage());
        }
        return code_files;

    }

    public static Map<Integer,File> readheadersFile(String header_file_path)
    {
        Map<Integer,File> header_files= new TreeMap<>();
        int headers_counter=0;
        try (BufferedReader br = new BufferedReader(new FileReader(header_file_path))) {
            String current_header_line;
            while ((current_header_line = br.readLine()) != null) {
                current_header_line=current_header_line.trim();
                header_files.put(headers_counter,new File(current_header_line));
                headers_counter++;
            }
        }
        catch(IOException ex){

            System.out.println(ex.getMessage());
        }
        return header_files;
    }


    public static void  func1(String[] args){
        String header_file_name=args[0];
        String sources_file_name=args[1];

        reportFile=new File("Report.txt");
        header_file=new File(header_file_name);
        sources_file=new File(sources_file_name);

        Map<Integer,File> code_files= readCodeList( sources_file.toPath().toString() );
        System.out.println("Total number of source files="+code_files.size());
        // прочитать список заголовочных файлов
        Map<Integer,File> header_files=readheadersFile(header_file.toPath().toString());
        System.out.println("Total number of header files = "+header_files.size());
        //Проверяем заголовочные файлы на используемость
        System.out.println("Proccessing Level 1 dependencies");
        List<InclPoints> result1=search_headers2(header_files,code_files);

        headers_nouse=new TreeMap<Integer,File>();
        headers_withuse = new TreeMap<Integer,File>();

        int headers_nouse_counter=0;
        int headers_withuse_counter=0;
        for(InclPoints ip:result1)
        {
            if(ip.points.size() ==0)
            {
                headers_nouse.put(headers_nouse_counter, ip.headers);
                headers_nouse_counter++;
            }
            else
            {
                headers_withuse.put(headers_withuse_counter,ip.headers);
                headers_withuse_counter++;
            }
        }
        System.out.println("Proccessing Level 2 dependencies");
        List<InclPoints> result2=search_headers2(headers_nouse,headers_withuse);


        for(InclPoints ip: result1)
        {
            appendUsingOutputStream(reportFile.toPath().toString(),"Header file : "+ip.headers+"\n");
            for(Point p: ip.points) {
                appendUsingOutputStream(reportFile.toPath().toString(), "    usage : "+p.src.toPath().toString()+" \n");
                appendUsingOutputStream(reportFile.toPath().toString(), "     line "+p.incl.line+" : "+p.incl.text+" \n");


            }
            appendUsingOutputStream(reportFile.toPath().toString(), "Number of entries = "+ip.points.size()+" \n\n");
        }
        for(InclPoints ip: result2)
        {
            appendUsingOutputStream(reportFile.toPath().toString(),"Header file : "+ip.headers+"\n");
            for(Point p: ip.points) {
                appendUsingOutputStream(reportFile.toPath().toString(), "    usage : "+p.src.toPath().toString()+" \n");
                appendUsingOutputStream(reportFile.toPath().toString(), "     line "+p.incl.line+" : "+p.incl.text+" \n");


            }
            appendUsingOutputStream(reportFile.toPath().toString(), "Number of entries = "+ip.points.size()+" \n\n");
        }
    }


    public static List<InclPoints> search_headers2(Map<Integer,File> headers,Map<Integer,File> sources)
    {
        List<Includes> incs_lst=new ArrayList<Includes>();
        incpo_lst = new ArrayList<InclPoints>();
        for(File curFilePath : sources.values())
        {
            Includes incs=new Includes();
            incs.file=curFilePath;
            try{
                BufferedReader cur_file = new BufferedReader(new FileReader(curFilePath));
                int line_number=0;
                for(String cur_line; (cur_line = cur_file.readLine()) != null; line_number++) {
                    Pattern p1 = Pattern.compile("#include.+?\\W.+\\W");
                    Matcher m2 = p1.matcher(cur_line);
                    if(m2.find())
                    {
                        Incl incl=new Incl();
                        incl.text = cur_line.trim();
                        incl.line = line_number;
                        incs.incl.add(incl);
                    }
                }
                cur_file.close();
                incs_lst.add(incs);
            }catch(IOException e)
            {
                System.out.println(e.getMessage());
            }
        }

        // перебираем heiders и ищим в инклюдах используемые
        for(File current_header: headers.values())
        {
            InclPoints point=new InclPoints();
            point.headers=current_header;
            point.points= new ArrayList<Point>();

            String header="";
            Pattern p = Pattern.compile("\\/?([\\w\\-\\.]+?)\\.h");
            String text=current_header.getPath();
            Matcher m = p.matcher(text);
            if(m.find())
            {
                System.out.println(String.format("|%-100s|",current_header));
                header=current_header.getPath().substring(m.start(), m.end());
                for(Includes inc:incs_lst)
                {

                    for(Incl incl:inc.incl) {
                        Pattern p1 = Pattern.compile("#include.+?\\W" + header + "\\W");
                        Matcher m2 = p1.matcher(incl.text);
                        if (m2.find()) {

                            Point po= new Point();
                            po.src= inc.file;
                            po.incl=incl;
                            point.points.add(po);
                            System.out.println(String.format("|%-60s| %-40s |",po.src.toString() ,po.incl.text));
                        }
                    }
                }
            }
            incpo_lst.add(point);
        }
        return incpo_lst;
    }
       // обновляем файл с помощью FileWriter
        private static void appendUsingOutputStream(String fileName, String data) {
        OutputStream os = null;
        try {
            //в конструкторе FileOutputStream используем флаг true, который обозначает обновление содержимого файла
            os = new FileOutputStream(new File(fileName), true);
            os.write(data.getBytes(), 0, data.length());

        } catch (IOException e) {
            e.printStackTrace();
        }finally{
            try {
                os.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

Алгоритм следующий:

Сначала просматриваем файлы с/cpp и ищем с помощью регулярного выражения директиву #include <…> запоминаем данную стоку и номер строки для файла. Далее для каждой найденной конструкции проверяем наличие include для h файлов. В итоге проверяем то же самое для *.h файлов. Если h файл не где не был подключен, то есть вероятность того, что он был подключен в используемых *.h файлах, для этого проверяем еще один раз наличие подключений *.h файлах в подключенных *.h файлах.

В итоге делаем отчет следующего вида:

Proccessing Level 1 dependencies
Header file : ./arch/powerpc/include/asm/udbg.h
usage : ./arch/powerpc/platforms/85xx/izgib.c
line : #include <asm/udbg.h>
usage : ./arch/powerpc/sysdev/cpm_common.c
line : #include <asm/udbg.h>
usage : ./arch/powerpc/kernel/legacy_serial.c
line : #include <asm/udbg.h>
usage : ./arch/powerpc/kernel/setup-common.c
line : #include <asm/udbg.h>
usage : ./arch/powerpc/kernel/setup_32.c
line : #include <asm/udbg.h>
usage : ./arch/powerpc/kernel/udbg.c
line : #include <asm/udbg.h>
usage : ./arch/powerpc/kernel/irq.c
line : #include <asm/udbg.h>
usage : ./arch/powerpc/kernel/udbg_16550.c
line : #include <asm/udbg.h>
Number of entries = 8

Header file : ./arch/powerpc/include/asm/termios.h
usage : ./net/unix/af_unix.c
line : #include <linux/termios.h>
usage : ./net/netlink/af_netlink.c
line : #include <linux/termios.h>
usage : ./drivers/tty/tty_ioctl.c
line : #include <linux/termios.h>
Number of entries = 3
Tags:
Hubs:
-8
Comments3

Articles

Change theme settings