From patchwork Thu Mar 9 19:28:18 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Malcolm X-Patchwork-Id: 737109 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 3vfKS131NRz9s8B for ; Fri, 10 Mar 2017 05:58:56 +1100 (AEDT) Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.b="yyW0IO8v"; dkim-atps=neutral DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:from :to:cc:subject:date:message-id; q=dns; s=default; b=AjbebjEhWi7U SRUbFnfVi0pIC8shyXk55YMxiBX4DELLqfa3emO3ZXeA1amE2YSEBodyLUedwnnT /M1ZepaaBLfL8P7tcmUiG/CFZ2azKMTkVF6j0sCqD7EryJmn+X5dU3kiv7/TTwvH okpZndu4t9q6rEK3r+2gDFo0ymNL/no= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:from :to:cc:subject:date:message-id; s=default; bh=P+u4hy4a5I7K1pxFOv XU/PM4tLI=; b=yyW0IO8vw2Ni2XN5NZL0MuBNbZt1wV4TsNhr3UzoYAnQO4je0e QLor/5WKLPCTu5f4rhjgCB+bu/1jIU50ztMOrV+3Vl1jsTvO/usN0EgeadsR5nE6 clIFb9g2S4qALV7phvggZzKa6J4S0efiHy2H1No1CSn0Lq852MgyASA/4= Received: (qmail 718 invoked by alias); 9 Mar 2017 18:58:43 -0000 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org Received: (qmail 650 invoked by uid 89); 9 Mar 2017 18:58:42 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-26.8 required=5.0 tests=BAYES_00, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, KAM_STOCKGEN, RP_MATCHES_RCVD, SPF_HELO_PASS autolearn=ham version=3.3.2 spammy= X-HELO: mx1.redhat.com Received: from mx1.redhat.com (HELO mx1.redhat.com) (209.132.183.28) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Thu, 09 Mar 2017 18:58:40 +0000 Received: from int-mx10.intmail.prod.int.phx2.redhat.com (int-mx10.intmail.prod.int.phx2.redhat.com [10.5.11.23]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id DDC7E4E359 for ; Thu, 9 Mar 2017 18:58:40 +0000 (UTC) Received: from c64.redhat.com (vpn-235-93.phx2.redhat.com [10.3.235.93]) by int-mx10.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id v29IweoM016530; Thu, 9 Mar 2017 13:58:40 -0500 From: David Malcolm To: gcc-patches@gcc.gnu.org Cc: David Malcolm Subject: [PATCH] Fix out-of-bounds write in RTL function reader (PR bootstrap/79952) Date: Thu, 9 Mar 2017 14:28:18 -0500 Message-Id: <1489087698-34807-1-git-send-email-dmalcolm@redhat.com> X-IsSubscribed: yes PR bootstrap/79952 identifies a crash that can occur when running -fself-test. The root cause is an out-of-bounds memory write in the RTL dump reader when handling SYMBOL_REFs with SYMBOL_FLAG_HAS_BLOCK_INFO set. Such SYMBOL_REFs are normally created by varasm.c:create_block_symbol, which has: /* Create the extended SYMBOL_REF. */ size = RTX_HDR_SIZE + sizeof (struct block_symbol); A normal SYMBOL_REF has the RTX_HDR_SIZE plus two rtunion on an x86_64 host this is: 8 + (2 * 8) = 24 bytes, whereas a SYMBOL_REF with SYMBOL_REF_HAS_BLOCK_INFO_P () has RTX_HDR_SIZE + sizeof (struct block_symbol); on an x86_64 host this is: 8 + 32 = 40 bytes So the reader allocates a 24-byte symbol_ref, whereas this line in function_reader::extra_parsing_for_operand_code_0: 1142 SYMBOL_REF_BLOCK (x) = NULL; implicitly assumes we have a 40-byte allocation, and writes zeros to whatever is in memory after the 24-byte allocation, and chaos ensues. The fix is to reallocate the SYMBOL_REF after parsing the flags if the pertinent flag is set. Successfully bootstrapped®rtested on x86_64-pc-linux-gnu. OK for trunk in stage 4? gcc/ChangeLog: PR bootstrap/79952 * read-rtl-function.c (function_reader::read_rtx_operand): Update x with result of extra_parsing_for_operand_code_0. (function_reader::extra_parsing_for_operand_code_0): Convert return type from void to rtx, returning x. When reading SYMBOL_REF with SYMBOL_FLAG_HAS_BLOCK_INFO, reallocate x to the larger size containing struct block_symbol. --- gcc/read-rtl-function.c | 32 ++++++++++++++++++++++++++------ 1 file changed, 26 insertions(+), 6 deletions(-) diff --git a/gcc/read-rtl-function.c b/gcc/read-rtl-function.c index 8552cd2..c5027971 100644 --- a/gcc/read-rtl-function.c +++ b/gcc/read-rtl-function.c @@ -103,7 +103,7 @@ class function_reader : public rtx_reader void read_rtx_operand_u (rtx x, int idx); void read_rtx_operand_i_or_n (rtx x, int idx, char format_char); rtx read_rtx_operand_r (rtx x); - void extra_parsing_for_operand_code_0 (rtx x, int idx); + rtx extra_parsing_for_operand_code_0 (rtx x, int idx); void add_fixup_insn_uid (file_location loc, rtx insn, int operand_idx, int insn_uid); @@ -923,7 +923,7 @@ function_reader::read_rtx_operand (rtx x, int idx) switch (format_char) { case '0': - extra_parsing_for_operand_code_0 (x, idx); + x = extra_parsing_for_operand_code_0 (x, idx); break; case 'w': @@ -1116,9 +1116,10 @@ function_reader::read_rtx_operand_r (rtx x) } /* Additional parsing for format code '0' in dumps, handling a variety - of special-cases in print_rtx, when parsing operand IDX of X. */ + of special-cases in print_rtx, when parsing operand IDX of X. + Return X, or possibly a reallocated copy of X. */ -void +rtx function_reader::extra_parsing_for_operand_code_0 (rtx x, int idx) { RTX_CODE code = GET_CODE (x); @@ -1137,9 +1138,26 @@ function_reader::extra_parsing_for_operand_code_0 (rtx x, int idx) read_name (&name); SYMBOL_REF_FLAGS (x) = strtol (name.string, NULL, 16); - /* We can't reconstruct SYMBOL_REF_BLOCK; set it to NULL. */ + /* The standard RTX_CODE_SIZE (SYMBOL_REF) used when allocating + x doesn't have space for the block_symbol information, so + we must reallocate it if this flag is set. */ if (SYMBOL_REF_HAS_BLOCK_INFO_P (x)) - SYMBOL_REF_BLOCK (x) = NULL; + { + /* Emulate the allocation normally done by + varasm.c:create_block_symbol. */ + unsigned int size = RTX_HDR_SIZE + sizeof (struct block_symbol); + rtx new_x = (rtx) ggc_internal_alloc (size); + + /* Copy data over from the smaller SYMBOL_REF. */ + memcpy (new_x, x, RTX_CODE_SIZE (SYMBOL_REF)); + x = new_x; + + /* We can't reconstruct SYMBOL_REF_BLOCK; set it to NULL. */ + SYMBOL_REF_BLOCK (x) = NULL; + + /* Zero the offset. */ + SYMBOL_REF_BLOCK_OFFSET (x) = 0; + } require_char (']'); } @@ -1185,6 +1203,8 @@ function_reader::extra_parsing_for_operand_code_0 (rtx x, int idx) else unread_char (c); } + + return x; } /* Implementation of rtx_reader::handle_any_trailing_information.