From patchwork Wed Jan 26 15:29:33 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Nick Clifton X-Patchwork-Id: 50456 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 97FA03851403 for ; Wed, 26 Jan 2022 15:30:26 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 97FA03851403 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1643211026; bh=fz0fQvh3mvhN4aoESNJUG4GzvflJ7reBR4FLtzmjm2Q=; h=To:Subject:Date:List-Id:List-Unsubscribe:List-Archive:List-Post: List-Help:List-Subscribe:From:Reply-To:From; b=tVahnH2xvYczCCYMna9FUCvlj5ixiMaC1d4X/xyg6GWML2QjlDAM8dVcD93ijiT7g GZO5AhbNt0993aRiH6zLvZWADVVlzoF3vl5B0XIeB7oqt0RNDtBr5PFYhf+YdqwvXs UepGEVmfTfaBnpdeyIw6HNnD14+hm68YH6h95TzY= X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) by sourceware.org (Postfix) with ESMTPS id 76E583857826 for ; Wed, 26 Jan 2022 15:29:56 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 76E583857826 Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-523-gV3tM02VPJKYYW4wawjwGQ-1; Wed, 26 Jan 2022 10:29:52 -0500 X-MC-Unique: gV3tM02VPJKYYW4wawjwGQ-1 Received: from smtp.corp.redhat.com (int-mx07.intmail.prod.int.phx2.redhat.com [10.5.11.22]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 0F53A100C629 for ; Wed, 26 Jan 2022 15:29:37 +0000 (UTC) Received: from comet.redhat.com (unknown [10.39.194.171]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 52076108BD32 for ; Wed, 26 Jan 2022 15:29:36 +0000 (UTC) To: gcc-patches@gcc.gnu.org Subject: RFA: libiberty: Fix infinite recursion in rust demangler (PRs 98886 and 99935) Date: Wed, 26 Jan 2022 15:29:33 +0000 Message-ID: <87lez25xcy.fsf@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.84 on 10.5.11.22 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com X-Spam-Status: No, score=-11.4 required=5.0 tests=BAYES_00, DKIMWL_WL_HIGH, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, RCVD_IN_DNSWL_LOW, RCVD_IN_MSPIKE_H3, RCVD_IN_MSPIKE_WL, SPF_HELO_NONE, SPF_NONE, 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: gcc-patches@gcc.gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gcc-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-Patchwork-Original-From: Nick Clifton via Gcc-patches From: Nick Clifton Reply-To: Nick Clifton Errors-To: gcc-patches-bounces+patchwork=sourceware.org@gcc.gnu.org Sender: "Gcc-patches" Hi Guys, I would like to propose the patch below to fix a couple of sources of infinite recursion in libiberty's rust demangling code. This patch is based upon the one submitted for PR 99935, but extended to cope with the case presented in PR 98886 and also fixed so that the "uint" type is not used. Tested with a patched version of the binutils sources on an x86-pc-linux-gnu target. Cheers Nick 2022-01-26 Nick Clifton * rust-demangle.c (struct rust_demangler): Add a recursion counter. (demangle_path): Increment/decrement the recursion counter upon entry and exit. Fail if the counter exceeds a fixed limit. (demangle_type): Likewise. (rust_demangle_callback): Initialise the recursion counter, disabling if requested by the option flags. diff --git a/libiberty/rust-demangle.c b/libiberty/rust-demangle.c index 18c760491bd..3b24d63892a 100644 --- a/libiberty/rust-demangle.c +++ b/libiberty/rust-demangle.c @@ -74,6 +74,12 @@ struct rust_demangler /* Rust mangling version, with legacy mangling being -1. */ int version; + /* Recursion depth. */ + unsigned int recursion; + /* Maximum number of times demangle_path may be called recursively. */ +#define RUST_MAX_RECURSION_COUNT 1024 +#define RUST_NO_RECURSION_LIMIT ((unsigned int) -1) + uint64_t bound_lifetime_depth; }; @@ -671,6 +677,15 @@ demangle_path (struct rust_demangler *rdm, int in_value) if (rdm->errored) return; + if (rdm->recursion != RUST_NO_RECURSION_LIMIT) + { + ++ rdm->recursion; + if (rdm->recursion > RUST_MAX_RECURSION_COUNT) + /* FIXME: There ought to be a way to report + that the recursion limit has been reached. */ + goto fail_return; + } + switch (tag = next (rdm)) { case 'C': @@ -688,10 +703,7 @@ demangle_path (struct rust_demangler *rdm, int in_value) case 'N': ns = next (rdm); if (!ISLOWER (ns) && !ISUPPER (ns)) - { - rdm->errored = 1; - return; - } + goto fail_return; demangle_path (rdm, in_value); @@ -776,9 +788,15 @@ demangle_path (struct rust_demangler *rdm, int in_value) } break; default: - rdm->errored = 1; - return; + goto fail_return; } + goto pass_return; + + fail_return: + rdm->errored = 1; + pass_return: + if (rdm->recursion != RUST_NO_RECURSION_LIMIT) + -- rdm->recursion; } static void @@ -870,6 +888,19 @@ demangle_type (struct rust_demangler *rdm) return; } + if (rdm->recursion != RUST_NO_RECURSION_LIMIT) + { + ++ rdm->recursion; + if (rdm->recursion > RUST_MAX_RECURSION_COUNT) + /* FIXME: There ought to be a way to report + that the recursion limit has been reached. */ + { + rdm->errored = 1; + -- rdm->recursion; + return; + } + } + switch (tag) { case 'R': @@ -1030,6 +1061,9 @@ demangle_type (struct rust_demangler *rdm) rdm->next--; demangle_path (rdm, 0); } + + if (rdm->recursion != RUST_NO_RECURSION_LIMIT) + -- rdm->recursion; } /* A trait in a trait object may have some "existential projections" @@ -1320,6 +1354,7 @@ rust_demangle_callback (const char *mangled, int options, rdm.skipping_printing = 0; rdm.verbose = (options & DMGL_VERBOSE) != 0; rdm.version = 0; + rdm.recursion = (options & DMGL_NO_RECURSE_LIMIT) ? RUST_NO_RECURSION_LIMIT : 0; rdm.bound_lifetime_depth = 0; /* Rust symbols always start with _R (v0) or _ZN (legacy). */