`Grpc.JsonTranscoding` `GetDurationText` unreachable branch / incorrect validation via `IsNormalized` due `toTimestamp` validator reuse
Los mantenedores suelen responder en 1 día
Nadie ha tomado este issue todavía.
Evaluación
- Dificultad
- 2/5
- Tiempo estimado
- 1-3 horas
- Aptitud para principiantes
- 69/100
Línea de trabajo
Empieza con src/Grpc/JsonTranscoding/src/Shared/Legacy.cs y compara la validación de GetDurationText con las reglas de signo para duraciones descritas en el issue. Revisa las pruebas existentes para el formato JSON de las duraciones y añade cobertura para una duración negativa inferior a un segundo, como seconds = 0, nanos = -500000000. El trabajo estará terminado cuando las duraciones negativas válidas se serialicen correctamente y los valores de duración no válidos se sigan rechazando.
Escrito por el modelo de indexación a partir del texto del issue.
Descripción
Is there an existing issue for this?
- I have searched the existing issues
Describe the bug
Describe the bug
In src/Grpc/JsonTranscoding/src/Shared/Legacy.cs, the GetDurationText(int nanos, long seconds) method erroneously reuses the IsNormalized method to validate a Duration.
However, IsNormalized in this file is a direct copy of the Timestamp validation logic from Google's TimestampPartial.cs, which strictly enforces nanoseconds >= 0. Reusing it inside GetDurationText breaks the serialization of valid negative durations and makes the subsequent nanos < 0 check inside GetDurationText completely unreachable (dead code).
Root Cause Analysis
In the official Google Protobuf C# runtime (protocolbuffers/protobuf), these two types are implemented using partial classes split across generated and manual files:
TimestampPartial.csenforcesnanoseconds >= 0because timestamps are absolute points in time.DurationPartial.cs(andJsonFormatter.cs) allows negative nanoseconds because durations can be negative (e.g.,-0.5sis represented asseconds = 0, nanos = -500,000,000).
When porting this logic into ASP.NET Core's internal Legacy.cs utility class, the Timestamp version of IsNormalized was accidentally applied to GetDurationText.
As a result:
// Inside Legacy.cs
public static string GetDurationText(int nanos, long seconds)
{
if (IsNormalized(seconds, nanos)) // <-- Rejects any negative nanos, returning false
{
// ...
if (seconds < 0 || nanos < 0) // <-- This branch is now dead code
{
builder.Append('-');
}
}
}
Expected Behavior
GetDurationText should either:
- Not use
IsNormalizedand instead implement the correct sign-matching validation rule forDuration(similar to how Google'sDuration.ToJsonworks). - Or use a separate
IsNormalizedForDurationvalidator that allows negative nanoseconds whenseconds <= 0.
Steps To Reproduce
Attempting to format a negative duration under 1 second (e.g., -0.5s -> seconds = 0, nanos = -500000000) will fail validation or format incorrectly because IsNormalized will evaluate -500000000 >= 0 to false.
Exceptions (if any)
No response
.NET Version
No response
Anything else?
No response
- Lenguaje dominante
- C#
- Estrellas
- 38.5k
- Forks
- 11.6k
- Merge medio
- 3 d 1 h
- PR fusionados (30 d)
- 289
Preparar el entorno
Inicia el contenedor de desarrollo del proyecto en tu navegador, con tu propia cuenta de GitHub.
- Sin Dockerfile ni archivo de Docker Compose
- Tiene una plantilla de pull request
- Leer la guía de contribución
Primeros pasos
- Lee el issue completo y luego la guía de contribución del proyecto.
- Comenta en el issue que vas a ocuparte — evita que dos personas hagan lo mismo.
- Haz un fork del repositorio y trabaja en una rama.
- Abre un pull request que haga referencia al número del issue.
Más de dotnet/aspnetcore
-
area-networking
Dificultad 2/5 1-3 horas Aptitud para principiantes 78/100
dotnet/aspnetcore#70545 · 1 comentario ·
Los mantenedores suelen responder en 1 día
-
area-infrastructure
Dificultad 2/5 1-3 horas Aptitud para principiantes 72/100
dotnet/aspnetcore#70524 · 1 comentario ·
Los mantenedores suelen responder en 1 día
-
[OpenTelemetry] Hosting replaces an Activity.DisplayName that the app set, when a route matchesAbiertoarea-hosting Regression
Dificultad 2/5 1-3 horas Aptitud para principiantes 78/100
dotnet/aspnetcore#70516 · 1 comentario · 1 reacción ·
Los mantenedores suelen responder en 1 día
-
[SSE] ServerSentEventsResult.WrapEvents is missing [EnumeratorCancellation], so RequestAborted never reaches the app's generator on the IAsyncEnumerable<T> overloadPosiblemente ocupada @bharatprajapati-coder la tomó hace 1 día. Abiertoarea-minimal
Dificultad 2/5 1-3 horas Aptitud para principiantes 78/100
dotnet/aspnetcore#70419 · 2 comentarios ·
Los mantenedores suelen responder en 1 día
-
[Blazor] DefaultInMemoryCircuitPersistenceProvider never disposes the retention CancellationTokenSource when a persist is rejected at capacityPosiblemente ocupada @Vinoth2562000 la tomó hace 1 día. Abiertoarea-blazor
Dificultad 2/5 1-3 horas Aptitud para principiantes 77/100
dotnet/aspnetcore#70418 · 1 comentario · 1 asignado ·
Los mantenedores suelen responder en 1 día
Todos los issues de dotnet/aspnetcore
Issues similares
-
bug emitter:client:csharp
Dificultad 2/5 1-3 horas Aptitud para principiantes 84/100
microsoft/typespec#12572 · 1 comentario · 1 reacción ·
Los mantenedores suelen responder en 1 día
-
needs-area-label
Dificultad 2/5 1-3 horas Aptitud para principiantes 78/100
Los mantenedores suelen responder en 2 días
-
AWS Lambda: KeyNotFoundException drops HTTP-triggered transactions when allowAllHeaders is disabledAbiertobug
Dificultad 2/5 1-3 horas Aptitud para principiantes 70/100
newrelic/newrelic-dotnet-agent#3949 · 1 comentario ·
Los mantenedores suelen responder en 1 día
-
Dificultad 2/5 1-3 horas Aptitud para principiantes 87/100
Los mantenedores suelen responder en 1 día
-
priority:P2
Dificultad 2/5 1-3 horas Aptitud para principiantes 80/100