Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion src/TruePBR/BSLightingShaderMaterialPBR.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,10 @@ BSLightingShaderMaterialPBR* BSLightingShaderMaterialPBR::Make()

RE::BSShaderMaterial* BSLightingShaderMaterialPBR::Create()
{
return Make();
// Must use regular heap (not scrap heap like Make()). BSLightingShaderProperty::LinkObject
// calls ScrapHeap::Free() after LinkMaterial — if Create() used scrap heap, it would pop
// the canonical off the stack, causing immediate use-after-free in property->material.
return new BSLightingShaderMaterialPBR();
}

void BSLightingShaderMaterialPBR::CopyMembers(RE::BSShaderMaterial* that)
Expand Down
8 changes: 8 additions & 0 deletions src/TruePBR/BSLightingShaderMaterialPBR.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,10 @@ class BSLightingShaderMaterialPBR : public RE::BSLightingShaderMaterialBase
~BSLightingShaderMaterialPBR();

// override (BSLightingShaderMaterialBase)
// Called by BSShaderMaterialHashMap::Link to produce the heap-allocated canonical copy.
// MUST use regular heap (new), NOT Make()/scrap heap. BSLightingShaderProperty::LinkObject
// calls ScrapHeap::Free() immediately after Link — a scrap-heap canonical would be popped
// off the stack and freed while property->material still points to it (use-after-free).
RE::BSShaderMaterial* Create() override; // 01
void CopyMembers(RE::BSShaderMaterial* that) override; // 02
std::uint32_t ComputeCRC32(uint32_t srcHash) override; // 04
Expand All @@ -64,6 +68,10 @@ class BSLightingShaderMaterialPBR : public RE::BSLightingShaderMaterialBase
uint32_t GetTextures(RE::NiSourceTexture** textures) override; // 0B
void LoadBinary(RE::NiStream& stream) override; // 0D

// Allocates a scrap-heap temp for use during BSLightingShaderProperty::LoadBinary.
// The temp is direct-assigned to property->material so that BSLightingShaderProperty::LinkObject
// (NiStream link phase) can find it, call BSShaderMaterialHashMap::Link to produce the canonical,
// then ScrapHeap::Free() to pop this temp. Never use Make() as the Create() implementation.
static BSLightingShaderMaterialPBR* Make();

void ApplyTextureSetData(const TruePBR::PBRTextureSetData& textureSetData);
Expand Down
5 changes: 4 additions & 1 deletion src/TruePBR/BSLightingShaderMaterialPBRLandscape.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,10 @@ BSLightingShaderMaterialPBRLandscape* BSLightingShaderMaterialPBRLandscape::Make

RE::BSShaderMaterial* BSLightingShaderMaterialPBRLandscape::Create()
{
return Make();
// Must use regular heap (not scrap heap like Make()). BSLightingShaderProperty::LinkObject
// calls ScrapHeap::Free() after LinkMaterial — if Create() used scrap heap, it would pop
// the canonical off the stack, causing immediate use-after-free in property->material.
return new BSLightingShaderMaterialPBRLandscape();
}

void BSLightingShaderMaterialPBRLandscape::CopyMembers(RE::BSShaderMaterial* that)
Expand Down
8 changes: 8 additions & 0 deletions src/TruePBR/BSLightingShaderMaterialPBRLandscape.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,21 @@ class BSLightingShaderMaterialPBRLandscape : public RE::BSLightingShaderMaterial
~BSLightingShaderMaterialPBRLandscape();

// override (BSLightingShaderMaterialBase)
// Called by BSShaderMaterialHashMap::Link to produce the heap-allocated canonical copy.
// MUST use regular heap (new), NOT Make()/scrap heap. BSLightingShaderProperty::LinkObject
// calls ScrapHeap::Free() immediately after Link — a scrap-heap canonical would be popped
// off the stack and freed while property->material still points to it (use-after-free).
RE::BSShaderMaterial* Create() override; // 01
void CopyMembers(RE::BSShaderMaterial* that) override; // 02
Feature GetFeature() const override; // 06
void ClearTextures() override; // 09
void ReceiveValuesFromRootMaterial(bool skinned, bool rimLighting, bool softLighting, bool backLighting, bool MSN) override; // 0A
uint32_t GetTextures(RE::NiSourceTexture** textures) override; // 0B

// Allocates a scrap-heap temp for use during BSLightingShaderProperty::LoadBinary.
// The temp is direct-assigned to property->material so that BSLightingShaderProperty::LinkObject
// (NiStream link phase) can find it, call BSShaderMaterialHashMap::Link to produce the canonical,
// then ScrapHeap::Free() to pop this temp. Never use Make() as the Create() implementation.
static BSLightingShaderMaterialPBRLandscape* Make();

bool HasGlint() const;
Expand Down
Loading