Skip to content

HybridCache: tags parsing issue breaks remove by tags behavior #6833

@Oleg52

Description

@Oleg52

Description

I see Cache backend data rejected: ParseFault. warning when calling GetOrCreateAsync without providing tags. I'm passing a key that i had previously added with 2 or more tags. I'm using Redis as a backend cache.

Reproduction Steps

using Microsoft.Extensions.Caching.Hybrid;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddStackExchangeRedisCache(options => { options.Configuration = "127.0.0.1:6379"; });
builder.Services.AddHybridCache();

var app = builder.Build();

app.MapGet("/tags", async (HybridCache hybridCache) =>
{
    string[] tags = ["tag1", "tag2"];
    return await hybridCache.GetOrCreateAsync("key", _ => ValueTask.FromResult("data"), tags: tags);
});

app.MapGet("/no-tags", async (HybridCache hybridCache) =>
{
    return await hybridCache.GetOrCreateAsync("key", _ => ValueTask.FromResult("data"));
});

app.Run();
  1. Run app and send GET request on /tags.
  2. Re-run app and send GET request on /no-tags.

Expected behavior

No warning is shown

Actual behavior

I get this warning:

      Cache backend data rejected: ParseFault.
      System.ArgumentException: Destination array was not long enough. Check the destination index, length, and the array's lower bounds. (Parameter 'destinationArray')
         at System.Array.CopyImpl(Array sourceArray, Int32 sourceIndex, Array destinationArray, Int32 destinationIndex, Int32 length, Boolean reliable)
         at System.Array.Copy(Array sourceArray, Int32 sourceIndex, Array destinationArray, Int32 destinationIndex, Int32 length)
         at System.Array.CopyTo(Array array, Int32 index)
         at Microsoft.Extensions.Caching.Hybrid.Internal.HybridCachePayload.TryParse(ArraySegment`1 source, String key, TagSet knownTags, DefaultHybridCache cache, ArraySegment`1& payload, TimeSpan& remainingTime, PayloadFlags& flags, UInt16& entropy, TagSet& pendingTags, Exception& fault)

Regression?

No response

Known Workarounds

No response

Configuration

.NET SDK:
 Version:           9.0.110
 Commit:            cecf5898ba
 Workload version:  9.0.100-manifests.d96a6bf8
 MSBuild version:   17.12.44+db5c766a7

Runtime Environment:
 OS Name:     Windows
 OS Version:  10.0.26100
 OS Platform: Windows
 RID:         win-x64
 Base Path:   C:\Program Files\dotnet\sdk\9.0.110\

.NET workloads installed:
There are no installed workloads to display.
Configured to use loose manifests when installing new manifests.

Host:
  Version:      9.0.9
  Architecture: x64
  Commit:       893c2ebbd4

.NET SDKs installed:
  9.0.101 [C:\Program Files\dotnet\sdk]
  9.0.110 [C:\Program Files\dotnet\sdk]

.NET runtimes installed:
  Microsoft.AspNetCore.App 9.0.0 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 9.0.9 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.NETCore.App 9.0.0 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 9.0.9 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.WindowsDesktop.App 9.0.0 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
  Microsoft.WindowsDesktop.App 9.0.9 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]

Packages:

Microsoft.Extensions.Caching.Hybrid                        9.9.0
Microsoft.Extensions.Caching.StackExchangeRedis            9.0.9

Other information

The problem seems to occur here

string[] newBuffer = ArrayPool<string>.Shared.Rent(Math.Max(4, pendingTagsCount * 2));
pendingTagBuffer.CopyTo(newBuffer, 0);
ArrayPool<string>.Shared.Return(pendingTagBuffer);
pendingTagBuffer = newBuffer;
pendingTagBuffer size is increased, and later in default case
default:
string[] final = new string[pendingTagsCount];
pendingTagBuffer.CopyTo(final, 0);
pendingTags = new(final);
break;
CopyTo fails because final array length is less than pendingTagBuffer

Metadata

Metadata

Assignees

No one assigned

    Labels

    area-caching-hybridbugThis issue describes a behavior which is not expected - a bug.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions