Independently spotted by both @Dentomologist and me while reviewing
PR #14805
The previous limit was correct for valid VPBs, but an invalid VPB
controlled by a malicious game could contain a non-fractional value
in current_pos_frac, which would allow writing an extra 15 samples
(30 bytes) into the stack. With AFC encoding, this is rounded up to 16
samples, but with much less control over which bytes are written.
Maybe we should be doing some validation, or bounds checking, but I'm
pretty sure this issue was copied from the original ucode, and we kinda
want to stay compatible.
The simpler fix is to just increase the size of raw_input_samples.
I've checked other code paths, and 0x514 samples seems to be the limit.
glMemoryBarrier comes from ARB_shader_image_load_store, so on a desktop context
below GL 4.2 the pointer is null. bSupportsBBox is set from
bSupportsFragmentStoresAndAtomics, which such a driver can still have, so saving
a state reads the bounding box and calls a null pointer.
UsePersistentStagingBuffers() in OGLTexture.cpp already guards the same call with
bSupportsImageLoadStore.
This started as a fixing a misalignment issue, but I got carried away.
Was originally 41 bytes (overflowing it's expected 40 bytes by 1 bit).
Now it's 27 bytes plus 8 bits of padding (ready for future expansion).
The savings come from:
- Removing UV usage from components, it can be reconstructed from
texcoord_elem_count (saved 8 bits)
- Removed the 8 unused bits from texMtxInfo_n_projection (saved 8 bits)
- Removing unused bit from from start of components (saved 1 bit)
- Removed extra bit from inputform, texgentype and sourcerow
- packed texMtxInfo_n_projection and texcoord_elem_count back into
the per texgen info space freed up above. (saved 24 bits)
- Overlayed postMtx index and Emboss mode shifts into a union based on
texgentype (saved 56 bits)
- Move to a single-bit union tag, freeing up an extra bit for regular
texgens.
- Move PotMtx normalize into the freed up space (saved 8 bits)
Total savings: 105 bits of data
EDIT: Even worse, MSVC wasn't respecting pack(1) for bitfields at all,
so on windows this struct was actually quite a bit larger.
Something like 80 bytes, if not more.
Fixed this by dropping the size of any enums used in these
bit structs to u8. Our Common::BitField allows for the underlying
type to be explicitly specified to something larger.
msvc's bitfield packing appears to be completely braindead, can't
mix sizes at all.
msg_in and msg_out were ending up with only 4-byte alignment, which
is undefined behaviour, since they contain 64-bit fields. Probably
doesn't cause any issues, but it showed up in ubsan.