![](https://i.imgur.com/r2Upi0M.png) ## Verificação e Validação de Software ### Professor: José Campos ### Alunos: João Lopes nº55812 Filipe Martins nº55814 # Assignment #1 ## JPass ### Projeto O projeto JPass é uma aplicação desktop que visa apresentar uma forma simples e portátil com a qual um utilizador consegue fazer a gestão das suas palavras-passes. Juntamente com as palavras-passes guardadas é possível associar as mesmas a um nome e um URL entre muitas outras opções. ### Organização O código apresenta-se organizado por diversas pastas: - **crypto**: Esta pasta está encarregue de ter todas as classes referentes a encriptação e desencriptação do projeto como também as devidas exceções. - **data**: Pasta que lida com as classes encarregues de guardar e interpretar toda a data da aplicação. - **ui**: Pasta onde estão todas as classes que lidam com a interface da aplicação. - **util**: Nesta pasta existem várias classes com métodos estáticos que ajudam e complementam várias funções pela aplicação. - **xml**: Pasta que trata de receber, enviar e converter ficheiros xml. ## Static Testing *Static testing* trata-se de uma técnica *white box* de testes que se aplicam a um software em desenvolvimento sem que este esteja em execução de forma a encontrar possíveis erros/faltas. Esta técnica divide-se em 2 tipos: - Manual: Examinação manual do código, ou seja, fazer *review* do código. - Automática: Analise automática do código com o auxílio de ferramentas externas ou internas. ### Importância Esta técnica apresenta alguns fatores que são cruciais para o bom desenvolvimento de software: - Deteção inicial de bugs antes da execução do software permite melhorar a produtividade, ao utilizar *static testing* podemos numa fase inicial detetar falhas e erros fáceis de corrigir. Irá também permitir diminuir o tempo alocado para fazer testes ao software e permitir aumentar o tempo alocado ao desenvolvimento de software. - Permite melhorar significativamente a manutenção do software. - Previne falhas e transmite conhecimento, a correção de bugs encontrados permite que no futuro os mesmos não se repitam. ## SpotBugs Trata-se de uma ferramenta que permite fazer a *static analysis* a código Java de uma forma automática que permite encontrar faltas/erros presentes no mesmo, para tal o SpotBugs utiliza mais de 400 padrões. ### Configuração para o IDE Intellij De modo a configurar o SpotBugs no IDE Intellij foi necessário primeiramente instalar o plugin do mesmo, através do *marketplace* do Intellij, e de modo a integrar a ferramenta no projeto foi preciso adicionar ao ficheiro pom.xml os dados relativos a ferramenta. ![](https://i.imgur.com/adID9QL.png) ![](https://i.imgur.com/SV9r7Ua.png) Depois de instalado podemos, através do menu do SpotBugs, definir quais as categorias que achamos relevantes este analisar e também nos permite escolher, entre os 400 padrões oferecidos, quais achamos relevantes para o nosso projeto e desta forma evitamos analises a padrões irrelevantes. ![](https://i.imgur.com/HpNUR5K.png) ### Padrões adicionados/removidos Visto que por definição bastantes padrões já se encontram selecionados, foi preciso verificar os mesmos, de modo a retirar padrões irrelevantes e a adicionar padrões que fizessem sentido de acordo com o nosso projeto. Como a aplicação JPass é simplesmente utilizada no computador do utilizador e não tem qualquer contacto com a WEB iniciamos a analise sobre este ponto, tendo removido o padrão ***CrossSiteScripting***, visto que não existe nenhuma página WEB, nem comunicações HTTP. De seguida verificamos que nesta aplicação não existe o uso de Threads, tendo removido todos os padrões que as analisam, neste caso os padrões: * ***MultithreadedInstanceAccess*** * ***SuspiciousThreadInterrupted*** * ***FindRunInvocations*** * ***FindSleepWithLockHeld*** * ***StartInConstructor*** Por fim como não a aplicação guarda os seus dados em ficheiros do tipo .jpass, e não numa base de dados removemos o padrão ***FindSqlInjection***. Passando aos padrões adicionados, começamos pelo padrão ***FindCircularDependencies***, visto que queremos ter a nossa aplicação o menos acoplada possivel e para tal não podemos ter dependencias circulares, após a adição deste padrão verificamos que o número de avisos aumentou. Depois verificamos que existem na aplicação conversões de objetos para arrays, sendo util verifica as mesmas, para tal é necessário o padrão ***InefficientToArray***. Por último verificamos também o uso do metodo `String.indexOf()`, tendo ativado o padrão ***InefficientIndexOf*** de modo a verificar se o uso do mesmo era necessário e se não havia problemas em termos de performance. ## Bugs Nesta secção iremos apresentar 5 bugs encontrados pelo SpotBugs, quais as suas implicações e a sua correção. ## Bug 1 Este bug ocorre quando o código desenvolvido é confuso, apresenta anomalias ou a sua utilização pode gerar confusão. Trata-se de um bug da categoria *Dodgy code* e tem o rank de *Troubling*. *Warning* apresentado pelo Spotbugs: - ***Warning*: Useless condition: it's always current < 65536 (0x10000) because variable type is char.** ``` if ((current == 0x9) || (current == 0xA) || (current == 0xD) || ((current >= 0x20) && (current <= 0xD7FF)) || ((current >= 0xE000) && (current <= 0xFFFD)) || ((current >= 0x10000) && (current <= 0x10FFFF))) { out.append(current); } else { out.append('?'); } ``` Neste caso, o bug reporta que a última validação do if nunca chegara a ser verificada. ### Solução Neste caso, o bug reporta que a última validação do if nunca chegara a ser verificada. De forma a resolver o bug bastou retirar a última validação apresentada no if, apesar de estas solução resolver o bug, a utilidade do método fica comprometida. Esta situação iria implicar uma revisão ao método e á sua utilidade. ``` if ((current == 0x9) || (current == 0xA) || (current == 0xD) || ((current >= 0x20) && (current <= 0xD7FF)) || ((current >= 0xE000) && (current <= 0xFFFD))) { out.append(current); } else { out.append('?'); } ``` ## Bug 2 Este bug ocorre caso a variável url seja null, levando a um *NullPointerException* aquando da chamada do método toURI(), este bug é da categoria *Correctness* e tem o rank de *Scary*. *Warning* apresentado pelo Spotbugs: * ***Warning*: Possible null pointer dereference of url in jpass.ui.SvgImageIcon.update().** ``` try { diagram = svgUniverse.getDiagram(url.toURI()); } catch (Exception ex) { LOG.log(Level.WARNING, String.format("Could not get SVG image [%s] due to [%s]", name, ex.getMessage())); } ``` ### Solução De modo a corrigir o mesmo, é necessário validar se o url é ou não null, e assim evitar o possível *NullPointerException*. ``` try { if (url != null) diagram = svgUniverse.getDiagram(url.toURI()); } catch (Exception ex) { LOG.log(Level.WARNING, String.format("Could not get SVG image [%s] due to [%s]", name, ex.getMessage())); } ``` ## Bug 3 Neste bug é referida a má pratica da utilização do caracter de newline `\n` ao invés do uso do caracter `%n`, pois com o caracter `%n` produz sempre o separador de linha específico da plataforma correta, ou seja, é portátil entre plataformas enquanto que o caracter `\n` não é. Este bug é da categoria *Bad practice* e tem o rank de *Of Concern*. *Warning* apresentado pelo Spotbugs: * ***Warning*: Format string should use %n rather than \n.** ``` private static final String FILE_OVERWRITE_QUESTION_MESSAGE = "File is already exists:\n%s\n\nDo you want to overwrite?"; ``` ### Solução A solução passa por substituir o caracter `\n` pelo caracter `%n` e desta forma este bug fica corrigido. ## Bug 4 Este bug refere a possibilidade de existir perigo de adversários conseguirem aceder ao código alterar o mesmo, comprometendo assim a integridade do código. Trata-se de um bug da categoria *Malicious Code* e tem o rank de *Of Concern*. *Warning* apresentado pelo Spotbugs: * ***Warning*: jpass.data.DataModel.getPassword() may expose internal representation by returning DataModel.password.** ``` public byte[] getPassword() { return this.password; } ``` Neste caso devolver a variável, esta fica exposta a alterações sendo que dependendo do tipo de variável pode ser algo que coloca em perigo o software. ### Solução A solução para este bug é bastante simples, passa por criar uma variável local e igualar à ao objeto, devolvendo depois o atributo pretendido. ``` public byte[] getPassword() { DataModel dM = DataModel.getInstance(); return dM.password; } ``` ## Bug 5 Por último temos um bug relativo a dependências circulares, onde a classe EntryHelper usa a classe `EntryDialog` e a classe `JPassFrame` e estas utilizam a classe `EntryHelper`, algo que aumenta o acoplamento. Este bug é da categoria *Dodgy code* e tem o rank de *Of Concern*. *Warning* apresentado pelo Spotbugs: * ***Warning*: Class EntryHelper has a circular dependency with other classes.** ###### Código relativo à classe `EntryHelper`: ``` public static void copyEntryField(JPassFrame parent, String content) { try { ClipboardUtils.setClipboardContent(content); } catch (Exception e) { showErrorMessage(parent, e.getMessage()); } } ``` ###### Código relativo à classe `EntryDialog`: ``` } else if ("copy_button".equals(command)) { copyEntryField(JPassFrame.getInstance(), String.valueOf(this.passwordField.getPassword())); } ``` ###### Código relativo à classe `JPassFrame`: ``` public void exitFrame() { if (Configuration.getInstance().is("clear.clipboard.on.exit.enabled", false)) { EntryHelper.copyEntryField(this, null); } ``` ### Solução De forma a resolver este problema foi criada uma classe `GenericHelper` que contem o método `copyEntryField` e desta forma é quebrada a dependência para com a classe `EntryHelper` e deixamos de ter uma dependência circular, passando as classes `EntryDialog` e `JPassFrame` a usar agora a classe `GenericHelper`.