get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

GET /api/1.2/patches/2231751/?format=api
HTTP 200 OK
Allow: GET, PUT, PATCH, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept

{
    "id": 2231751,
    "url": "http://patchwork.ozlabs.org/api/1.2/patches/2231751/?format=api",
    "web_url": "http://patchwork.ozlabs.org/project/glibc/patch/20260501112421.3373616-3-avinal.xlvii@gmail.com/",
    "project": {
        "id": 41,
        "url": "http://patchwork.ozlabs.org/api/1.2/projects/41/?format=api",
        "name": "GNU C Library",
        "link_name": "glibc",
        "list_id": "libc-alpha.sourceware.org",
        "list_email": "libc-alpha@sourceware.org",
        "web_url": "",
        "scm_url": "",
        "webscm_url": "",
        "list_archive_url": "",
        "list_archive_url_format": "",
        "commit_url_format": ""
    },
    "msgid": "<20260501112421.3373616-3-avinal.xlvii@gmail.com>",
    "list_archive_url": null,
    "date": "2026-05-01T11:24:05",
    "name": "[v2,2/2] intl: Add tests for plural expression hardening",
    "commit_ref": null,
    "pull_url": null,
    "state": "new",
    "archived": false,
    "hash": "1d8e7a16ee8fdf116fc8381e1f1f97117724ae52",
    "submitter": {
        "id": 88549,
        "url": "http://patchwork.ozlabs.org/api/1.2/people/88549/?format=api",
        "name": "Avinal Kumar",
        "email": "avinal.xlvii@gmail.com"
    },
    "delegate": null,
    "mbox": "http://patchwork.ozlabs.org/project/glibc/patch/20260501112421.3373616-3-avinal.xlvii@gmail.com/mbox/",
    "series": [
        {
            "id": 502445,
            "url": "http://patchwork.ozlabs.org/api/1.2/series/502445/?format=api",
            "web_url": "http://patchwork.ozlabs.org/project/glibc/list/?series=502445",
            "date": "2026-05-01T11:24:03",
            "name": "intl: Import plural expression hardening from GNU gettext",
            "version": 2,
            "mbox": "http://patchwork.ozlabs.org/series/502445/mbox/"
        }
    ],
    "comments": "http://patchwork.ozlabs.org/api/patches/2231751/comments/",
    "check": "pending",
    "checks": "http://patchwork.ozlabs.org/api/patches/2231751/checks/",
    "tags": {},
    "related": [],
    "headers": {
        "Return-Path": "<libc-alpha-bounces~incoming=patchwork.ozlabs.org@sourceware.org>",
        "X-Original-To": [
            "incoming@patchwork.ozlabs.org",
            "libc-alpha@sourceware.org"
        ],
        "Delivered-To": [
            "patchwork-incoming@legolas.ozlabs.org",
            "libc-alpha@sourceware.org"
        ],
        "Authentication-Results": [
            "legolas.ozlabs.org;\n\tdkim=pass (2048-bit key;\n unprotected) header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256\n header.s=20251104 header.b=oDWpWHxX;\n\tdkim-atps=neutral",
            "legolas.ozlabs.org;\n spf=pass (sender SPF authorized) smtp.mailfrom=sourceware.org\n (client-ip=2620:52:6:3111::32; helo=vm01.sourceware.org;\n envelope-from=libc-alpha-bounces~incoming=patchwork.ozlabs.org@sourceware.org;\n receiver=patchwork.ozlabs.org)",
            "sourceware.org;\n\tdkim=pass (2048-bit key,\n unprotected) header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256\n header.s=20251104 header.b=oDWpWHxX",
            "sourceware.org;\n dmarc=pass (p=none dis=none) header.from=gmail.com",
            "sourceware.org; spf=pass smtp.mailfrom=gmail.com",
            "server2.sourceware.org;\n arc=none smtp.remote-ip=2607:f8b0:4864:20::1033"
        ],
        "Received": [
            "from vm01.sourceware.org (vm01.sourceware.org\n [IPv6:2620:52:6:3111::32])\n\t(using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)\n\t key-exchange x25519 server-signature ECDSA (secp384r1) server-digest SHA384)\n\t(No client certificate requested)\n\tby legolas.ozlabs.org (Postfix) with ESMTPS id 4g6TJR17Slz1xqf\n\tfor <incoming@patchwork.ozlabs.org>; Fri, 01 May 2026 21:26:31 +1000 (AEST)",
            "from vm01.sourceware.org (localhost [127.0.0.1])\n\tby sourceware.org (Postfix) with ESMTP id 2E67443B5518\n\tfor <incoming@patchwork.ozlabs.org>; Fri,  1 May 2026 11:26:29 +0000 (GMT)",
            "from mail-pj1-x1033.google.com (mail-pj1-x1033.google.com\n [IPv6:2607:f8b0:4864:20::1033])\n by sourceware.org (Postfix) with ESMTPS id AD25A436F7CF\n for <libc-alpha@sourceware.org>; Fri,  1 May 2026 11:25:00 +0000 (GMT)",
            "by mail-pj1-x1033.google.com with SMTP id\n 98e67ed59e1d1-35da1af3e10so1997324a91.3\n for <libc-alpha@sourceware.org>; Fri, 01 May 2026 04:25:00 -0700 (PDT)",
            "from fedoraemon.neon-universe.ts.net\n ([2406:7400:11d:a9dc:9a14:72eb:1a60:868a])\n by smtp.gmail.com with ESMTPSA id\n 98e67ed59e1d1-364be028cd6sm5198006a91.14.2026.05.01.04.24.56\n (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256);\n Fri, 01 May 2026 04:24:57 -0700 (PDT)"
        ],
        "DKIM-Filter": [
            "OpenDKIM Filter v2.11.0 sourceware.org 2E67443B5518",
            "OpenDKIM Filter v2.11.0 sourceware.org AD25A436F7CF"
        ],
        "DMARC-Filter": "OpenDMARC Filter v1.4.2 sourceware.org AD25A436F7CF",
        "ARC-Filter": "OpenARC Filter v1.0.0 sourceware.org AD25A436F7CF",
        "ARC-Seal": "i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1777634700; cv=none;\n b=oqKGCIxv5HrceYAVz92/Yh42eycXcVzr/cjcL8uvUHHLXA//QFCIUf+Uxzt/P+73mg5SPxzwsFpKAQawfnoF2WiITY407r0DT9yeTrj6PCNlATSKxnqD0hVkeO75A5SFQYuwRKuX0/3BF/IQPGGxxN13Ef72PGVOSQDaVyvcejU=",
        "ARC-Message-Signature": "i=1; a=rsa-sha256; d=sourceware.org; s=key;\n t=1777634700; c=relaxed/simple;\n bh=MTn3W3TUWciHm4OqjXLgr3J+hYLW7XhaGsFMnd0Nvi0=;\n h=DKIM-Signature:From:To:Subject:Date:Message-ID:MIME-Version;\n b=EPsyQOMgo2132r5hISRLaozxE+vmOPWZP1PApsmDBVonv6E1yC71/EBSr6GCOtusyl30KG+kXX6zNVcou4bmXkIT68M7hsKitctf9iv4YYnPfWx//eruMYa6V7BGeAEGACTilwv7ORRR4QcUz5PCEKiZMU5s3k4kxFGIM1VU5z8=",
        "ARC-Authentication-Results": "i=1; server2.sourceware.org",
        "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed;\n d=gmail.com; s=20251104; t=1777634699; x=1778239499; darn=sourceware.org;\n h=content-transfer-encoding:mime-version:references:in-reply-to\n :message-id:date:subject:cc:to:from:from:to:cc:subject:date\n :message-id:reply-to;\n bh=5mXv/S4o3zx3T0/fJsWUuEtbNlKbycVYQoaBHliDf9w=;\n b=oDWpWHxXQ/yKgzPl7VJDe1WI1DRkUG1ph206MDlf0BnP9D4JIx8Yvc8MpiSQyu2toh\n JecrGUZDHOV6T3GHHI6ntjzqRfg4bYJz2+Bsg0rM/SbyRY8iPZxoGwDWcaG3isVTdCEw\n 2Whs6u5DkECnboJb6vpGB6TDEoB/kfTlsWeXfT+ErAuvNSCVS2t9BIlNvpeh9bpgSv2g\n kRvk8wZzOb5BlLkMp2K3zMON47AicJK6uRECyINM3B8lQAjYWeN4TtTKeRrvwWPX9XMx\n +mujX542pU2eEftrhkQeOBLTMkxDpCsf5U1ImLSj0LbvaLnMW79Qztlat9LKdDCzMkMG\n sgrg==",
        "X-Google-DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed;\n d=1e100.net; s=20251104; t=1777634699; x=1778239499;\n h=content-transfer-encoding:mime-version:references:in-reply-to\n :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from\n :to:cc:subject:date:message-id:reply-to;\n bh=5mXv/S4o3zx3T0/fJsWUuEtbNlKbycVYQoaBHliDf9w=;\n b=T4hhuHNoyOJvhvFpJZWTeNVHeutwkfx+ocDwYATQdU11sjaWe39OsdvNL/XNjXsYKl\n RQQpq6M4foUCSJ7nWHYYmRWNUXu7QohsusZ21qzjhEAhH5ORL5o6ikNiX6meGMEYCMdc\n W+YLIJgwcFgsf7RjhoYNQx2GJWoiwpYOP6Hu3pJZy7jT35W6dcFELb2VBSRq9y8JLD/n\n ucLM32NqUQZ19pwlri5xHpLbrin5r0BRikezzwoLqeABzZ91bLr5WfUVYeiFatyz/OzV\n Pwv/aSz2gzuztfZtf8YG0bR1pq9B9bSUpYz7wz98P8a4zGCfE04lo6W1JKYs45d8dKgE\n YkXg==",
        "X-Gm-Message-State": "AOJu0YzJhqVKSFZnuPaTFisJiSUsY74IQTmIcmoN+qyDsnr2l3c+VUux\n 2zcGhlHqtJvt9ipyS6zvFCCCp8uHaCsuW6LvECu5T9GlSeZS7xYx9Ni2G0iBiA==",
        "X-Gm-Gg": "AeBDieuiPA1dpfgg7DMPhkJXcWLRBhItcab+v9N8fn15+6Ucxzz8lXlWZx21NmkBpuq\n RqUqzerOqFl1AJXXvwQWh6TgTKbpniQCKXcZIBHBMyX3J7YiPpMYV88DZrO6SNK+OTrSYtwVaOw\n ueNlkdcF9PqugsiHeFViVPemy1HVsTqNzXwaIOQ8QBkSIacRMP+majtSeJVz5z8iaSnH3FpDD76\n Mnf8QSbFznd1Hr5Z3GIiONyKT/cbDaU92BczSXv+7xG4PFNYX/sUtPDWcCff771z95wjwuJtnVe\n 7Qd8D6eo+Q5pUlU9wz6V/ere1qA9jTAqxUJnpqPc/RoljlW8e79xH8XV/yTC8zsjXXqXxgJ4i2E\n rxHUQDaTCj4Gpnuo60d0SHHUDPODdr+AnWdNiq3Rw/E/AUqyI59cFCwBQivbi2Q6bTSnEXyGZIl\n f+c9DQqN8/3OVcAoE7CIyaiSK3WZMdBSBuhFd8zWGlwypW6fRu+GspYClcvG7b4sL50Q==",
        "X-Received": "by 2002:a17:90b:270b:b0:35c:30a8:330 with SMTP id\n 98e67ed59e1d1-364c2d9f623mr7260109a91.0.1777634698991;\n Fri, 01 May 2026 04:24:58 -0700 (PDT)",
        "From": "Avinal Kumar <avinal.xlvii@gmail.com>",
        "To": "libc-alpha@sourceware.org",
        "Cc": "adhemerval.zanella@linaro.org",
        "Subject": "[PATCH v2 2/2] intl: Add tests for plural expression hardening",
        "Date": "Fri,  1 May 2026 16:54:05 +0530",
        "Message-ID": "<20260501112421.3373616-3-avinal.xlvii@gmail.com>",
        "X-Mailer": "git-send-email 2.54.0",
        "In-Reply-To": "<20260501112421.3373616-1-avinal.xlvii@gmail.com>",
        "References": "<20260501112421.3373616-1-avinal.xlvii@gmail.com>",
        "MIME-Version": "1.0",
        "Content-Transfer-Encoding": "8bit",
        "X-BeenThere": "libc-alpha@sourceware.org",
        "X-Mailman-Version": "2.1.30",
        "Precedence": "list",
        "List-Id": "Libc-alpha mailing list <libc-alpha.sourceware.org>",
        "List-Unsubscribe": "<https://sourceware.org/mailman/options/libc-alpha>,\n <mailto:libc-alpha-request@sourceware.org?subject=unsubscribe>",
        "List-Archive": "<https://sourceware.org/pipermail/libc-alpha/>",
        "List-Post": "<mailto:libc-alpha@sourceware.org>",
        "List-Help": "<mailto:libc-alpha-request@sourceware.org?subject=help>",
        "List-Subscribe": "<https://sourceware.org/mailman/listinfo/libc-alpha>,\n <mailto:libc-alpha-request@sourceware.org?subject=subscribe>",
        "Errors-To": "libc-alpha-bounces~incoming=patchwork.ozlabs.org@sourceware.org"
    },
    "content": "The first test checks for stack overflow.  It uses a plural expression\nnested 5000 levels deep using the !(1-(...)) pattern.  The parser\naccepts it (below YYMAXDEPTH=10000), but evaluation exeeds\nEVAL_MAXDEPTH=100 and falls back to index 0 instead of crashing with\nSIGSEGV.\n\nThe second test checks for division by zero in plural expression.  The\nexpression (n!=1)+1/(n!=1729) triggers 1/0 for n=1729.  msgfmt only\nvalidates 0<= n <= 1000, so the .mo file is accepted. Evaluation\nreturns PE_INTDIV and falls back instead of raining SIGFPE.\n\nAdaptations from gettext to glibc:\n\n- gettext's plural-3 embeds the nested expresion as a literal string.\nThis test uses an AWK script (plural-depth.awk) to generate the same\nexpression.\n\n- gettext uses LANGUAGE= (empty) with LC_ALL=ll and its own locale\nsetup.  glibc requires a real locale for setlocale() or else the \"C\"\nlocale override in dcigettext.c ignores LANGUAGE entriely).\n\nThe tests are derived from GNU gettext's plural-3 (commit 021348871a22)\nand plural-4 (commit 429ba6c6b835), adapted to glibc's test framework.\nOriginal author: Bruno Haible <bruno@clisp.org>\n\nSigned-off-by: Avinal Kumar <avinal.xlvii@gmail.com>\n---\n intl/Makefile           | 11 ++++--\n intl/plural-depth.awk   | 54 +++++++++++++++++++++++++++++\n intl/tst-plural-eval.c  | 75 +++++++++++++++++++++++++++++++++++++++++\n intl/tst-plural-eval.sh | 67 ++++++++++++++++++++++++++++++++++++\n 4 files changed, 205 insertions(+), 2 deletions(-)\n create mode 100644 intl/plural-depth.awk\n create mode 100644 intl/tst-plural-eval.c\n create mode 100644 intl/tst-plural-eval.sh",
    "diff": "diff --git a/intl/Makefile b/intl/Makefile\nindex 42875eb1a9..abfe3ac28c 100644\n--- a/intl/Makefile\n+++ b/intl/Makefile\n@@ -28,7 +28,8 @@ routines = bindtextdom dcgettext dgettext gettext\t\\\n aux =\t   l10nflist explodename plural plural-exp hash-string\n \n multithread-test-srcs := tst-gettext4 tst-gettext5 tst-gettext6\n-test-srcs := tst-gettext tst-translit tst-gettext2 tst-codeset tst-gettext3\n+test-srcs := tst-gettext tst-translit tst-gettext2 tst-codeset tst-gettext3 \\\n+\ttst-plural-eval\n ifeq ($(have-thread-library),yes)\n test-srcs += $(multithread-test-srcs)\n endif\n@@ -55,7 +56,7 @@ ifeq (yes,$(build-shared))\n ifneq ($(strip $(MSGFMT)),:)\n tests-special += $(objpfx)tst-translit.out $(objpfx)tst-gettext.out \\\n \t\t $(objpfx)tst-gettext2.out $(objpfx)tst-codeset.out \\\n-\t\t $(objpfx)tst-gettext3.out\n+\t\t $(objpfx)tst-gettext3.out $(objpfx)tst-plural-eval.out\n ifeq ($(have-thread-library),yes)\n tests-special += $(objpfx)tst-gettext4.out $(objpfx)tst-gettext5.out \\\n \t\t $(objpfx)tst-gettext6.out\n@@ -103,6 +104,10 @@ $(objpfx)tst-gettext4.out: tst-gettext4.sh $(objpfx)tst-gettext4\n $(objpfx)tst-gettext6.out: tst-gettext6.sh $(objpfx)tst-gettext6\n \t$(SHELL) $< $(common-objpfx) '$(test-program-prefix)' $(common-objpfx)intl/; \\\n \t$(evaluate-test)\n+$(objpfx)tst-plural-eval.out: tst-plural-eval.sh $(objpfx)tst-plural-eval\n+\t$(SHELL) $< $(common-objpfx) '$(test-program-prefix)' \\\n+\t  $(common-objpfx)intl/; \\\n+\t$(evaluate-test)\n \n $(objpfx)tst-codeset.out: $(codeset_mo)\n $(objpfx)tst-gettext3.out: $(codeset_mo)\n@@ -140,6 +145,7 @@ CFLAGS-tst-gettext3.c += -DOBJPFX=\\\"$(objpfx)\\\"\n CFLAGS-tst-gettext4.c += -DOBJPFX=\\\"$(objpfx)\\\"\n CFLAGS-tst-gettext5.c += -DOBJPFX=\\\"$(objpfx)\\\"\n CFLAGS-tst-gettext6.c += -DOBJPFX=\\\"$(objpfx)\\\"\n+CFLAGS-tst-plural-eval.c += -DOBJPFX=\\\"$(objpfx)\\\"\n \n ifeq ($(have-thread-library),yes)\n ifeq (yes,$(build-shared))\n@@ -156,6 +162,7 @@ $(objpfx)tst-gettext3.out: $(objpfx)tst-gettext.out\n $(objpfx)tst-gettext4.out: $(objpfx)tst-gettext.out\n $(objpfx)tst-gettext5.out: $(objpfx)tst-gettext.out\n $(objpfx)tst-gettext6.out: $(objpfx)tst-gettext.out\n+$(objpfx)tst-plural-eval.out: $(objpfx)tst-gettext.out\n \n CPPFLAGS += -D'LOCALEDIR=\"$(localedir)\"' \\\n \t    -D'LOCALE_ALIAS_PATH=\"$(localedir)\"' \\\ndiff --git a/intl/plural-depth.awk b/intl/plural-depth.awk\nnew file mode 100644\nindex 0000000000..7b200c00e9\n--- /dev/null\n+++ b/intl/plural-depth.awk\n@@ -0,0 +1,54 @@\n+# plural-depth.awk - Generate .po file with deeply nested plural expression.\n+# Copyright (C) 2026 Free Software Foundation, Inc.\n+#\n+# This file is part of the GNU C Library.\n+#\n+# The GNU C Library is free software; you can redistribute it and/or\n+# modify it under the terms of the GNU Lesser General Public\n+# License as published by the Free Software Foundation; either\n+# version 2.1 of the License, or (at your option) any later version.\n+#\n+# The GNU C Library is distributed in the hope that it will be useful,\n+# but WITHOUT ANY WARRANTY; without even the implied warranty of\n+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n+# Lesser General Public License for more details.\n+#\n+# You should have received a copy of the GNU Lesser General Public\n+# License along with the GNU C Library; if not, see\n+# <https://www.gnu.org/licenses/>.\n+\n+# Generate a .po file whose Plural-Forms header contains a plural\n+# expression nested DEPTH levels deep.  Each level wraps as !(1-(...)),\n+# producing an expression that is accepted by the parser (YYMAXDEPTH=10000)\n+# but exceeds EVAL_MAXDEPTH=100 at runtime.\n+#\n+# Usage: awk -v DEPTH=5000 -f plural-depth.awk > plural-depth.po\n+\n+BEGIN {\n+    if (DEPTH == 0)\n+\tDEPTH = 5000\n+\n+    expr = \"\"\n+    for (i = 0; i < DEPTH; i++)\n+\texpr = expr \"!(1-\"\n+    expr = expr \"(n!=1)\"\n+    for (i = 0; i < DEPTH; i++)\n+\texpr = expr \")\"\n+\n+    print \"msgid \\\"\\\"\"\n+    print \"msgstr \\\"\\\"\"\n+    print \"\\\"Project-Id-Version: test\\\\n\\\"\"\n+    print \"\\\"PO-Revision-Date: 2026-01-01 00:00+0000\\\\n\\\"\"\n+    print \"\\\"Last-Translator: \\\\n\\\"\"\n+    print \"\\\"Language-Team: \\\\n\\\"\"\n+    print \"\\\"Language: ll\\\\n\\\"\"\n+    print \"\\\"MIME-Version: 1.0\\\\n\\\"\"\n+    print \"\\\"Content-Type: text/plain; charset=ASCII\\\\n\\\"\"\n+    print \"\\\"Content-Transfer-Encoding: 8bit\\\\n\\\"\"\n+    print \"\\\"Plural-Forms: nplurals=2; plural=\" expr \";\\\\n\\\"\"\n+    print \"\"\n+    print \"msgid \\\"X\\\"\"\n+    print \"msgid_plural \\\"Y\\\"\"\n+    print \"msgstr[0] \\\"x\\\"\"\n+    print \"msgstr[1] \\\"y\\\"\"\n+}\ndiff --git a/intl/tst-plural-eval.c b/intl/tst-plural-eval.c\nnew file mode 100644\nindex 0000000000..cdbc84c6b6\n--- /dev/null\n+++ b/intl/tst-plural-eval.c\n@@ -0,0 +1,75 @@\n+/* Test plural expression evaluation hardening.\n+   Copyright (C) 2026 Free Software Foundation, Inc.\n+   This file is part of the GNU C Library.\n+\n+   The GNU C Library is free software; you can redistribute it and/or\n+   modify it under the terms of the GNU Lesser General Public\n+   License as published by the Free Software Foundation; either\n+   version 2.1 of the License, or (at your option) any later version.\n+\n+   The GNU C Library is distributed in the hope that it will be useful,\n+   but WITHOUT ANY WARRANTY; without even the implied warranty of\n+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n+   Lesser General Public License for more details.\n+\n+   You should have received a copy of the GNU Lesser General Public\n+   License along with the GNU C Library; if not, see\n+   <https://www.gnu.org/licenses/>.  */\n+\n+#include <libintl.h>\n+#include <locale.h>\n+#include <stdio.h>\n+#include <stdlib.h>\n+#include <string.h>\n+#include <support/check.h>\n+\n+static int\n+do_test (void)\n+{\n+  unsetenv (\"OUTPUT_CHARSET\");\n+\n+  /* Use a real locale so that the active locale is not \"C\".  */\n+  setenv (\"LC_ALL\", \"de_DE.UTF-8\", 1);\n+  setlocale (LC_ALL, \"\");\n+  /* Set a dummy langauge to override lookup.  */\n+  setenv (\"LANGUAGE\", \"ll\", 1);\n+\n+  /* Test 1: Stack overflow in plural evaluation.\n+     The .mo file has a plural expression with 5000 levels of nesting\n+     like !(1-(!(1-(...(n!=1)...)))).  Before the fix, plural_eval()\n+     used unbounded recursion and would crash with SIGSEGV on threads\n+     with small stacks.  After the fix, EVAL_MAXDEPTH=100 causes\n+     plural_eval_recurse() to return PE_STACKOVF, and plural_lookup()\n+     falls back to index 0 (the singular form).  */\n+\n+  bindtextdomain (\"plural-depth\", OBJPFX \"domaindir\");\n+  textdomain (\"plural-depth\");\n+\n+  /* ngettext must not crash.  The return value depends on whether\n+     the depth limit is hit (falls back to index 0) or the expression\n+     evaluates successfully.  Either result is acceptable.  */\n+\n+  const char *tr = ngettext (\"X\", \"Y\", 42);\n+  TEST_VERIFY (tr != NULL);\n+  TEST_VERIFY (strcmp (tr, \"x\") == 0 || strcmp (tr, \"y\") == 0);\n+\n+  /* Test 2: Division by zero in plural evaluation.\n+     The .mo file has plural expression (n!=1)+1/(n!=1729).\n+     For n=1729, (n!=1729) is 0, so 1/0 triggers division by zero.\n+     Before the fix, this raised SIGFPE.  After the fix,\n+     plural_eval_recurse() returns PE_INTDIV, and plural_lookup()\n+     falls back to index 0.  */\n+\n+  bindtextdomain (\"plural-divzero\", OBJPFX \"domaindir\");\n+  textdomain (\"plural-divzero\");\n+\n+  /* ngettext with n=1729 must not crash with SIGFPE.  */\n+  tr = ngettext (\"X\", \"Y\", 1729);\n+  TEST_VERIFY (tr != NULL);\n+  TEST_VERIFY (strcmp (tr, \"x\") == 0 || strcmp (tr, \"y\") == 0\n+\t       || strcmp (tr, \"z\") == 0);\n+\n+  return 0;\n+}\n+\n+#include <support/test-driver.c>\ndiff --git a/intl/tst-plural-eval.sh b/intl/tst-plural-eval.sh\nnew file mode 100644\nindex 0000000000..f020fa9925\n--- /dev/null\n+++ b/intl/tst-plural-eval.sh\n@@ -0,0 +1,67 @@\n+#!/bin/sh\n+# Test plural expression evaluation hardening.\n+# Copyright (C) 2026 Free Software Foundation, Inc.\n+# This file is part of the GNU C Library.\n+\n+# The GNU C Library is free software; you can redistribute it and/or\n+# modify it under the terms of the GNU Lesser General Public\n+# License as published by the Free Software Foundation; either\n+# version 2.1 of the License, or (at your option) any later version.\n+\n+# The GNU C Library is distributed in the hope that it will be useful,\n+# but WITHOUT ANY WARRANTY; without even the implied warranty of\n+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n+# Lesser General Public License for more details.\n+\n+# You should have received a copy of the GNU Lesser General Public\n+# License along with the GNU C Library; if not, see\n+# <https://www.gnu.org/licenses/>.\n+\n+set -e\n+\n+common_objpfx=$1\n+test_program_prefix=$2\n+objpfx=$3\n+\n+# Create domain directories.\n+mkdir -p ${objpfx}domaindir/ll/LC_MESSAGES\n+\n+# Test 1: Deeply nested plural expression (stack overflow test).\n+# This expression has 5000 levels of nesting, well above EVAL_MAXDEPTH=100\n+# but below YYMAXDEPTH=10000 so the parser accepts it.\n+LC_ALL=C awk -v DEPTH=5000 -f plural-depth.awk > ${objpfx}plural-depth.po\n+\n+msgfmt -o ${objpfx}domaindir/ll/LC_MESSAGES/plural-depth.mo \\\n+       ${objpfx}plural-depth.po || exit 1\n+\n+# Test 2: Division by zero in plural expression (SIGFPE test).\n+# The expression 1/(n!=1729) triggers division by zero for n=1729.\n+# msgfmt -c only checks 0 <= n <= 1000, so this passes validation.\n+cat > ${objpfx}plural-divzero.po <<EOF\n+msgid \"\"\n+msgstr \"\"\n+\"Project-Id-Version: test\\n\"\n+\"PO-Revision-Date: 2026-01-01 00:00+0000\\n\"\n+\"Last-Translator: \\n\"\n+\"Language-Team: \\n\"\n+\"Language: ll\\n\"\n+\"MIME-Version: 1.0\\n\"\n+\"Content-Type: text/plain; charset=ASCII\\n\"\n+\"Content-Transfer-Encoding: 8bit\\n\"\n+\"Plural-Forms: nplurals=3; plural=(n!=1)+1/(n!=1729);\\n\"\n+\n+msgid \"X\"\n+msgid_plural \"Y\"\n+msgstr[0] \"x\"\n+msgstr[1] \"y\"\n+msgstr[2] \"z\"\n+EOF\n+\n+msgfmt -o ${objpfx}domaindir/ll/LC_MESSAGES/plural-divzero.mo \\\n+       ${objpfx}plural-divzero.po || exit 1\n+\n+# Run the test.\n+${test_program_prefix} \\\n+${objpfx}tst-plural-eval ${objpfx}domaindir\n+\n+exit $?\n",
    "prefixes": [
        "v2",
        "2/2"
    ]
}