[gdb/ada] Handle shrink resize in replace_operator_with_call
authorTom de Vries <tdevries@suse.de>
Mon, 7 Dec 2020 08:07:32 +0000 (09:07 +0100)
committerTom de Vries <tdevries@suse.de>
Mon, 7 Dec 2020 08:07:32 +0000 (09:07 +0100)
In replace_operator_with_call, we resize the elts array like this:
...
  exp->nelts = exp->nelts + 7 - oplen;
  exp->resize (exp->nelts);
...

Although all the current callers ensure that the new size is bigger, it could
also be smaller, in which case the following memmove possibly reads out of
bounds:
...
   memmove (exp->elts + pc + 7, exp->elts + pc + oplen,
           EXP_ELEM_TO_BYTES (save_nelts - pc - oplen));
...

Fix this by doing the resize after the memmove in case the new size is
smaller.

Tested on x86_64-linux.

gdb/ChangeLog:

2020-12-07  Tom de Vries  <tdevries@suse.de>

* ada-lang.c (replace_operator_with_call): Handle shrink resize.

gdb/ChangeLog
gdb/ada-lang.c

index 3c21cff271f62e74edafcc5cf6b9f9290271a7e8..8b94c029cf8bcdbbc9cad1d79dcbb3c5247454cb 100644 (file)
@@ -1,3 +1,7 @@
+2020-12-07  Tom de Vries  <tdevries@suse.de>
+
+       * ada-lang.c (replace_operator_with_call): Handle shrink resize.
+
 2020-12-06  Tom Tromey  <tom@tromey.com>
 
        PR ada/26999
index 7d062294aa5b7c7fbb3ad78049d475a92bbe98dc..8a1d9df5411fe5be54876f7016aabd108472ebc6 100644 (file)
@@ -4005,11 +4005,15 @@ replace_operator_with_call (expression_up *expp, int pc, int nargs,
      expression.  */
   struct expression *exp = expp->get ();
   int save_nelts = exp->nelts;
-  exp->nelts = exp->nelts + 7 - oplen;
-  exp->resize (exp->nelts);
+  int extra_elts = 7 - oplen;
+  exp->nelts += extra_elts;
 
+  if (extra_elts > 0)
+    exp->resize (exp->nelts);
   memmove (exp->elts + pc + 7, exp->elts + pc + oplen,
           EXP_ELEM_TO_BYTES (save_nelts - pc - oplen));
+  if (extra_elts < 0)
+    exp->resize (exp->nelts);
 
   exp->elts[pc].opcode = exp->elts[pc + 2].opcode = OP_FUNCALL;
   exp->elts[pc + 1].longconst = (LONGEST) nargs;