Source: libnet-idn-encode-perl Version: 2.500-5 Severity: important Tags: security upstream X-Debbugs-Cc: [email protected], Debian Security Team <[email protected]>
Hi, The following vulnerabilities were published for libnet-idn-encode-perl. CVE-2026-74765[0]: | Net::IDN::Punycode versions before 2.590 for Perl allow an out-of- | bounds read via integer overflow of the delta accumulator in | encode_punycode. The XS backend keeps the punycode delta, and the | digit index derived from it, in a signed int. The accumulation | `delta += (m-n) * (h+1)` has no overflow check, so a large enough | code point wraps the delta and the digit index leaves the range of | the 36-entry digit table. The bound before the final table access | tests only for an index above 36, so a negative index passes it, as | does 36 itself. Perl strings hold code points beyond the Unicode | range, and one such code point overflows the accumulation on its | own. Valid input wraps it as well, for example 1927 ASCII letters | followed by U+10FFFF. The conversion functions encode a label before | they check its length, so a long label reaches the encoder through | the documented API. Only the XS backend is affected. Encoding an | attacker-supplied string copies a byte from outside the digit table | into the encoded result or crashes the process. CVE-2026-74766[1]: | Net::IDN::Punycode versions from 2.301 before 2.590 for Perl allow a | heap use-after-free via a decoded code point that reallocates the | output buffer in decode_punycode. The XS backend inserts each | decoded code point into the string buffer of the scalar it returns. | decode_punycode computes the insertion pointer first and only then | grows the buffer when the code point does not fit. The growth | reallocates the buffer and updates every pointer except the | insertion pointer, so the move that follows and the write of the | code point go through a freed pointer. The buffer starts at twice | the label length, and a code point above U+FFFF takes four bytes in | the output, so a label of such code points outgrows it and forces | the reallocation. Version 2.301, the fix for CVE-2016-15059, | introduced the defect. Only the XS backend is affected. Decoding an | attacker-supplied punycode label reads and writes freed heap memory. CVE-2026-87078[2]: | Net::IDN::Punycode versions from 2.302 before 2.590 for Perl leak | the output buffer on every rejected label in decode_punycode. The | XS backend allocates the scalar it returns before it validates the | input, sizing the buffer at twice the input length. The scalar is | released only on the success path, so each of the three croaks that | reject a label leaves the scalar and its buffer allocated. Nothing | bounds the label length in the to-Unicode direction, since the | 63-byte DNS limit is checked only when converting to ASCII. Only | the XS backend is affected. A sender who supplies invalid labels | grows the process by twice the label length per rejected call, with | no successful call needed. CVE-2026-87079[3]: | Net::IDN::Punycode versions before 2.590 for Perl allow CPU | exhaustion via quadratic insertion cost when decoding a long label | in decode_punycode. The XS backend inserts each decoded code point | into a UTF-8 buffer and finds the insertion point by scanning that | buffer from the start, one character at a time. The scan runs once | per code point over the output built so far, so the cost is | quadratic in the label length. The pure-Perl backend downgrades its | input to bytes so that substr can index it directly, but takes its | working copy before the downgrade, so when the input carries the | UTF-8 flag every substr on the copy scans from the start, with the | same quadratic cost. Nothing bounds the label length in the to- | Unicode direction. The 63-byte DNS limit is checked only when | converting to ASCII, so domain_to_unicode and uts46_to_unicode pass | an attacker-supplied label of any length to the decoder. CVE-2026-87080[4]: | Net::IDN::Punycode::PP versions before 2.590 for Perl decode a | truncated label to a name containing a character it never encoded in | decode_punycode. The pure-Perl decoder reads one digit at a time | with four-argument substr and tests the result with defined to | detect the end of the input. substr on an exhausted string returns | the empty string rather than undef, so decoding continues past the | end. The empty string converts to a digit value below the range, | reducing the accumulator, and the decoder derives one extra code | point and its position from it. The result is deterministic. The XS | backend rejects the same label. Net::IDN::Punycode uses this | backend wherever the XS does not build. The two backends disagree | about what such a label means, so a sender can pick a label that one | installation resolves to a name and another rejects. CVE-2026-87081[5]: | Net::IDN::UTS46 versions before 2.590 for Perl allow CPU exhaustion | via quadratic punycode encoding of an overlong label before the | length check in to_ascii. to_ascii punycode encodes each label and | only then applies the 63-byte DNS limit. encode_punycode in both | backends follows the sample implementation in RFC 3492, whose outer | loop runs once per distinct non-ASCII code point and scans the whole | input each round, so a label of distinct non-ASCII characters costs | the square of its length before the limit rejects it. Every ASCII | conversion in the distribution, including domain_to_ascii and | email_to_ascii, goes through to_ascii. CVE-2026-87082[6]: | Net::IDN::Punycode versions before 2.590 for Perl hang, crash or | return a wrong label via unvalidated malformed UTF-8 in | encode_punycode. Neither backend checks that its input is well- | formed UTF-8, so a string with the UTF-8 flag set over malformed | bytes, as the :utf8 PerlIO layer produces from any malformed input, | reaches the encoder unchecked. On perl 5.32 and later the XS backend | reports a malformed sequence with a length of `(STRLEN)-1`, so the | scan steps back one byte instead of forward and never ends. On | earlier perls the XS returns a valid label for a different name. The | pure-Perl backend runs a regex over the flagged string. Depending on | the bytes, it aborts with SIGBUS on perl 5.28 and later, dies with a | panic, or returns a wrong label. The documented conversion | functions match the label against Unicode properties first and that | match dies on such a string, so only a direct call to | encode_punycode reaches the defect. The decoder is not affected. A | direct caller encoding attacker-supplied bytes hangs, crashes or | gets a label for a name the input never held. If you fix the vulnerabilities please also make sure to include the CVE (Common Vulnerabilities & Exposures) ids in your changelog entry. For further information see: [0] https://security-tracker.debian.org/tracker/CVE-2026-74765 https://www.cve.org/CVERecord?id=CVE-2026-74765 [1] https://security-tracker.debian.org/tracker/CVE-2026-74766 https://www.cve.org/CVERecord?id=CVE-2026-74766 [2] https://security-tracker.debian.org/tracker/CVE-2026-87078 https://www.cve.org/CVERecord?id=CVE-2026-87078 [3] https://security-tracker.debian.org/tracker/CVE-2026-87079 https://www.cve.org/CVERecord?id=CVE-2026-87079 [4] https://security-tracker.debian.org/tracker/CVE-2026-87080 https://www.cve.org/CVERecord?id=CVE-2026-87080 [5] https://security-tracker.debian.org/tracker/CVE-2026-87081 https://www.cve.org/CVERecord?id=CVE-2026-87081 [6] https://security-tracker.debian.org/tracker/CVE-2026-87082 https://www.cve.org/CVERecord?id=CVE-2026-87082 Regards, Salvatore

