microsoft / microsoft/DirectXShaderCompiler

Memleak for PAQs with more than four shader stages

Open
#7,104 1 comment 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

bug
Dominant language
C++
Stars
3.7k
Forks
900
Avg merge
2d 11h
Merged PRs (30d)
44

Description

Description
When declaring a payload struct with PAQs, memory leaks if one of the PAQ clauses specifies more than four shader stages.
This is because the hlsl::PayloadAccessAnnotation keeps those stages in a llvm::SmallVector<hlsl::DXIL::PayloadAccessShaderStage, 4u> field, which starts allocating memory in this case. Since UnusualAnnotation has no virtual deconstructor this memory is never free'd.

Steps to Reproduce

  1. Create a dxc Release build on Linux with Clang 18 + Asan enabled (asan only reported the leak in this specific configuration).
  2. Create an hlsl file with a payload struct. One of the payload fields needs to have more than four shader stages, eg:
struct [raypayload] Payload
{
     float elem
          : write(caller,closesthit,anyhit,closesthit,miss)
          : read(caller,closesthit,anyhit,closesthit,miss);
          : write(caller,anyhit,closesthit,miss)
          : read(caller,anyhit,closesthit,miss);
};

Actual Behavior
This was observed in a CI run for https://github.com/microsoft/DirectXShaderCompiler/pull/7097 (commit https://github.com/microsoft/DirectXShaderCompiler/pull/7097/commits/cb132036cfa5ea01283af5de6b8ecea15c141ac6). The test case in this PR has since been fixed to only specify four stages to workaround this issue.

******************** TEST 'Clang :: SemaHLSL/hlsl/objects/HitObject/hitobject-entry-errors.hlsl' FAILED ********************
Script:
--
/home/vsts/work/1/s/build/./bin/dxc -T lib_6_9 /home/vsts/work/1/s/tools/clang/test/SemaHLSL/hlsl/objects/HitObject/hitobject-entry-errors.hlsl -verify
--
Exit Code: 1

Command Output (stderr):
--

=================================================================
==18293==ERROR: LeakSanitizer: detected memory leaks

Direct leak of 72 byte(s) in 2 object(s) allocated from:
    #0 0x55a3223affbd in operator new[](unsigned long) (/home/vsts/work/1/s/build/bin/dxc-3.7+0x203fbd) (BuildId: 34f0a07c804d72cd)
    #1 0x7f129b11d3b6 in llvm::SmallVectorBase::grow_pod(void*, unsigned long, unsigned long) /home/vsts/work/1/s/lib/Support/SmallVector.cpp:27:19
    #2 0x7f129ce097f5 in grow_pod /home/vsts/work/1/s/include/llvm/ADT/SmallVector.h:81:22
    #3 0x7f129ce097f5 in grow /home/vsts/work/1/s/include/llvm/ADT/SmallVector.h:327:11
    #4 0x7f129ce097f5 in llvm::SmallVectorImpl<hlsl::DXIL::PayloadAccessShaderStage>::operator=(llvm::SmallVectorImpl<hlsl::DXIL::PayloadAccessShaderStage> const&) /home/vsts/work/1/s/include/llvm/ADT/SmallVector.h:763:11
    #5 0x7f129cdd88d2 in SmallVector /home/vsts/work/1/s/include/llvm/ADT/SmallVector.h:894:27
    #6 0x7f129cdd88d2 in PayloadAccessAnnotation /home/vsts/work/1/s/tools/clang/include/clang/AST/HlslTypes.h:282:8
    #7 0x7f129cdd88d2 in clang::Parser::MaybeParseHLSLAttributes(std::__1::vector<hlsl::UnusualAnnotation*, std::__1::allocator<hlsl::UnusualAnnotation*>>&) /home/vsts/work/1/s/tools/clang/lib/Parse/ParseDecl.cpp:418:38
    #8 0x7f129cdff895 in MaybeParseHLSLAttributes /home/vsts/work/1/s/tools/clang/include/clang/Parse/Parser.h:2102:12
    #9 0x7f129cdff895 in clang::Parser::ParseDirectDeclarator(clang::Declarator&) /home/vsts/work/1/s/tools/clang/lib/Parse/ParseDecl.cpp:6315:9
    #10 0x7f129cdfcfe9 in clang::Parser::ParseDeclaratorInternal(clang::Declarator&, void (clang::Parser::*)(clang::Declarator&)) /home/vsts/work/1/s/tools/clang/lib/Parse/ParseDecl.cpp:5903:7
    #11 0x7f129ce20015 in clang::Parser::ParseCXXMemberDeclaratorBeforeInitializer(clang::Declarator&, clang::VirtSpecifiers&, clang::ActionResult<clang::Expr*, true>&, clang::Parser::LateParsedAttrList&) /home/vsts/work/1/s/tools/clang/lib/Parse/ParseDeclCXX.cpp:2107:5
    #12 0x7f129ce236cc in clang::Parser::ParseCXXClassMemberDeclaration(clang::AccessSpecifier, clang::AttributeList*, clang::Parser::ParsedTemplateInfo const&, clang::ParsingDeclRAIIObject*) /home/vsts/work/1/s/tools/clang/lib/Parse/ParseDeclCXX.cpp:2489:7
    #13 0x7f129ce1cf24 in clang::Parser::ParseCXXMemberSpecification(clang::SourceLocation, clang::SourceLocation, clang::Parser::ParsedAttributesWithRange&, unsigned int, clang::Decl*) /home/vsts/work/1/s/tools/clang/lib/Parse/ParseDeclCXX.cpp:3153:7
    #14 0x7f129ce18816 in clang::Parser::ParseClassSpecifier(clang::tok::TokenKind, clang::SourceLocation, clang::DeclSpec&, clang::Parser::ParsedTemplateInfo const&, clang::AccessSpecifier, bool, clang::Parser::DeclSpecContext, clang::Parser::ParsedAttributesWithRange&) /home/vsts/work/1/s/tools/clang/lib/Parse/ParseDeclCXX.cpp:1786:7
    #15 0x7f129cde4876 in clang::Parser::ParseDeclarationSpecifiers(clang::DeclSpec&, clang::Parser::ParsedTemplateInfo const&, clang::AccessSpecifier, clang::Parser::DeclSpecContext, clang::Parser::LateParsedAttrList*) /home/vsts/work/1/s/tools/clang/lib/Parse/ParseDecl.cpp:4151:7
    #16 0x7f129cd88700 in clang::Parser::ParseDeclOrFunctionDefInternal(clang::Parser::ParsedAttributesWithRange&, clang::ParsingDeclSpec&, clang::AccessSpecifier) /home/vsts/work/1/s/tools/clang/lib/Parse/Parser.cpp:908:3
    #17 0x7f129cd882d7 in clang::Parser::ParseDeclarationOrFunctionDefinition(clang::Parser::ParsedAttributesWithRange&, clang::ParsingDeclSpec*, clang::AccessSpecifier) /home/vsts/work/1/s/tools/clang/lib/Parse/Parser.cpp:981:12
    #18 0x7f129cd87368 in clang::Parser::ParseExternalDeclaration(clang::Parser::ParsedAttributesWithRange&, clang::ParsingDeclSpec*) /home/vsts/work/1/s/tools/clang/lib/Parse/Parser.cpp:839:12
    #19 0x7f129cd86cf7 in clang::Parser::ParseTopLevelDecl(clang::OpaquePtr<clang::DeclGroupRef>&) /home/vsts/work/1/s/tools/clang/lib/Parse/Parser.cpp:606:12
    #20 0x7f129cce8da7 in clang::ParseAST(clang::Sema&, bool, bool) /home/vsts/work/1/s/tools/clang/lib/Parse/ParseAST.cpp:140:11
    #21 0x7f129b75b50d in clang::FrontendAction::Execute() /home/vsts/work/1/s/tools/clang/lib/Frontend/FrontendAction.cpp:455:8
    #22 0x7f129a1b9959 in DxcCompiler::Compile(DxcBuffer const*, wchar_t const**, unsigned int, IDxcIncludeHandler*, _GUID const&, void**) /home/vsts/work/1/s/tools/clang/tools/dxcompiler/dxcompilerobj.cpp:933:18
    #23 0x7f129a1b005c in hlsl::DxcCompilerAdapter::WrapCompile(bool, IDxcBlob*, wchar_t const*, wchar_t const*, wchar_t const*, wchar_t const**, unsigned int, DxcDefine const*, unsigned int, IDxcIncludeHandler*, IDxcOperationResult**, wchar_t**, IDxcBlob**) /home/vsts/work/1/s/tools/clang/tools/dxcompiler/dxcompilerobj.cpp:1855:5
    #24 0x7f129a1b2e2c in hlsl::DxcCompilerAdapter::CompileWithDebug(IDxcBlob*, wchar_t const*, wchar_t const*, wchar_t const*, wchar_t const**, unsigned int, DxcDefine const*, unsigned int, IDxcIncludeHandler*, IDxcOperationResult**, wchar_t**, IDxcBlob**) /home/vsts/work/1/s/tools/clang/tools/dxcompiler/dxcompilerobj.cpp:1758:10
    #25 0x7f129a1b47c8 in hlsl::DxcCompilerAdapter::Compile(IDxcBlob*, wchar_t const*, wchar_t const*, wchar_t const*, wchar_t const**, unsigned int, DxcDefine const*, unsigned int, IDxcIncludeHandler*, IDxcOperationResult**) /home/vsts/work/1/s/tools/clang/tools/dxcompiler/dxcompileradapter.h:75:12
    #26 0x55a3223c0d06 in DxcContext::Compile() /home/vsts/work/1/s/tools/clang/tools/dxclib/dxc.cpp:874:9
    #27 0x55a3223c9fd4 in dxc::main(int, char const**) /home/vsts/work/1/s/tools/clang/tools/dxclib/dxc.cpp:1502:24
    #28 0x7f1298629d8f  (/lib/x86_64-linux-gnu/libc.so.6+0x29d8f) (BuildId: 490fef8403240c91833978d494d39e537409b92e)

SUMMARY: AddressSanitizer: 72 byte(s) leaked in 2 allocation(s).

Environment
Observed with

  • DXC top of tree
  • Azure CI Clang /Release/linux pipeline. Reproduced locally using Ubuntu on WSL / Clang 18.1.3 / Release build with cmake -DLLVM_USE_SANITIZER=Address

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start in tools/clang/include/clang/AST/HlslTypes.h, where PayloadAccessAnnotation and UnusualAnnotation are defined, then inspect their allocation and cleanup through tools/clang/lib/Parse/ParseDecl.cpp. Reproduce with the payload containing more than four shader stages using a Release Linux build with Clang 18 and AddressSanitizer. Done means the reproducer no longer reports a leak.

Written by the indexing model from the issue text.

Assessment

Tech stack
cpp
Domain
compilers
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Stale
Clarity
Clearly specified
Newbie friendliness
45/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.