Skip to content

Commit

Permalink
Merge pull request #11049 from dependabot/dev/brettfo/nuget-deseriali…
Browse files Browse the repository at this point in the history
…ze-dependency-info

filter out invalid requirement strings from array
  • Loading branch information
randhircs authored Dec 4, 2024
2 parents c98a329 + 926785f commit e49ff5f
Show file tree
Hide file tree
Showing 4 changed files with 94 additions and 26 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -1238,4 +1238,35 @@ await TestAnalyzeAsync(
}
);
}

[Fact]
public void DeserializeDependencyInfo_UnsupportedIgnoredVersionsAreIgnored()
{
// arrange
// "1.0.0.pre.rc2" isn't a valid NuGet version; ignore that requirement
var json = """
{
"Name": "Some.Package",
"Version": "1.10.0",
"IsVulnerable": false,
"IgnoredVersions": [
"> 1.0.0.pre.rc2, < 2",
"< 1.0.1"
],
"Vulnerabilities": []
}
""";

// act
var dependencyInfo = AnalyzeWorker.DeserializeDependencyInfo(json);

// assert
Assert.NotNull(dependencyInfo);
Assert.Equal("Some.Package", dependencyInfo.Name);
Assert.Equal("1.10.0", dependencyInfo.Version);
Assert.False(dependencyInfo.IsVulnerable);
Assert.Single(dependencyInfo.IgnoredVersions);
Assert.Equal("< 1.0.1", dependencyInfo.IgnoredVersions.Single().ToString());
Assert.Empty(dependencyInfo.Vulnerabilities);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ public partial class AnalyzeWorker : IAnalyzeWorker
internal static readonly JsonSerializerOptions SerializerOptions = new()
{
WriteIndented = true,
Converters = { new JsonStringEnumConverter(), new RequirementConverter() },
Converters = { new JsonStringEnumConverter(), new RequirementArrayConverter() },
};

public AnalyzeWorker(ILogger logger)
Expand All @@ -32,15 +32,15 @@ public AnalyzeWorker(ILogger logger)
public async Task RunAsync(string repoRoot, string discoveryPath, string dependencyPath, string analysisDirectory)
{
var analysisResult = await RunWithErrorHandlingAsync(repoRoot, discoveryPath, dependencyPath);
var dependencyInfo = await DeserializeJsonFileAsync<DependencyInfo>(dependencyPath, nameof(DependencyInfo));
var dependencyInfo = await DeserializeDependencyInfoFileAsync(dependencyPath);
await WriteResultsAsync(analysisDirectory, dependencyInfo.Name, analysisResult, _logger);
}

internal async Task<AnalysisResult> RunWithErrorHandlingAsync(string repoRoot, string discoveryPath, string dependencyPath)
{
AnalysisResult analysisResult;
var discovery = await DeserializeJsonFileAsync<WorkspaceDiscoveryResult>(discoveryPath, nameof(WorkspaceDiscoveryResult));
var dependencyInfo = await DeserializeJsonFileAsync<DependencyInfo>(dependencyPath, nameof(DependencyInfo));
var discovery = await DeserializeWorkspaceDiscoveryResultFileAsync(discoveryPath);
var dependencyInfo = await DeserializeDependencyInfoFileAsync(dependencyPath);

try
{
Expand Down Expand Up @@ -197,13 +197,28 @@ private static bool IsUpdateNecessary(DependencyInfo dependencyInfo, ImmutableAr
!d.IsTransitive));
}

internal static async Task<T> DeserializeJsonFileAsync<T>(string path, string fileType)
private static Task<WorkspaceDiscoveryResult> DeserializeWorkspaceDiscoveryResultFileAsync(string path)
{
var json = File.Exists(path)
? await File.ReadAllTextAsync(path)
: throw new FileNotFoundException($"{fileType} file not found.", path);
return DeserializeJsonFileAsync(path, nameof(WorkspaceDiscoveryResult), json => JsonSerializer.Deserialize<WorkspaceDiscoveryResult>(json, SerializerOptions));
}

private static Task<DependencyInfo> DeserializeDependencyInfoFileAsync(string path)
{
return DeserializeJsonFileAsync(path, nameof(DependencyInfo), DeserializeDependencyInfo);
}

internal static DependencyInfo? DeserializeDependencyInfo(string content)
{
return JsonSerializer.Deserialize<DependencyInfo>(content, SerializerOptions);
}

private static async Task<T> DeserializeJsonFileAsync<T>(string filePath, string fileType, Func<string, T?> deserializer)
{
var json = File.Exists(filePath)
? await File.ReadAllTextAsync(filePath)
: throw new FileNotFoundException($"{fileType} file not found.", filePath);

return JsonSerializer.Deserialize<T>(json, SerializerOptions)
return deserializer(json)
?? throw new InvalidOperationException($"{fileType} file is empty.");
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
using System.Collections.Immutable;
using System.Text.Json;
using System.Text.Json.Serialization;

namespace NuGetUpdater.Core.Analyze;

public class RequirementArrayConverter : JsonConverter<ImmutableArray<Requirement>>
{
public override ImmutableArray<Requirement> Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
var requirements = new List<Requirement>();
var requirementStrings = JsonSerializer.Deserialize<string[]>(ref reader, options) ?? [];
foreach (var requirementString in requirementStrings)
{
try
{
var requirement = Requirement.Parse(requirementString);
requirements.Add(requirement);
}
catch (ArgumentException)
{
// couldn't parse, nothing to do
}
}

return requirements.ToImmutableArray();
}

public override void Write(Utf8JsonWriter writer, ImmutableArray<Requirement> value, JsonSerializerOptions options)
{
writer.WriteStartArray();
foreach (var requirement in value)
{
writer.WriteStringValue(requirement.ToString());
}

writer.WriteEndArray();
}
}

This file was deleted.

0 comments on commit e49ff5f

Please sign in to comment.