Skip to content

Commit

Permalink
Avoid requesting duplicate uri to download next page which could lead…
Browse files Browse the repository at this point in the history
… to infinite loop.

Fix NuGet/Home#2891
  • Loading branch information
jainaashish committed Jun 20, 2016
1 parent a1b540b commit f80b4a8
Show file tree
Hide file tree
Showing 8 changed files with 233 additions and 3 deletions.
16 changes: 13 additions & 3 deletions src/NuGet.Core/NuGet.Protocol.Core.v3/LegacyFeed/V2FeedParser.cs
Expand Up @@ -373,9 +373,11 @@ private static string GetValue(XElement parent, XName childName)
CancellationToken token)
{
var results = new List<V2FeedPackageInfo>();
var uris = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
var page = 1;

var uri = string.Format("{0}{1}", _baseAddress, relativeUri);
uris.Add(uri);

// first request
Task<XDocument> docRequest = LoadXmlAsync(uri, ignoreNotFounds, log, token);
Expand All @@ -402,12 +404,20 @@ private static string GetValue(XElement parent, XName childName)
if (max < 0 || results.Count < max)
{
// Request the next url in parallel to parsing the current page
if (!string.IsNullOrEmpty(nextUri) && uri != nextUri)
if (!string.IsNullOrEmpty(nextUri))
{
// a bug on the server side causes the same next link to be returned
// for every page. To avoid falling into an infinite loop we must
// keep track here.
uri = nextUri;
// keep track of all uri and error out for any duplicate uri which means
// potential bug at server side.

if (!uris.Add(nextUri))
{
throw new FatalProtocolException(string.Format(
CultureInfo.CurrentCulture,
Strings.Protocol_duplicateUri,
nextUri));
}

docRequest = LoadXmlAsync(nextUri, ignoreNotFounds, log, token);
}
Expand Down
Expand Up @@ -150,6 +150,9 @@ private async Task<IEnumerable<PackageInfo>> FindPackagesByIdAsyncCore(string id
try
{
var results = new List<PackageInfo>();
var uris = new HashSet<string>(StringComparer.OrdinalIgnoreCase);

uris.Add(uri);
var page = 1;
while (true)
{
Expand Down Expand Up @@ -194,6 +197,15 @@ private async Task<IEnumerable<PackageInfo>> FindPackagesByIdAsyncCore(string id
break;
}

// check for any duplicate url and error out
if (!uris.Add(nextUri))
{
throw new FatalProtocolException(string.Format(
CultureInfo.CurrentCulture,
Strings.Protocol_duplicateUri,
nextUri));
}

uri = nextUri;
page++;
}
Expand Down
9 changes: 9 additions & 0 deletions src/NuGet.Core/NuGet.Protocol.Core.v3/Strings.Designer.cs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions src/NuGet.Core/NuGet.Protocol.Core.v3/Strings.resx
Expand Up @@ -342,4 +342,7 @@ The "ms" should be localized to the abbreviation for milliseconds.</comment>
<data name="NupkgPath_InvalidEx" xml:space="preserve">
<value>'{0}' is not a valid nupkg file. Error: '{1}'.</value>
</data>
<data name="Protocol_duplicateUri" xml:space="preserve">
<value>'{0}' is a duplicate url which has already been downloaded and will lead to a cyclic dependency. Please correct from server.</value>
</data>
</root>
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
Expand Down Expand Up @@ -582,5 +583,43 @@ public async Task V2FeedParser_NexusFindPackagesByIdNullDependencyRange()
Assert.Equal(VersionRange.All, latest.DependencySets.Single().Packages.Where(p => p.Id == "PackageB").Single().VersionRange);
Assert.Equal("any", latest.DependencySets.First().TargetFramework.GetShortFolderName());
}

[Fact]
public async Task V2FeedParser_DuplicateNextUrl()
{
// Arrange
var dupUrl =
"https://www.nuget.org/api/v2/FindPackagesById?id='ravendb.client'&$skiptoken='RavenDB.Client','1.2.2067-Unstable'";
var serviceAddress = TestUtility.CreateServiceAddress();

var responses = new Dictionary<string, string>();
responses.Add(serviceAddress + "FindPackagesById()?id='ravendb.client'",
TestUtility.GetResource("NuGet.Protocol.Core.v3.Tests.compiler.resources.CyclicDependency.xml", GetType()));
responses.Add(serviceAddress, string.Empty);
responses.Add(dupUrl,
TestUtility.GetResource("NuGet.Protocol.Core.v3.Tests.compiler.resources.CyclicDependencyPage1.xml", GetType()));
responses.Add("https://www.nuget.org/api/v2/FindPackagesById?id='ravendb.client'&$skiptoken='RavenDB.Client','2.0.2183-Unstable'",
TestUtility.GetResource("NuGet.Protocol.Core.v3.Tests.compiler.resources.CyclicDependencyPage2.xml", GetType()));

var httpSource = new TestHttpSource(new PackageSource(serviceAddress), responses);

V2FeedParser parser = new V2FeedParser(httpSource, serviceAddress);

FatalProtocolException duplicateUrlException = null;
try
{
// Act
var packages =
await parser.FindPackagesByIdAsync("ravendb.client", NullLogger.Instance, CancellationToken.None);
}
catch (FatalProtocolException ex)
{
duplicateUrlException = ex;
}

// Assert
Assert.NotNull(duplicateUrlException);
Assert.Equal(string.Format(CultureInfo.CurrentCulture, Strings.Protocol_duplicateUri, dupUrl), duplicateUrlException.Message);
}
}
}
@@ -0,0 +1,53 @@
<?xml version="1.0" encoding="utf-8"?>
<feed xml:base="https://www.nuget.org/api/v2/" xmlns="http://www.w3.org/2005/Atom" xmlns:d="http://schemas.microsoft.com/ado/2007/08/dataservices" xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata">
<id>https://www.nuget.org/api/v2/FindPackagesById</id>
<title type="text">FindPackagesById</title>
<updated>2016-02-17T01:35:06Z</updated>
<link rel="self" title="FindPackagesById" href="FindPackagesById" />
<entry>
<id>https://www.nuget.org/api/v2/Packages(Id='RavenDB.Client',Version='1.0.531')</id>
<category term="NuGetGallery.V2FeedPackage" scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" />
<link rel="edit" title="V2FeedPackage" href="Packages(Id='RavenDB.Client',Version='1.0.531')" />
<title type="text">RavenDB.Client</title>
<summary type="text"></summary>
<updated>2015-04-30T22:35:23Z</updated>
<author>
<name>Hibernating Rhinos</name>
</author>
<link rel="edit-media" title="V2FeedPackage" href="Packages(Id='RavenDB.Client',Version='1.0.531')/$value" />
<content type="application/zip" src="https://www.nuget.org/api/v2/package/RavenDB.Client/1.0.531" />
<m:properties>
<d:Version>1.0.531</d:Version>
<d:NormalizedVersion>1.0.531</d:NormalizedVersion>
<d:Copyright>Copyright 2011</d:Copyright>
<d:Created m:type="Edm.DateTime">2011-12-12T02:15:35.653</d:Created>
<d:Dependencies>NLog:[2.0.0.2000]|Newtonsoft.Json:[4.0.5]|AsyncCTP:[0.3]</d:Dependencies>
<d:Description>This is the client only for Raven which is a document database for the .NET/Windows platform, offering a flexible data model design to fit the needs of real world systems.</d:Description>
<d:DownloadCount m:type="Edm.Int32">501741</d:DownloadCount>
<d:GalleryDetailsUrl>https://www.nuget.org/packages/RavenDB.Client/1.0.531</d:GalleryDetailsUrl>
<d:IconUrl>http://static.ravendb.net/logo-for-nuget.png</d:IconUrl>
<d:IsLatestVersion m:type="Edm.Boolean">false</d:IsLatestVersion>
<d:IsAbsoluteLatestVersion m:type="Edm.Boolean">false</d:IsAbsoluteLatestVersion>
<d:IsPrerelease m:type="Edm.Boolean">false</d:IsPrerelease>
<d:Language m:null="true" />
<d:Published m:type="Edm.DateTime">1900-01-01T00:00:00</d:Published>
<d:PackageHash>/vQRNvohpcR62tWU77evahBTwVemJIAygKtMkMKauXinwhDWenGIIUn/r8F1ACXumpfJ+96fiPKp21SREv0Prg==</d:PackageHash>
<d:PackageHashAlgorithm>SHA512</d:PackageHashAlgorithm>
<d:PackageSize m:type="Edm.Int64">167051</d:PackageSize>
<d:ProjectUrl>http://www.ravendb.net/</d:ProjectUrl>
<d:ReportAbuseUrl>https://www.nuget.org/package/ReportAbuse/RavenDB.Client/1.0.531</d:ReportAbuseUrl>
<d:ReleaseNotes m:null="true" />
<d:RequireLicenseAcceptance m:type="Edm.Boolean">true</d:RequireLicenseAcceptance>
<d:Summary m:null="true" />
<d:Tags xml:space="preserve"> nosql ravendb raven document database </d:Tags>
<d:Title>RavenDB (Client Only)</d:Title>
<d:VersionDownloadCount m:type="Edm.Int32">155</d:VersionDownloadCount>
<d:MinClientVersion m:null="true" />
<d:LastEdited m:type="Edm.DateTime" m:null="true" />
<d:LicenseUrl>http://www.ravendb.net/licensing</d:LicenseUrl>
<d:LicenseNames m:null="true" />
<d:LicenseReportUrl m:null="true" />
</m:properties>
</entry>
<link rel="next" href="https://www.nuget.org/api/v2/FindPackagesById?id='ravendb.client'&amp;$skiptoken='RavenDB.Client','1.2.2067-Unstable'" />
</feed>
@@ -0,0 +1,52 @@
<?xml version="1.0" encoding="utf-8"?>
<feed xml:base="https://www.nuget.org/api/v2/" xmlns="http://www.w3.org/2005/Atom" xmlns:d="http://schemas.microsoft.com/ado/2007/08/dataservices" xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata">
<id>https://www.nuget.org/api/v2/FindPackagesById</id>
<title type="text">FindPackagesById</title>
<updated>2016-02-17T01:37:00Z</updated>
<link rel="self" title="FindPackagesById" href="FindPackagesById" />
<entry>
<id>https://www.nuget.org/api/v2/Packages(Id='RavenDB.Client',Version='1.2.2068-Unstable')</id>
<category term="NuGetGallery.V2FeedPackage" scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" />
<link rel="edit" title="V2FeedPackage" href="Packages(Id='RavenDB.Client',Version='1.2.2068-Unstable')" />
<title type="text">RavenDB.Client</title>
<summary type="text">This package includes the client API of RavenDB.</summary>
<updated>2015-04-20T03:53:56Z</updated>
<author>
<name>Hibernating Rhinos</name>
</author>
<link rel="edit-media" title="V2FeedPackage" href="Packages(Id='RavenDB.Client',Version='1.2.2068-Unstable')/$value" />
<content type="application/zip" src="https://www.nuget.org/api/v2/package/RavenDB.Client/1.2.2068-Unstable" />
<m:properties>
<d:Version>1.2.2068-Unstable</d:Version>
<d:NormalizedVersion>1.2.2068-Unstable</d:NormalizedVersion>
<d:Copyright m:null="true" />
<d:Created m:type="Edm.DateTime">2012-08-22T09:46:43.48</d:Created>
<d:Dependencies></d:Dependencies>
<d:Description>This package includes the client API of RavenDB. RavenDB is a document database for the .NET platform, offering a flexible data model design to fit the needs of real world systems.</d:Description>
<d:DownloadCount m:type="Edm.Int32">501741</d:DownloadCount>
<d:GalleryDetailsUrl>https://www.nuget.org/packages/RavenDB.Client/1.2.2068-Unstable</d:GalleryDetailsUrl>
<d:IconUrl>http://static.ravendb.net/logo-for-nuget.png</d:IconUrl>
<d:IsLatestVersion m:type="Edm.Boolean">false</d:IsLatestVersion>
<d:IsAbsoluteLatestVersion m:type="Edm.Boolean">false</d:IsAbsoluteLatestVersion>
<d:IsPrerelease m:type="Edm.Boolean">true</d:IsPrerelease>
<d:Language>en-US</d:Language>
<d:Published m:type="Edm.DateTime">2012-08-22T09:46:43.48</d:Published>
<d:PackageHash>gMALeuyi3Xekunq5gnMCgHf43+hea+9W0SKDhdnE0HuTOHfA2uU389ZvdmYocAHlR/QtlC2VZOJ7SywHyoXV2w==</d:PackageHash>
<d:PackageHashAlgorithm>SHA512</d:PackageHashAlgorithm>
<d:PackageSize m:type="Edm.Int64">4066418</d:PackageSize>
<d:ProjectUrl>http://www.ravendb.net/</d:ProjectUrl>
<d:ReportAbuseUrl>https://www.nuget.org/package/ReportAbuse/RavenDB.Client/1.2.2068-Unstable</d:ReportAbuseUrl>
<d:ReleaseNotes m:null="true" />
<d:RequireLicenseAcceptance m:type="Edm.Boolean">true</d:RequireLicenseAcceptance>
<d:Tags xml:space="preserve"> nosql ravendb raven document database client </d:Tags>
<d:Title>RavenDB Client</d:Title>
<d:VersionDownloadCount m:type="Edm.Int32">178</d:VersionDownloadCount>
<d:MinClientVersion m:null="true" />
<d:LastEdited m:type="Edm.DateTime" m:null="true" />
<d:LicenseUrl>http://www.ravendb.net/licensing</d:LicenseUrl>
<d:LicenseNames m:null="true" />
<d:LicenseReportUrl m:null="true" />
</m:properties>
</entry>
<link rel="next" href="https://www.nuget.org/api/v2/FindPackagesById?id='ravendb.client'&amp;$skiptoken='RavenDB.Client','2.0.2183-Unstable'" />
</feed>
@@ -0,0 +1,52 @@
<?xml version="1.0" encoding="utf-8"?>
<feed xml:base="https://www.nuget.org/api/v2/" xmlns="http://www.w3.org/2005/Atom" xmlns:d="http://schemas.microsoft.com/ado/2007/08/dataservices" xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata">
<id>https://www.nuget.org/api/v2/FindPackagesById</id>
<title type="text">FindPackagesById</title>
<updated>2016-02-17T01:41:51Z</updated>
<link rel="self" title="FindPackagesById" href="FindPackagesById" />
<entry>
<id>https://www.nuget.org/api/v2/Packages(Id='RavenDB.Client',Version='2.0.2184-Unstable')</id>
<category term="NuGetGallery.V2FeedPackage" scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" />
<link rel="edit" title="V2FeedPackage" href="Packages(Id='RavenDB.Client',Version='2.0.2184-Unstable')" />
<title type="text">RavenDB.Client</title>
<summary type="text">This package includes the client API of RavenDB.</summary>
<updated>2015-04-20T03:58:59Z</updated>
<author>
<name>Hibernating Rhinos</name>
</author>
<link rel="edit-media" title="V2FeedPackage" href="Packages(Id='RavenDB.Client',Version='2.0.2184-Unstable')/$value" />
<content type="application/zip" src="https://www.nuget.org/api/v2/package/RavenDB.Client/2.0.2184-Unstable" />
<m:properties>
<d:Version>2.0.2184-Unstable</d:Version>
<d:NormalizedVersion>2.0.2184-Unstable</d:NormalizedVersion>
<d:Copyright m:null="true" />
<d:Created m:type="Edm.DateTime">2012-12-27T00:34:59.4</d:Created>
<d:Dependencies></d:Dependencies>
<d:Description>This package includes the client API of RavenDB. RavenDB is a document database for the .NET platform, offering a flexible data model design to fit the needs of real world systems.</d:Description>
<d:DownloadCount m:type="Edm.Int32">501741</d:DownloadCount>
<d:GalleryDetailsUrl>https://www.nuget.org/packages/RavenDB.Client/2.0.2184-Unstable</d:GalleryDetailsUrl>
<d:IconUrl>http://static.ravendb.net/logo-for-nuget.png</d:IconUrl>
<d:IsLatestVersion m:type="Edm.Boolean">false</d:IsLatestVersion>
<d:IsAbsoluteLatestVersion m:type="Edm.Boolean">false</d:IsAbsoluteLatestVersion>
<d:IsPrerelease m:type="Edm.Boolean">true</d:IsPrerelease>
<d:Language>en-US</d:Language>
<d:Published m:type="Edm.DateTime">2012-12-27T00:34:59.4</d:Published>
<d:PackageHash>PpQ23WcyHAAgUs+d9ub0aIrbT4HDgTghXnkFmD59jZwsFruSqYpvXK0h268lAjaXCctnGmiLUmRjwxDn0C5iZA==</d:PackageHash>
<d:PackageHashAlgorithm>SHA512</d:PackageHashAlgorithm>
<d:PackageSize m:type="Edm.Int64">3487446</d:PackageSize>
<d:ProjectUrl>http://www.ravendb.net/</d:ProjectUrl>
<d:ReportAbuseUrl>https://www.nuget.org/package/ReportAbuse/RavenDB.Client/2.0.2184-Unstable</d:ReportAbuseUrl>
<d:ReleaseNotes m:null="true" />
<d:RequireLicenseAcceptance m:type="Edm.Boolean">true</d:RequireLicenseAcceptance>
<d:Tags xml:space="preserve"> nosql ravendb raven document database client </d:Tags>
<d:Title>RavenDB Client</d:Title>
<d:VersionDownloadCount m:type="Edm.Int32">96</d:VersionDownloadCount>
<d:MinClientVersion m:null="true" />
<d:LastEdited m:type="Edm.DateTime" m:null="true" />
<d:LicenseUrl>http://www.ravendb.net/licensing</d:LicenseUrl>
<d:LicenseNames m:null="true" />
<d:LicenseReportUrl m:null="true" />
</m:properties>
</entry>
<link rel="next" href="https://www.nuget.org/api/v2/FindPackagesById?id='ravendb.client'&amp;$skiptoken='RavenDB.Client','1.2.2067-Unstable'" />
</feed>

0 comments on commit f80b4a8

Please sign in to comment.