From patchwork Fri Oct 9 21:42:00 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Joel Brobecker X-Patchwork-Id: 9030 Received: (qmail 20685 invoked by alias); 9 Oct 2015 21:42:20 -0000 Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org Delivered-To: mailing list gdb-patches@sourceware.org Received: (qmail 20561 invoked by uid 89); 9 Oct 2015 21:42:20 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-2.1 required=5.0 tests=AWL, BAYES_00, RCVD_IN_DNSWL_LOW, SPF_PASS, T_RP_MATCHES_RCVD autolearn=ham version=3.3.2 X-HELO: rock.gnat.com Received: from rock.gnat.com (HELO rock.gnat.com) (205.232.38.15) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with (AES256-SHA encrypted) ESMTPS; Fri, 09 Oct 2015 21:42:15 +0000 Received: from localhost (localhost.localdomain [127.0.0.1]) by filtered-rock.gnat.com (Postfix) with ESMTP id 847932912D for ; Fri, 9 Oct 2015 17:42:13 -0400 (EDT) Received: from rock.gnat.com ([127.0.0.1]) by localhost (rock.gnat.com [127.0.0.1]) (amavisd-new, port 10024) with LMTP id 08ZizO9m4H1j for ; Fri, 9 Oct 2015 17:42:13 -0400 (EDT) Received: from joel.gnat.com (localhost.localdomain [127.0.0.1]) by rock.gnat.com (Postfix) with ESMTP id 5343E29080 for ; Fri, 9 Oct 2015 17:42:13 -0400 (EDT) Received: by joel.gnat.com (Postfix, from userid 1000) id E92D742BBA; Fri, 9 Oct 2015 14:42:11 -0700 (PDT) From: Joel Brobecker To: gdb-patches@sourceware.org Subject: [PATCH 7/8] [Ada] Buffer overflow in ada_unpack_from_contents Date: Fri, 9 Oct 2015 14:42:00 -0700 Message-Id: <1444426921-19985-8-git-send-email-brobecker@adacore.com> In-Reply-To: <1444426921-19985-1-git-send-email-brobecker@adacore.com> References: <1444426921-19985-1-git-send-email-brobecker@adacore.com> This patch fixes a buffer overflow in ada_unpack_from_contents caused by one of the previous commits. This happens when trying to print the value of an array of variant records. The overflow happens while trying to print one element of the array. Because the size of each element in the array is variable, the array has a DWARF byte_stride attribute, which makes us treat the array as if it was packed. And during the extraction of each array element, we try to unpack an object using the array's byte stride as the size, into an element whose size is actually less than the stride. This patch fixes the issue by overriding the byte-stride with the actual element's length. gdb/ChangeLog: * ada-lang.c (ada_value_primitive_packed_val): Move src_len variable to local block where used. Override BIT_SIZE if bigger than size of resolved type. --- gdb/ChangeLog | 6 ++++++ gdb/ada-lang.c | 14 +++++++++++++- 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 9787afe..45e04ae 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,5 +1,11 @@ 2015-10-09 Joel Brobecker + * ada-lang.c (ada_value_primitive_packed_val): Move + src_len variable to local block where used. Override + BIT_SIZE if bigger than size of resolved type. + +2015-10-09 Joel Brobecker + * gdbtypes.h (is_scalar_type): Add extern declaration. * gdbtypes.c (is_scalar_type): Make non-static. * ada-lang.c (ada_value_primitive_packed_val): Use is_scalar_type diff --git a/gdb/ada-lang.c b/gdb/ada-lang.c index d9bbed9..b7440e2 100644 --- a/gdb/ada-lang.c +++ b/gdb/ada-lang.c @@ -2517,7 +2517,6 @@ ada_value_primitive_packed_val (struct value *obj, const gdb_byte *valaddr, { struct value *v; gdb_byte *src; /* First byte containing data to unpack */ - int src_len = (bit_size + bit_offset + HOST_CHAR_BIT - 1) / 8; gdb_byte *unpacked; const int is_scalar = is_scalar_type (type); const int is_big_endian = gdbarch_bits_big_endian (get_type_arch (type)); @@ -2550,6 +2549,17 @@ ada_value_primitive_packed_val (struct value *obj, const gdb_byte *valaddr, is_big_endian, has_negatives (type), is_scalar); type = resolve_dynamic_type (type, staging, 0); + if (TYPE_LENGTH (type) < (bit_size + HOST_CHAR_BIT - 1) / HOST_CHAR_BIT) + { + /* This happens when the length of the object is dynamic, + and is actually smaller than the space reserved for it. + For instance, in an array of variant records, the bit_size + we're given is the array stride, which is constant and + normally equal to the maximum size of its element. + But, in reality, each element only actually spans a portion + of that stride. */ + bit_size = TYPE_LENGTH (type) * HOST_CHAR_BIT; + } } if (obj == NULL) @@ -2559,6 +2569,8 @@ ada_value_primitive_packed_val (struct value *obj, const gdb_byte *valaddr, } else if (VALUE_LVAL (obj) == lval_memory && value_lazy (obj)) { + int src_len = (bit_size + bit_offset + HOST_CHAR_BIT - 1) / 8; + v = value_at (type, value_address (obj) + offset); src = alloca (src_len); read_memory (value_address (v), src, src_len);