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

    Доброго времени суток. Сегодня расскажу о том как выполнить часть работ по сертификации кода по требованиям РД ФСТЭК(контроль отсутствия недкларированных возможностей). В требованиях по статическому анализу есть требование контроля компиляции файлов или ответить на вопрос все ли файлы компилируются в объектные файлы и есть ли файлы которые не компилируются. Для этого составим списки файлов 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
    • –8
    • 1,7k
    • 3
    Поделиться публикацией
    Ой, у вас баннер убежал!

    Ну, и что?
    Реклама
    Комментарии 3
    • НЛО прилетело и опубликовало эту надпись здесь
      • 0
        Условную компиляцию не проверяет. Проверяет только подключения. Для условной компиляции нужно разбирать препроцессинг.
        • НЛО прилетело и опубликовало эту надпись здесь

      Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

      Самое читаемое