Fixed: Stream leakage inside CurlHttpDispatcher

pull/3227/head
Leonardo Galli 6 years ago
parent d02d71c336
commit 899bd086ec

@ -66,95 +66,96 @@ namespace NzbDrone.Common.Http.Dispatchers
lock (CurlGlobalHandle.Instance) lock (CurlGlobalHandle.Instance)
{ {
Stream responseStream = new MemoryStream(); using (Stream responseStream = new MemoryStream())
Stream headerStream = new MemoryStream(); using (Stream headerStream = new MemoryStream())
using (var curlEasy = new CurlEasy())
{ {
curlEasy.AutoReferer = false; using (var curlEasy = new CurlEasy())
curlEasy.WriteFunction = (b, s, n, o) =>
{
responseStream.Write(b, 0, s * n);
return s * n;
};
curlEasy.HeaderFunction = (b, s, n, o) =>
{
headerStream.Write(b, 0, s * n);
return s * n;
};
AddProxy(curlEasy, request);
curlEasy.Url = request.Url.FullUri;
switch (request.Method)
{
case HttpMethod.GET:
curlEasy.HttpGet = true;
break;
case HttpMethod.POST:
curlEasy.Post = true;
break;
case HttpMethod.PUT:
curlEasy.Put = true;
break;
default:
throw new NotSupportedException(string.Format("HttpCurl method {0} not supported", request.Method));
}
curlEasy.FollowLocation = false;
curlEasy.UserAgent = request.UseSimplifiedUserAgent ? UserAgentBuilder.UserAgentSimplified : UserAgentBuilder.UserAgent; ;
if (request.RequestTimeout != TimeSpan.Zero)
{
curlEasy.Timeout = (int)Math.Ceiling(request.RequestTimeout.TotalSeconds);
}
if (OsInfo.IsWindows)
{
curlEasy.CaInfo = _caBundleFilePath;
}
if (cookies != null)
{
curlEasy.Cookie = cookies.GetCookieHeader((Uri)request.Url);
}
if (request.ContentData != null)
{
curlEasy.PostFieldSize = request.ContentData.Length;
curlEasy.SetOpt(CurlOption.CopyPostFields, new string(Array.ConvertAll(request.ContentData, v => (char)v)));
}
// Yes, we have to keep a ref to the object to prevent corrupting the unmanaged state
using (var httpRequestHeaders = SerializeHeaders(request))
{ {
curlEasy.HttpHeader = httpRequestHeaders; curlEasy.AutoReferer = false;
curlEasy.WriteFunction = (b, s, n, o) =>
var result = curlEasy.Perform(); {
responseStream.Write(b, 0, s * n);
if (result != CurlCode.Ok) return s * n;
};
curlEasy.HeaderFunction = (b, s, n, o) =>
{
headerStream.Write(b, 0, s * n);
return s * n;
};
AddProxy(curlEasy, request);
curlEasy.Url = request.Url.FullUri;
switch (request.Method)
{
case HttpMethod.GET:
curlEasy.HttpGet = true;
break;
case HttpMethod.POST:
curlEasy.Post = true;
break;
case HttpMethod.PUT:
curlEasy.Put = true;
break;
default:
throw new NotSupportedException(string.Format("HttpCurl method {0} not supported", request.Method));
}
curlEasy.FollowLocation = false;
curlEasy.UserAgent = request.UseSimplifiedUserAgent ? UserAgentBuilder.UserAgentSimplified : UserAgentBuilder.UserAgent; ;
if (request.RequestTimeout != TimeSpan.Zero)
{
curlEasy.Timeout = (int)Math.Ceiling(request.RequestTimeout.TotalSeconds);
}
if (OsInfo.IsWindows)
{
curlEasy.CaInfo = _caBundleFilePath;
}
if (cookies != null)
{
curlEasy.Cookie = cookies.GetCookieHeader((Uri)request.Url);
}
if (request.ContentData != null)
{ {
switch (result) curlEasy.PostFieldSize = request.ContentData.Length;
curlEasy.SetOpt(CurlOption.CopyPostFields, new string(Array.ConvertAll(request.ContentData, v => (char)v)));
}
// Yes, we have to keep a ref to the object to prevent corrupting the unmanaged state
using (var httpRequestHeaders = SerializeHeaders(request))
{
curlEasy.HttpHeader = httpRequestHeaders;
var result = curlEasy.Perform();
if (result != CurlCode.Ok)
{ {
case CurlCode.SslCaCert: switch (result)
case (CurlCode)77: {
throw new WebException(string.Format("Curl Error {0} for Url {1}, issues with your operating system SSL Root Certificate Bundle (ca-bundle).", result, curlEasy.Url)); case CurlCode.SslCaCert:
default: case (CurlCode)77:
throw new WebException(string.Format("Curl Error {0} for Url {1}", result, curlEasy.Url)); throw new WebException(string.Format("Curl Error {0} for Url {1}, issues with your operating system SSL Root Certificate Bundle (ca-bundle).", result, curlEasy.Url));
default:
throw new WebException(string.Format("Curl Error {0} for Url {1}", result, curlEasy.Url));
}
} }
} }
var webHeaderCollection = ProcessHeaderStream(request, cookies, headerStream);
var responseData = ProcessResponseStream(request, responseStream, webHeaderCollection);
var httpHeader = new HttpHeader(webHeaderCollection);
return new HttpResponse(request, httpHeader, responseData, (HttpStatusCode)curlEasy.ResponseCode);
} }
var webHeaderCollection = ProcessHeaderStream(request, cookies, headerStream);
var responseData = ProcessResponseStream(request, responseStream, webHeaderCollection);
var httpHeader = new HttpHeader(webHeaderCollection);
return new HttpResponse(request, httpHeader, responseData, (HttpStatusCode)curlEasy.ResponseCode);
} }
} }
} }
@ -259,6 +260,7 @@ namespace NzbDrone.Common.Http.Dispatchers
private byte[] ProcessResponseStream(HttpRequest request, Stream responseStream, WebHeaderCollection webHeaderCollection) private byte[] ProcessResponseStream(HttpRequest request, Stream responseStream, WebHeaderCollection webHeaderCollection)
{ {
byte[] bytes = null;
responseStream.Position = 0; responseStream.Position = 0;
if (responseStream.Length != 0) if (responseStream.Length != 0)
@ -268,21 +270,27 @@ namespace NzbDrone.Common.Http.Dispatchers
{ {
if (encoding.IndexOf("gzip") != -1) if (encoding.IndexOf("gzip") != -1)
{ {
responseStream = new GZipStream(responseStream, CompressionMode.Decompress); using (var zipStream = new GZipStream(responseStream, CompressionMode.Decompress))
{
bytes = zipStream.ToBytes();
}
webHeaderCollection.Remove("Content-Encoding"); webHeaderCollection.Remove("Content-Encoding");
} }
else if (encoding.IndexOf("deflate") != -1) else if (encoding.IndexOf("deflate") != -1)
{ {
responseStream = new DeflateStream(responseStream, CompressionMode.Decompress); using (var deflateStream = new DeflateStream(responseStream, CompressionMode.Decompress))
{
bytes = deflateStream.ToBytes();
}
webHeaderCollection.Remove("Content-Encoding"); webHeaderCollection.Remove("Content-Encoding");
} }
} }
} }
return responseStream.ToBytes(); if (bytes == null) bytes = responseStream.ToBytes();
return bytes;
} }
} }

Loading…
Cancel
Save