Skip to content

Conversation

Copy link
Contributor

Copilot AI commented Jan 22, 2026

Description

Avoid disposing user-supplied target user CSV streams in invite APIs, preventing ObjectDisposedException after call completion. Disposal now only occurs for internally-created streams.

  • Stream ownership: Gate disposal on ResetPositionTo == null, respecting caller-owned streams in CreateChannelInviteAsync and UpdateInviteTargetUsersAsync.
  • Null safety: Added null guards around disposal paths to avoid NullReferenceException.
  • Position reset: Existing position reset remains for caller streams.

Example:

// Caller stream remains usable after the API call
using var ms = new MemoryStream(Encoding.UTF8.GetBytes("Users\n1\n"));
await client.UpdateInviteTargetUsersAsync("code", ms, reason: "sync");
// ms is not disposed here

Type of change

Please delete options that are not relevant.

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • This change requires a documentation update

How Has This Been Tested?

Please describe the tests that you ran to verify your changes. Provide instructions so we can reproduce. Please also list any relevant details for your test configuration

  • Test A (dotnet test DisCatSharp.Tests/DisCatSharp.CopilotTests/DisCatSharp.CopilotTests.csproj)
  • Test B

Test Configuration:

  • Firmware version:
  • Hardware:
  • Toolchain:
  • SDK:

Checklist:

  • My code follows the style guidelines of this project
  • I have performed a self-review of my own code
  • I have commented my code, particularly in hard-to-understand areas
  • I have made corresponding changes to the documentation
  • My changes generate no new warnings
  • Any dependent changes have been merged and published in downstream modules

@Aiko-IT-Systems/discatsharp

Original prompt

Review the code at the location below. A potential bug has been identified by an AI
agent.
Verify if this is a real issue. If it is, propose a fix; if not, explain why it's not
valid.

Location: DisCatSharp/Net/Rest/DiscordApiClient.cs#L3902-L3910

Potential issue: In CreateChannelInviteAsync and UpdateInviteTargetUsersAsync, if a
user supplies a Stream via the targetUsersFile parameter, the method takes ownership
and disposes of it after the API call. This violates the .NET convention where the
creator of a resource is responsible for its disposal. The code can distinguish between
user-provided streams (where ResetPositionTo is not null) and internally-created
streams, but it fails to use this distinction in the disposal logic. This will cause an
ObjectDisposedException if the caller attempts to access their stream after the method
completes.


✨ Let Copilot coding agent set things up for you — coding agent works faster and does higher quality work when set up for your repo.

Copilot AI changed the title [WIP] Fix disposal logic for user-provided streams in invite methods Preserve caller-owned invite target streams Jan 22, 2026
Copilot AI requested a review from Lulalaby January 22, 2026 05:11
@Lulalaby Lulalaby marked this pull request as ready for review January 22, 2026 05:12
@Lulalaby Lulalaby requested a review from a team as a code owner January 22, 2026 05:12
@Lulalaby Lulalaby requested review from NyuwBot, Saalvage and Copilot and removed request for Copilot January 22, 2026 05:12
@Lulalaby Lulalaby merged commit ea60ce8 into main Jan 22, 2026
4 of 5 checks passed
@Lulalaby Lulalaby deleted the copilot/fix-stream-disposal-logic branch January 22, 2026 05:13
Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 73f8051043

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +3902 to +3906
if (targetUsersCsv is not null && targetUsersCsv.ResetPositionTo is null)
{
// ignore
try
{
targetUsersCsv.Stream.Dispose();

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Avoid disposing user-owned non-seekable streams

This disposal guard treats ResetPositionTo == null as “internally owned,” but user-supplied streams that are not seekable also produce ResetPositionTo == null in CreateTargetUsersFile. In that case, the caller’s stream will still be disposed here, which contradicts the intent of preserving caller ownership and can still trigger ObjectDisposedException if the caller reuses the stream after CreateChannelInviteAsync. Consider tracking ownership separately (e.g., a flag from the targetUsersFile parameter) rather than relying on ResetPositionTo alone.

Useful? React with 👍 / 👎.

Comment on lines +5158 to +5161
else if (targetUsersCsv is not null)
{
// ignore
try
{

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Avoid disposing user-owned non-seekable streams

This disposal path still closes user-owned streams that are not seekable because CreateTargetUsersFile sets ResetPositionTo only when stream.CanSeek is true. For non-seekable caller streams, ResetPositionTo remains null and this block disposes them anyway, defeating the ownership fix and risking ObjectDisposedException for callers who reuse the stream after UpdateInviteTargetUsersAsync completes.

Useful? React with 👍 / 👎.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

2 participants