diff mbox

[1/3] gdb: New set/show max-value-size command.

Message ID 57e2731e179d11c584e8cde994ab1e822a9893b0.1449869722.git.andrew.burgess@embecosm.com
State New
Headers show

Commit Message

Andrew Burgess Dec. 11, 2015, 9:38 p.m. UTC
For languages with dynamic types, an incorrect program could result in
an incorrect, overly large type being associated with a value.
Currently, attempting to print such a variable will result in gdb
attempting to allocate an overly large buffer.

This could result in the allocation failing, and gdb terminating, or the
buffer might be allocated, but the machine on which gdb is being run
might struggle due to the high memory requirement of gdb.

A new user visible variable in gdb helps guard against such problems,
two new commands are available:

   set max-value-size
   show max-value-size

The 'max-value-size' is the maximum size in bytes that the contents of a
value may allocate.  Any attempt to allocate a value with size greater
than this will result in an error.  The default for this variable is
currently unlimited.

Setting the default to unlimited reduces the use of this variable a
little bit, if a user hits one of these rogue types without realising
it, then gdb will still allocate the large buffer, with all the problems
that this entails.  The user will then be forced to probably restart
their gdb session, and then set the 'max-value-size' variable to guard
against future crashes.

However, it's not clear what a good default would actually be, given the
huge range of resources that are available on different machines.  One
solution might be to introduce platform specific code that attempts to
figure out what memory resources are available on the machine running
gdb, we could then set the max-value-size to some percentage of the
available memory, while still defaulting to unlimited for those machines
where we can't figure out a good alternative.  Such a feature is not
implemented in this commit, but could be added later.

gdb/ChangeLog:

	* value.c (max_value_size): New variable.
	(show_max_value_size): New function.
	(check_type_length_before_alloc): New function.
	(allocate_value_contents): Call check_type_length_before_alloc.
	(set_value_enclosing_type): Likewise.
	(_initialize_values): Add set/show handler for max-value-size.
	* NEWS: Mention new set/show command.

gdb/doc/ChangeLog:

	* gdb.texinfo (Value Sizes): New section.

gdb/testsuite/ChangeLog:

	* gdb.base/max-value-size.c: New file.
	* gdb.base/max-value-size.exp: New file.
---
 gdb/ChangeLog                             | 11 +++++
 gdb/NEWS                                  |  6 +++
 gdb/doc/ChangeLog                         |  4 ++
 gdb/doc/gdb.texinfo                       | 35 +++++++++++++++
 gdb/testsuite/ChangeLog                   |  5 +++
 gdb/testsuite/gdb.base/max-value-size.c   | 26 +++++++++++
 gdb/testsuite/gdb.base/max-value-size.exp | 68 +++++++++++++++++++++++++++++
 gdb/value.c                               | 71 +++++++++++++++++++++++++++++--
 8 files changed, 222 insertions(+), 4 deletions(-)
 create mode 100644 gdb/testsuite/gdb.base/max-value-size.c
 create mode 100644 gdb/testsuite/gdb.base/max-value-size.exp

Comments

Joel Brobecker Jan. 1, 2016, 9:43 a.m. UTC | #1
On Fri, Dec 11, 2015 at 09:38:35PM +0000, Andrew Burgess wrote:
> For languages with dynamic types, an incorrect program could result in
> an incorrect, overly large type being associated with a value.
> Currently, attempting to print such a variable will result in gdb
> attempting to allocate an overly large buffer.
> 
> This could result in the allocation failing, and gdb terminating, or the
> buffer might be allocated, but the machine on which gdb is being run
> might struggle due to the high memory requirement of gdb.
> 
> A new user visible variable in gdb helps guard against such problems,
> two new commands are available:
> 
>    set max-value-size
>    show max-value-size
> 
> The 'max-value-size' is the maximum size in bytes that the contents of a
> value may allocate.  Any attempt to allocate a value with size greater
> than this will result in an error.  The default for this variable is
> currently unlimited.
> 
> Setting the default to unlimited reduces the use of this variable a
> little bit, if a user hits one of these rogue types without realising
> it, then gdb will still allocate the large buffer, with all the problems
> that this entails.  The user will then be forced to probably restart
> their gdb session, and then set the 'max-value-size' variable to guard
> against future crashes.
> 
> However, it's not clear what a good default would actually be, given the
> huge range of resources that are available on different machines.  One
> solution might be to introduce platform specific code that attempts to
> figure out what memory resources are available on the machine running
> gdb, we could then set the max-value-size to some percentage of the
> available memory, while still defaulting to unlimited for those machines
> where we can't figure out a good alternative.  Such a feature is not
> implemented in this commit, but could be added later.

I think it is important to activate this feature by default, precisely
for the reasons you mention. It sounds like one of the reasons why
you elected not to provide a default is that you weren't sure about
what value to use as the default. But, luckily, AdaCore has been using
65536 for as long as I remember as its default varsize_limit. We have
customers of all kinds, and I don't remember anyone telling us that
the default limit is too small.

I think a default of 65536 is a good start. It's large enough that
I can't see any user wanting to display an object that large.
But it's small enough that it'll prevent GDB from unexpectedly
allocate such a chunk of memory that it'll take the user's GDB
session down.

By the way, here is the documentation we have in our manual regarding
this setting. Part of it was prompted by customer feedback. In
particular, it touches on something that made me think when
looking at this new setting: how this limit is applied can be
fairly obscure, when you think about it from the user's perspective.
For instance, when you consider the following expression...

    (gdb) print huge_array[2]

... it is likely that the expression evaluation will first create
a struct value for huge_array. Fortunately, the evalutor is smart
and creates a lazy value, meaning that the limit does not kick in.
Therefore, the limit would only apply to the element of that huge_array,
which hopefully for the user is small enough to pass that check.

| @table @code
| @kindex set varsize-limit
| @item set varsize-limit @var{size}
| Limit the size of the types of objects to @var{size} bytes
| when those sizes are computed from run-time quantities.
| When this limit is set to 0, there is no
| limit.  By default, it is about 65K.  The purpose of having such a limit is
| to prevent @value{GDBN} from trying to grab enormous chunks of virtual
| memory when asked to evaluate a quantity whose bounds have been corrupted
| or have not yet been fully initialized.
| The limit applies to the results
| of some subexpressions as well as to complete expressions.  For example, an
| expression denoting a simple integer component, such as @code{x.y.z}, may
| fail if the size of @var{x.y} is dynamic and exceeds @var{size}.
| On the other hand, @value{GDBN} is sometimes clever;
| the expression @code{A(i)}, where @var{A} is an
| array variable with non-constant size, will generally succeed regardless of the
| bounds on @var{A}, as long as the component size is less than @var{size}.

> gdb/ChangeLog:
> 
> 	* value.c (max_value_size): New variable.
> 	(show_max_value_size): New function.
> 	(check_type_length_before_alloc): New function.
> 	(allocate_value_contents): Call check_type_length_before_alloc.
> 	(set_value_enclosing_type): Likewise.
> 	(_initialize_values): Add set/show handler for max-value-size.
> 	* NEWS: Mention new set/show command.
> 
> gdb/doc/ChangeLog:
> 
> 	* gdb.texinfo (Value Sizes): New section.
> 
> gdb/testsuite/ChangeLog:
> 
> 	* gdb.base/max-value-size.c: New file.
> 	* gdb.base/max-value-size.exp: New file.

You probably already know this, but the NEWS and doco parts are
reviewed by Eli (FAOD).

> +Whenever @value{GDBN} prints a value memory will be allocated within
> +@value{GDBN} to hold the contents of the value.  It is possible in
> +some languages with dynamic typing systems, that an invalid program
> +may indicate a value that is incorrectly large, this in turn may cause
> +@value{GDBN} to try and allocate an overly large ammount of memory.

(not just an invalid program; also uninitialized variables);
you can use our documentation as inspiration, if you'd like.

> diff --git a/gdb/testsuite/gdb.base/max-value-size.c b/gdb/testsuite/gdb.base/max-value-size.c
> new file mode 100644
> index 0000000..4d47280
> --- /dev/null
> +++ b/gdb/testsuite/gdb.base/max-value-size.c
> @@ -0,0 +1,26 @@
> +/* This testcase is part of GDB, the GNU debugger.
> +
> +   Copyright 2015 Free Software Foundation, Inc.

You'll need to change the year to be 2015-2016 for all the files
your patch adds :-).  Also, while at it, I think the FSF prefers
the (C) to be there. Thus:

   Copyright (C) 2015-2016 Free Software Foundation, Inc.

> +char one;
> +char ten [10];
> +char one_hundred [100];
> +
> +int
> +main ()

[we decided that, as much as possible, example programs in the testsuite
would also follow the GDB Coding Style]

Can you change "main ()" to "main (void)"?

> +with_test_prefix "max-value-size is 'unlimited'" {
> +    gdb_test "p/d one" " = 0"
> +    gdb_test "p/d one_hundred" " = \\{0 <repeats 100 times>\\}"
> +}
> +
> +# Check that setting it low does prevent values being allocated.
> +gdb_test_no_output "set max-value-size 25"
> +with_test_prefix "max-value-size is '25'" {
> +    gdb_test "p/d one" " = 0"
> +    gdb_test "p/d one_hundred" "value contents too large \\(100 bytes\\)"

> +# Check we can set it to something "large", and then view our values.
> +gdb_test_no_output "set max-value-size 200"
> +gdb_test "show max-value-size" \
> +    "Maximum value size is 200 bytes." \
> +    "check that the value shows as 200 bytes"
> +with_test_prefix "max-value-size is '200'" {
> +    gdb_test "p/d one" " = 0"
> +    gdb_test "p/d one_hundred" " = \\{0 <repeats 100 times>\\}"
> +}
> +
> +# Check we can restore it too unlimited.
> +gdb_test_no_output "set max-value-size unlimited"
> +gdb_test "show max-value-size" \
> +    "Maximum value size is unlimited." \
> +    "check that the unlimited maximum restored correctly"
> +with_test_prefix "max-value-size is 'unlimited' again" {
> +    gdb_test "p/d one" " = 0"
> +    gdb_test "p/d one_hundred" " = \\{0 <repeats 100 times>\\}"
> +}
In all "with_test_prefix" cases, I would add a test to print
one element of one_hundred. This is particularly interesting
in the second situation, where although we can't print one_hundred
in its entirety, we can still print one element. This will help
catch situations where an array value is unexpectedly fetched.

> diff --git a/gdb/value.c b/gdb/value.c
> index 91bf49e..9554333 100644
> --- a/gdb/value.c
> +++ b/gdb/value.c
> @@ -955,13 +955,60 @@ allocate_value_lazy (struct type *type)
>    return val;
>  }
>  
> +/* The maximum size, in bytes, that the contents of a value might have.
> +   Setting this to -1 indicates unlimited.  Adjust this variable does not
> +   invalidate already allocated values, only prevents future large values
> +   being allocated.  */
> +
> +static int max_value_size = -1;

What I would do, to document this static global, is just reference
the user-visible setting.  That way, you do not have to repeat
the user documentation.

Please add an empty line after this variable, to separate it from
the rest of the code.

> +static void
> +set_max_value_size (char *args, int from_tty,
> +		    struct cmd_list_element *c)

Every new function should be documented individually. In this case,
it's implementing the "set max-value-size" command, so it's sufficient
to just say that in the function's intro comment. Eg:

/* Implement the "set max-value-size" command.  */

> +{
> +  if (max_value_size > -1 && max_value_size < sizeof (LONGEST))
> +    {
> +      max_value_size = sizeof (LONGEST);
> +      error (_("max-value-size set too low, increasing to %u bytes"),
> +	     ((unsigned int) max_value_size));
> +    }

sizeof (LONGEST) depends on the host, so it opens the door for
GDB behaving differently depending on the host it runs on, which
can be surprising.

I suggest either: remove the minimum limit entirely, or just choose
an arbitrary one (Eg: 8).

Also, why are you printing max_value_size as an unsigned int, rather
than an int in the error message? This forces us to add a cast, and
its purpose is unclear to me.

> +static void
> +show_max_value_size (struct ui_file *file, int from_tty,
> +		     struct cmd_list_element *c, const char *value)

Same as above; a trivial function intro is suffficient.

> +/* Called before we attempt to allocate or reallocate a buffer for the
> +   contents of a value.  TYPE is the type of the value for which we are
> +   allocating the buffer.  If the buffer is too large (based on the user
> +   controllable setting) then throw an error.  If this function returns
> +   then we should attempt to allocate the buffer.  */
> +
> +static void
> +check_type_length_before_alloc (const struct type *type)
> +{
> +  int length = TYPE_LENGTH (type);
> +  if (max_value_size > -1 && (length < 0 || length > max_value_size))
> +    error (_("value contents too large (%u bytes)"),
> +	   ((unsigned int) length));
> +}

Small style issue - the GDB coding style requires that we have
an empty line after local variable declarations. So can you add
an empty line after "int length = ....", please?

More importantly, why is length an int when TYPE_LENGTH (type)
is an unsigned int? Similarly to be fore, it then opens the door
for having to check for length being negative which does not make
sense, and it also then forces a cast when using it to print
the type's length.

In terms of the function's behavior, I would add a couple of things
to the error message:
  1. Tell the user that he can increase the maximum using
     the "set max-value-size SIZE" command;
  2. print the type's name, if avaiable, in the error message,
     for easier tracking of the issue.

>  /* Allocate the contents of VAL if it has not been allocated yet.  */
>  
>  static void
>  allocate_value_contents (struct value *val)
>  {
>    if (!val->contents)
> -    val->contents = (gdb_byte *) xzalloc (TYPE_LENGTH (val->enclosing_type));
> +    {
> +      check_type_length_before_alloc (val->enclosing_type);
> +      val->contents =
> +	(gdb_byte *) xzalloc (TYPE_LENGTH (val->enclosing_type));

smll formatting nit, binary operators should be at the start of
the next line, rather than the end of the previous one. For the
assignement, this gives us:

      val->contents
        = (gdb_byte *) xzalloc (TYPE_LENGTH (val->enclosing_type));

>  void
>  set_value_enclosing_type (struct value *val, struct type *new_encl_type)
>  {
> -  if (TYPE_LENGTH (new_encl_type) > TYPE_LENGTH (value_enclosing_type (val))) 
> -    val->contents =
> -      (gdb_byte *) xrealloc (val->contents, TYPE_LENGTH (new_encl_type));
> +  if (TYPE_LENGTH (new_encl_type) > TYPE_LENGTH (value_enclosing_type (val)))
> +    {
> +      check_type_length_before_alloc (new_encl_type);
> +      val->contents =
> +	(gdb_byte *) xrealloc (val->contents, TYPE_LENGTH (new_encl_type));

Same here.
diff mbox

Patch

diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 03ae010..8e36907 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,3 +1,14 @@ 
+2015-12-11  Andrew Burgess  <andrew.burgess@embecosm.com>
+
+	* value.c (max_value_size): New variable.
+	(set_max_value_size): New function.
+	(show_max_value_size): New function.
+	(check_type_length_before_alloc): New function.
+	(allocate_value_contents): Call check_type_length_before_alloc.
+	(set_value_enclosing_type): Likewise.
+	(_initialize_values): Add set/show handler for max-value-size.
+	* NEWS: Mention new set/show command.
+
 2015-12-10  Antoine Tremblay  <antoine.tremblay@ericsson.com>
 
 	* linux-thread-db.c (find_new_threads_callback): Use record_thread.
diff --git a/gdb/NEWS b/gdb/NEWS
index 9ca7f49..2fb264a 100644
--- a/gdb/NEWS
+++ b/gdb/NEWS
@@ -60,6 +60,12 @@  show ada print-signatures"
   Control whether parameter types and return types are displayed in overloads
   selection menus.  It is activaled (@code{on}) by default.
 
+set max-value-size
+show max-value-size
+  Control the maximum size, in bytes, that GDB will allocate for value
+  contents.  Prevent incorrect programs from causing GDB to allocate
+  overly large buffers.  Default is unlimited.
+
 * The "disassemble" command accepts a new modifier: /s.
   It prints mixed source+disassembly like /m with two differences:
   - disassembled instructions are now printed in program order, and
diff --git a/gdb/doc/ChangeLog b/gdb/doc/ChangeLog
index fc81d09..796e2cd 100644
--- a/gdb/doc/ChangeLog
+++ b/gdb/doc/ChangeLog
@@ -1,3 +1,7 @@ 
+2015-12-11  Andrew Burgess  <andrew.burgess@embecosm.com>
+
+	* gdb.texinfo (Value Sizes): New section.
+
 2015-12-10  Pedro Alves  <palves@redhat.com>
 
 	* gdb.texinfo (Threads): Replace warning with explanation
diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index bb68e21..5d8b579 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -11592,6 +11592,41 @@  $1 = 1
 $2 = (void *) 0x8049560
 @end smallexample
 
+@node Value Sizes
+@section Value Sizes
+
+Whenever @value{GDBN} prints a value memory will be allocated within
+@value{GDBN} to hold the contents of the value.  It is possible in
+some languages with dynamic typing systems, that an invalid program
+may indicate a value that is incorrectly large, this in turn may cause
+@value{GDBN} to try and allocate an overly large ammount of memory.
+
+@table @code
+@kindex set max-value-size
+@itemx set max-value-size @var{bytes}
+@itemx set max-value-size unlimited
+Set the maximum size, in bytes, that @value{GDBN} will allocate for
+the contents of a value to @var{bytes}.  Any value whose contents
+require more than this number of bytes can't be displayed by
+@value{GDBN}, and trying to display the value will result in an error.
+
+Setting this variable does not effect values that have already been
+allocated within gdb, only future allocations.
+
+By default this variable is set to @var{unlimited}, meaning
+@value{GDBN} will always attempt to allocate space for the values
+contents.
+
+There's a minimum size that @code{max-value-size} can be set too in
+order that @value{GDBN} can still operate correctly.  This varies by
+target, but will generally be around 8 bytes.
+
+@kindex show max-value-size
+@item show max-value-size
+Show the maximum size, in bytes, that @value{GDBN} will allocate for
+the contents of a value.
+@end table
+
 @node Optimized Code
 @chapter Debugging Optimized Code
 @cindex optimized code, debugging
diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog
index ab7a324..93bb3bb 100644
--- a/gdb/testsuite/ChangeLog
+++ b/gdb/testsuite/ChangeLog
@@ -1,3 +1,8 @@ 
+2015-12-11  Andrew Burgess  <andrew.burgess@embecosm.com>
+
+	* gdb.base/max-value-size.c: New file.
+	* gdb.base/max-value-size.exp: New file.
+
 2015-12-10  Pedro Alves  <palves@redhat.com>
 
 	* gdb.multi/base.exp: Remove stale "spaces" references.
diff --git a/gdb/testsuite/gdb.base/max-value-size.c b/gdb/testsuite/gdb.base/max-value-size.c
new file mode 100644
index 0000000..4d47280
--- /dev/null
+++ b/gdb/testsuite/gdb.base/max-value-size.c
@@ -0,0 +1,26 @@ 
+/* This testcase is part of GDB, the GNU debugger.
+
+   Copyright 2015 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+char one;
+char ten [10];
+char one_hundred [100];
+
+int
+main ()
+{
+  return 0;
+}
diff --git a/gdb/testsuite/gdb.base/max-value-size.exp b/gdb/testsuite/gdb.base/max-value-size.exp
new file mode 100644
index 0000000..cb09ad8
--- /dev/null
+++ b/gdb/testsuite/gdb.base/max-value-size.exp
@@ -0,0 +1,68 @@ 
+# Copyright 2015 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+standard_testfile
+
+if {[prepare_for_testing $testfile.exp $testfile $srcfile debug]} {
+    untested $testfile.exp
+    return -1
+}
+
+if ![runto_main] then {
+    fail "Can't run to main"
+    return 0
+}
+
+gdb_test "show max-value-size" \
+    "Maximum value size is unlimited." \
+    "the initial value of max-value-size is unlimited"
+
+with_test_prefix "max-value-size is 'unlimited'" {
+    gdb_test "p/d one" " = 0"
+    gdb_test "p/d one_hundred" " = \\{0 <repeats 100 times>\\}"
+}
+
+# Check that setting it low does prevent values being allocated.
+gdb_test_no_output "set max-value-size 25"
+with_test_prefix "max-value-size is '25'" {
+    gdb_test "p/d one" " = 0"
+    gdb_test "p/d one_hundred" "value contents too large \\(100 bytes\\)"
+}
+
+# Check that we can't set the maximum size stupidly low.
+gdb_test "set max-value-size 1" \
+    "max-value-size set too low, increasing to \[0-9\]+ bytes"
+gdb_test "set max-value-size 0" \
+    "max-value-size set too low, increasing to \[0-9\]+ bytes"
+
+# Check we can set it to something "large", and then view our values.
+gdb_test_no_output "set max-value-size 200"
+gdb_test "show max-value-size" \
+    "Maximum value size is 200 bytes." \
+    "check that the value shows as 200 bytes"
+with_test_prefix "max-value-size is '200'" {
+    gdb_test "p/d one" " = 0"
+    gdb_test "p/d one_hundred" " = \\{0 <repeats 100 times>\\}"
+}
+
+# Check we can restore it too unlimited.
+gdb_test_no_output "set max-value-size unlimited"
+gdb_test "show max-value-size" \
+    "Maximum value size is unlimited." \
+    "check that the unlimited maximum restored correctly"
+with_test_prefix "max-value-size is 'unlimited' again" {
+    gdb_test "p/d one" " = 0"
+    gdb_test "p/d one_hundred" " = \\{0 <repeats 100 times>\\}"
+}
diff --git a/gdb/value.c b/gdb/value.c
index 91bf49e..9554333 100644
--- a/gdb/value.c
+++ b/gdb/value.c
@@ -955,13 +955,60 @@  allocate_value_lazy (struct type *type)
   return val;
 }
 
+/* The maximum size, in bytes, that the contents of a value might have.
+   Setting this to -1 indicates unlimited.  Adjust this variable does not
+   invalidate already allocated values, only prevents future large values
+   being allocated.  */
+
+static int max_value_size = -1;
+static void
+set_max_value_size (char *args, int from_tty,
+		    struct cmd_list_element *c)
+{
+  if (max_value_size > -1 && max_value_size < sizeof (LONGEST))
+    {
+      max_value_size = sizeof (LONGEST);
+      error (_("max-value-size set too low, increasing to %u bytes"),
+	     ((unsigned int) max_value_size));
+    }
+}
+static void
+show_max_value_size (struct ui_file *file, int from_tty,
+		     struct cmd_list_element *c, const char *value)
+{
+  if (max_value_size == -1)
+    fprintf_filtered (file, _("Maximum value size is unlimited.\n"));
+  else
+    fprintf_filtered (file, _("Maximum value size is %d bytes.\n"),
+		      max_value_size);
+}
+
+/* Called before we attempt to allocate or reallocate a buffer for the
+   contents of a value.  TYPE is the type of the value for which we are
+   allocating the buffer.  If the buffer is too large (based on the user
+   controllable setting) then throw an error.  If this function returns
+   then we should attempt to allocate the buffer.  */
+
+static void
+check_type_length_before_alloc (const struct type *type)
+{
+  int length = TYPE_LENGTH (type);
+  if (max_value_size > -1 && (length < 0 || length > max_value_size))
+    error (_("value contents too large (%u bytes)"),
+	   ((unsigned int) length));
+}
+
 /* Allocate the contents of VAL if it has not been allocated yet.  */
 
 static void
 allocate_value_contents (struct value *val)
 {
   if (!val->contents)
-    val->contents = (gdb_byte *) xzalloc (TYPE_LENGTH (val->enclosing_type));
+    {
+      check_type_length_before_alloc (val->enclosing_type);
+      val->contents =
+	(gdb_byte *) xzalloc (TYPE_LENGTH (val->enclosing_type));
+    }
 }
 
 /* Allocate a  value  and its contents for type TYPE.  */
@@ -2986,9 +3033,12 @@  value_static_field (struct type *type, int fieldno)
 void
 set_value_enclosing_type (struct value *val, struct type *new_encl_type)
 {
-  if (TYPE_LENGTH (new_encl_type) > TYPE_LENGTH (value_enclosing_type (val))) 
-    val->contents =
-      (gdb_byte *) xrealloc (val->contents, TYPE_LENGTH (new_encl_type));
+  if (TYPE_LENGTH (new_encl_type) > TYPE_LENGTH (value_enclosing_type (val)))
+    {
+      check_type_length_before_alloc (new_encl_type);
+      val->contents =
+	(gdb_byte *) xrealloc (val->contents, TYPE_LENGTH (new_encl_type));
+    }
 
   val->enclosing_type = new_encl_type;
 }
@@ -4013,4 +4063,17 @@  Check whether an expression is void.\n\
 Usage: $_isvoid (expression)\n\
 Return 1 if the expression is void, zero otherwise."),
 			 isvoid_internal_fn, NULL);
+
+  add_setshow_zuinteger_unlimited_cmd ("max-value-size",
+				       class_support, &max_value_size, _("\
+Set maximum sized value gdb will load from the inferior."), _("\
+Show maximum sized value gdb will load from the inferior."), _("\
+Use this to control the maximum size, in bytes, of a value that gdb\n\
+will load from the inferior.  Setting this value to 'unlimited'\n\
+disables checking.\n\
+Setting this does not invalidate already allocated values, it only\n\
+prevents future values, larger than this size, from being allocated."),
+			    set_max_value_size,
+			    show_max_value_size,
+			    &setlist, &showlist);
 }