From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail-pf1-x42a.google.com (mail-pf1-x42a.google.com [IPv6:2607:f8b0:4864:20::42a]) by sourceware.org (Postfix) with ESMTPS id EEFF63857C6F for ; Sat, 10 Jul 2021 04:02:53 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org EEFF63857C6F Received: by mail-pf1-x42a.google.com with SMTP id q10so10559069pfj.12 for ; Fri, 09 Jul 2021 21:02:53 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:from:to:subject:message-id:mime-version :content-disposition; bh=V0Sckx07TTv24ttQx3vn7kHMKWBOTLaqDnm6EArC7VI=; b=Bhef8kbN9Ch5hbUVw0mkO/zPfaZevdCsrA8dgL9uXmcD7LDprtP0IUkFNdeorRHy9X 6BUm2zXZA/J7RCY5XMS6fyMcGPyH4FfBQ/pS4TSduVDXJjFSUqAo//DDyo6daV5dvkZN LiJcV5ra2c2ootUX+vaWPpxoUTD2k+jLfzd4B8qpKvLCa/0X+7voqkca75pxglBOlHsk RgvTKXYucj2rcw8wn3Apr1QQh0OH6BEjcVP/PiUzBUNBD+2sh0WxF3cWiXU1u5/NL8TG 1T2Nnos4JXVxjGpiYZJkLIiD4hp8RtowmRndtbsGd0cYcsmjWhbjLGxDEX1HCuRXnPh0 3Zfw== X-Gm-Message-State: AOAM531CwXUqAsOtVS+GAHMj7247s/xs+F9k8vJSl5wq+bRe3KXTHwSD 4KsC3e6Th951OX54UCz0H3oR5aVnjzbL5A== X-Google-Smtp-Source: ABdhPJxeqOj95faBfsPjEY4aeWuM4Ocp+0LcPIr2uqbv49YFDEZTyeSsqcSw9H3cJUcGsXuSH5IU7g== X-Received: by 2002:a05:6a00:1a4b:b029:315:77ff:b5c3 with SMTP id h11-20020a056a001a4bb029031577ffb5c3mr41280653pfv.21.1625889772580; Fri, 09 Jul 2021 21:02:52 -0700 (PDT) Received: from squeak.grove.modra.org ([2406:3400:51d:8cc0:3cd7:ff06:db01:8db3]) by smtp.gmail.com with ESMTPSA id d191sm9427989pga.27.2021.07.09.21.02.50 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 09 Jul 2021 21:02:51 -0700 (PDT) Received: by squeak.grove.modra.org (Postfix, from userid 1000) id 544141140016; Sat, 10 Jul 2021 13:32:48 +0930 (ACST) Date: Sat, 10 Jul 2021 13:32:48 +0930 From: Alan Modra To: binutils@sourceware.org Subject: PR28069, assertion fail in dwarf.c:display_discr_list Message-ID: MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline X-Spam-Status: No, score=-3038.4 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, FREEMAIL_FROM, GIT_PATCH_0, RCVD_IN_DNSWL_NONE, SPF_HELO_NONE, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.4 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on server2.sourceware.org X-BeenThere: binutils@sourceware.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Binutils mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 10 Jul 2021 04:02:55 -0000 We shouldn't be asserting on anything to do with leb128 values, or reporting file and line numbers when something unexpected happens. leb128 data is of indeterminate length, perfect for fuzzer mayhem. It would only make sense to assert or report dwarf.c/readelf.c source lines if the code had already sized and sanity checked the leb128 values. After removing the assertions, the testcase then gave: <37> DW_AT_discr_list : 5 byte block: 0 0 0 0 0 (label 0, label 0, label 0, label 0, readelf: Warning: corrupt discr_list - unrecognized discriminant byte 0x5 <3d> DW_AT_encoding : 0 (void) <3e> DW_AT_identifier_case: 0 (case_sensitive) <3f> DW_AT_virtuality : 0 (none) <40> DW_AT_decimal_sign: 5 (trailing separate) So the DW_AT_discr_list was showing more data than just the 5 byte block. That happened due to "end" pointing a long way past the end of block, and uvalue decrementing past zero on one of the leb128 bytes. PR 28069 * dwarf.c (display_discr_list): Remove assertions. Delete "end" parameter, use initial "data" pointer as the end. Formatting. Don't count down bytes as they are read. (read_and_display_attr_value): Adjust display_discr_list call. (read_and_print_leb128): Don't pass __FILE__ and __LINE__ to report_leb_status. * dwarf.h (report_leb_status): Don't report file and line numbers. Delete file and lnum parameters, (READ_ULEB, READ_SLEB): Adjust. diff --git a/binutils/dwarf.c b/binutils/dwarf.c index ad1ee97d9bf..fbd5d6aea5a 100644 --- a/binutils/dwarf.c +++ b/binutils/dwarf.c @@ -2280,7 +2280,7 @@ read_and_print_leb128 (unsigned char *data, int status; dwarf_vma val = read_leb128 (data, end, is_signed, bytes_read, &status); if (status != 0) - report_leb_status (status, __FILE__, __LINE__); + report_leb_status (status); else printf ("%s", dwarf_vmatoa (is_signed ? "d" : "u", val)); } @@ -2289,9 +2289,10 @@ static void display_discr_list (unsigned long form, dwarf_vma uvalue, unsigned char * data, - unsigned const char * end, int level) { + unsigned char *end = data; + if (uvalue == 0) { printf ("[default]"); @@ -2320,41 +2321,32 @@ display_discr_list (unsigned long form, return; } - bool is_signed = - (level > 0 && level <= MAX_CU_NESTING) - ? level_type_signed [level - 1] : false; + bool is_signed = (level > 0 && level <= MAX_CU_NESTING + ? level_type_signed [level - 1] : false); printf ("("); - while (uvalue) + while (data < end) { unsigned char discriminant; unsigned int bytes_read; SAFE_BYTE_GET_AND_INC (discriminant, data, 1, end); - -- uvalue; - assert (uvalue > 0); switch (discriminant) { case DW_DSC_label: printf ("label "); read_and_print_leb128 (data, & bytes_read, end, is_signed); - assert (bytes_read <= uvalue && bytes_read > 0); - uvalue -= bytes_read; data += bytes_read; break; case DW_DSC_range: printf ("range "); read_and_print_leb128 (data, & bytes_read, end, is_signed); - assert (bytes_read <= uvalue && bytes_read > 0); - uvalue -= bytes_read; data += bytes_read; printf (".."); read_and_print_leb128 (data, & bytes_read, end, is_signed); - assert (bytes_read <= uvalue && bytes_read > 0); - uvalue -= bytes_read; data += bytes_read; break; @@ -2365,7 +2357,7 @@ display_discr_list (unsigned long form, return; } - if (uvalue) + if (data < end) printf (", "); } @@ -3230,7 +3222,7 @@ read_and_display_attr_value (unsigned long attribute, case DW_AT_discr_list: printf ("\t"); - display_discr_list (form, uvalue, data, end, level); + display_discr_list (form, uvalue, data, level); break; case DW_AT_frame_base: diff --git a/binutils/dwarf.h b/binutils/dwarf.h index 2070c6f3daf..887b720f632 100644 --- a/binutils/dwarf.h +++ b/binutils/dwarf.h @@ -264,12 +264,12 @@ extern unsigned char * get_build_id (void *); #endif static inline void -report_leb_status (int status, const char *file, unsigned long lnum) +report_leb_status (int status) { if ((status & 1) != 0) - error (_("%s:%lu: end of data encountered whilst reading LEB\n"), file, lnum); + error (_("end of data encountered whilst reading LEB\n")); else if ((status & 2) != 0) - error (_("%s:%lu: read LEB value is too large to store in destination variable\n"), file, lnum); + error (_("read LEB value is too large to store in destination variable\n")); } #define SKIP_ULEB(start, end) \ @@ -302,7 +302,7 @@ report_leb_status (int status, const char *file, unsigned long lnum) (var) = _val; \ if ((var) != _val) \ _status |= 2; \ - report_leb_status (_status, __FILE__, __LINE__); \ + report_leb_status (_status); \ } \ while (0) @@ -318,6 +318,6 @@ report_leb_status (int status, const char *file, unsigned long lnum) (var) = _val; \ if ((var) != _val) \ _status |= 2; \ - report_leb_status (_status, __FILE__, __LINE__); \ + report_leb_status (_status); \ } \ while (0) -- Alan Modra Australia Development Lab, IBM