TheAssemblyArmada / Thyme

An open source re-implementation of Generals : Zero Hour written in C++.
GNU General Public License v2.0
584 stars 59 forks source link

w3dview texture crash #1131

Open xezon opened 3 months ago

xezon commented 3 months ago

Easiest Repro:

When selecting loaded model:

    vcruntime140.dll!memcpy(unsigned char * dst, unsigned char * src, unsigned long count) Line 319 Unknown
    w3dview.exe!DDSFileClass::Copy_Level_To_Surface(unsigned int level, WW3DFormat dst_format, unsigned int dst_width, unsigned int dst_height, unsigned char * dst_surface, unsigned int dst_pitch, const Vector3 & color_shift) Line 228  C++
>   w3dview.exe!TextureLoadTaskClass::Load_Compressed_Mipmap() Line 351 C++
    w3dview.exe!TextureLoadTaskClass::Load() Line 600   C++
    w3dview.exe!LoaderThreadClass::Thread_Function() Line 89    C++
    w3dview.exe!ThreadClass::Internal_Thread_Function(void * params) Line 99    C++
    [External Code] 
    [Frames below may be incorrect and/or missing, no symbols loaded for ucrtbase.dll]  

DDSFileClass

  Name Value Type
this 0x0e00fd18 {m_width=256 m_height=256 m_depth=0 ...} DDSFileClass *
  m_width 256 unsigned int
  m_height 256 unsigned int
  m_depth 0 unsigned int
  m_maxWidth 256 unsigned int
  m_maxHeight 256 unsigned int
  m_maxDepth 0 unsigned int
  m_mipLevels 7 unsigned int
  m_time 1660749779 __int64
  m_reductionFactor 0 unsigned int
  ▶ m_DDSMemory 0x11cbc9d4 "\x1" unsigned char *
  m_format WW3D_FORMAT_DXT1 (20) WW3DFormat
  m_textureType 0 unsigned int
  ▶ m_levelSizes 0x030378cc {32768} unsigned int *
  ▶ m_levelOffsets 0x030378f8 {16} unsigned int *
  m_totalSizeMaybe 0 unsigned int
  ▶ m_fileHeader {dwSize=124 dwFlags=659463 dwHeight=256 ...} DDSHeader
  ▶ m_name 0x0e00fdd8 "cbh2oplnt_ng.dds" char[256]

Watch

Name Value Type
m_mipLevelCount 7 unsigned int
level 2 unsigned int
m_levelOffsets[2] 1937076072 unsigned int
m_DDSMemory[m_levelOffsets[2]] Unable to read memory -
m_levelSizes[2] 2048 unsigned int
dst_surface 0x11f0e320 "" unsigned char *
m_DDSMemory 0x11cbc9d4 "\x1" unsigned char *
m_levelOffsets,7 0x030378f8 {16, 15, 1937076072, 1819239269, 775058031, 7562340, 43680} unsigned int[7]
[0] 16 unsigned int
[1] 15 unsigned int
[2] 1937076072 unsigned int
[3] 1819239269 unsigned int
[4] 775058031 unsigned int
[5] 7562340 unsigned int
[6] 43680 unsigned int
m_levelSizes,7 0x030378cc {32768, 8192, 2048, 512, 128, 32, 8} unsigned int[7]
[0] 32768 unsigned int
[1] 8192 unsigned int
[2] 2048 unsigned int
[3] 512 unsigned int
[4] 128 unsigned int
[5] 32 unsigned int
[6] 8 unsigned int
m_mipLevels 7 unsigned int

m_levelOffsets at index 2 has garbage value.

xezon commented 3 months ago

Here is what these values look like on a healthy load, same texture cbh2oplnt_ng.dds

  Name Value Type
this 0x012fefec {m_width=256 m_height=256 m_depth=0 ...} DDSFileClass *
  m_width 256 unsigned int
  m_height 256 unsigned int
  m_depth 0 unsigned int
  m_maxWidth 256 unsigned int
  m_maxHeight 256 unsigned int
  m_maxDepth 0 unsigned int
  m_mipLevels 7 unsigned int
  m_time 1660749779 __int64
  m_reductionFactor 0 unsigned int
  ▶ m_DDSMemory 0x00000000 unsigned char *
  m_format WW3D_FORMAT_DXT1 (20) WW3DFormat
  m_textureType 0 unsigned int
  ▶ m_levelSizes 0x036671c0 {32768} unsigned int *
  ▶ m_levelOffsets 0x036671ec {0} unsigned int *
  m_totalSizeMaybe 0 unsigned int
  ▶ m_fileHeader {dwSize=124 dwFlags=659463 dwHeight=256 ...} DDSHeader
  ▶ m_name 0x012ff0ac "cbh2oplnt_ng.dds" char[256]
  Name Value Type
m_levelOffsets,7 0x036671ec {0, 32768, 40960, 43008, 43520, 43648, 43680} unsigned int[7]
  [0] 0 unsigned int
  [1] 32768 unsigned int
  [2] 40960 unsigned int
  [3] 43008 unsigned int
  [4] 43520 unsigned int
  [5] 43648 unsigned int
  [6] 43680 unsigned int
m_levelSizes,7 0x036671c0 {32768, 8192, 2048, 512, 128, 32, 8} unsigned int[7]
  [0] 32768 unsigned int
  [1] 8192 unsigned int
  [2] 2048 unsigned int
  [3] 512 unsigned int
  [4] 128 unsigned int
  [5] 32 unsigned int
  [6] 8 unsigned int
xezon commented 3 months ago

Looks like memory corruption to me. Something has corrupted part of m_levelOffsets

xezon commented 2 months ago

This issue still happens with latest w3dview

xezon commented 2 months ago
Exception thrown at 0x72B2E830 (vcruntime140.dll) in w3dview.exe: 0xC0000005: Access violation writing location 0x139A6000.

dst_surface = 0x1399e460

0x139A6000 - 0x1399E460 = 0x7BA0

m_levelSizes[0] = 0x00008000

So dst_surface is a bit too small?

Perhaps is a threading issue?

xezon commented 2 months ago

I noticed there are some bad/missing locks around g_backgroundQueue and g_foregroundQueue. I have now made a local change with various fixes and will observe if that prevents crash.

xezon commented 2 months ago

This crash occurred again. Fixing the locks around g_backgroundQueue and g_foregroundQueue did not fix the problem.

xezon commented 2 months ago

Callstack

    vcruntime140.dll!memcpy(unsigned char * dst, unsigned char * src, unsigned long count) Line 319 Unknown
>   w3dview.exe!DDSFileClass::Copy_Level_To_Surface(unsigned int level, WW3DFormat dst_format, unsigned int dst_width, unsigned int dst_height, unsigned char * dst_surface, unsigned int dst_pitch, const Vector3 & color_shift) Line 234  C++
    w3dview.exe!TextureLoadTaskClass::Load_Compressed_Mipmap() Line 358 C++
    w3dview.exe!TextureLoadTaskClass::Load() Line 597   C++
    w3dview.exe!LoaderThreadClass::Thread_Function() Line 98    C++
    w3dview.exe!ThreadClass::Internal_Thread_Function(void * params) Line 99    C++
    ucrtbase.dll!778fc5b3() Unknown
    [Frames below may be incorrect and/or missing, no symbols loaded for ucrtbase.dll]  
    kernel32.dll!7703fcc9() Unknown
    ntdll.dll!__RtlUserThreadStart()    Unknown
    ntdll.dll!__RtlUserThreadStart@8()  Unknown

Error

Exception thrown at 0x74E2E830 (vcruntime140.dll) in w3dview.exe: 0xC0000005: Access violation reading location 0x13485000.
  Name Value Type
  level 1 unsigned int
&this->m_DDSMemory[m_levelOffsets[level]] 0x13481024 unsigned char *
  this->m_levelSizes[level] 32768 unsigned int

this->m_levelSizes[0] is too large for the m_DDSMemory texture buffer.

  Name Value Type
this 0x0cfcf5d0 {m_width=128 m_height=128 m_depth=0 ...} DDSFileClass *
  m_width 128 unsigned int
  m_height 128 unsigned int
  m_depth 0 unsigned int
  m_maxWidth 128 unsigned int
  m_maxHeight 128 unsigned int
  m_maxDepth 0 unsigned int
  m_mipLevels 6 unsigned int
  m_time 1660747162 __int64
  m_reductionFactor 0 unsigned int
  ▶ m_DDSMemory 0x1347f024 unsigned char *
  m_format WW3D_FORMAT_DXT1 (20) WW3DFormat
  m_textureType 0 unsigned int
  ▶ m_levelSizes 0x02f91834 {0} unsigned int *
  ▶ m_levelOffsets 0x02f918b8 {0} unsigned int *
  m_totalSizeMaybe 0 unsigned int
  ◢ m_fileHeader {dwSize=124 dwFlags=659463 dwHeight=128 ...} DDSHeader
  dwSize 124 unsigned int
  dwFlags 659463 unsigned int
  dwHeight 128 unsigned int
  dwWidth 128 unsigned int
  dwPitchOrLinearSize 8192 unsigned int
  dwDepth 0 unsigned int
  dwMipMapCount 8 unsigned int
  ▶ dwReserved1 0x0cfcf630 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} unsigned int[11]
  ▶ ddspf {dwSize=32 dwFlags=4 dwFourCC=827611204 ...} DDSPixelFormat
  dwCaps 4198408 unsigned int
  dwCaps2 0 unsigned int
  dwCaps3 1481851972 unsigned int
  dwCaps4 4294967295 unsigned int
  dwReserved2 4294967295 unsigned int
  ▶ m_name 0x0cfcf690 "pmsandbags2.dds" char[256]

128 x 128 is just 16384

  Name Value Type
this->m_levelSizes,8 0x02f91834 {0, 32768, 40960, 43008, 43520, 43648, 43680, 174752} unsigned int[8]
this->m_levelOffsets,8 0x02f918b8 {0, 8192, 10240, 10752, 10880, 10912, 0, 0} unsigned int[8]

Both sizes and offsets look strange?

xezon commented 2 months ago

Loading that same texture "pmsandbags2.dds" fresh will show create proper sizes and offsets:

  Name Value Type
this->m_levelSizes,8 0x02e68834 {8192, 2048, 512, 128, 32, 8, 174720, 174752} unsigned int[8]
this->m_levelOffsets,8 0x02e68860 {0, 8192, 10240, 10752, 10880, 10912, 32, 8} unsigned int[8]

This looks like both buffers were previously corrupted.

xezon commented 1 month ago

w3dview crash happens very often when loading and viewing cbngovbuil models.