google / guava

Google core libraries for Java

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Found 24 NPEs in guava

LLM4IG opened this issue · comments

Description

During the use of Guava, I have identified several potential NPEs that are not explicitly listed in the method signatures.

Personally, I believe that exceptions that are not listed in the throws during usage can be considered unexpected behavior, where I don't know how guava's maintainers perceive this. If all the unhandled NullPointerExceptions in this issue are considered expected, then I can close this issue.

Example

1. com.google.common.io.Resources::readLines(URL, Charset)

When charset is null, it throws NPE.

show code

public static List readLines(URL url, Charset charset) throws IOException {
// don't use asCharSource(url, charset).readLines() because that returns
// an immutable list, which would change the behavior of this method
return readLines(
url,
charset,
new LineProcessor<List>() {
final List result = Lists.newArrayList();

      @Override
      public boolean processLine(String line) {
        result.add(line);
        return true;
      }

      @Override
      public List<String> getResult() {
        return result;
      }
    });

}

2. com.google.common.primitives.Shorts::contains(short[], short)

When array is null, it throws NPE.

show code
  public static boolean contains(short[] array, short target) {
    for (short value : array) {
      if (value == target) {
        return true;
      }
    }
    return false;
  }

3. com.google.common.primitives.Longs::contains(long[], long)

The same as 2.

4. com.google.common.primitives.Booleans::contains(boolean[], boolean)

The same as 2.

5. com.google.common.primitives.Ints::contains(int[], int)

When array is null, it throws NPE.

show code
  public static boolean contains(int[] array, int target) {
    for (int value : array) {
      if (value == target) {
        return true;
      }
    }
    return false;
  }

6. com.google.common.primitives.Floats::contains(float[], float)

The same as 5.

7. com.google.common.primitives.Bytes::contains(byte[], byte)

The same as 5.

8. com.google.common.primitives.Doubles::contains(double[], double)

The same as 5.

9. com.google.common.primitives.Shorts::max(short...)

When the first argument in array is null, it throws NPE.

show code
  /**
   * Returns the greatest value present in {@code array}.
   *
   * @param array a <i>nonempty</i> array of {@code short} values
   * @return the value present in {@code array} that is greater than or equal to every other value
   *     in the array
   * @throws IllegalArgumentException if {@code array} is empty
   */
  @GwtIncompatible(
      "Available in GWT! Annotation is to avoid conflict with GWT specialization of base class.")
  public static short max(short... array) {
    checkArgument(array.length > 0);
    short max = array[0];
    for (int i = 1; i < array.length; i++) {
      if (array[i] > max) {
        max = array[i];
      }
    }
    return max;
  }

10. com.google.common.net.InetAddresses::toUriString(InetAddress)

When ip is null, it throws NPE.

show code
  public static String toUriString(InetAddress ip) {
    if (ip instanceof Inet6Address) {
      return "[" + toAddrString(ip) + "]";
    }
    return toAddrString(ip);
  }

11. com.google.common.net.InternetDomainName::isValid(String)

When name is null, it throws NPE.

show code
  public static boolean isValid(String name) {
    try {
      InternetDomainName unused = from(name);
      return true;
    } catch (IllegalArgumentException e) {
      return false;
    }
  }

12. com.google.common.primitives.Longs::concat(long[]...)

When arrays is null, it throws NPE.

show code
  public static long[] concat(long[]... arrays) {
    long length = 0;
    for (long[] array : arrays) {
      length += array.length;
    }
    long[] result = new long[checkNoOverflow(length)];
    int pos = 0;
    for (long[] array : arrays) {
      System.arraycopy(array, 0, result, pos, array.length);
      pos += array.length;
    }
    return result;
  }

13. com.google.common.primitives.ImmutableLongArray::copyOf(Iterable<Long>)

When values is null, it throws NPE.

show code
  public static ImmutableLongArray copyOf(Iterable<Long> values) {
    if (values instanceof Collection) {
      return copyOf((Collection<Long>) values);
    }
    return builder().addAll(values).build();
  }

14. com.google.common.primitives.ImmutableDoubleArray::copyOf(Iterable<Double>)

The same as 13.

15. com.google.common.primitives.ImmutableIntArray::copyOf(Iterable<Integer>)

The same as 13.

16. com.google.common.net.InetAddresses::getCoercedIPv4Address(InetAddress)

When ip is null, it throws NPE.

show code
  public static Inet4Address getCoercedIPv4Address(InetAddress ip) {
    if (ip instanceof Inet4Address) {
      return (Inet4Address) ip;
    }

    // Special cases:
    byte[] bytes = ip.getAddress();
    boolean leadingBytesOfZero = true;
    for (int i = 0; i < 15; ++i) {
      if (bytes[i] != 0) {
        leadingBytesOfZero = false;
        break;
      }
    }
    if (leadingBytesOfZero && (bytes[15] == 1)) {
      return LOOPBACK4; // ::1
    } else if (leadingBytesOfZero && (bytes[15] == 0)) {
      return ANY4; // ::0
    }

    Inet6Address ip6 = (Inet6Address) ip;
    long addressAsLong = 0;
    if (hasEmbeddedIPv4ClientAddress(ip6)) {
      addressAsLong = getEmbeddedIPv4ClientAddress(ip6).hashCode();
    } else {
      // Just extract the high 64 bits (assuming the rest is user-modifiable).
      addressAsLong = ByteBuffer.wrap(ip6.getAddress(), 0, 8).getLong();
    }

    // Many strategies for hashing are possible. This might suffice for now.
    int coercedHash = Hashing.murmur3_32_fixed().hashLong(addressAsLong).asInt();

    // Squash into 224/4 Multicast and 240/4 Reserved space (i.e. 224/3).
    coercedHash |= 0xe0000000;

    // Fixup to avoid some "illegal" values. Currently the only potential
    // illegal value is 255.255.255.255.
    if (coercedHash == 0xffffffff) {
      coercedHash = 0xfffffffe;
    }

    return getInet4Address(Ints.toByteArray(coercedHash));
  }

17. com.google.common.io.Flushables::flushQuietly(Flushable)

When flushable is null, it throws NPE.

show code
  @Beta
  public static void flushQuietly(Flushable flushable) {
    try {
      flush(flushable, true);
    } catch (IOException e) {
      logger.log(Level.SEVERE, "IOException should not have been thrown.", e);
    }
  }

18. com.google.common.primitives.Chars::concat(char[]...)

The same as 12.

19. com.google.common.primitives.Booleans::concat(boolean[]...)

The same as 12.

20. com.google.common.primitives.Floats::concat(float[]...)

The same as 12.

21. com.google.common.primitives.Bytes::concat(byte[]...)

The same as 12.

22. com.google.common.net.InetAddresses::isIsatapAddress(Inet6Address)

When ip is null, it throws NPE.

show code
  public static boolean isIsatapAddress(Inet6Address ip) {

    // If it's a Teredo address with the right port (41217, or 0xa101)
    // which would be encoded as 0x5efe then it can't be an ISATAP address.
    if (isTeredoAddress(ip)) {
      return false;
    }

    byte[] bytes = ip.getAddress();

    if ((bytes[8] | (byte) 0x03) != (byte) 0x03) {

      // Verify that high byte of the 64 bit identifier is zero, modulo
      // the U/L and G bits, with which we are not concerned.
      return false;
    }

    return (bytes[9] == (byte) 0x00) && (bytes[10] == (byte) 0x5e) && (bytes[11] == (byte) 0xfe);
  }

23. com.google.common.io.MoreFiles::listFiles(Path)

When dir is null, it throws NPE.

show code
  public static ImmutableList<Path> listFiles(Path dir) throws IOException {
    try (DirectoryStream<Path> stream = Files.newDirectoryStream(dir)) {
      return ImmutableList.copyOf(stream);
    } catch (DirectoryIteratorException e) {
      throw e.getCause();
    }
  }

24. com.google.common.io.MoreFiles::createParentDirectories(Path, FileAttribute<?>...)

When path is null, it throws NPE.

show code
  public static void createParentDirectories(Path path, FileAttribute<?>... attrs)
      throws IOException {
    // Interestingly, unlike File.getCanonicalFile(), Path/Files provides no way of getting the
    // canonical (absolute, normalized, symlinks resolved, etc.) form of a path to a nonexistent
    // file. getCanonicalFile() can at least get the canonical form of the part of the path which
    // actually exists and then append the normalized remainder of the path to that.
    Path normalizedAbsolutePath = path.toAbsolutePath().normalize();
    Path parent = normalizedAbsolutePath.getParent();
    if (parent == null) {
      // The given directory is a filesystem root. All zero of its ancestors exist. This doesn't
      // mean that the root itself exists -- consider x:\ on a Windows machine without such a
      // drive -- or even that the caller can create it, but this method makes no such guarantees
      // even for non-root files.
      return;
    }

    // Check if the parent is a directory first because createDirectories will fail if the parent
    // exists and is a symlink to a directory... we'd like for this to succeed in that case.
    // (I'm kind of surprised that createDirectories would fail in that case; doesn't seem like
    // what you'd want to happen.)
    if (!Files.isDirectory(parent)) {
      Files.createDirectories(parent, attrs);
      if (!Files.isDirectory(parent)) {
        throw new IOException("Unable to create parent directories of " + path);
      }
    }
  }

Expected Behavior

I think some of them are not supposed to throw NPE and others need append NullPointerException to throws at least.

Actual Behavior

They all throws java.lang.NullPointerException.

Packages

com.google.common.io, com.google.common.net, com.google.common.primitives

Platforms

No response

Checklist

Guava is null hostile so unless explicitly documented it is assumed that a null parameter is disallowed. This is declared on the package, e.g.

@ParametersAreNonnullByDefault