Avoid crash on single-field union in Rust
authorTom Tromey <tom@tromey.com>
Thu, 3 Oct 2019 23:21:52 +0000 (17:21 -0600)
committerTom Tromey <tom@tromey.com>
Fri, 4 Oct 2019 02:56:22 +0000 (20:56 -0600)
PR rust/24976 points out a crash in gdb when a single-field union is
used in Rust.

The immediate problem was a NULL pointer dereference in
quirk_rust_enum.  However, that code is also erroneously treating a
single-field union as if it were a univariant enum.  Looking at the
output of an older Rust compiler, it turns out that univariant enums
are distinguished by having a single *anonymous* field.  This patch
changes quirk_rust_enum to limit its fixup to this case.

Tested with a new-enough version of the Rust compiler to cause the
crash; plus by using an older executable that uses the old univariant
encoding.

gdb/ChangeLog
2019-10-03  Tom Tromey  <tom@tromey.com>

PR rust/24976:
* dwarf2read.c (quirk_rust_enum): Handle single-element unions.

gdb/testsuite/ChangeLog
2019-10-03  Tom Tromey  <tom@tromey.com>

PR rust/24976:
* gdb.rust/simple.rs (Union2): New type.
(main): Use Union2.
* gdb.rust/simple.exp: Add test.

gdb/ChangeLog
gdb/dwarf2read.c
gdb/testsuite/ChangeLog
gdb/testsuite/gdb.rust/simple.exp
gdb/testsuite/gdb.rust/simple.rs

index 446c45501dcd778d8aeaba446cfe1ac01aa352ae..4eeed4931e7ce554ec5f1d0f77337c3ed0e88ddb 100644 (file)
@@ -1,3 +1,8 @@
+2019-10-03  Tom Tromey  <tom@tromey.com>
+
+       PR rust/24976:
+       * dwarf2read.c (quirk_rust_enum): Handle single-element unions.
+
 2019-10-03  Andrew Burgess  <andrew.burgess@embecosm.com>
 
        * f-lang.c (f_language_defn): Use cp_get_symbol_name_matcher and
index c0dd199a79792b342211cf43e6a5f07542d21841..ee9df34ed27ca30a6354ba7b92754db50ad33fa9 100644 (file)
@@ -10076,10 +10076,10 @@ quirk_rust_enum (struct type *type, struct objfile *objfile)
       SET_FIELD_BITPOS (TYPE_FIELD (type, 0), 0);
       TYPE_FIELD_NAME (type, 0) = "<<variants>>";
     }
-  else if (TYPE_NFIELDS (type) == 1)
+  /* A union with a single anonymous field is probably an old-style
+     univariant enum.  */
+  else if (TYPE_NFIELDS (type) == 1 && streq (TYPE_FIELD_NAME (type, 0), ""))
     {
-      /* We assume that a union with a single field is a univariant
-        enum.  */
       /* Smash this type to be a structure type.  We have to do this
         because the type has already been recorded.  */
       TYPE_CODE (type) = TYPE_CODE_STRUCT;
index fd7614403c23f584fccc8b2ffb9e1e7bdb1ab1ad..f42a0a3c83c689c9b0bb3c606cb1158a829bd65c 100644 (file)
@@ -1,3 +1,10 @@
+2019-10-03  Tom Tromey  <tom@tromey.com>
+
+       PR rust/24976:
+       * gdb.rust/simple.rs (Union2): New type.
+       (main): Use Union2.
+       * gdb.rust/simple.exp: Add test.
+
 2019-10-03  Andrew Burgess  <andrew.burgess@embecosm.com>
 
        * gdb.fortran/nested-funcs-2.exp: Run tests with and without the
index 7211bd29be2548ed31e2822885129cdd5ac8b04e..dcbfb90920fbe898e47243c94f0133dae3144e57 100644 (file)
@@ -309,6 +309,8 @@ gdb_test_sequence "ptype/o SimpleLayout" "" {
     "                         }"
 }
 
+gdb_test "print u2" " = simple::Union2 {name: \\\[1\\\]}"
+
 # PR rust/23626 - this used to crash.  Note that the results are
 # fairly lax because most existing versions of Rust (those before the
 # DW_TAG_variant patches) do not emit what gdb wants here; and there
index e6e0efd3b16b9e3fd24eeb905a5c74bd50b450cc..65b57f42df6a7cc38c597875b63cd854dd4193a9 100644 (file)
@@ -85,6 +85,10 @@ union Union {
     f2: u8,
 }
 
+pub union Union2 {
+    pub name: [u8; 1],
+}
+
 struct StringAtOffset {
     pub field1: &'static str,
     pub field2: i32,
@@ -180,6 +184,8 @@ fn main () {
 
     let empty_enum_value: EmptyEnum;
 
+    let u2 = Union2 { name: [1] };
+
     println!("{}, {}", x.0, x.1);        // set breakpoint here
     println!("{}", diff2(92, 45));
     empty();