[{"id":3684821,"web_url":"http://patchwork.ozlabs.org/comment/3684821/","msgid":"<232f5615-05ab-48df-a2fb-53d6c431fa3c@linaro.org>","list_archive_url":null,"date":"2026-04-30T16:18:39","subject":"Re: [PATCH] intl: Import plural expression hardening from GNU gettext","submitter":{"id":66065,"url":"http://patchwork.ozlabs.org/api/people/66065/","name":"Adhemerval Zanella Netto","email":"adhemerval.zanella@linaro.org"},"content":"On 29/04/26 14:04, Avinal Kumar wrote:\n> The plural expression evaluator plural_eval() in eval-plural.h uses\n> unbounded recursion, which can cause a stack overflow crash with\n> deeply nested expressions in malicious .mo files.  This is\n> particularly dangerous on threads with small stacks (musl libc\n> default: 128 KB, AIX 7 default: 96 KB, glibc after ulimit -s 260:\n> ~3919 recursions max).\n> \n> Additionally, division by zero in plural expressions triggers\n> raise(SIGFPE), which is not multithread-safe, catching SIGFPE\n> requires per-process signal handlers that race with other threads.\n> \n> Fix both by importing the hardening from GNU gettext:\n> \n> - Replace unbounded plural_eval() with depth-limited\n>   plural_eval_recurse() (EVAL_MAXDEPTH=100), returning a\n>   struct eval_result with status instead of a bare unsigned long.\n> \n> - Return PE_INTDIV status on division by zero instead of raising\n>   SIGFPE.  Remove the architecture-specific INTDIV0_RAISES_SIGFPE\n>   macro and the conditional #include <signal.h>.\n> \n> - Update plural_lookup() in dcigettext.c to handle the new return\n>   type, falling back to index 0 on any evaluation failure.\n> \n> Based on GNU gettext commits ef37a1540 and 726bfb1d1.\n> Original author: Bruno Haible <bruno@clisp.org>\n> \n> Signed-off-by: Avinal Kumar <avinal.xlvii@gmail.com>\n> ---\n> This is the first in a series of patches to sync glibc's intl/ with\n> upstream GNU gettext.  The last sync was about 1.5 years ago.\n> Since then, gettext has accumulated security fixes, bug fixes, and\n> dead code cleanup that glibc lacks.\n> \n> After excluding Windows-specific and build system changes (which\n> account for ~80% of the raw diff), approximately 540 lines of\n> meaningful change need to be imported across ~10 files.\n> \n> This particular change was already discussed and approved on\n> https://sourceware.org/pipermail/libc-alpha/2023-October/152010.html\n> but wasn't followed by any patches.\n\nThanks for working on this, the patch looks good to me. Maybe also\nadd similar tests as done in gettext [1][2].\n\n[1] https://gitweb.git.savannah.gnu.org/gitweb/?p=gettext.git;a=commitdiff;h=021348871a22041cd9d2625ab958dd4808fd282d\n[2] https://gitweb.git.savannah.gnu.org/gitweb/?p=gettext.git;a=commitdiff;h=429ba6c6b835756ceb83f4396580ad5abe36abcf\n\n> \n> \n>  intl/dcigettext.c  |  27 +++------\n>  intl/eval-plural.h | 139 ++++++++++++++++++++++++++++++++++-----------\n>  intl/plural-exp.h  |  21 ++++++-\n>  3 files changed, 134 insertions(+), 53 deletions(-)\n> \n> diff --git a/intl/dcigettext.c b/intl/dcigettext.c\n> index 9ebc54eeec..fb948c1092 100644\n> --- a/intl/dcigettext.c\n> +++ b/intl/dcigettext.c\n> @@ -68,20 +68,6 @@ extern int errno;\n>  \n>  #include <locale.h>\n>  \n> -#ifdef _LIBC\n> -  /* Guess whether integer division by zero raises signal SIGFPE.\n> -     Set to 1 only if you know for sure.  In case of doubt, set to 0.  */\n> -# if defined __alpha__ || defined __arm__ || defined __i386__ \\\n> -     || defined __m68k__ || defined __s390x__\n> -#  define INTDIV0_RAISES_SIGFPE 1\n> -# else\n> -#  define INTDIV0_RAISES_SIGFPE 0\n> -# endif\n> -#endif\n> -#if !INTDIV0_RAISES_SIGFPE\n> -# include <signal.h>\n> -#endif\n> -\n>  #if defined HAVE_SYS_PARAM_H || defined _LIBC\n>  # include <sys/param.h>\n>  #endif\n> @@ -1381,14 +1367,19 @@ plural_lookup (struct loaded_l10nfile *domain, unsigned long int n,\n>  \t       const char *translation, size_t translation_len)\n>  {\n>    struct loaded_domain *domaindata = (struct loaded_domain *) domain->data;\n> +  struct eval_result result;\n>    unsigned long int index;\n>    const char *p;\n>  \n> -  index = plural_eval (domaindata->plural, n);\n> -  if (index >= domaindata->nplurals)\n> -    /* This should never happen.  It means the plural expression and the\n> -       given maximum value do not match.  */\n> +  result = plural_eval (domaindata->plural, n);\n> +  if (result.status != PE_OK)\n> +    /* The plural expression evaluation failed.  */\n>      index = 0;\n> +  else if (result.value >= domaindata->nplurals)\n> +    /* The plural expression and the given maximum value do not match.  */\n> +    index = 0;\n> +  else\n> +    index = result.value;\n>  \n>    /* Skip INDEX strings at TRANSLATION.  */\n>    p = translation;\n> diff --git a/intl/eval-plural.h b/intl/eval-plural.h\n> index 243f6027a1..e231e9bfd3 100644\n> --- a/intl/eval-plural.h\n> +++ b/intl/eval-plural.h\n> @@ -14,24 +14,59 @@\n>     You should have received a copy of the GNU Lesser General Public License\n>     along with this program.  If not, see <https://www.gnu.org/licenses/>.  */\n>  \n> +/* Written by Ulrich Drepper and Bruno Haible.  */\n> +\n>  #ifndef STATIC\n>  #define STATIC static\n>  #endif\n>  \n> -/* Evaluate the plural expression and return an index value.  */\n> -STATIC\n> -unsigned long int\n> -plural_eval (const struct expression *pexp, unsigned long int n)\n> +/* While the bison parser is able to support expressions of a maximum depth\n> +   of YYMAXDEPTH = 10000, the runtime evaluation of a parsed plural expression\n> +   has a smaller maximum recursion depth.\n> +   If we did not limit the recursion depth, a program that just invokes\n> +   ngettext() on a thread other than the main thread could get a crash by\n> +   stack overflow in the following circumstances:\n> +     - On systems with glibc, after the stack size has been reduced,\n> +       e.g. on x86_64 systems after \"ulimit -s 260\".\n> +       This stack size is only sufficient for ca. 3919 recursions.\n> +       Cf. <https://unix.stackexchange.com/questions/620720/>\n> +     - On systems with musl libc, because there the thread stack size (for a\n> +       thread other than the main thread) by default is only 128 KB, see\n> +       <https://wiki.musl-libc.org/functional-differences-from-glibc.html#Thread-stack-size>.\n> +     - On AIX 7 systems, because there the thread stack size (for a thread\n> +       other than the main thread) by default is only 96 KB, see\n> +       <https://www.ibm.com/docs/en/aix/7.1?topic=programming-threads-library-options>.\n> +       This stack size is only sufficient for between 887 and 1363 recursions,\n> +       depending on the compiler and compiler optimization options.\n> +   A maximum depth of 100 is a large enough for all practical needs\n> +   and also small enough to avoid stack overflow even with small thread stack\n> +   sizes.  */\n> +#ifndef EVAL_MAXDEPTH\n> +# define EVAL_MAXDEPTH 100\n> +#endif\n> +\n> +/* A shorthand that denotes a successful evaluation result with a value V.  */\n> +#define OK(v) (struct eval_result) { .status = PE_OK, .value = (v) }\n> +\n> +/* Evaluates a plural expression PEXP for n=N, up to ALLOWED_DEPTH.  */\n> +static struct eval_result\n> +plural_eval_recurse (const struct expression *pexp, unsigned long int n,\n> +\t\t     unsigned int allowed_depth)\n>  {\n> +  if (allowed_depth == 0)\n> +    /* The allowed recursion depth is exhausted.  */\n> +    return (struct eval_result) { .status = PE_STACKOVF };\n> +  allowed_depth--;\n> +\n>    switch (pexp->nargs)\n>      {\n>      case 0:\n>        switch (pexp->operation)\n>  \t{\n>  \tcase var:\n> -\t  return n;\n> +\t  return OK (n);\n>  \tcase num:\n> -\t  return pexp->val.num;\n> +\t  return OK (pexp->val.num);\n>  \tdefault:\n>  \t  break;\n>  \t}\n> @@ -40,52 +75,73 @@ plural_eval (const struct expression *pexp, unsigned long int n)\n>      case 1:\n>        {\n>  \t/* pexp->operation must be lnot.  */\n> -\tunsigned long int arg = plural_eval (pexp->val.args[0], n);\n> -\treturn ! arg;\n> +\tstruct eval_result arg =\n> +\t  plural_eval_recurse (pexp->val.args[0], n, allowed_depth);\n> +\tif (arg.status != PE_OK)\n> +\t  return arg;\n> +\treturn OK (! arg.value);\n>        }\n>      case 2:\n>        {\n> -\tunsigned long int leftarg = plural_eval (pexp->val.args[0], n);\n> +\tstruct eval_result leftarg =\n> +\t  plural_eval_recurse (pexp->val.args[0], n, allowed_depth);\n> +\tif (leftarg.status != PE_OK)\n> +\t  return leftarg;\n>  \tif (pexp->operation == lor)\n> -\t  return leftarg || plural_eval (pexp->val.args[1], n);\n> +\t  {\n> +\t    if (leftarg.value)\n> +\t      return OK (1);\n> +\t    struct eval_result rightarg =\n> +\t      plural_eval_recurse (pexp->val.args[1], n, allowed_depth);\n> +\t    if (rightarg.status != PE_OK)\n> +\t      return rightarg;\n> +\t    return OK (rightarg.value ? 1 : 0);\n> +\t  }\n>  \telse if (pexp->operation == land)\n> -\t  return leftarg && plural_eval (pexp->val.args[1], n);\n> +\t  {\n> +\t    if (!leftarg.value)\n> +\t      return OK (0);\n> +\t    struct eval_result rightarg =\n> +\t      plural_eval_recurse (pexp->val.args[1], n, allowed_depth);\n> +\t    if (rightarg.status != PE_OK)\n> +\t      return rightarg;\n> +\t    return OK (rightarg.value ? 1 : 0);\n> +\t  }\n>  \telse\n>  \t  {\n> -\t    unsigned long int rightarg = plural_eval (pexp->val.args[1], n);\n> +\t    struct eval_result rightarg =\n> +\t      plural_eval_recurse (pexp->val.args[1], n, allowed_depth);\n> +\t    if (rightarg.status != PE_OK)\n> +\t      return rightarg;\n>  \n>  \t    switch (pexp->operation)\n>  \t      {\n>  \t      case mult:\n> -\t\treturn leftarg * rightarg;\n> +\t\treturn OK (leftarg.value * rightarg.value);\n>  \t      case divide:\n> -#if !INTDIV0_RAISES_SIGFPE\n> -\t\tif (rightarg == 0)\n> -\t\t  raise (SIGFPE);\n> -#endif\n> -\t\treturn leftarg / rightarg;\n> +\t\tif (rightarg.value == 0)\n> +\t\t  return (struct eval_result) { .status = PE_INTDIV };\n> +\t\treturn OK (leftarg.value / rightarg.value);\n>  \t      case module:\n> -#if !INTDIV0_RAISES_SIGFPE\n> -\t\tif (rightarg == 0)\n> -\t\t  raise (SIGFPE);\n> -#endif\n> -\t\treturn leftarg % rightarg;\n> +\t\tif (rightarg.value == 0)\n> +\t\t  return (struct eval_result) { .status = PE_INTDIV };\n> +\t\treturn OK (leftarg.value % rightarg.value);\n>  \t      case plus:\n> -\t\treturn leftarg + rightarg;\n> +\t\treturn OK (leftarg.value + rightarg.value);\n>  \t      case minus:\n> -\t\treturn leftarg - rightarg;\n> +\t\treturn OK (leftarg.value - rightarg.value);\n>  \t      case less_than:\n> -\t\treturn leftarg < rightarg;\n> +\t\treturn OK (leftarg.value < rightarg.value);\n>  \t      case greater_than:\n> -\t\treturn leftarg > rightarg;\n> +\t\treturn OK (leftarg.value > rightarg.value);\n>  \t      case less_or_equal:\n> -\t\treturn leftarg <= rightarg;\n> +\t\treturn OK (leftarg.value <= rightarg.value);\n>  \t      case greater_or_equal:\n> -\t\treturn leftarg >= rightarg;\n> +\t\treturn OK (leftarg.value >= rightarg.value);\n>  \t      case equal:\n> -\t\treturn leftarg == rightarg;\n> +\t\treturn OK (leftarg.value == rightarg.value);\n>  \t      case not_equal:\n> -\t\treturn leftarg != rightarg;\n> +\t\treturn OK (leftarg.value != rightarg.value);\n>  \t      default:\n>  \t\tbreak;\n>  \t      }\n> @@ -96,10 +152,25 @@ plural_eval (const struct expression *pexp, unsigned long int n)\n>      case 3:\n>        {\n>  \t/* pexp->operation must be qmop.  */\n> -\tunsigned long int boolarg = plural_eval (pexp->val.args[0], n);\n> -\treturn plural_eval (pexp->val.args[boolarg ? 1 : 2], n);\n> +\tstruct eval_result boolarg =\n> +\t  plural_eval_recurse (pexp->val.args[0], n, allowed_depth);\n> +\tif (boolarg.status != PE_OK)\n> +\t  return boolarg;\n> +\treturn plural_eval_recurse (pexp->val.args[boolarg.value ? 1 : 2], n,\n> +\t\t\t\t    allowed_depth);\n>        }\n>      }\n>    /* NOTREACHED */\n> -  return 0;\n> +  return (struct eval_result) { .status = PE_ASSERT };\n> +}\n> +\n> +/* Evaluates a plural expression PEXP for n=N.  */\n> +STATIC\n> +struct eval_result\n> +plural_eval (const struct expression *pexp, unsigned long int n)\n> +{\n> +  return plural_eval_recurse (pexp, n, EVAL_MAXDEPTH);\n>  }\n> +\n> +#undef OK\n> +\n> diff --git a/intl/plural-exp.h b/intl/plural-exp.h\n> index f0d3a611e1..e2e0c30563 100644\n> --- a/intl/plural-exp.h\n> +++ b/intl/plural-exp.h\n> @@ -26,6 +26,7 @@\n>  extern \"C\" {\n>  #endif\n>  \n> +/* Parsing a plural expression.  */\n>  \n>  enum expression_operator\n>  {\n> @@ -109,8 +110,26 @@ extern void EXTRACT_PLURAL_EXPRESSION (const char *nullentry,\n>  \t\t\t\t       unsigned long int *npluralsp)\n>       attribute_hidden;\n>  \n> +/* Evaluating a parsed plural expression.  */\n> +\n> +enum eval_status\n> +{\n> +  PE_OK,        /* Evaluation succeeded, produced a value */\n> +  PE_INTDIV,    /* Integer division by zero */\n> +  PE_INTOVF,    /* Integer overflow */\n> +  PE_STACKOVF,  /* Stack overflow */\n> +  PE_ASSERT     /* Assertion failure */\n> +};\n> +\n> +struct eval_result\n> +{\n> +  enum eval_status status;\n> +  unsigned long int value;      /* Only relevant for status == PE_OK */\n> +};\n> +\n> +\n>  #if !defined (_LIBC) && !defined (IN_LIBINTL) && !defined (IN_LIBGLOCALE)\n> -extern unsigned long int plural_eval (const struct expression *pexp,\n> +extern struct eval_result plural_eval (const struct expression *pexp,\n>  \t\t\t\t      unsigned long int n);\n>  #endif\n>","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=linaro.org header.i=@linaro.org header.a=rsa-sha256\n header.s=google header.b=UDMDA/VY;\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=linaro.org header.i=@linaro.org header.a=rsa-sha256\n header.s=google header.b=UDMDA/VY","sourceware.org;\n dmarc=pass (p=none dis=none) header.from=linaro.org","sourceware.org; spf=pass smtp.mailfrom=linaro.org","server2.sourceware.org;\n arc=none smtp.remote-ip=2607:f8b0:4864:20::1132"],"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 4g5zrZ32Rrz1yGq\n\tfor <incoming@patchwork.ozlabs.org>; Fri, 01 May 2026 02:19:10 +1000 (AEST)","from vm01.sourceware.org (localhost [127.0.0.1])\n\tby sourceware.org (Postfix) with ESMTP id 89988436F3E1\n\tfor <incoming@patchwork.ozlabs.org>; Thu, 30 Apr 2026 16:19:08 +0000 (GMT)","from mail-yw1-x1132.google.com (mail-yw1-x1132.google.com\n [IPv6:2607:f8b0:4864:20::1132])\n by sourceware.org (Postfix) with ESMTPS id C3B2A4BB8F43\n for <libc-alpha@sourceware.org>; Thu, 30 Apr 2026 16:18:45 +0000 (GMT)","by mail-yw1-x1132.google.com with SMTP id\n 00721157ae682-79a60975dc5so13818197b3.0\n for <libc-alpha@sourceware.org>; Thu, 30 Apr 2026 09:18:45 -0700 (PDT)","from ?IPV6:2804:1b3:a7c0:44cb:1515:6c52:b4a9:e795?\n ([2804:1b3:a7c0:44cb:1515:6c52:b4a9:e795])\n by smtp.gmail.com with ESMTPSA id\n 00721157ae682-7bd5500d83fsm10422387b3.30.2026.04.30.09.18.42\n (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128);\n Thu, 30 Apr 2026 09:18:43 -0700 (PDT)"],"DKIM-Filter":["OpenDKIM Filter v2.11.0 sourceware.org 89988436F3E1","OpenDKIM Filter v2.11.0 sourceware.org C3B2A4BB8F43"],"DMARC-Filter":"OpenDMARC Filter v1.4.2 sourceware.org C3B2A4BB8F43","ARC-Filter":"OpenARC Filter v1.0.0 sourceware.org C3B2A4BB8F43","ARC-Seal":"i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1777565926; cv=none;\n b=E1KoKxVJtBGKE+Xsb0V8aTjTXnKkYE4WDR/8xXQTy6FOJCsk7q+msJikJJ9v0Io0x6HBXgzLTya2CF1OXXLzeFUdsWib8SraYRzhNBTr+/vmvsUUXEWaJVlc9Xbk5PfXTXhRX5cu7emIkkjnJWzdeszNWKIBiW9yWIxhDrvp8k0=","ARC-Message-Signature":"i=1; a=rsa-sha256; d=sourceware.org; s=key;\n t=1777565926; c=relaxed/simple;\n bh=0OVcJsCarj57JATivmbs9UY1l7NeNIq+nlsGZHv4YUI=;\n h=DKIM-Signature:Message-ID:Date:MIME-Version:Subject:To:From;\n b=PMLJwxD6/Wl5Eba4PH9fo8nvqYSP1jLcGUwTMY5IXSdMEU7yvAXjBGiID4LCLAbVl18bgZ0zEr0HSvUfiA2R+tpX1MsF0YnPEg3PO0QlAZ06ncMoWnsuFD8S1Zxt9Lfg5nUxKBRVe6QtRstWEylTgzcT4hqYWo8l4wAqAxirL2w=","ARC-Authentication-Results":"i=1; server2.sourceware.org","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed;\n d=linaro.org; s=google; t=1777565925; x=1778170725; darn=sourceware.org;\n h=content-transfer-encoding:in-reply-to:organization:from\n :content-language:references:to:subject:user-agent:mime-version:date\n :message-id:from:to:cc:subject:date:message-id:reply-to;\n bh=qJMvAE6BZL2DPzV+WR1LPeidfuB/9Za1H7XLVKCsdPM=;\n b=UDMDA/VYIgs5cX5qmgFKMJ+39j5Ms7M8eDT9aqA7Id252OkixeEL0rRlElVKGZuDK0\n ZR9EjwRSlTTVweuampc38SV1J2mwJZNmeI3itR7mkMmbICYKDXCGgqJ/iquaTbzfDjNK\n 8MH2sxFP4ytKorcfKzyL5MG/rU/Cguurg7K7rZ0odVnqJ3mjmWhI/bQPLketE5SXa3b/\n 5misxk98TX7cVy6JOabeXJXOzKo9YK0gj/69QAx+qv7W762bZgwzzknyJzTgUP92TmbV\n iTzb6iKw5g55N/0+SR9i/LwTIQxptzdHjICp18KyxvsL4Rjd2BnnkJfiew2lRlOFyqG6\n EGVg==","X-Google-DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed;\n d=1e100.net; s=20251104; t=1777565925; x=1778170725;\n h=content-transfer-encoding:in-reply-to:organization:from\n :content-language:references:to:subject:user-agent:mime-version:date\n :message-id:x-gm-gg:x-gm-message-state:from:to:cc:subject:date\n :message-id:reply-to;\n bh=qJMvAE6BZL2DPzV+WR1LPeidfuB/9Za1H7XLVKCsdPM=;\n b=GKsHGfrATd8G7XU+9Ua7q3yMNs4yYvnQKp7okttF4ImQBT28q+q3lc4EEk0Akp+tQa\n bxnSJgWwIWGKBuljVe2hVnue4kMvHBNYDK5WBGrPBNw2xARWKmTuOFrz0gF8VpfgGvIt\n 71Xfvj2qXarfrJ4nn6g59MkU1zvKQwjgG4Pe/VeBvvjT7pxKuXZlRIIzNj82Hbw06MI3\n WConP/18gjWuVBe+kWBz8444EMsomEZuaRnkUeI9QhPtpOpYizpIf3uIzQxSt/ecqSW1\n 79yG+OsmtNw0R4WPvoebxwe229unixHuYOFE52Lz0yWU3X5hW0q50te4topMjJVqalJV\n sJzw==","X-Forwarded-Encrypted":"i=1;\n AFNElJ9KYtgBtszMc7iWSwZ/kLY7tWbux93dYjuNyhwkN0kzbxp/QsolR7pjrwevG3SPkbLaAUyFa4XCBkYG@sourceware.org","X-Gm-Message-State":"AOJu0Yzyc4cwx1rgW/TGKWuS/Q7bEBsaKLKd/sS42XWY/TvoXGs0fvvg\n /23a5q77h/PC4tcI7X+QXhT3ISoedZmA/KKZNG3GSZ318aGpbJ1Ympva97vmmJXHy5Y=","X-Gm-Gg":"AeBDiet6AB9QDWkNe3zaPMTNToc4JFRjZPOJKZvf3w6DD/JjEH4su/2RntTjOHgjxcL\n lpKFlFseUpZVOat6Sd3GqnCpxExkqhsNXZTvtbgAMwF1QZgcsSSivPV0edU2ze5w5Zvt/ibmIrV\n mxNrlwu1BGECUFOXXuTfpgRnz94QAtTjdxpeIOKHQkS7EB5K9kcyLb4pxXqYPSPmakqyVlt11jR\n lGhurwiryXwZyGRKC9pGBMgWBs/TUQ93Ej+y1FkGgtE+KMiHupvwEONBS6qfAEc4MLngJ+jo9bV\n F0/zXHOh7TSiO4SN/irFbnXCGy/no+3UgH517qnDWwMMLpbwca+UTSZxLRvfsyKS3WKV7FJss61\n d32VccGW8qwzTckaIDUHSsqeqSzvo0ui+3kl53deYX7WuwLi1z8PWtcryj1SS48/zjYoYMdPpnU\n jV2E9+umh9zqXEdajCmsK3k0porXYD7sMcdg+9UKVIZpt2Dm9g6g9bbX+KZUnAK/ZX+c1PFhpEY\n DaJKGeu8J4orT1V9WDqVZ4Mg/CKbLS0ruQ29F5gFzf/","X-Received":"by 2002:a05:690c:9201:b0:7b2:c6bb:434a with SMTP id\n 00721157ae682-7bd52ab877dmr34745557b3.44.1777565924834;\n Thu, 30 Apr 2026 09:18:44 -0700 (PDT)","Message-ID":"<232f5615-05ab-48df-a2fb-53d6c431fa3c@linaro.org>","Date":"Thu, 30 Apr 2026 13:18:39 -0300","MIME-Version":"1.0","User-Agent":"Mozilla Thunderbird","Subject":"Re: [PATCH] intl: Import plural expression hardening from GNU gettext","To":"Avinal Kumar <avinal.xlvii@gmail.com>, libc-alpha@sourceware.org","References":"<20260429170428.1743554-1-avinal.xlvii@gmail.com>","Content-Language":"en-US","From":"Adhemerval Zanella Netto <adhemerval.zanella@linaro.org>","Organization":"Linaro","In-Reply-To":"<20260429170428.1743554-1-avinal.xlvii@gmail.com>","Content-Type":"text/plain; charset=UTF-8","Content-Transfer-Encoding":"7bit","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"}}]