Skip to content

Thread- and exception-safety: CloudEventEnvelopeExtensions.Serialize mutates inputΒ #950

@tba76

Description

@tba76

Summary

The method CloudEventEnvelopeExtensions.Serialize temporarily sets envelope.CloudEvent = null to serialize the rest of the envelope and then restores it. This is not thread-safe and is not exception-safe.

Context

  • File: src/Events/Extensions/CloudEventEnvelopeExtensions.cs
  • Method: Altinn.Platform.Events.Extensions.CloudEventEnvelopeExtensions.Serialize(CloudEventEnvelope envelope)

Problem

  • Temporary mutation of envelope.CloudEvent introduces a data race: concurrent callers may observe CloudEvent as null.
  • If JsonSerializer.Serialize throws, envelope.CloudEvent may remain null (no try/finally), leaving the object in an inconsistent state.

Impact

  • Intermittent NullReferenceExceptions or incorrect behavior under concurrent usage.
  • Difficult-to-diagnose flakiness if the same envelope instance is reused.

Proposed fixes (either approach is fine)

  1. Preferred: Avoid mutating the input. Compose the JSON output via JsonObject/JsonNode (or serialize a shallow copy that excludes CloudEvent), then insert the serialized CloudEvent payload (cloudEvent.Serialize()) into the final JSON.
  2. Minimal: If we must keep the current approach, wrap the mutation around the serialize call in a try/finally to guarantee restoration even if serialization throws.

Acceptance criteria

  • Serialize no longer mutates shared state during serialization, or mutation is fully exception-safe (try/finally).
  • Unit tests:
    • Serialize leaves envelope.CloudEvent unchanged after success and after a forced serialization exception.
    • Optional: a simple parallel invocation smoke test that ensures CloudEvent is not observed as null (or document thread-safety expectations explicitly).

References

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    Status

    πŸ†• New

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions