gdb: Check for not allocated/associated values during array slicing

Message ID 20190523212308.27617-1-andrew.burgess@embecosm.com
State New, archived
Headers

Commit Message

Andrew Burgess May 23, 2019, 9:23 p.m. UTC
  When extracting an array slice we should give up if the array is
not-allocated or not-associated.  For Fortran, at least in gfortran
compiled code, the upper and lower bounds are undefined if the array
is not allocated or not associated, in which case performing checks
against these bounds will result in undefined behaviour.

Better then to throw an error if we try to slice such an array.  This
changes the error message that the user will receive in these
cases (if they got an error message before).  Previously they may have
gotten "slice out of range" now they'll get "array not allocated" or
"array not associated".

gdb/ChangeLog:

	* valops.c (value_slice): Check for not allocated or not
	associated values.

gdb/testsuite/ChangeLog:

	* gdb.fortran/vla-sizeof.exp: Update expected results.
---
 gdb/ChangeLog                            | 5 +++++
 gdb/testsuite/ChangeLog                  | 4 ++++
 gdb/testsuite/gdb.fortran/vla-sizeof.exp | 4 ++--
 gdb/valops.c                             | 5 +++++
 4 files changed, 16 insertions(+), 2 deletions(-)
  

Comments

Tom Tromey June 7, 2019, 9:23 p.m. UTC | #1
>>>>> "Andrew" == Andrew Burgess <andrew.burgess@embecosm.com> writes:

Andrew> When extracting an array slice we should give up if the array is
Andrew> not-allocated or not-associated.  For Fortran, at least in gfortran
Andrew> compiled code, the upper and lower bounds are undefined if the array
Andrew> is not allocated or not associated, in which case performing checks
Andrew> against these bounds will result in undefined behaviour.

Andrew> Better then to throw an error if we try to slice such an array.  This
Andrew> changes the error message that the user will receive in these
Andrew> cases (if they got an error message before).  Previously they may have
Andrew> gotten "slice out of range" now they'll get "array not allocated" or
Andrew> "array not associated".

I don't know Fortran, so I hesitated to comment on this patch.  But,
maybe you are waiting for some feedback?  I don't have an objection to
it, though that isn't super comforting considering that I don't know
what an associated type is.

Tom
  
Andrew Burgess June 10, 2019, 10:03 p.m. UTC | #2
* Tom Tromey <tom@tromey.com> [2019-06-07 15:23:56 -0600]:

> >>>>> "Andrew" == Andrew Burgess <andrew.burgess@embecosm.com> writes:
> 
> Andrew> When extracting an array slice we should give up if the array is
> Andrew> not-allocated or not-associated.  For Fortran, at least in gfortran
> Andrew> compiled code, the upper and lower bounds are undefined if the array
> Andrew> is not allocated or not associated, in which case performing checks
> Andrew> against these bounds will result in undefined behaviour.
> 
> Andrew> Better then to throw an error if we try to slice such an array.  This
> Andrew> changes the error message that the user will receive in these
> Andrew> cases (if they got an error message before).  Previously they may have
> Andrew> gotten "slice out of range" now they'll get "array not allocated" or
> Andrew> "array not associated".
> 
> I don't know Fortran, so I hesitated to comment on this patch.  But,
> maybe you are waiting for some feedback?  I don't have an objection to
> it, though that isn't super comforting considering that I don't know
> what an associated type is.

Pointer types are in an associated state when they are pointing at
something.  Being not associated is similar to being a nullptr.

Pointers can also be allocated, this means its had some space
dynamically allocated to it.  When a pointer is allocated it is also
associated with the space that was allocated.

Arrays declared as deferred shape (where the dimensions are given
simply as ':' rather than actual upper and lower bounds) can also be
allocated and/or associated, which is where this patch fits in.

In theory I think we could get away with only checking for associated,
as an allocated array will be associated with the space that was
allocated, however, it seemed more informative to check for the
allocated status first.

I'll go ahead and push this for now, if there's follow up feedback
then I'm happy to make adjustments later.

Thanks,
Andrew
  

Patch

diff --git a/gdb/testsuite/gdb.fortran/vla-sizeof.exp b/gdb/testsuite/gdb.fortran/vla-sizeof.exp
index b6fdaebbf51..4fe6938445c 100644
--- a/gdb/testsuite/gdb.fortran/vla-sizeof.exp
+++ b/gdb/testsuite/gdb.fortran/vla-sizeof.exp
@@ -32,7 +32,7 @@  gdb_test "print sizeof(vla1)" " = 0" "print sizeof non-allocated vla1"
 gdb_test "print sizeof(vla1(3,2,1))" \
     "no such vector element \\(vector not allocated\\)" \
     "print sizeof non-allocated indexed vla1"
-gdb_test "print sizeof(vla1(3:4,2,1))" "slice out of range" \
+gdb_test "print sizeof(vla1(3:4,2,1))" "array not allocated" \
     "print sizeof non-allocated sliced vla1"
 
 # Try to access value in allocated VLA
@@ -49,7 +49,7 @@  gdb_test "print sizeof(pvla)" " = 0" "print sizeof non-associated pvla"
 gdb_test "print sizeof(pvla(3,2,1))" \
     "no such vector element \\(vector not associated\\)" \
     "print sizeof non-associated indexed pvla"
-gdb_test "print sizeof(pvla(3:4,2,1))" "slice out of range" \
+gdb_test "print sizeof(pvla(3:4,2,1))" "array not associated" \
     "print sizeof non-associated sliced pvla"
 
 # Try to access values in pointer to VLA and compare them
diff --git a/gdb/valops.c b/gdb/valops.c
index fd92a4d1655..cbf2eccde3e 100644
--- a/gdb/valops.c
+++ b/gdb/valops.c
@@ -3801,6 +3801,11 @@  value_slice (struct value *array, int lowbound, int length)
       && TYPE_CODE (array_type) != TYPE_CODE_STRING)
     error (_("cannot take slice of non-array"));
 
+  if (type_not_allocated (array_type))
+    error (_("array not allocated"));
+  if (type_not_associated (array_type))
+    error (_("array not associated"));
+
   range_type = TYPE_INDEX_TYPE (array_type);
   if (get_discrete_bounds (range_type, &lowerbound, &upperbound) < 0)
     error (_("slice from bad array or bitstring"));