You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

112 lines
3.1 KiB

From: Markus Koschany <apo@debian.org>
Date: Mon, 27 Mar 2017 21:56:37 +0200
Subject: CVE-2017-7272
Bug-Upstream: https://bugs.php.net/bug.php?id=74216
Origin: https://github.com/php/php-src/commit/bab0b99f376dac9170ac81382a5ed526938d595a
---
ext/standard/tests/streams/parseip-001.phpt | 37 +++++++++++++++++++++++++++++
main/streams/xp_socket.c | 27 ++++++++++++---------
2 files changed, 53 insertions(+), 11 deletions(-)
create mode 100644 ext/standard/tests/streams/parseip-001.phpt
diff --git a/ext/standard/tests/streams/parseip-001.phpt b/ext/standard/tests/streams/parseip-001.phpt
new file mode 100644
index 0000000..594756d
--- /dev/null
+++ b/ext/standard/tests/streams/parseip-001.phpt
@@ -0,0 +1,37 @@
+--TEST--
+Use of double-port in fsockopen()
+--FILE--
+<?php
+
+$try = [
+ '127.0.0.1:80',
+ 'tcp://127.0.0.1:80',
+ '[::1]:80',
+ 'tcp://[::1]:80',
+ 'localhost:80',
+ 'tcp://localhost:80',
+];
+
+foreach ($try as $addr) {
+ echo "== $addr ==\n";
+ var_dump(@fsockopen($addr, 81, $errno, $errstr), $errstr);
+}
+--EXPECTF--
+== 127.0.0.1:80 ==
+bool(false)
+string(41) "Failed to parse address "127.0.0.1:80:81""
+== tcp://127.0.0.1:80 ==
+bool(false)
+string(41) "Failed to parse address "127.0.0.1:80:81""
+== [::1]:80 ==
+bool(false)
+string(37) "Failed to parse address "[::1]:80:81""
+== tcp://[::1]:80 ==
+bool(false)
+string(37) "Failed to parse address "[::1]:80:81""
+== localhost:80 ==
+bool(false)
+string(41) "Failed to parse address "localhost:80:81""
+== tcp://localhost:80 ==
+bool(false)
+string(41) "Failed to parse address "localhost:80:81""
\ No newline at end of file
diff --git a/main/streams/xp_socket.c b/main/streams/xp_socket.c
index 53f0769..80bf6a7 100644
--- a/main/streams/xp_socket.c
+++ b/main/streams/xp_socket.c
@@ -527,18 +527,23 @@ static inline char *parse_ip_address_ex(const char *str, int str_len, int *portn
char *host = NULL;
#ifdef HAVE_IPV6
- char *p;
if (*(str) == '[' && str_len > 1) {
/* IPV6 notation to specify raw address with port (i.e. [fe80::1]:80) */
- p = memchr(str + 1, ']', str_len - 2);
+ char *p = memchr(str + 1, ']', str_len - 2), *e = NULL;
if (!p || *(p + 1) != ':') {
if (get_err) {
spprintf(err, 0, "Failed to parse IPv6 address \"%s\"", str);
}
return NULL;
}
- *portno = atoi(p + 2);
+ *portno = strtol(p + 2, &e, 10);
+ if (e && *e) {
+ if (get_err) {
+ spprintf(err, 0, "Failed to parse address \"%s\"", str);
+ }
+ return NULL;
+ }
return estrndup(str + 1, p - str - 1);
}
#endif
@@ -548,16 +553,16 @@ static inline char *parse_ip_address_ex(const char *str, int str_len, int *portn
colon = NULL;
}
if (colon) {
- *portno = atoi(colon + 1);
- host = estrndup(str, colon - str);
- } else {
- if (get_err) {
- spprintf(err, 0, "Failed to parse address \"%s\"", str);
+ char *e = NULL;
+ *portno = strtol(colon + 1, &e, 10);
+ if (!e || !*e) {
+ return estrndup(str, colon - str);
}
- return NULL;
}
-
- return host;
+ if (get_err) {
+ spprintf(err, 0, "Failed to parse address \"%s\"", str);
+ }
+ return NULL;
}
static inline char *parse_ip_address(php_stream_xport_param *xparam, int *portno TSRMLS_DC)