Re: com php-src: Support Unicode characters in the local part of an e-mail address.: ext/filter/filter.c ext/filter/filter_private.h
ext/filter/logical_filters.c ext/filter/tests/058.phpt
| From: | Yasuo Ohgaki | Date: | Thu, 28 Jul 2016 06:43:09 +0000 |
| Subject: | Re: com php-src: Support Unicode characters in the local part of an e-mail address.: ext/filter/filter.c ext/filter/filter_private.h ext/filter/logical_filters.c ext/filter/tests/058.phpt |
||
| References: | 1 2 | Groups: | php.cvs |
| Request: | Send a blank email to php-cvs+get-93441@lists.php.net to get a copy of this message | ||
Hi Anatol,
I'm not comfortable with complex regex....
http://stackstatus.net/post/147710624694/outage-postmortem-july-20-2016
This attack pattern works with PCRE even it has backtrack//stack limit.
Try following ruby code. You'll see exponential execution time increase.
80 chars mail address requires 421 sec on my Core i7 fedora.
We are using PCRE, but I'm not comfortable with complex ereg...
n = 5;
while n < 12 do
s = "username@host"+".abcde"*n+"."
start = Time.now();
p /\A([\w+\-].?)+@[a-z\d\-]+(\.[a-z]+)*\.[a-z]+\z/i =~ s
p s.length.to_s + ': ' + (Time.now() - start).to_s;
n += 1
end
--
Yasuo Ohgaki
yohgaki@ohgaki.net
On Tue, Jul 19, 2016 at 5:44 PM, Yasuo Ohgaki <yohgaki@ohgaki.net> wrote:
> Hi Anatol,
>
> Although I'm not certain, I worry about ReDoS risks with this complex regex.
>
>
> https://www.checkmarx.com/wp-content/uploads/2015/03/ReDoS-Attacks.pdf
>
> How about to use much simpler regex or string filter before applying the
> complex regex to reduce ReDoS risk?
>
> --
> Yasuo Ohgaki
> yohgaki@ohgaki.net
>
>
> On Tue, Jul 19, 2016 at 4:52 AM, Anatol Belski <ab@php.net> wrote:
>> Commit: 8f4050709c833b9d42cd65349b7747f8e61d171f
>> Author: Leo Feyer <github@contao.org> Thu, 15 Oct 2015 11:07:25 +0200
>> Committer: Anatol Belski <ab@php.net> Mon, 18 Jul 2016 21:52:35 +0200
>> Parents: 42260325a47480bc97f7dceb2ac5d8e8d7799928
>> Branches: master
>>
>> Link:
>> http://git.php.net/?p=php-src.git;a=commitdiff;h=8f4050709c833b9d42cd65349b7747f8e61d171f
>>
>> Log:
>> Support Unicode characters in the local part of an e-mail address.
>>
>> See RFC 6531 (https://tools.ietf.org/html/rfc6531).
>>
>> Encode IDNA domains.
>>
>> Add the missing "Done" to the expected output.
>>
>> Add the FILTER_FLAG_EMAIL_RFC6531 flag.
>>
>> Fix the filter_var() call.
>>
>> Changed paths:
>> M ext/filter/filter.c
>> M ext/filter/filter_private.h
>> M ext/filter/logical_filters.c
>> A ext/filter/tests/058.phpt
>>
>>
>> Diff:
>> diff --git a/ext/filter/filter.c b/ext/filter/filter.c
>> index 2c8dde9..3d79a77 100644
>> --- a/ext/filter/filter.c
>> +++ b/ext/filter/filter.c
>> @@ -286,6 +286,8 @@ PHP_MINIT_FUNCTION(filter)
>>
>> REGISTER_LONG_CONSTANT("FILTER_FLAG_HOSTNAME", FILTER_FLAG_HOSTNAME,
>> CONST_CS | CONST_PERSISTENT);
>>
>> + REGISTER_LONG_CONSTANT("FILTER_FLAG_EMAIL_RFC6531",
>> FILTER_FLAG_EMAIL_RFC6531, CONST_CS | CONST_PERSISTENT);
>> +
>> sapi_register_input_filter(php_sapi_filter, php_sapi_filter_init);
>>
>> return SUCCESS;
>> diff --git a/ext/filter/filter_private.h b/ext/filter/filter_private.h
>> index 2f9abc3..ffce723 100644
>> --- a/ext/filter/filter_private.h
>> +++ b/ext/filter/filter_private.h
>> @@ -57,6 +57,8 @@
>>
>> #define FILTER_FLAG_HOSTNAME 0x100000
>>
>> +#define FILTER_FLAG_EMAIL_RFC6531 0x100000
>> +
>> #define FILTER_VALIDATE_INT 0x0101
>> #define FILTER_VALIDATE_BOOLEAN 0x0102
>> #define FILTER_VALIDATE_FLOAT 0x0103
>> diff --git a/ext/filter/logical_filters.c b/ext/filter/logical_filters.c
>> index 5fd057d..03d4795 100644
>> --- a/ext/filter/logical_filters.c
>> +++ b/ext/filter/logical_filters.c
>> @@ -598,7 +598,12 @@ void php_filter_validate_email(PHP_INPUT_FILTER_PARAM_DECL) /* {{{ */
>> * Feel free to use and redistribute this code. But please keep this copyright
>> notice.
>> *
>> */
>> - const char regexp[] =
>> "/^(?!(?:(?:\\x22?\\x5C[\\x00-\\x7E]\\x22?)|(?:\\x22?[^\\x5C\\x22]\\x22?)){255,})(?!(?:(?:\\x22?\\x5C[\\x00-\\x7E]\\x22?)|(?:\\x22?[^\\x5C\\x22]\\x22?)){65,}@)(?:(?:[\\x21\\x23-\\x27\\x2A\\x2B\\x2D\\x2F-\\x39\\x3D\\x3F\\x5E-\\x7E]+)|(?:\\x22(?:[\\x01-\\x08\\x0B\\x0C\\x0E-\\x1F\\x21\\x23-\\x5B\\x5D-\\x7F]|(?:\\x5C[\\x00-\\x7F]))*\\x22))(?:\\.(?:(?:[\\x21\\x23-\\x27\\x2A\\x2B\\x2D\\x2F-\\x39\\x3D\\x3F\\x5E-\\x7E]+)|(?:\\x22(?:[\\x01-\\x08\\x0B\\x0C\\x0E-\\x1F\\x21\\x23-\\x5B\\x5D-\\x7F]|(?:\\x5C[\\x00-\\x7F]))*\\x22)))*@(?:(?:(?!.*[^.]{64,})(?:(?:(?:xn--)?[a-z0-9]+(?:-+[a-z0-9]+)*\\.){1,126}){1,}(?:(?:[a-z][a-z0-9]*)|(?:(?:xn--)[a-z0-9]+))(?:-+[a-z0-9]+)*)|(?:\\[(?:(?:IPv6:(?:(?:[a-f0-9]{1,4}(?::[a-f0-9]{1,4}){7})|(?:(?!(?:.*[a-f0-9][:\\]]){7,})(?:[a-f0-9]{1,4}(?::[a-f0-9]{1,4}){0,5})?::(?:[a-f0-9]{1,4}(?::[a-f0-9]{1,4}){0,5})?)))|(?:(?:IPv6:(?:(?:[a-f0-9]{1,4}(?::[a-f0-9]{1,4}){5}:)|(?:(?!(?:.*[a-f0-9]:){5,})(?:[a-f0-9]{1,4}(?::[a-f0-9]{1,4}){0,3})?::(?:[a-f0-9]{1,4}(?::[a-f0-9]{1,4}){0,3}:)?)))?(?:(?:25[0-5])|(?:2[0-4][0-9])|(?:1[0-9]{2})|(?:[1-9]?[0-9]))(?:\\.(?:(?:25[0-5])|(?:2[0-4][0-9])|(?:1[0-9]{2})|(?:[1-9]?[0-9]))){3}))\\]))$/iD";
>> + if (flags & FILTER_FLAG_EMAIL_RFC6531) {
>> + const char regexp[] =
>> "/^(?!(?:(?:\\x22?\\x5C[\\x00-\\x7E]\\x22?)|(?:\\x22?[^\\x5C\\x22]\\x22?)){255,})(?!(?:(?:\\x22?\\x5C[\\x00-\\x7E]\\x22?)|(?:\\x22?[^\\x5C\\x22]\\x22?)){65,}@)(?:(?:[\\x21\\x23-\\x27\\x2A\\x2B\\x2D\\x2F-\\x39\\x3D\\x3F\\x5E-\\x7E\\pL\\pN]+)|(?:\\x22(?:[\\x01-\\x08\\x0B\\x0C\\x0E-\\x1F\\x21\\x23-\\x5B\\x5D-\\x7F\\pL\\pN]|(?:\\x5C[\\x00-\\x7F]))*\\x22))(?:\\.(?:(?:[\\x21\\x23-\\x27\\x2A\\x2B\\x2D\\x2F-\\x39\\x3D\\x3F\\x5E-\\x7E\\pL\\pN]+)|(?:\\x22(?:[\\x01-\\x08\\x0B\\x0C\\x0E-\\x1F\\x21\\x23-\\x5B\\x5D-\\x7F\\pL\\pN]|(?:\\x5C[\\x00-\\x7F]))*\\x22)))*@(?:(?:(?!.*[^.]{64,})(?:(?:(?:xn--)?[a-z0-9]+(?:-+[a-z0-9]+)*\\.){1,126}){1,}(?:(?:[a-z][a-z0-9]*)|(?:(?:xn--)[a-z0-9]+))(?:-+[a-z0-9]+)*)|(?:\\[(?:(?:IPv6:(?:(?:[a-f0-9]{1,4}(?::[a-f0-9]{1,4}){7})|(?:(?!(?:.*[a-f0-9][:\\]]){7,})(?:[a-f0-9]{1,4}(?::[a-f0-9]{1,4}){0,5})?::(?:[a-f0-9]{1,4}(?::[a-f0-9]{1,4}){0,5})?)))|(?:(?:IPv6:(?:(?:[a-f0-9]{1,4}(?::[a-f0-9]{1,4}){5}:)|(?:(?!(?:.*[a-f0-9]:){5,})(?:[a-f0-9]{1,4}(?::[a-f0-9]{1,4}){0,3})?::(?:[a-f0-9]{1,4}(?::[a-f0-9]{1,4}){0,3}:)?)))?(?:(?:25[0-5])|(?:2[0-4][0-9])|(?:1[0-9]{2})|(?:[1-9]?[0-9]))(?:\\.(?:(?:25[0-5])|(?:2[0-4][0-9])|(?:1[0-9]{2})|(?:[1-9]?[0-9]))){3}))\\]))$/iDu";
>> + } else {
>> + const char regexp[] =
>> "/^(?!(?:(?:\\x22?\\x5C[\\x00-\\x7E]\\x22?)|(?:\\x22?[^\\x5C\\x22]\\x22?)){255,})(?!(?:(?:\\x22?\\x5C[\\x00-\\x7E]\\x22?)|(?:\\x22?[^\\x5C\\x22]\\x22?)){65,}@)(?:(?:[\\x21\\x23-\\x27\\x2A\\x2B\\x2D\\x2F-\\x39\\x3D\\x3F\\x5E-\\x7E]+)|(?:\\x22(?:[\\x01-\\x08\\x0B\\x0C\\x0E-\\x1F\\x21\\x23-\\x5B\\x5D-\\x7F]|(?:\\x5C[\\x00-\\x7F]))*\\x22))(?:\\.(?:(?:[\\x21\\x23-\\x27\\x2A\\x2B\\x2D\\x2F-\\x39\\x3D\\x3F\\x5E-\\x7E]+)|(?:\\x22(?:[\\x01-\\x08\\x0B\\x0C\\x0E-\\x1F\\x21\\x23-\\x5B\\x5D-\\x7F]|(?:\\x5C[\\x00-\\x7F]))*\\x22)))*@(?:(?:(?!.*[^.]{64,})(?:(?:(?:xn--)?[a-z0-9]+(?:-+[a-z0-9]+)*\\.){1,126}){1,}(?:(?:[a-z][a-z0-9]*)|(?:(?:xn--)[a-z0-9]+))(?:-+[a-z0-9]+)*)|(?:\\[(?:(?:IPv6:(?:(?:[a-f0-9]{1,4}(?::[a-f0-9]{1,4}){7})|(?:(?!(?:.*[a-f0-9][:\\]]){7,})(?:[a-f0-9]{1,4}(?::[a-f0-9]{1,4}){0,5})?::(?:[a-f0-9]{1,4}(?::[a-f0-9]{1,4}){0,5})?)))|(?:(?:IPv6:(?:(?:[a-f0-9]{1,4}(?::[a-f0-9]{1,4}){5}:)|(?:(?!(?:.*[a-f0-9]:){5,})(?:[a-f0-9]{1,4}(?::[a-f0-9]{1,4}){0,3})?::(?:[a-f0-9]{1,4}(?::[a-f0-9]{1,4}){0,3}:)?)))?(?:(?:25[0-5])|(?:2[0-4][0-9])|(?:1[0-9]{2})|(?:[1-9]?[0-9]))(?:\\.(?:(?:25[0-5])|(?:2[0-4][0-9])|(?:1[0-9]{2})|(?:[1-9]?[0-9]))){3}))\\]))$/iD";
>> + }
>> +
>> pcre *re = NULL;
>> pcre_extra *pcre_extra = NULL;
>> int preg_options = 0;
>> diff --git a/ext/filter/tests/058.phpt b/ext/filter/tests/058.phpt
>> new file mode 100644
>> index 0000000..a10f844
>> --- /dev/null
>> +++ b/ext/filter/tests/058.phpt
>> @@ -0,0 +1,57 @@
>> +--TEST--
>> +FILTER_VALIDATE_EMAIL unicode support (https://tools.ietf.org/html/rfc6531)
>> +--SKIPIF--
>> +<?php if (!extension_loaded("filter")) die("skip"); ?>
>> +--FILE--
>> +<?php
>> +$values = Array(
>> +'niceändsimple@example.com',
>> +'véry.çommon@example.com',
>> +'a.lîttle.lengthy.but.fiñe@dept.example.com',
>> +'dîsposable.style.émail.with+symbol@example.com',
>> +'other.émail-with-dash@example.com',
>> +'üser@[IPv6:2001:db8:1ff::a0b:dbd0]',
>> +'"verî.uñusual.@.uñusual.com"@example.com',
>> +'"verî.(),:;<>[]\".VERÎ.\"verî@\
>> \"verî\".unüsual"@strange.example.com',
>> +'tést@example.com',
>> +'tést.child@example.com',
>> +'tést@xn--exmple-cua.com',
>> +'tést@xn----zfa.xe',
>> +'tést@subexample.wizard',
>> +'tést@[255.255.255.255]',
>> +'tést@[IPv6:2001:0db8:85a3:08d3:1319:8a2e:0370:7344]',
>> +'tést@[IPv6:2001::7344]',
>> +'tést@[IPv6:1111:2222:3333:4444:5555:6666:255.255.255.255]',
>> +'tést+reference@example.com',
>> +'üñîçøðé@example.com',
>> +'"üñîçøðé"@example.com',
>> +'DžǼ੧ఘⅧ⒇৪@example.com',
>> +);
>> +foreach ($values as $value) {
>> + var_dump(filter_var($value, FILTER_VALIDATE_EMAIL, FILTER_FLAG_EMAIL_RFC6531));
>> +}
>> +echo "Done\n";
>> +?>
>> +--EXPECT--
>> +string(26) "niceändsimple@example.com"
>> +string(25) "véry.çommon@example.com"
>> +string(44) "a.lîttle.lengthy.but.fiñe@dept.example.com"
>> +string(48) "dîsposable.style.émail.with+symbol@example.com"
>> +string(34) "other.émail-with-dash@example.com"
>> +string(35) "üser@[IPv6:2001:db8:1ff::a0b:dbd0]"
>> +string(43) ""verî.uñusual.@.uñusual.com"@example.com"
>> +string(74) ""verî.(),:;<>[]\".VERÎ.\"verî@\
>> \"verî\".unüsual"@strange.example.com"
>> +string(17) "tést@example.com"
>> +string(23) "tést.child@example.com"
>> +string(24) "tést@xn--exmple-cua.com"
>> +string(18) "tést@xn----zfa.xe"
>> +string(23) "tést@subexample.wizard"
>> +string(23) "tést@[255.255.255.255]"
>> +string(52) "tést@[IPv6:2001:0db8:85a3:08d3:1319:8a2e:0370:7344]"
>> +string(23) "tést@[IPv6:2001::7344]"
>> +string(58) "tést@[IPv6:1111:2222:3333:4444:5555:6666:255.255.255.255]"
>> +string(27) "tést+reference@example.com"
>> +string(26) "üñîçøðé@example.com"
>> +string(28) ""üñîçøðé"@example.com"
>> +string(31) "DžǼ੧ఘⅧ⒇৪@example.com"
>> +Done
>>
>>
>> --
>> PHP CVS Mailing List (http://www.php.net/)
>> To unsubscribe, visit: http://www.php.net/unsub.php
>>