php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #72506 idn_to_ascii for UTS #46 incorrect for long domain names
Submitted: 2016-06-27 14:57 UTC Modified: 2017-06-21 08:36 UTC
Votes:2
Avg. Score:2.5 ± 0.5
Reproduced:1 of 1 (100.0%)
Same Version:1 (100.0%)
Same OS:1 (100.0%)
From: kulikovdn at gmail dot com Assigned:
Status: Re-Opened Package: intl (PECL)
PHP Version: 7.1.0alpha1 OS: Linux Ubuntu 14.04
Private report: No CVE-ID:
Have you experienced this issue?
Rate the importance of this bug to you:

 [2016-06-27 14:57 UTC] kulikovdn at gmail dot com
Description:
------------
Function "idn_to_ascii" from intl extension works incorrect for very long domain names if used UTS #46 algorithm.
Appearance of bug depends on string length. For ASCII strings with length < 255 characters function works correct, 255 characters cause fatal error, > 255 characters lead to incorrect result, but without fatal error.

If you think that this bug can be easily workarounded by testing of string length - it is not true, domain name may contain non-ASCII characters, in this case bug will happen for smaller string lengths and it is not possible to predict for which length it will happen.

Looks like bug affects all PHP versions.

Execute test scripts:
https://3v4l.org/tuM9l
https://3v4l.org/eX6aA
https://3v4l.org/EUSlJ

Related pages in docs:
http://php.net/manual/en/function.idn-to-ascii.php
http://php.net/manual/en/intl.constants.php

Test script:
---------------
// First test.
// 255 characters, max allowed for FQDN is 253, note that trailing dot ignored
$value = str_repeat('a.', 126) . 'aaa';
// Fatal error
$result = idn_to_ascii($value, 0, INTL_IDNA_VARIANT_UTS46, $idnaInfo);

// Second test.
// 256 characters, one character added
$value = str_repeat('a.', 126) . 'aaaa';
$result = idn_to_ascii($value, 0, INTL_IDNA_VARIANT_UTS46, $idnaInfo);
var_dump($result);
// $idnaInfo is empty array, it is incorrect
// $idnaInfo['errors'] should be equal to 4, it is value of IDNA_ERROR_DOMAIN_NAME_TOO_LONG
var_dump($idnaInfo);

// Third test.
// "ф" is cyrillic symbol, only 38 characters, but after conversion to ASCII will be much more
$value = str_repeat('ф.', 31) . 's.s.s.s';
// Fatal error
$result = idn_to_ascii($value, 0, INTL_IDNA_VARIANT_UTS46, $idnaInfo);


Expected result:
----------------
Fatal error should not happen.
Variable $idnaInfo should contain array like this:
[
  'result' => 'VERY LONG STRING ...',
  'isTransitionalDifferent' => false,
  'errors' => 4,
]

See correct result for 254 characters:
https://3v4l.org/CijFV

Actual result:
--------------
Fatal error happens.
$idnaInfo contains empty array.

Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2016-06-30 06:06 UTC] kulikovdn at gmail dot com
Text of fatal error:
"Fatal error: idn_to_ascii(): ICU returned an unexpected length"
 [2016-07-11 23:18 UTC] cmb@php.net
-Status: Open +Status: Verified -Assigned To: +Assigned To: cmb
 [2016-07-11 23:18 UTC] cmb@php.net
Indeed, idn_to_ascii() appears to be overly restrictive. If the
resulting domain is 255 bytes long, it raises an error[1], if it
is longer, it returns FALSE and doesn't fill $idna_info[2]. This
inconsistency is definitely a bug.

Not filling $idna_info when the resulting domain is longer than
254 bytes is also a bug according to the documentation[3] which
states:

| In that case, it will be filled with an array with the keys
| 'result', the possibly illegal result of the transformation, […]

The issue here is that we have to allocate a buffer in advance
(i.e. before the length of the resulting domain is known)[4]. Of
course, it would be possible to allocate a larger buffer, but that
might still not be big enough, and appears to be useless anyway,
because the domain name would be invalid. Therefore I suggest to
set $idna_info['result'] to NULL for excessive resulting domains,
and to only do this as of PHP 7.1, due to the (minor) BC break.
For current versions, the documentation should be fixed.

[1] <https://github.com/php/php-src/blob/php-5.6.23/ext/intl/idn/idn.c#L167-L169>
[2] <https://github.com/php/php-src/blob/php-5.6.23/ext/intl/idn/idn.c#L161-L166>
[3] <http://php.net/manual/en/function.idn-to-ascii.php>
[4] <https://github.com/php/php-src/blob/php-5.6.23/ext/intl/idn/idn.c#L142-L143>
 [2016-07-12 12:28 UTC] cmb@php.net
-Summary: idn_to_ascii with INTL_IDNA_VARIANT_UTS46 works incorrect for long domain names +Summary: idn_to_ascii for UTS #46 incorrect for long domain names
 [2016-07-12 12:57 UTC] cmb@php.net
Automatic comment on behalf of cmb
Revision: http://git.php.net/?p=php-src.git;a=commit;h=76e249d31c51d0b4f8f11507c550ca1eec1dd38a
Log: Partially fix #72506: idn_to_ascii for UTS #46 incorrect for long domain names
 [2016-07-12 12:57 UTC] cmb@php.net
-Status: Verified +Status: Closed
 [2016-07-12 12:58 UTC] cmb@php.net
-Status: Closed +Status: Re-Opened -Assigned To: cmb +Assigned To:
 [2016-10-17 10:11 UTC] bwoebi@php.net
Automatic comment on behalf of cmb
Revision: http://git.php.net/?p=php-src.git;a=commit;h=76e249d31c51d0b4f8f11507c550ca1eec1dd38a
Log: Partially fix #72506: idn_to_ascii for UTS #46 incorrect for long domain names
 [2016-10-17 10:11 UTC] bwoebi@php.net
-Status: Re-Opened +Status: Closed
 [2016-11-22 13:00 UTC] cmb@php.net
-Status: Closed +Status: Re-Opened
 [2016-11-22 13:00 UTC] cmb@php.net
This has been inadvertantly closed – reopening.
 [2016-11-23 13:22 UTC] cmb@php.net
-Assigned To: +Assigned To: cmb
 [2017-06-21 08:36 UTC] cmb@php.net
-Assigned To: cmb +Assigned To:
 
PHP Copyright © 2001-2017 The PHP Group
All rights reserved.
Last updated: Thu Jun 22 18:02:00 2017 UTC