Discord-Net-Labs / Discord.Net-Labs

An experimental fork of Discord.Net that implements the newest discord features for testing and development to eventually get merged into Discord.Net
https://labs.discordnet.dev
MIT License
156 stars 42 forks source link

[Bug]: SendFilesAsync accesses Stream's Length property without checking CanSeek #416

Closed MihaZupan closed 2 years ago

MihaZupan commented 2 years ago

Check The Docs

Verify Issue Source

Check your intents

Description

After #399, the SendFilesAsync helper will sum up the Stream lengths to determine if they fit into MaxUploadLimit.

https://github.com/Discord-Net-Labs/Discord.Net-Labs/blob/fc475251acc2dcfb8714007889370d51f05ffadf/src/Discord.Net.Rest/Entities/Channels/ChannelHelper.cs#L377

The Stream.Length accessor may throw a NotSupportedException if the Stream does not support seeking. Callers should check CanSeek prior to accessing the Length property. See remarks from CanSeek docs.

One such Stream that does not support seeking is the response stream from SocketsHttpHandler. This can be worked around by buffering the whole content in memory first, which clearly isn't ideal.

I believe this library should check CanSeek and either:

Version

3.6.1

Working Version

Versions before #399

Logs

System.NotSupportedException: Specified method is not supported.
   at System.Net.Http.HttpBaseStream.get_Length()
   at Discord.Rest.ChannelHelper.<>c.<SendFilesAsync>b16_0(FileAttachment x)
   at System.Linq.Enumerable.Sum[TSource](IEnumerable1 source, Func2 selector)
   at Discord.Rest.ChannelHelper.SendFilesAsync(IMessageChannel channel, BaseDiscordClient client, IEnumerable`1 attachments, String text, Boolean isTTS, Embed embed, AllowedMentions allowedMentions, MessageReference messageReference, MessageComponent components, ISticker[] stickers, RequestOptions options, Embed[] embeds)
   at Discord.Rest.ChannelHelper.SendFileAsync(IMessageChannel channel, BaseDiscordClient client, Stream stream, String filename, String text, Boolean isTTS, Embed embed, AllowedMentions allowedMentions, MessageReference messageReference, MessageComponent components, ISticker[] stickers, RequestOptions options, Boolean isSpoiler, Embed[] embeds)

Sample

using HttpResponseMessage response = await _http.SendAsync(request, HttpCompletionOption.ResponseHeadersRead);
using Stream responseStream = await response.Content.ReadAsStreamAsync();

await channel.SendFileAsync(responseStream, "file.mp4");