Skip to content

Commit

Permalink
fix(dds): Fix div by 0 during DXT4 DDS load (#3959)
Browse files Browse the repository at this point in the history
Fixes #3950

Fix the div-by-0 when handling unassociated alpha during a DXT4 DDS
load. The code mirrors what other formats do by first checking to see if
the alpha value is not 0 before continuing.

Added the 218-byte file from the bug to the local test suite.

---------

Signed-off-by: Jesse Yurkovich <[email protected]>
  • Loading branch information
jessey-git authored Aug 25, 2023
1 parent 38aed29 commit a5c7a0c
Show file tree
Hide file tree
Showing 4 changed files with 20 additions and 11 deletions.
24 changes: 13 additions & 11 deletions src/dds.imageio/ddsinput.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -117,12 +117,12 @@ GetBaseType(Compression cmp)
static int
GetChannelCount(Compression cmp, bool isNormal)
{
if (isNormal)
return 3;
if (cmp == Compression::DXT5)
return isNormal ? 3 : 4;
if (cmp == Compression::BC5)
return isNormal ? 3 : 2;
if (cmp == Compression::BC4)
return 1;
if (cmp == Compression::BC5)
return 2;
if (cmp == Compression::BC6HU || cmp == Compression::BC6HS)
return 3;
return 4;
Expand Down Expand Up @@ -788,13 +788,15 @@ DDSInput::internal_readimg(unsigned char* dst, int w, int h, int d)
int k;
for (int y = 0; y < h; y++) {
for (int x = 0; x < w; x++) {
k = (y * w + x) * 4;
dst[k + 0] = (unsigned char)((int)dst[k + 0] * 255
/ (int)dst[k + 3]);
dst[k + 1] = (unsigned char)((int)dst[k + 1] * 255
/ (int)dst[k + 3]);
dst[k + 2] = (unsigned char)((int)dst[k + 2] * 255
/ (int)dst[k + 3]);
k = (y * w + x) * 4;
if (dst[k + 3]) {
dst[k + 0] = (unsigned char)((int)dst[k + 0] * 255
/ (int)dst[k + 3]);
dst[k + 1] = (unsigned char)((int)dst[k + 1] * 255
/ (int)dst[k + 3]);
dst[k + 2] = (unsigned char)((int)dst[k + 2] * 255
/ (int)dst[k + 3]);
}
}
}
}
Expand Down
6 changes: 6 additions & 0 deletions testsuite/dds/ref/out.txt
Original file line number Diff line number Diff line change
Expand Up @@ -208,3 +208,9 @@ src/crash-1634.dds : 16 x 8, 1 channel, uint8 dds
oiiotool ERROR: read : "src/crash-1635.dds": Unsupported DDS bit depth: 1048576 (maybe it's a corrupted file?)
Full command line was:
> oiiotool --info -v -a --hash src/crash-1635.dds
Reading src/crash-3950.dds
src/crash-3950.dds : 16 x 1, 4 channel, uint8 dds
SHA-1: EAAFC1B407635293A2F156CCBA32225D37469178
channel list: R, G, B, A
compression: "DXT4"
textureformat: "Plain Texture"
1 change: 1 addition & 0 deletions testsuite/dds/run.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,3 +51,4 @@
# Test more corrupted files or those that used to crash
command += info_command ("src/crash-1634.dds", hash=True)
command += info_command ("src/crash-1635.dds", hash=True)
command += info_command ("src/crash-3950.dds", hash=True)
Binary file added testsuite/dds/src/crash-3950.dds
Binary file not shown.

0 comments on commit a5c7a0c

Please sign in to comment.