changeset 1787:f3c017005021

Fix infinite loop in StorageAuthInfoGetter.getPassword() on short input. Reviewed-by: aazores Review-thread: http://icedtea.classpath.org/pipermail/thermostat/2015-September/015940.html PR2620
author Severin Gehwolf <sgehwolf@redhat.com>
date Wed, 09 Sep 2015 18:32:31 +0200
parents d9e78b81ecdf
children ee586d51072d
files common/core/src/main/java/com/redhat/thermostat/common/tools/StorageAuthInfoGetter.java common/core/src/test/java/com/redhat/thermostat/common/tools/StorageAuthInfoGetterTest.java
diffstat 2 files changed, 66 insertions(+), 70 deletions(-) [+]
line wrap: on
line diff
--- a/common/core/src/main/java/com/redhat/thermostat/common/tools/StorageAuthInfoGetter.java	Fri Aug 28 16:00:34 2015 -0400
+++ b/common/core/src/main/java/com/redhat/thermostat/common/tools/StorageAuthInfoGetter.java	Wed Sep 09 18:32:31 2015 +0200
@@ -53,6 +53,7 @@
  */
 public class StorageAuthInfoGetter {
 
+    private static final int EOF = -1;
     private static final int PW_SIZE_INCREMENT = 16;
 
     private final ConsoleReader reader;
@@ -114,8 +115,11 @@
         Character oldEcho = reader.getEchoCharacter();
         reader.setEchoCharacter('\0');
         int pwChar = reader.readCharacter();
+        if (pwChar == EOF) {
+            return null;
+        }
         int length = 0;
-        while ((char) pwChar != '\n' && (char) pwChar != '\r') {
+        while ((char) pwChar != '\n' && (char) pwChar != '\r' && pwChar != EOF) {
             password[length] = (char) pwChar;
             length++;
             if (length >= password.length) {
--- a/common/core/src/test/java/com/redhat/thermostat/common/tools/StorageAuthInfoGetterTest.java	Fri Aug 28 16:00:34 2015 -0400
+++ b/common/core/src/test/java/com/redhat/thermostat/common/tools/StorageAuthInfoGetterTest.java	Wed Sep 09 18:32:31 2015 +0200
@@ -36,44 +36,13 @@
 
 package com.redhat.thermostat.common.tools;
 
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import java.io.ByteArrayInputStream;
 import java.io.IOException;
-import java.io.InputStream;
-/*
- * Copyright 2012-2014 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are not obligated to do so.  If you do not wish
- * to do so, delete this exception statement from your version.
- */
-
 import java.io.PrintStream;
 
 import org.junit.Before;
@@ -81,63 +50,86 @@
 
 import com.redhat.thermostat.common.cli.Console;
 
-import static org.junit.Assert.assertEquals;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
-
 public class StorageAuthInfoGetterTest {
 
-    private StorageAuthInfoGetter getter;
-    private InputStream in;
-    private PrintStream out;
+    private Console console;
 
     @Before
     public void setUp() throws IOException {
-        in = mock(InputStream.class);
-        out = mock(PrintStream.class);
-        Console console = mock(Console.class);
-        when(console.getInput()).thenReturn(in);
-        when(console.getOutput()).thenReturn(out);
-        getter = new StorageAuthInfoGetter(console);
+        console = mock(Console.class);
+        when(console.getOutput()).thenReturn(mock(PrintStream.class));
+    }
+    
+    /*
+     * This must not loop infinitely.
+     */
+    @Test
+    public void testGetPasswordEmpty() throws IOException {
+        String input = "";
+        ByteArrayInputStream bin = new ByteArrayInputStream(input.getBytes());
+        when(console.getInput()).thenReturn(bin);
+        StorageAuthInfoGetter getter = new StorageAuthInfoGetter(console);
+        char[] password = getter.getPassword("no matter");
+        assertNull(password);
+    }
+    
+    @Test
+    public void testGetUsernameEmpty() throws IOException {
+        String input = "";
+        ByteArrayInputStream bin = new ByteArrayInputStream(input.getBytes());
+        when(console.getInput()).thenReturn(bin);
+        StorageAuthInfoGetter getter = new StorageAuthInfoGetter(console);
+        String username = getter.getUserName("no matter");
+        assertNull(username);
     }
 
     @Test
     public void testGetUserNameCarriageReturn() throws IOException {
-        testGetUsername((int) '\r');
+        testGetUsername("user\r\n", "user");
     }
 
     @Test
     public void testGetUserNameNewLine() throws IOException {
-        testGetUsername((int) '\n');
+        testGetUsername("user\n", "user");
+    }
+    
+    @Test
+    public void testGetUserNameNoNewLine() throws IOException {
+        testGetUsername("user", null);
     }
 
-    private void testGetUsername(int newLineChar) throws IOException {
-        when(in.read()).thenReturn((int) 'u')
-                .thenReturn((int) 's')
-                .thenReturn((int) 'e')
-                .thenReturn((int) 'r')
-                .thenReturn(newLineChar);
-        assertEquals("user", getter.getUserName("url_doesn't_matter"));
+    private void testGetUsername(String input, String expectedUsername) throws IOException {
+        ByteArrayInputStream bin = new ByteArrayInputStream(input.getBytes());
+        when(console.getInput()).thenReturn(bin);
+        StorageAuthInfoGetter getter = new StorageAuthInfoGetter(console);
+        assertEquals(expectedUsername, getter.getUserName("url_doesn't_matter"));
     }
 
     @Test
     public void testGetPasswordCarriageReturn() throws IOException {
-        testGetPassword((int) '\r');
+        testGetPassword("pass\r\n", "pass");
     }
 
     @Test
     public void testGetPasswordNewLine() throws IOException {
-        testGetPassword((int) '\n');
+        testGetPassword("pass\n", "pass");
+    }
+    
+    @Test
+    public void testGetPasswordNoNewLine() throws IOException {
+        testGetPassword("pass?", "pass?");
+    }
+    
+    @Test
+    public void testGetPasswordLongerThanIncrement() throws IOException {
+        testGetPassword("pass|pass|pass|pass\n", "pass|pass|pass|pass");
     }
 
-    private void testGetPassword(int newLineChar) throws IOException {
-        char[] pass = new char[] {'p', 'a', 's', 's'};
-        when(in.read()).thenReturn((int) 'p')
-                .thenReturn((int) 'a')
-                .thenReturn((int) 's')
-                .thenReturn((int) 's')
-                .thenReturn((int) '\r');
-        assertEquals(new String(pass), new String(getter.getPassword("url_doesn't_matter")));
+    private void testGetPassword(String input, String expectedPassword) throws IOException {
+        ByteArrayInputStream bin = new ByteArrayInputStream(input.getBytes());
+        when(console.getInput()).thenReturn(bin);
+        StorageAuthInfoGetter getter = new StorageAuthInfoGetter(console);
+        assertEquals(expectedPassword, new String(getter.getPassword("url_doesn't_matter")));
     }
 }