8074368: ThreadMXBean.getThreadInfo() corrupts memory when called with empty array for thread ids
authorjbachorik
Fri, 03 Apr 2015 15:39:38 +0200
changeset 30348 9a9e6c13ab1d
parent 30335 b7b1fab1fb2f
child 30349 09ee9c48f1c3
8074368: ThreadMXBean.getThreadInfo() corrupts memory when called with empty array for thread ids Reviewed-by: mchung
jdk/src/java.management/share/classes/sun/management/ThreadImpl.java
jdk/test/java/lang/management/ThreadMXBean/ThreadInfoArray.java
--- a/jdk/src/java.management/share/classes/sun/management/ThreadImpl.java	Fri Apr 03 13:46:22 2015 -0700
+++ b/jdk/src/java.management/share/classes/sun/management/ThreadImpl.java	Fri Apr 03 15:39:38 2015 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -165,6 +165,10 @@
                 "Invalid maxDepth parameter: " + maxDepth);
         }
 
+        // ids has been verified to be non-null
+        // an empty array of ids should return an empty array of ThreadInfos
+        if (ids.length == 0) return new ThreadInfo[0];
+
         Util.checkMonitorAccess();
 
         ThreadInfo[] infos = new ThreadInfo[ids.length]; // nulls
@@ -436,6 +440,10 @@
                                       boolean lockedMonitors,
                                       boolean lockedSynchronizers) {
         verifyThreadIds(ids);
+        // ids has been verified to be non-null
+        // an empty array of ids should return an empty array of ThreadInfos
+        if (ids.length == 0) return new ThreadInfo[0];
+
         verifyDumpThreads(lockedMonitors, lockedSynchronizers);
         return dumpThreads0(ids, lockedMonitors, lockedSynchronizers);
     }
--- a/jdk/test/java/lang/management/ThreadMXBean/ThreadInfoArray.java	Fri Apr 03 13:46:22 2015 -0700
+++ b/jdk/test/java/lang/management/ThreadMXBean/ThreadInfoArray.java	Fri Apr 03 15:39:38 2015 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2004, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2004, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -23,11 +23,12 @@
 
 /*
  * @test
- * @bug     5058327
- * @summary Test if getThreadInfo(long[]) returns a ThreadInfo[]
- *          with null elements with no exception.
+ * @bug     5058327 8074368
+ * @summary Tests the correct behaviour of getThreadInfo(long[]) for non-existent
+ *          thread IDs and the empty thread id array.
  *
  * @author  Mandy Chung
+ * @author  Jaroslav Bachorik
  *
  * @build ThreadInfoArray
  * @run main ThreadInfoArray
@@ -35,15 +36,30 @@
 
 import java.lang.management.*;
 import javax.management.*;
-import java.util.*;
 import static java.lang.management.ManagementFactory.*;
 
 public class ThreadInfoArray {
     public static void main(String[] argv) throws Exception {
+        MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
+        ObjectName on = new ObjectName(THREAD_MXBEAN_NAME);
+
         ThreadMXBean mbean = ManagementFactory.getThreadMXBean();
+        ThreadMXBean proxy = newPlatformMXBeanProxy(mbs,
+                                 on.toString(),
+                                 ThreadMXBean.class);
 
+        checkNullElement(mbean, proxy, mbs, on);
+        checkEmptyArray(mbean, proxy, mbs, on);
+        System.out.println("Test passed");
+    }
+
+    private static void checkNullElement(ThreadMXBean mbean, ThreadMXBean proxy,
+                                         MBeanServer mbs, ObjectName on)
+        throws Exception {
+        System.out.println("--- Check null element");
         // ID for a new thread
         long [] ids = {new Thread().getId()};
+        // direct call
         ThreadInfo[] tinfos = mbean.getThreadInfo(ids);
 
         if (tinfos[0] != null) {
@@ -52,8 +68,6 @@
         }
 
         // call getThreadInfo through MBeanServer
-        MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
-        ObjectName on = new ObjectName(THREAD_MXBEAN_NAME);
         Object[] params = {ids};
         String[] sigs = {"[J"};
         Object[] result = (Object[]) mbs.invoke(on, "getThreadInfo", params, sigs);
@@ -64,14 +78,57 @@
         }
 
         // call getThreadInfo through proxy
-        ThreadMXBean proxy = newPlatformMXBeanProxy(mbs,
-                                 on.toString(),
-                                 ThreadMXBean.class);
         tinfos = proxy.getThreadInfo(ids);
         if (tinfos[0] != null) {
             throw new RuntimeException("TEST FAILED: " +
                 "Expected to have a null element");
         }
-        System.out.println("Test passed");
+        System.out.println("--- PASSED");
+    }
+
+    private static void checkEmptyArray(ThreadMXBean mbean, ThreadMXBean proxy,
+                                        MBeanServer mbs, ObjectName on)
+        throws Exception {
+        System.out.println("--- Check empty TID array");
+
+        long[] ids = new long[0];
+        // direct call
+        assertEmptyArray(mbean.getThreadInfo(ids), "Expected empty ThreadInfo array");
+        assertEmptyArray(mbean.getThreadInfo(ids, 1), "Expected empty ThreadInfo array");
+        assertEmptyArray(mbean.getThreadInfo(ids, true, true), "Expected empty ThreadInfo array");
+
+        // call getThreadInfo through MBeanServer
+        assertEmptyArray(
+            (Object[]) mbs.invoke(
+                on, "getThreadInfo", new Object[]{ids}, new String[]{"[J"}
+            ),
+            "Expected empty ThreadInfo array via MBeanServer"
+        );
+        assertEmptyArray(
+            (Object[]) mbs.invoke(
+                on, "getThreadInfo", new Object[]{ids, 1},
+                new String[]{"[J", "int"}
+            ),
+            "Expected empty ThreadInfo array via MBeanServer"
+        );
+        assertEmptyArray(
+            (Object[]) mbs.invoke(
+                on, "getThreadInfo", new Object[]{ids, true, true},
+                new String[]{"[J", "boolean", "boolean"}
+            ),
+            "Expected empty ThreadInfo array via MBeanServer"
+        );
+
+        // call getThreadInfo through proxy
+        assertEmptyArray(proxy.getThreadInfo(ids), "Expected empty ThreadInfo array");
+        assertEmptyArray(proxy.getThreadInfo(ids, 1), "Expected empty ThreadInfo array");
+        assertEmptyArray(proxy.getThreadInfo(ids, true, true), "Expected empty ThreadInfo array");
+        System.out.println("--- PASSED");
+    }
+
+    private static void assertEmptyArray(Object[] arr, String message) throws Exception {
+        if (arr.length > 0) {
+            throw new RuntimeException("TEST FAILED: " + message);
+        }
     }
 }