1 /*
   2  * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  */
  23 
  24 /**
  25  * @test
  26  * @bug 4446677
  27  * @bug 8158237
  28  * @summary debuggee used to crash when debugging under jbuilder
  29  * @author jjh
  30  *
  31  * @run build TestScaffold VMConnection TargetListener TargetAdapter
  32  * @run compile -g BacktraceFieldTest.java
  33  * @run driver BacktraceFieldTest
  34  */
  35 
  36 /*
  37  * The fix for this bug filters out the backtrace field from the list
  38  * of fields for java.lang.Throwable.
  39  * This test verifies that this really happens, and also verifies that the fix
  40  * doesn't incorrectly discard other fields.
  41  */
  42 
  43 import com.sun.jdi.*;
  44 import com.sun.jdi.event.*;
  45 import com.sun.jdi.request.*;
  46 
  47 import java.util.*;
  48 
  49 /********** target program **********/
  50 
  51 class Testy {
  52     /*
  53      * This is used to verify that the fix doesn't filter out fields that it
  54      * shouldn't.  7 is an abitrary number, and this isn't a definitive
  55      * test; the fix could conceivably filter out the 89th field of a class
  56      * named Foo.
  57      * To verify that this part of this test works, first uncomment the field8
  58      * line and verify that the test fails, and then rename a field to xxx and
  59      * verify that the test fails.
  60      */
  61     int field1;
  62     int field2;
  63     int field3;
  64     int field4;
  65     int field5;
  66     int field6;
  67     final static int field7 = 7;  // Value is the number of fields.
  68     //int field8;
  69 
  70     Testy() {
  71     }
  72 }
  73 
  74 
  75 class BacktraceFieldTarg {
  76     public static void gus() {
  77     }
  78 
  79     public static void main(String[] args) {
  80         Testy myTesty = new Testy();
  81         try {
  82             throw new RuntimeException("jjException");
  83         } catch (Exception ee) {
  84             gus();
  85             System.out.println("debuggee: Exception: " + ee);
  86         }
  87     }
  88 }
  89 
  90 /********** test program **********/
  91 
  92 public class BacktraceFieldTest extends TestScaffold {
  93     ThreadReference mainThread;
  94 
  95     BacktraceFieldTest (String args[]) {
  96         super(args);
  97     }
  98 
  99     public static void main(String[] args)      throws Exception {
 100         new BacktraceFieldTest(args).startTests();
 101     }
 102 
 103     private void printval(ArrayReference backTraceVal, int index) throws Exception {
 104         ArrayReference val = (ArrayReference)backTraceVal.getValue(index);
 105         println("BT: val at " + index + " = " + val);
 106 
 107         // The segv used to happen here for index = 0
 108         // Now all objects in the backtrace are objects.
 109         Object xVal = (Object)val.getValue(0);
 110         println("BT: xVal = " + xVal);
 111     }
 112 
 113     /********** test core **********/
 114 
 115     protected void runTests() throws Exception {
 116         /*
 117          * Get to the top of gus()
 118          * to determine mainThread
 119          */
 120         BreakpointEvent bpe = startTo("BacktraceFieldTarg", "gus", "()V");
 121         mainThread = bpe.thread();
 122 
 123         /*
 124          * We are now one frame below the exception frame that contains
 125          * our ee var.
 126          */
 127         StackFrame myFrame = mainThread.frame(1);
 128 
 129         LocalVariable lv = myFrame.visibleVariableByName("ee");
 130         println("BT: lv = " + lv);
 131         println("BT: lvType = " + lv.typeName());
 132 
 133         List allFields = ((ReferenceType)(lv.type())).allFields();
 134         println("BT: allFields = " + allFields);
 135 
 136         /*
 137          * Search through the fields of ee to verify that
 138          * java.lang.Throwable.backtrace isn't there.
 139          */
 140         boolean backtrace_found = false;
 141         Iterator iter = allFields.iterator();
 142         while(iter.hasNext()) {
 143             Field ff = (Field)iter.next();
 144             if (ff.toString().equals("java.lang.Throwable.backtrace")) {
 145                 backtrace_found = true;
 146                 println("java.lang.Throwable.backtrace field not filtered out.");
 147 
 148                 /*
 149                  * If you want to experience the segv this bug causes, change
 150                  * this test to 1 == 1 and run it with jdk 1.4, build 74 or earlier
 151                  */
 152                 if (1 == 1) {
 153                     // The following code will show the segv that this can cause.
 154                     ObjectReference myVal = (ObjectReference)myFrame.getValue(lv);
 155                     println("BT: myVal = " + myVal);
 156 
 157                     ArrayReference backTraceVal = (ArrayReference)myVal.getValue(ff);
 158                     println("BT: backTraceVal = " + backTraceVal);
 159 
 160                     printval(backTraceVal, 0);
 161                     printval(backTraceVal, 1);
 162                     printval(backTraceVal, 2);
 163                     printval(backTraceVal, 3);  // backtrace has 4 elements
 164 
 165                     try {
 166                         printval(backTraceVal, 4);
 167                     } catch (Exception e) {
 168                         println("Exception " + e);
 169                     }
 170                 }
 171                 break;
 172             }
 173         }
 174 
 175         if (!backtrace_found) {
 176             failure("ERROR: java.lang.Throwable.backtrace field filtered out.");
 177         }
 178 
 179         // Next, verify that we don't accidently discard a field that we shouldn't
 180 
 181         if (!testFailed) {
 182             lv = myFrame.visibleVariableByName("myTesty");
 183 
 184             allFields = ((ReferenceType)(lv.type())).allFields();
 185             println("BT: allFields = " + allFields);
 186 
 187             if (allFields.size() != Testy.field7) {
 188                 failure("ERROR: wrong number of fields; expected " + Testy.field7 + ", Got " + allFields.size());
 189             } else {
 190                 iter = allFields.iterator();
 191                 while(iter.hasNext()) {
 192                     String fieldName = ((Field)iter.next()).toString();
 193                     if (!fieldName.startsWith("Testy.field", 0)) {
 194                         failure("ERROR: Found bogus field: " + fieldName.toString());
 195                     }
 196                 }
 197             }
 198         }
 199 
 200         listenUntilVMDisconnect();
 201 
 202         /*
 203          * deal with results of test
 204          * if anything has called failure("foo") testFailed will be true
 205          */
 206         if (!testFailed) {
 207             println("BacktraceFieldTest: passed");
 208         } else {
 209             throw new Exception("BacktraceFieldTest: failed");
 210         }
 211     }
 212 }