From patchwork Sun Nov 1 21:15:40 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Simon Glass X-Patchwork-Id: 1391867 X-Patchwork-Delegate: trini@ti.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=lists.denx.de (client-ip=2a01:238:438b:c500:173d:9f52:ddab:ee01; helo=phobos.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Authentication-Results: ozlabs.org; dmarc=pass (p=none dis=none) header.from=chromium.org Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=chromium.org header.i=@chromium.org header.a=rsa-sha256 header.s=google header.b=hboxhJgx; dkim-atps=neutral Received: from phobos.denx.de (phobos.denx.de [IPv6:2a01:238:438b:c500:173d:9f52:ddab:ee01]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 4CPTQl1pH1z9sRR for ; Mon, 2 Nov 2020 08:17:35 +1100 (AEDT) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id 11F4E8256D; Sun, 1 Nov 2020 22:16:29 +0100 (CET) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=chromium.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Authentication-Results: phobos.denx.de; dkim=pass (1024-bit key; unprotected) header.d=chromium.org header.i=@chromium.org header.b="hboxhJgx"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id 7349882537; Sun, 1 Nov 2020 22:16:07 +0100 (CET) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on phobos.denx.de X-Spam-Level: X-Spam-Status: No, score=-2.0 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,SPF_HELO_NONE,URIBL_BLOCKED autolearn=ham autolearn_force=no version=3.4.2 Received: from mail-io1-xd41.google.com (mail-io1-xd41.google.com [IPv6:2607:f8b0:4864:20::d41]) (using TLSv1.3 with cipher TLS_AES_128_GCM_SHA256 (128/128 bits)) (No client certificate requested) by phobos.denx.de (Postfix) with ESMTPS id 01C498251C for ; Sun, 1 Nov 2020 22:15:59 +0100 (CET) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=chromium.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=sjg@chromium.org Received: by mail-io1-xd41.google.com with SMTP id h21so13010284iob.10 for ; Sun, 01 Nov 2020 13:15:59 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=X1ZS/Z6XoUmz0fIaB30cl9ro+0rKOB/rm5XaOqf8np4=; b=hboxhJgxxyIPVoedvrRLcOzrznqppZesDL5rMb01rWZBiKmzeqv0ZQ/STxmcrXN6ts ihIjopquUYfSgnqgmDynZJMha2Utp6PamT54gxxMRjRW8ouozQmtDXsbXMtpljBt6+WX XTkSGVp5VG7Xy1+lcrycgNLU1ZHrRxz3n9Hc0= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=X1ZS/Z6XoUmz0fIaB30cl9ro+0rKOB/rm5XaOqf8np4=; b=uhVOsNcqAu1OGEvYBkJGMb7r+DRCQW3C4f8Jjgfzwc60YcOpoq2ap0GwmPg0KVs+2C U5xoutxmtCYfdDAabN9yuToO7OvFugotLj2v4wEgr/dzPf5g5MWvYEAwmHRfnCClrXEu B8jstxp+UtNjFC+CwUfdjAzupBFzA7hmred1ryxl/QKcPQ5DITnRlEXVsJUj6jGLm1+c YPKstQN8JppjyDRYqtGe5etegUq5NfD2AW91kIYTEvN8VWglgNP3rBCMnlKWEfseeg4k NMJ5ryag0nxFGwrP2EMVvmxmkBBgxMXlPRt3WA5vhx2KCAAyU3PNiLp5Kp4r0Zaprzpa fs6g== X-Gm-Message-State: AOAM530Y+ublrvDO6uNEaPo3hcJd6J1+UQPM70cVi3Ay1eC5WtMSQk4K qnQNnJw4v5XgpYecyjDQ7IShLGCLwItRRyMB X-Google-Smtp-Source: ABdhPJzUyhMl1nS0VOh1K+2oOwxcfqtD8LyyB7ENGlQMwMSmvNcFdL7RJICDFgGE4AjO1Jpc8wMeXw== X-Received: by 2002:a05:6638:dcc:: with SMTP id m12mr9118477jaj.30.1604265358542; Sun, 01 Nov 2020 13:15:58 -0800 (PST) Received: from localhost.localdomain (c-73-14-175-90.hsd1.co.comcast.net. [73.14.175.90]) by smtp.gmail.com with ESMTPSA id r3sm4131534iot.21.2020.11.01.13.15.57 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 01 Nov 2020 13:15:58 -0800 (PST) From: Simon Glass To: U-Boot Mailing List Cc: Tom Rini , Wolfgang Denk , Simon Glass Subject: [PATCH 06/10] setexpr: Add some tests for buffer overflow and backref Date: Sun, 1 Nov 2020 14:15:40 -0700 Message-Id: <20201101211544.3579850-7-sjg@chromium.org> X-Mailer: git-send-email 2.29.1.341.ge80a0c044ae-goog In-Reply-To: <20201101211544.3579850-1-sjg@chromium.org> References: <20201101211544.3579850-1-sjg@chromium.org> MIME-Version: 1.0 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.34 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" X-Virus-Scanned: clamav-milter 0.102.3 at phobos.denx.de X-Virus-Status: Clean Add tests to check for buffer overflow using simple replacement as well as back references. At present these don't fully pass. Signed-off-by: Simon Glass --- cmd/setexpr.c | 21 +++-------- include/command.h | 17 +++++++++ test/cmd/setexpr.c | 89 ++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 110 insertions(+), 17 deletions(-) diff --git a/cmd/setexpr.c b/cmd/setexpr.c index fe3435b4d99..dbb43b3be2f 100644 --- a/cmd/setexpr.c +++ b/cmd/setexpr.c @@ -134,22 +134,8 @@ static char *substitute(char *string, int *slen, int ssize, return p + nlen; } -/** - * regex_sub() - Replace a regex pattern with a string - * - * @data: Buffer containing the string to update - * @data_size: Size of buffer (must be large enough for the new string) - * @nbuf: Back-reference buffer - * @nbuf_size: Size of back-reference buffer (must be larger enough for @s plus - * all back-reference expansions) - * @r: Regular expression to find - * @s: String to replace with - * @global: true to replace all matches in @data, false to replace just the - * first - * @return 0 if OK, 1 on error - */ -static int regex_sub(char *data, uint data_size, char *nbuf, uint nbuf_size, - const char *r, const char *s, bool global) +int setexpr_regex_sub(char *data, uint data_size, char *nbuf, uint nbuf_size, + const char *r, const char *s, bool global) { struct slre slre; char *datap = data; @@ -325,7 +311,8 @@ static int regex_sub_var(const char *name, const char *r, const char *s, strcpy(data, t); - ret = regex_sub(data, SLRE_BUFSZ, nbuf, SLRE_PATSZ, r, s, global); + ret = setexpr_regex_sub(data, SLRE_BUFSZ, nbuf, SLRE_PATSZ, r, s, + global); if (ret) return 1; diff --git a/include/command.h b/include/command.h index e900f97df33..e229bf2825c 100644 --- a/include/command.h +++ b/include/command.h @@ -183,6 +183,23 @@ extern int do_env_set_efi(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]); #endif +/** + * setexpr_regex_sub() - Replace a regex pattern with a string + * + * @data: Buffer containing the string to update + * @data_size: Size of buffer (must be large enough for the new string) + * @nbuf: Back-reference buffer + * @nbuf_size: Size of back-reference buffer (must be larger enough for @s plus + * all back-reference expansions) + * @r: Regular expression to find + * @s: String to replace with + * @global: true to replace all matches in @data, false to replace just the + * first + * @return 0 if OK, 1 on error + */ +int setexpr_regex_sub(char *data, uint data_size, char *nbuf, uint nbuf_size, + const char *r, const char *s, bool global); + /* * Error codes that commands return to cmd_process(). We use the standard 0 * and 1 for success and failure, but add one more case - failure with a diff --git a/test/cmd/setexpr.c b/test/cmd/setexpr.c index de54561917c..a6940fd82dd 100644 --- a/test/cmd/setexpr.c +++ b/test/cmd/setexpr.c @@ -209,6 +209,95 @@ static int setexpr_test_regex_inc(struct unit_test_state *uts) } SETEXPR_TEST(setexpr_test_regex_inc, UT_TESTF_CONSOLE_REC); +/* Test setexpr_regex_sub() directly to check buffer usage */ +static int setexpr_test_sub(struct unit_test_state *uts) +{ + char *buf, *nbuf; + int i; + + buf = map_sysmem(0, BUF_SIZE); + nbuf = map_sysmem(0x1000, BUF_SIZE); + + /* Add a pattern so we can check the buffer limits */ + memset(buf, '\xff', BUF_SIZE); + memset(nbuf, '\xff', BUF_SIZE); + for (i = BUF_SIZE; i < 0x1000; i++) { + buf[i] = i & 0xff; + nbuf[i] = i & 0xff; + } + strcpy(buf, "this is a test"); + + /* + * This is a regression test, since a bug was found in the use of + * memmove() in setexpr + */ + ut_assertok(setexpr_regex_sub(buf, BUF_SIZE, nbuf, BUF_SIZE, "is", + "us it is longer", true)); + ut_asserteq_str("thus it is longer us it is longer a test", buf); + + /* The following checks fail at present due to a bug in setexpr */ + return 0; + for (i = BUF_SIZE; i < 0x1000; i++) { + ut_assertf(buf[i] == (char)i, + "buf byte at %x should be %02x, got %02x)\n", + i, i & 0xff, (u8)buf[i]); + ut_assertf(nbuf[i] == (char)i, + "nbuf byte at %x should be %02x, got %02x)\n", + i, i & 0xff, (u8)nbuf[i]); + } + + unmap_sysmem(buf); + + return 0; +} +SETEXPR_TEST(setexpr_test_sub, UT_TESTF_CONSOLE_REC); + +/* Test setexpr_regex_sub() with back references */ +static int setexpr_test_backref(struct unit_test_state *uts) +{ + char *buf, *nbuf; + int i; + + buf = map_sysmem(0, BUF_SIZE); + nbuf = map_sysmem(0x1000, BUF_SIZE); + + /* Add a pattern so we can check the buffer limits */ + memset(buf, '\xff', BUF_SIZE); + memset(nbuf, '\xff', BUF_SIZE); + for (i = BUF_SIZE; i < 0x1000; i++) { + buf[i] = i & 0xff; + nbuf[i] = i & 0xff; + } + strcpy(buf, "this is surely a test is it? yes this is indeed a test"); + + /* + * This is a regression test, since a bug was found in the use of + * memmove() in setexpr + */ + ut_assertok(setexpr_regex_sub(buf, BUF_SIZE, nbuf, BUF_SIZE, + "(this) (is) (surely|indeed)", + "us \\1 \\2 \\3!", true)); + + /* The following checks fail at present due to bugs in setexpr */ + return 0; + ut_asserteq_str("us this is surely! a test is it? yes us this is indeed! a test", + buf); + + for (i = BUF_SIZE; i < 0x1000; i++) { + ut_assertf(buf[i] == (char)i, + "buf byte at %x should be %02x, got %02x)\n", + i, i & 0xff, (u8)buf[i]); + ut_assertf(nbuf[i] == (char)i, + "nbuf byte at %x should be %02x, got %02x)\n", + i, i & 0xff, (u8)nbuf[i]); + } + + unmap_sysmem(buf); + + return 0; +} +SETEXPR_TEST(setexpr_test_backref, UT_TESTF_CONSOLE_REC); + int do_ut_setexpr(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) { struct unit_test *tests = ll_entry_start(struct unit_test,