From nobody Thu Apr 2 07:59:30 2026 X-Original-To: dev-commits-src-all@mlmmj.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mlmmj.nyi.freebsd.org (Postfix) with ESMTP id 4fmZ540gFQz6XxTl for ; Thu, 02 Apr 2026 07:59:36 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "R12" (not verified)) by mx1.freebsd.org (Postfix) with ESMTPS id 4fmZ536bpbz3qk6 for ; Thu, 02 Apr 2026 07:59:35 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1775116775; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=OR9Ns5RW+gYwgNW039+xF1rVquln6aHUF/CMIwoTAnM=; b=F8LaMBwOZ1dzYN6xVHPdkBDilhNoBt+RC6cr/Wk+QWsMoXtZxaJUnqW4rjLjb3sXJvIibO 9c3v/7QVNelmOQI6mPQsZD5QCHNleZhyLl3WteLyCFYDu4fhtkxAwz8z9iGGF7zm5FTR6N Wz8W5ZxkC5rObAOK/LCDGXvfGzmTE0AUsR+ESYOcPRxrBdXn3WjewEULMhgaO3/bubn7Jz 7EkMIRRk9H90JoZLG6Kzf5jPhIas52DyGpTfAIygCETwENB6De8i4JUQR4gRhT3OeUNN4k lvxoson/RogQmoVky8YK9Fsa60U7NtmHch4mh8PvqZFzXQDXvGzAwdRqavF/2Q== ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1775116775; a=rsa-sha256; cv=none; b=sD84bmRfaeCkv5tla6uDM41g3Nm0ihTk6RVSF5PyvaOdT1oqIudlfBnzFviEzm7NJ0Qc7v MBgnflpkj0Plpq6XoH2fT89G4fdAA7agpIBMHWimERToGVtWkhPYvFLNERoZ2yGct8WH8W lkNR9mV8IKmA0X/TqWnqpr6N6tdIMm8D+/HlLuleH+tZeORhZ2IdM72VxveRgZiyli30Dm xSxiFq8z+SwpmMQ3YkOhpQeqF679hM8WemSSr6FQqhp3RtoowTIWkSUkAawHJ1EV0yezoR OsJUKmtN8ayK33ewV21TpknkgTvHuz/W/Pm34ZT+ssLMchT6La/2owm29iJ4Zw== ARC-Authentication-Results: i=1; mx1.freebsd.org; none ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1775116775; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=OR9Ns5RW+gYwgNW039+xF1rVquln6aHUF/CMIwoTAnM=; b=fbvVGOIhJ/DsNgZZVgnlKi5ckyAZZU87Xifpsc85sfLGXSQCmqReWOEVcaNaNDYtbBEJTu qeDp7zqrDLtyOSKqA409xLVf6+v6VbIwcMhtXrbY3OBtGFLvTtQthtBtDtEjQNlCVbeR9n GdrE6HMOePW4956vNlgjJAmVB42+V6bNX+NR362pshTiTfscdt4aoOTBYSBdmNj8llZftk Rsr/DwHi06X5blwUSHmUqcvuJRCuaXvwA1cXX2iRHN/wWFerfbd+DLTWLke+2nySwTNhRS hCBJvzyXoH6Mo6FLT7nSPitCiXDQ/+DkZUYUFpQ2fYOMgCmrFvTHdY5cwEsq7Q== Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) by mxrelay.nyi.freebsd.org (Postfix) with ESMTP id 4fmZ5368hdzt9N for ; Thu, 02 Apr 2026 07:59:35 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from git (uid 1279) (envelope-from git@FreeBSD.org) id 3060f by gitrepo.freebsd.org (DragonFly Mail Agent v0.13+ on gitrepo.freebsd.org); Thu, 02 Apr 2026 07:59:30 +0000 To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-branches@FreeBSD.org From: Robert Clausecker Subject: git: 81114ff7ebc1 - stable/15 - libc/amd64/strrchr.S: rewrite and fix scalar implementation List-Id: Commit messages for all branches of the src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-all List-Help: List-Post: List-Subscribe: List-Unsubscribe: X-BeenThere: dev-commits-src-all@freebsd.org Sender: owner-dev-commits-src-all@FreeBSD.org MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: fuz X-Git-Repository: src X-Git-Refname: refs/heads/stable/15 X-Git-Reftype: branch X-Git-Commit: 81114ff7ebc1efbd65d071869836c76f6fded2b3 Auto-Submitted: auto-generated Date: Thu, 02 Apr 2026 07:59:30 +0000 Message-Id: <69ce21e2.3060f.35b51ea4@gitrepo.freebsd.org> The branch stable/15 has been updated by fuz: URL: https://cgit.FreeBSD.org/src/commit/?id=81114ff7ebc1efbd65d071869836c76f6fded2b3 commit 81114ff7ebc1efbd65d071869836c76f6fded2b3 Author: Robert Clausecker AuthorDate: 2026-03-22 12:37:06 +0000 Commit: Robert Clausecker CommitDate: 2026-04-02 07:58:52 +0000 libc/amd64/strrchr.S: rewrite and fix scalar implementation The original scalar implementation of strrchr() had incorrect logic that failed if the character searched for was the NUL character. It was also possibly affected by the issue fixed in 3d8ef251a for strchrnul(). Rewrite the function with logic that actually works. We defer checking for the character until after we have checked for NUL. When we encounter the final NUL byte, we mask out the characters beyond the tail before checking for a match. This bug only affects users running on amd64 with ARCHLEVEL=scalar (cf. simd(7)). The default configuration is not affected. The bug was unfortunately not caught by the unit test inherited from NetBSD. An extended unit test catching the issue is proposed in D56037. PR: 293915 Reported by: safonov.paul@gmail.com Tested by: safonov.paul@gmail.com Fixes: 2ed514a220edbac6ca5ec9f40a3e0b3f2804796d See also: https://reviews.freebsd.org/D56037 MFC after: 1 week (cherry picked from commit 253f15c016ca699906f78b8e522a3f7ed675929b) (cherry picked from commit 23d6516773916d8f324bea51867b0713c476f379) --- lib/libc/amd64/string/strrchr.S | 78 ++++++++++++++--------------------------- 1 file changed, 26 insertions(+), 52 deletions(-) diff --git a/lib/libc/amd64/string/strrchr.S b/lib/libc/amd64/string/strrchr.S index e397bbcd3478..a22a821a1d4d 100644 --- a/lib/libc/amd64/string/strrchr.S +++ b/lib/libc/amd64/string/strrchr.S @@ -1,5 +1,6 @@ /*- * Copyright (c) 2023 The FreeBSD Foundation + * Copyright (c) 2026 Robert Clausecker * * This software was developed by Robert Clausecker * under sponsorship from the FreeBSD Foundation. @@ -65,77 +66,50 @@ ARCHENTRY(strrchr, scalar) xor %rax, %rcx # str ^ c or %r10, %rax # ensure str != 0 before string or %r10, %rcx # ensure str^c != 0 before string - bswap %rcx # in reverse order, to find last match - mov %rdi, %r10 # location of initial mismatch (if any) - xor %r11, %r11 # initial mismatch (none) + xor %r11, %r11 # vector of last match (0 -> no match) add $8, %rdi # advance to next iteration lea (%rax, %r8, 1), %rdx # str - 0x01..01 not %rax # ~str and %rdx, %rax # (str - 0x01..01) & ~str - and %r9, %rax # not including junk bits - jnz 1f # end of string? - - lea (%rcx, %r8, 1), %rdx # (str ^ c) - 0x01..01 - not %rcx # ~(str ^ c) - and %rdx, %rcx # ((str ^ c - 0x01..01) & ~(str ^ c) - and %r9, %rcx # not including junk bits - mov %rcx, %r11 # remember mismatch in head - jmp 0f - - /* main loop unrolled twice */ - ALIGN_TEXT -3: lea (%rcx, %r8, 1), %rdx # (str ^ c) - 0x01..01 - not %rcx # ~(str ^ c) - and %rdx, %rcx # ((str ^ c - 0x01..01) & ~(str ^ c) - and %r9, %rcx # not including junk bits - lea -8(%rdi), %rdx - cmovnz %rdx, %r10 # remember location of current mismatch - cmovnz %rcx, %r11 - -0: mov (%rdi), %rax # str - mov %rsi, %rcx - xor %rax, %rcx # str ^ c - bswap %rcx # in reverse order, to find last match - lea (%rax, %r8, 1), %rdx # str - 0x01..01 - not %rax # ~str - and %rdx, %rax # (str - 0x01..01) & ~str - and %r9, %rax # not including junk bits + and %r9, %rax # NUL bytes in str, not including junk bits jnz 2f # end of string? + /* main loop */ + ALIGN_TEXT +3: mov (%rdi), %rax # str + bswap %rcx # (str ^ c) in reverse order, to find last match lea (%rcx, %r8, 1), %rdx # (str ^ c) - 0x01..01 not %rcx # ~(str ^ c) and %rdx, %rcx # ((str ^ c - 0x01..01) & ~(str ^ c) - and %r9, %rcx # not including junk bits - cmovnz %rdi, %r10 # remember location of current mismatch - cmovnz %rcx, %r11 + and %r9, %rcx # matches in str, not including junk bits + cmovnz %rdi, %r10 # if match found, update match vector + cmovnz %rcx, %r11 # ... and match pointer - mov 8(%rdi), %rax # str - add $16, %rdi + add $8, %rdi # advance to next iteration mov %rsi, %rcx xor %rax, %rcx # str ^ c - bswap %rcx lea (%rax, %r8, 1), %rdx # str - 0x01..01 not %rax # ~str and %rdx, %rax # (str - 0x01..01) & ~str - and %r9, %rax # not including junk bits + and %r9, %rax # NUL bytes in str, not including junk bits jz 3b # end of string? - /* NUL found */ -1: sub $8, %rdi # undo advance past buffer -2: lea (%rcx, %r8, 1), %rdx # (str ^ c) - 0x01..01 + /* NUL found, check for match in tail */ +2: mov %rax, %rdx + neg %rax + xor %rdx, %rax # all bytes behind the NUL byte + or %rax, %rcx # (str ^ c) without matches behind NUL byte + bswap %rcx # (src ^ c) in reverse order, to find last match + lea (%rcx, %r8, 1), %rdx # (str ^ c) - 0x01..01 not %rcx # ~(str ^ c) and %rdx, %rcx # ((str ^ c - 0x01..01) & ~(str ^ c) - and %r9, %rcx # not including junk bits - lea -1(%rax), %rdx - xor %rdx, %rax # mask of bytes in the string - bswap %rdx # in reverse order - and %rdx, %rcx # c found in the tail? - cmovnz %rdi, %r10 - cmovnz %rcx, %r11 - bswap %r11 # unreverse byte order - bsr %r11, %rcx # last location of c in (R10) - shr $3, %rcx # as byte offset - lea (%r10, %rcx, 1), %rax # pointer to match + and %r9, %rcx # matches in str, not including junk bits + cmovnz %rdi, %r10 # if match found, update match vector + cmovnz %rcx, %r11 # ... and match pointer + tzcnt %r11, %rcx # location of last match + lea -1(%r10), %rax # address of last character in vector + shr $3, %ecx # as byte offset + sub %rcx, %rax # subtract character offset test %r11, %r11 # was there actually a match? cmovz %r11, %rax # if not, return null pointer ret