summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEugen Wissner <belka@caraus.de>2017-07-17 04:57:33 +0200
committerEugen Wissner <belka@caraus.de>2017-07-17 04:57:33 +0200
commite5fb95ceb03c6e6adb649f96e13293133346ed2a (patch)
tree811bc1a232fe703400d5b3be1e1ae98d51e81fac
parent9ef5986288172fd9505ec88e51dee839c7eab32f (diff)
downloadtanya-e5fb95ceb03c6e6adb649f96e13293133346ed2a.tar.gz
Fix #254
network.url Range violation. Add a check after parsing "scheme://" whether only the scheme is available.
-rw-r--r--source/tanya/net/uri.d43
1 files changed, 27 insertions, 16 deletions
diff --git a/source/tanya/net/uri.d b/source/tanya/net/uri.d
index da90011..74ab38e 100644
--- a/source/tanya/net/uri.d
+++ b/source/tanya/net/uri.d
@@ -69,14 +69,14 @@ struct URL
/**
* Attempts to parse an URL from a string.
* Output string data (scheme, user, etc.) are just slices of input string
- * (e.g., no memory allocation and copying).
+ * (i.e., no memory allocation and copying).
*
* Params:
* source = The string containing the URL.
*
* Throws: $(D_PSYMBOL URIException) if the URL is malformed.
*/
- this(const char[] source) @nogc
+ this(const char[] source) pure @nogc
{
auto value = source;
ptrdiff_t pos = -1, endPos = value.length, start;
@@ -94,15 +94,15 @@ struct URL
}
// Check if the colon is a part of the scheme or the port and parse
- // the appropriate part
+ // the appropriate part.
if (value.length > 1 && value[0] == '/' && value[1] == '/')
{
- // Relative scheme
+ // Relative scheme.
start = 2;
}
else if (pos > 0)
{
- // Validate scheme
+ // Validate scheme:
// [ toLower(alpha) | digit | "+" | "-" | "." ]
foreach (ref c; value[0 .. pos])
{
@@ -120,7 +120,7 @@ struct URL
}
}
- if (value.length == pos + 1) // only scheme is available
+ if (value.length == pos + 1) // only "scheme:" is available.
{
this.scheme = value[0 .. $ - 1];
return;
@@ -132,11 +132,15 @@ struct URL
if (value.length > pos + 2 && value[pos + 2] == '/')
{
start = pos + 3;
- if (this.scheme == "file"
- && value.length > start
- && value[start] == '/')
+
+ if (value.length <= start)
+ {
+ // Only "scheme://" is available.
+ return;
+ }
+ if (this.scheme == "file" && value[start] == '/')
{
- // Windows drive letters
+ // Windows drive letters.
if (value.length - start > 2 && value[start + 2] == ':')
{
++start;
@@ -164,7 +168,7 @@ struct URL
}
else if (pos == 0 && parsePort(value[pos .. $]))
{
- // An URL shouldn't begin with a port number
+ // An URL shouldn't begin with a port number.
throw defaultAllocator.make!URIException("URL begins with port");
}
else
@@ -172,7 +176,7 @@ struct URL
goto ParsePath;
}
- // Parse host
+ // Parse host.
pos = -1;
for (ptrdiff_t i = start; i < value.length; ++i)
{
@@ -187,7 +191,7 @@ struct URL
}
}
- // Check for login and password
+ // Check for login and password.
if (pos != -1)
{
// *( unreserved / pct-encoded / sub-delims / ":" )
@@ -226,8 +230,8 @@ struct URL
pos = endPos;
if (endPos <= 1 || value[start] != '[' || value[endPos - 1] != ']')
{
- // Short circuit portscan
- // IPv6 embedded address
+ // Short circuit portscan.
+ // IPv6 embedded address.
for (ptrdiff_t i = endPos - 1; i >= start; --i)
{
if (value[i] == ':')
@@ -243,7 +247,7 @@ struct URL
}
}
- // Check if we have a valid host, if we don't reject the string as url
+ // Check if we have a valid host, if we don't reject the string as URL.
if (pos <= start)
{
this.scheme = this.user = this.pass = null;
@@ -534,6 +538,13 @@ private @nogc unittest
defaultAllocator.dispose(exception);
}
+// Issue 254: https://issues.caraus.io/issues/254.
+private @system @nogc unittest
+{
+ auto u = URL("ftp://");
+ assert(u.scheme == "ftp");
+}
+
/**
* Attempts to parse an URL from a string and returns the specified component
* of the URL or $(D_PSYMBOL URL) if no component is specified.