Hi Kevin,

On 2026-05-18T18:34:25+0800, Kevin J. McCarthy wrote:
> +static char *intl_to_utf8(char *orig_user, char *orig_domain)
> +{
> +  char *utf8_user, *utf8_domain, *mailbox = NULL, *tmp = NULL;
> +
> +  utf8_user = orig_user;
> +  utf8_domain = safe_strdup(orig_domain);
> +
> +#if defined(HAVE_LIBIDN) || defined(HAVE_LIBIDN2)
> +  /* NOTE: since this transform is currently used for key lookups,
> +   * the check for option(OPTIDNDECODE) is not included here.
> +   * Compare to the invocation in intl_to_local()
> +   */
> +  if (check_idn(utf8_domain))
> +  {
> +    if (idna_to_unicode_8z8z(utf8_domain, &tmp, IDNA_ALLOW_UNASSIGNED) != 
> IDNA_SUCCESS)
> +      goto cleanup;
> +    mutt_str_replace(&utf8_domain, tmp);
> +  }
> +#endif
> +
> +  mailbox = safe_malloc(mutt_strlen(utf8_user) + mutt_strlen(utf8_domain) + 
> 2);
> +  sprintf(mailbox, "%s@%s", NONULL(utf8_user), NONULL(utf8_domain)); /* 
> __SPRINTF_CHECKED__ */

Should we use an sprintf(3) variant that allocates itself?  That could
simplify this to:

        mailbox = aprintf("%s@%s", NONULL(utf8_user), NONULL(utf8_domain));
        if (mailbox == NULL)
                goto fail;

It would make it impossible to calculate the size of the buffer
incorrectly, or any other misuses.

Also, we could have a wrapper that fails on OOM, as we do with
malloc(3):

        mailbox = xaprintf("%s@%s", NONULL(utf8_user), NONULL(utf8_domain));

Which doesn't need error handling code.

I'm working on a patch for adding aprintf(3) in glibc (we've already
added it in gnulib, and it already has a manual page).  It's also quite
easy to implement it portably with C99 functions.  Here's a paper I
wrote, which specifies the function, and shows a portable
implementation:
<https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3750.txt>

        char *
        vaprintf(const char *restrict fmt, va_list ap)
        {
                char     *p;
                size_t   size, len;
                va_list  ap2;

                va_copy(ap2, ap);
                len = vsnprintf(NUL, 0, fmt, ap);
                va_end(ap2);
                if (len < 0)
                        return NULL;

                size = len + 1;
                p = malloc(size);
                if (p == NULL)
                        return NULL;

                if (vsnprintf(p, size, fmt, ap) < 0) {
                        free(p);
                        return NULL;
                }

                return p;
        }


Have a lovely day!
Alex

-- 
<https://www.alejandro-colomar.es>

Attachment: signature.asc
Description: PGP signature

Reply via email to