Source: https://code.google.com/p/google-security-research/issues/detail?id=524

Fuzzing CHM files with Kaspersky Antivirus produced the attached crash.

(83c.fec): Access violation - code c0000005 (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
eax=0bd3e470 ebx=00000ef1 ecx=00000000 edx=0b002fb0 esi=00000018 edi=0bd3e473
eip=15edb522 esp=0bd3e234 ebp=0bd3e240 iopl=0         nv up ei pl nz na pe nc
cs=0023  ss=002b  ds=002b  es=002b  fs=0053  gs=002b             efl=00010206
15edb522 8a12            mov     dl,byte ptr [edx]          ds:002b:0b002fb0=??

Where does edx come from?

0:085> uf 15edb4f0
15edb4f0 55              push    ebp
...
15edb520 8b10            mov     edx,dword ptr [eax]
15edb522 8a12            mov     dl,byte ptr [edx]
15edb524 8817            mov     byte ptr [edi],dl
15edb526 ff00            inc     dword ptr [eax]
15edb528 47              inc     edi
15edb529 83c6ff          add     esi,0FFFFFFFFh
15edb52c 83d1ff          adc     ecx,0FFFFFFFFh
15edb52f 8bd6            mov     edx,esi
15edb531 0bd1            or      edx,ecx
15edb533 75eb            jne     15edb520

...

Edx is a parameter, and this is a simple memcpy loop.

for (i = ArgSize; i > 0; i--) {
    *argDestPtr++ = *argSrcPtr++;
}

But why is the input pointer corrupt, that should be a pointer to the input buffer (i.e. the CHM being scanned)?

0:018> kvn1
 # ChildEBP RetAddr  Args to Child
00 03f4e1c0 15edb73b 0000022f 00000000 0afda8d4 0x15edb522
0:018> ub 15edb73b
15edb725 3bc1            cmp     eax,ecx
15edb727 774f            ja      15edb778
15edb729 52              push    edx
15edb72a 50              push    eax
15edb72b 8d95e8fdffff    lea     edx,[ebp-218h]    <-- destination buffer
15edb731 8bcb            mov     ecx,ebx
15edb733 8d45fc          lea     eax,[ebp-4]
15edb736 e8b5fdffff      call    15edb4f0


Ah, the destination is a fixed size stack buffer (I'm guessing 512 bytes), so if the size read from the input is greater than 512 (in this case it's 0x22f), the stack will be corrupted.

The input pointer is corrupt because the loop overwrites the src pointer with attacker controlled input and then it crashes trying to read from it. That can obviously be fixed by an attacker, so this is an exploitable stack buffer overflow.

It seems likely /GS would have made this unexploitable.

Proof of Concept:
https://gitlab.com/exploit-database/exploitdb-bin-sploits/-/raw/main/bin-sploits/38285.zip