Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:129002 X-Original-To: internals@lists.php.net Delivered-To: internals@lists.php.net Received: from php-smtp4.php.net (php-smtp4.php.net [45.112.84.5]) by lists.php.net (Postfix) with ESMTPS id EA77D1A00BC for ; Wed, 29 Oct 2025 22:04:03 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=php.net; s=mail; t=1761775448; bh=qlCtvDSDutuQgWwcH7X+VKeDB80AIL6U75v87xa+fog=; h=References:In-Reply-To:From:Date:Subject:To:From; b=GSLT36JqTIG+k9H82xpNTM9Wp+XnGiTp2GilvqYHKzTOEVhJ2KC9Kp1pnY0z0igra oD+PGBgFL73/6Zz4dAtxm/I4FtrJntEOHSsd332partOEABSmqKxqhoCcosWZ/quhw hmWhPGewQF6k4eXxLU2St2ieTx9s21sPNy8aYRH1s2yXjzsdm8QkErHOoFFC+/5bB/ ZBan1433NM7jMkOqdYvAHw0sKIJZpTA/5Ofl8G2MljhjmXb6w+8z/7w2v0xvZwVKCi P0fUFRINtI53UehBaDDkx2m5optso8sK8OckmkU1lzK5nzqcDXuJZgnsVoCr2jrcPw x4GGoCMZhDwQw== Received: from php-smtp4.php.net (localhost [127.0.0.1]) by php-smtp4.php.net (Postfix) with ESMTP id 8D8421801E1 for ; Wed, 29 Oct 2025 22:04:07 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 4.0.1 (2024-03-25) on php-smtp4.php.net X-Spam-Level: X-Spam-Status: No, score=-2.1 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,DMARC_PASS,HTML_MESSAGE, RCVD_IN_DNSWL_NONE,RCVD_IN_MSPIKE_H2,SPF_HELO_NONE,SPF_PASS autolearn=no autolearn_force=no version=4.0.1 X-Spam-Virus: No X-Envelope-From: Received: from mail-yw1-f171.google.com (mail-yw1-f171.google.com [209.85.128.171]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by php-smtp4.php.net (Postfix) with ESMTPS for ; Wed, 29 Oct 2025 22:04:07 +0000 (UTC) Received: by mail-yw1-f171.google.com with SMTP id 00721157ae682-78485808eb3so5678357b3.3 for ; Wed, 29 Oct 2025 15:04:02 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=intuitivetechnology.com; s=google; t=1761775441; x=1762380241; darn=lists.php.net; h=to:subject:message-id:date:from:in-reply-to:references:mime-version :from:to:cc:subject:date:message-id:reply-to; bh=qlCtvDSDutuQgWwcH7X+VKeDB80AIL6U75v87xa+fog=; b=C94y15Hu1DC/mlsaFJvWHxvAhFKWqau/inP/HTrGouzU8l9u0UZeG7VQ/gzwZmDe2t AR+lvGbeROT06bKYbldrO1pt0ugOG/oRsCfdveVUywR4skXkkTwZerAdVktGks573XOQ 0NBZLzQWg6Jdz9zdUitenGMhuTB3KppwKjrGXG1Hm61AxqSEmejofVjO5dywIZyfVgVN R6JpxSisr2f4TAzR7yboMhcPLFjgrElJpZMFz2iGOJNVZ444DDItBDAztCXPyR7LiEUO 67nViSuKu1MLiJDk61wjbuXfIPcx7/C5DF122pke/raZrtkxc9kLTJVQ6HNlN3EAuZ5F ES6A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1761775441; x=1762380241; h=to:subject:message-id:date:from:in-reply-to:references:mime-version :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=qlCtvDSDutuQgWwcH7X+VKeDB80AIL6U75v87xa+fog=; b=XOCiEaPtTl9kLvUwtsN2nIVbAuqN8ywIA9TeXi/uTvB0U5s9sE49xcvJNVaT/1Wits H/atMBX23gpLhnDC2sHw03G8+Z6IIX+Pe5m25tneJJPe1K/5+iquhtZwY9rq8aFwEsU+ 5d4chOKX5MMEOOzmmORMLHDCpN5PsiBpSQus2iZQMi6b4o+KWr/0yhEXbVPiIXnXloqU t/QVI2/EVoB9M7FNxA0JyqAJJvM0c20Anpye5eigrLXTUF515fi8QhpoQm/7w4wpqmKp XCRDxYkytGIVTXZtB0z00KLvCVsSOISCvUEaDw2C68Blx0+l5np95zZWH2SlmxId7ogs hIcQ== X-Gm-Message-State: AOJu0Ywq8FBDvjUXoBtTgwWI9fEmvh0mQl4b/zkQCT9QaoLRUSZvWDZl 1CPA3PUPJp8El8TEcr3NLnirKKduBFvOXesLu1Hsn5y6j7GCUT7iX+qAlHIn0WUMmJQ+eii2XRo 5HQusXA9cgbgon8StFkC656hk6kTpzZqfcSzPYXnZfeJxfhTCwY7KIi8= X-Gm-Gg: ASbGncvuENM9lbFlz5pOXyu78dC9SMxr5RLwQ9P3aP4GW4q/vSnKsZa9rN/O9cRnH8+ FWf/l5H/UCY8qlmNy3/8CzCvueoLLLexhEAO9FeMixW8uMileYo0pf82yA2Qq/ev3AqjrOnZLgh bMRFT0S1x2mIn0aQoharid7CQeK3O5dqnVues+CRY1vuS9P1cGYsNF7IjLtbPGp6A9ZQZ2JTIFs Sd05KpSVduKhLUYLJEs1esR9+m+QRbBBlpZs6AgiQNNzGJsiz42xxsoC+koWWd5+IJWT5Jn X-Google-Smtp-Source: AGHT+IG2yVqCxj1VdWgczR2CVlmZT0I+zsqALGaoqpdBFmpp+GXLH9J2kHycHkDUWePBDV9hKMlGIngleIHb7Qa1Qz4= X-Received: by 2002:a05:690c:45c2:b0:781:44f0:5ef with SMTP id 00721157ae682-78629041e19mr45203427b3.51.1761775441030; Wed, 29 Oct 2025 15:04:01 -0700 (PDT) Precedence: list list-help: list-unsubscribe: list-post: List-Id: x-ms-reactions: disallow MIME-Version: 1.0 References: In-Reply-To: Date: Wed, 29 Oct 2025 15:03:49 -0700 X-Gm-Features: AWmQ_blRNBsBEZp5Ysp9qXXeROsvL0j7kVoyPOQnCfT-a8vSQsIhI5DKn53985I Message-ID: Subject: [PHP-DEV] Re: Review request: Enabling `transitive_compare_mode` to fix SORT_REGULAR To: PHP internals Content-Type: multipart/alternative; boundary="000000000000563ff80642534f03" From: jmarble@intuitivetechnology.com (Jason Marble) --000000000000563ff80642534f03 Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable Quick update: The variation11 tests I mentioned are now passing after fixing: 1. Empty string ordering - now sorts before numbers to match '' < 5 2. Windows ZTS - initialization in init_executor() All CI tests pass. PR ready for review: https://github.com/php/php-src/pull/20315 - Jason On Wed, Oct 29, 2025 at 9:56=E2=80=AFAM Jason Marble < jmarble@intuitivetechnology.com> wrote: > Hello PHP Internals! > > I believe I've found an acceptable solution to the issue that's plagued > SORT_REGULAR since the dawn of time. > > Fundamentally, all sorting algorithms require transitive comparisons (if = A > =E2=89=A4 B and B =E2=89=A4 C, then A =E2=89=A4 C). However, PHP's SORT_R= EGULAR comparison function > violates transitivity when mixing numeric strings, non-numeric strings, a= nd > numbers, leading to unpredictable and non-deterministic sort results. > > **The Solution:** > Add a `transitive_compare_mode` flag to executor_globals (TLS) that > signals zendi_smart_strcmp() to enforce consistent ordering during > SORT_REGULAR operations: > - Numeric strings are consistently ordered relative to non-numeric string= s > - Eliminates circular comparisons > - Maintains PHP 8+ semantics (numeric-types < numeric-strings < > non-numeric) > > **Implementation:** > - PR: https://github.com/php/php-src/pull/20315 > - Uses save/restore pattern for reentrancy safety > - New test coverage included > > **Historical Context:** > Raghubansh Kumar documented this issue in 2007, creating tests with the > note "(OK to fail as result is unpredectable)". Nikita Popov's 2019 RFC > improved string-to-number comparison semantics but didn't eliminate the > transitivity violation. This fix completes that work. > > **Test Results:** > Four variation11 tests currently fail as expected, but their outputs are > now deterministic and more "sane" than both the 2007 and 2019 versions im= o: > https://gist.github.com/jmarble/957a096cb2bf25b577de47449305723f > > **ABI Considerations:** > This adds a field to _zend_executor_globals, which is technically an ABI > break appropriate for PHP 8.6. However, practical impact is minimal, I > think, since most extensions access executor_globals through the EG() mac= ro > (which abstracts the struct layout), > not via direct struct manipulation. > > I'd appreciate review and feedback on this approach. This is a > long-standing correctness issue. > > Thank you for your time and consideration! > > - Jason > --000000000000563ff80642534f03 Content-Type: text/html; charset="UTF-8" Content-Transfer-Encoding: quoted-printable
Quick update: The variation11 tests I mentioned are now pa= ssing after fixing:

1. Empty string ordering - now sorts before numb= ers to match '' < 5
2. Windows ZTS - initialization in init_e= xecutor()

All CI tests pass. PR ready for review: https://github.com/php/php-src/pull/203= 15

- Jason

On Wed, Oct 29, 2025 at 9:56=E2= =80=AFAM Jason Marble <jmarble@intuitivetechnology.com> wrote:
Hello PHP Internals!=

I believe I've found an acceptable solution t= o the issue that's plagued SORT_REGULAR since the dawn of time.

Fundamentally, all sorting algorithms require transitive = comparisons (if A =E2=89=A4 B and B =E2=89=A4 C, then A =E2=89=A4 C). Howev= er, PHP's SORT_REGULAR comparison function violates transitivity when m= ixing numeric strings, non-numeric strings, and numbers, leading to unpredi= ctable and non-deterministic sort results.

**The S= olution:**
Add a `transitive_compare_mode` flag to executor_globals (TLS= ) that signals zendi_smart_strcmp() to enforce consistent ordering during S= ORT_REGULAR operations:
- Numeric strings are consistently ordered relat= ive to non-numeric strings
- Eliminates circular comparisons
- Mainta= ins PHP 8+ semantics (numeric-types < numeric-strings < non-numeric)<= /div>

**Implementation:**
- PR: https://github.com/php/p= hp-src/pull/20315
- Uses save/restore pattern for reentrancy safety<= br>- New test coverage included

**Historical Conte= xt:**
Raghubansh Kumar documented this issue in 2007, creating tests wit= h the note "(OK to fail as result is unpredectable)". Nikita Popo= v's 2019 RFC improved string-to-number comparison semantics but didn= 9;t eliminate the transitivity violation. This fix completes that work.

**Test Results:**
Four variation11 tests currently= fail as expected, but their outputs are now deterministic and more "s= ane" than both the 2007 and 2019 versions imo:
= https://gist.github.com/jmarble/957a096cb2bf25b577de47449305723f
<= div>
**ABI Considerations:**
This adds a field to _zend_ex= ecutor_globals, which is technically an ABI break appropriate for PHP 8.6. = However, practical impact is minimal, I think, since most extensions access= executor_globals through the EG() macro (which abstracts the struct layout= ),
not via direct struct manipulation.

I'd = appreciate review and feedback on this approach. This is a long-standing co= rrectness issue.

Thank you for your time and consideration!

- Jason
--000000000000563ff80642534f03--