From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: by sourceware.org (Postfix, from userid 1791) id 55C6F385B501; Thu, 23 Feb 2023 14:24:42 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 55C6F385B501 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sourceware.org; s=default; t=1677162282; bh=2gRHtvbnvkAIi8VwC+jh5HS8/UYrYdqvwVKFA6ZQsbo=; h=From:To:Subject:Date:From; b=Xf97CqiVL9Teg0lOCr8AkuqXtFI2MwS2Dp475yy8V+o10+pDcYDH7em16Qv+3TKth wxrW5eI3h76hoSGCRWvsSX9fLOjUhEoIKbpcbDLg7Kc5ByH2016mZnT6DZuzx4FSdP 7J15JbUiajt362K/yYvMo+7aP4G9Czkj5CC2PGbU= Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: Adhemerval Zanella To: glibc-cvs@sourceware.org Subject: [glibc/azanella/strncmp-fix] string: Fix OOB read on generic strncmp X-Act-Checkin: glibc X-Git-Author: Adhemerval Zanella X-Git-Refname: refs/heads/azanella/strncmp-fix X-Git-Oldrev: 8b014a1b1f7aee1e3348db108aeea396359d481e X-Git-Newrev: 52cb8571a851e954830a5f4b3c80f3b0f705ce1d Message-Id: <20230223142442.55C6F385B501@sourceware.org> Date: Thu, 23 Feb 2023 14:24:42 +0000 (GMT) List-Id: https://sourceware.org/git/gitweb.cgi?p=glibc.git;h=52cb8571a851e954830a5f4b3c80f3b0f705ce1d commit 52cb8571a851e954830a5f4b3c80f3b0f705ce1d Author: Adhemerval Zanella Date: Tue Feb 21 16:03:19 2023 -0300 string: Fix OOB read on generic strncmp For unaligned case, reading ahead can only be done if parting reads matches the aligned input. Also extend the stratcliff tests to check such cases. Checked on x86_64-linux-gnu, i686-linux-gnu, powerpc64-linux-gnu, and powerpc-linux-gnu by removing the arch-specific assembly implementation and disabling multi-arch (it covers both LE and BE for 64 and 32 bits). Reviewed-by: Szabolcs Nagy Diff: --- string/stratcliff.c | 17 ++++++++++++++++- string/strncmp.c | 13 ++++++++++++- 2 files changed, 28 insertions(+), 2 deletions(-) diff --git a/string/stratcliff.c b/string/stratcliff.c index 74d64cc03d..88ac787088 100644 --- a/string/stratcliff.c +++ b/string/stratcliff.c @@ -401,12 +401,27 @@ do_test (void) result = 1; } - if (STRNCMP (dest + nchars - outer, adr + middle, outer) <= 0) + /* Also check for size larger than the string. */ + if (STRNCMP (adr + middle, dest + nchars - outer, outer + 99) >= 0) { printf ("%s 2 flunked for outer = %zu, middle = %zu, full\n", + STRINGIFY (STRNCMP), outer + 99, middle); + result = 1; + } + + if (STRNCMP (dest + nchars - outer, adr + middle, outer) <= 0) + { + printf ("%s 3 flunked for outer = %zu, middle = %zu, full\n", STRINGIFY (STRNCMP), outer, middle); result = 1; } + + if (STRNCMP (dest + nchars - outer, adr + middle, outer + 99) <= 0) + { + printf ("%s 4 flunked for outer = %zu, middle = %zu, full\n", + STRINGIFY (STRNCMP), outer + 99, middle); + result = 1; + } } /* strncpy/wcsncpy tests */ diff --git a/string/strncmp.c b/string/strncmp.c index 4c8bf36bb9..751bf53d55 100644 --- a/string/strncmp.c +++ b/string/strncmp.c @@ -73,7 +73,11 @@ strncmp_unaligned_loop (const op_t *x1, const op_t *x2, op_t w1, uintptr_t ofs, uintptr_t sh_2 = sizeof(op_t) * CHAR_BIT - sh_1; op_t w2 = MERGE (w2a, sh_1, (op_t)-1, sh_2); - if (!has_zero (w2) && n > (sizeof (op_t) - ofs)) + + /* Reading ahead is wrong if w1 and w2 already differs. */ + op_t w1a = MERGE (w1, 0, (op_t)-1, sh_2); + + if (!has_zero (w2) && w2 == w1a && n >= (sizeof (op_t) - ofs)) { op_t w2b; @@ -90,6 +94,13 @@ strncmp_unaligned_loop (const op_t *x1, const op_t *x2, op_t w1, uintptr_t ofs, if (has_zero (w2b) || n <= (sizeof (op_t) - ofs)) break; w1 = *x1++; + + /* Reading ahead is wrong if w1 and w2 already differs. */ + w2 = MERGE (w2b, sh_1, (op_t)-1, sh_2); + w1a = MERGE (w1, 0, (op_t)-1, sh_2); + if (w2 != w1a) + return final_cmp (w1a, w2, n); + w2a = w2b; }