Fix #254
network.url Range violation. Add a check after parsing "scheme://" whether only the scheme is available.
This commit is contained in:
parent
9ef5986288
commit
e5fb95ceb0
@ -69,14 +69,14 @@ struct URL
|
|||||||
/**
|
/**
|
||||||
* Attempts to parse an URL from a string.
|
* Attempts to parse an URL from a string.
|
||||||
* Output string data (scheme, user, etc.) are just slices of input 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:
|
* Params:
|
||||||
* source = The string containing the URL.
|
* source = The string containing the URL.
|
||||||
*
|
*
|
||||||
* Throws: $(D_PSYMBOL URIException) if the URL is malformed.
|
* Throws: $(D_PSYMBOL URIException) if the URL is malformed.
|
||||||
*/
|
*/
|
||||||
this(const char[] source) @nogc
|
this(const char[] source) pure @nogc
|
||||||
{
|
{
|
||||||
auto value = source;
|
auto value = source;
|
||||||
ptrdiff_t pos = -1, endPos = value.length, start;
|
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
|
// 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] == '/')
|
if (value.length > 1 && value[0] == '/' && value[1] == '/')
|
||||||
{
|
{
|
||||||
// Relative scheme
|
// Relative scheme.
|
||||||
start = 2;
|
start = 2;
|
||||||
}
|
}
|
||||||
else if (pos > 0)
|
else if (pos > 0)
|
||||||
{
|
{
|
||||||
// Validate scheme
|
// Validate scheme:
|
||||||
// [ toLower(alpha) | digit | "+" | "-" | "." ]
|
// [ toLower(alpha) | digit | "+" | "-" | "." ]
|
||||||
foreach (ref c; value[0 .. pos])
|
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];
|
this.scheme = value[0 .. $ - 1];
|
||||||
return;
|
return;
|
||||||
@ -132,11 +132,15 @@ struct URL
|
|||||||
if (value.length > pos + 2 && value[pos + 2] == '/')
|
if (value.length > pos + 2 && value[pos + 2] == '/')
|
||||||
{
|
{
|
||||||
start = pos + 3;
|
start = pos + 3;
|
||||||
if (this.scheme == "file"
|
|
||||||
&& value.length > start
|
if (value.length <= start)
|
||||||
&& value[start] == '/')
|
|
||||||
{
|
{
|
||||||
// Windows drive letters
|
// Only "scheme://" is available.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (this.scheme == "file" && value[start] == '/')
|
||||||
|
{
|
||||||
|
// Windows drive letters.
|
||||||
if (value.length - start > 2 && value[start + 2] == ':')
|
if (value.length - start > 2 && value[start + 2] == ':')
|
||||||
{
|
{
|
||||||
++start;
|
++start;
|
||||||
@ -164,7 +168,7 @@ struct URL
|
|||||||
}
|
}
|
||||||
else if (pos == 0 && parsePort(value[pos .. $]))
|
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");
|
throw defaultAllocator.make!URIException("URL begins with port");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -172,7 +176,7 @@ struct URL
|
|||||||
goto ParsePath;
|
goto ParsePath;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Parse host
|
// Parse host.
|
||||||
pos = -1;
|
pos = -1;
|
||||||
for (ptrdiff_t i = start; i < value.length; ++i)
|
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)
|
if (pos != -1)
|
||||||
{
|
{
|
||||||
// *( unreserved / pct-encoded / sub-delims / ":" )
|
// *( unreserved / pct-encoded / sub-delims / ":" )
|
||||||
@ -226,8 +230,8 @@ struct URL
|
|||||||
pos = endPos;
|
pos = endPos;
|
||||||
if (endPos <= 1 || value[start] != '[' || value[endPos - 1] != ']')
|
if (endPos <= 1 || value[start] != '[' || value[endPos - 1] != ']')
|
||||||
{
|
{
|
||||||
// Short circuit portscan
|
// Short circuit portscan.
|
||||||
// IPv6 embedded address
|
// IPv6 embedded address.
|
||||||
for (ptrdiff_t i = endPos - 1; i >= start; --i)
|
for (ptrdiff_t i = endPos - 1; i >= start; --i)
|
||||||
{
|
{
|
||||||
if (value[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)
|
if (pos <= start)
|
||||||
{
|
{
|
||||||
this.scheme = this.user = this.pass = null;
|
this.scheme = this.user = this.pass = null;
|
||||||
@ -534,6 +538,13 @@ private @nogc unittest
|
|||||||
defaultAllocator.dispose(exception);
|
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
|
* 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.
|
* of the URL or $(D_PSYMBOL URL) if no component is specified.
|
||||||
|
Loading…
Reference in New Issue
Block a user