Allow IDNA/punycode hosts
authorMichael Wallner <mike@php.net>
Wed, 1 Jun 2016 07:28:08 +0000 (09:28 +0200)
committerMichael Wallner <mike@php.net>
Wed, 1 Jun 2016 07:28:08 +0000 (09:28 +0200)
Closes #42

src/php_http_url.c
tests/gh-issue42.phpt [new file with mode: 0644]

index 07121df42c0d9c7992e72c92a70639ec0520e7fc..9140c6824e32ad2a7819b20982fd322d4e111187 100644 (file)
@@ -1095,9 +1095,7 @@ static ZEND_RESULT_CODE parse_hostinfo(struct parse_state *state, const char *pt
                        state->buffer[state->offset++] = *ptr;
                        break;
 
-               case '!': case '$': case '&': case '\'': case '(': case ')': case '*':
-               case '+': case ',': case ';': case '=': /* sub-delims */
-               case '-': case '.': case '_': case '~': /* unreserved */
+               case '.':
                        if (port || !label) {
                                /* sort of a compromise, just ensure we don't end up
                                 * with a dot at the beginning or two consecutive dots
@@ -1112,6 +1110,21 @@ static ZEND_RESULT_CODE parse_hostinfo(struct parse_state *state, const char *pt
                        label = NULL;
                        break;
 
+               case '-':
+                       if (!label) {
+                               /* sort of a compromise, just ensure we don't end up
+                                * with a hyphen at the beginning
+                                */
+                               php_error_docref(NULL TSRMLS_CC, E_WARNING,
+                                               "Failed to parse %s; unexpected '%c' at pos %u in '%s'",
+                                               port ? "port" : "host",
+                                               (unsigned char) *ptr, (unsigned) (ptr - tmp), tmp);
+                               return FAILURE;
+                       }
+                       /* no break */
+               case '_': case '~': /* unreserved */
+               case '!': case '$': case '&': case '\'': case '(': case ')': case '*':
+               case '+': case ',': case ';': case '=': /* sub-delims */
                case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': case 'G':
                case 'H': case 'I': case 'J': case 'K': case 'L': case 'M': case 'N':
                case 'O': case 'P': case 'Q': case 'R': case 'S': case 'T': case 'U':
diff --git a/tests/gh-issue42.phpt b/tests/gh-issue42.phpt
new file mode 100644 (file)
index 0000000..a6f9ded
--- /dev/null
@@ -0,0 +1,16 @@
+--TEST--
+URL barfs on punycode
+--SKIPIF--
+<?php
+include "./skipif.inc";
+?>
+--FILE--
+<?php 
+echo "Test\n";
+echo new http\Url("http://www.xn--kln-sna.de"), "\n";
+?>
+===DONE===
+--EXPECT--
+Test
+http://www.xn--kln-sna.de/
+===DONE===