dotnet / dotnet/winforms

Image.FromStream can throw undocumented exceptions

Open
#8,820 4 comments 0 reactions 0 assignees View on GitHub
area-System.Drawing
Dominant language
C#
Stars
4.9k
Forks
1.1k
Avg merge
20h 23m
Merged PRs (30d)
103

Description

The [documentation](https://docs.microsoft.com/en-us/dotnet/api/system.drawing.image.fromstream?view=netcore-2.2) for ```Image.FromStream``` indicates that an ArgumentException can be thrown if the provided image is not of a supported format. However, on Windows, it can also throw InvalidOperationException, ExternalException, FileNotFoundException, etc. as per the [StatusException](https://github.com/dotnet/corefx/blob/master/src/System.Drawing.Common/src/System/Drawing/Gdiplus.cs) method. The callers of this method do not catch and wrap these exceptions into ArgumentExceptions.

It should also be noted that an ExternalException *can* be thrown in the event that the stream does not contain a valid image. Further, in this case, the actual HResult is clobbered by E_FAIL, so the caller of Image.FromStream cannot even handle the case themselves by catching the ExternalException and checking for the appropriate HResult.

You can reproduce the above issue with the image generated by:

```
// this is a magic number length which, when containing the right bits, the GDI+ library that the Image
// class leverages is unable to handle
var photo = new byte[15633];
// this is a jpeg header
var header = Convert.FromBase64String("/9j/4AAQSkZJRgABAQEAAA==");
// this is a sequence of bytes which, when at the end of a jpeg of the given length, is not a valid jpeg
// format and GDI+ does not handle gracefully
var footer = Convert.FromBase64String(
"/8AAEQgEOAeAAwEiAAIRAQMRAf/EAB8AAAEFAQEBAQEBAAAAAAAAAAABAgMEBQYHCAkKC//EALUQAAIBAwMCBAMFBQQEAAABfQE" +
"CAwAEEQUSITFBBhNRYQcicRQygZGhCCNCscEVUtHwJDNicoIJChYXGBkaJSYnKCkqNDU2Nzg5OkNERUZHSElKU1RVVldYWVpjZG" +
"VmZ2hpanN0dXZ3eHl6g4SFhoeIiYqSk5SVlpeYmZqio6Slpqeoqaqys7S1tre4ubrCw8TFxsfIycrS09TV1tfY2drh4uPk5ebn6" +
"Onq8fLz9PX29/j5+v/EAB8BAAMBAQEBAQEBAQEAAAAAAAABAgMEBQYHCAkKC//EALURAAIBAgQEAwQHBQQEAAECdwABAgMRBAUh" +
"MQYSQVEHYXETIjKBCBRCkaGxwQkjM1LwFWJy0QoWJDThJfEXGBkaJicoKSo1Njc4OTpDREVGR0hJSlNUVVZXWFlaY2RlZmdoaWp" +
"zdHV2d3h5eoKDhIWGh4iJipKTlJWWl5iZmqKjpKWmp6ipqrKztLW2t7i5usLDxMXGx8jJytLT1NXW19jZ2uLj5OXm5+jp6vLz9P" +
"X29/j5+v/aAAwDAQACEQM=");
Buffer.BlockCopy(header, 0, photo, 0, header.Length);
Buffer.BlockCopy(footer, 0, photo, photo.Length - footer.Length, footer.Length);
```

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.