Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[clang] API: isFlexibleArrayMember will crash when the type source location associated with the Expr is invalid and macros are skipped #63074

Open
2over12 opened this issue Jun 2, 2023 · 3 comments
Labels
clang:frontend Language frontend issues, e.g. anything involving "Sema" crash Prefer [crash-on-valid] or [crash-on-invalid]

Comments

@2over12
Copy link

2over12 commented Jun 2, 2023

Minimal reproducing example:

#include <clang/AST/ASTContext.h>
#include <clang/AST/Decl.h>
#include <clang/AST/DeclarationName.h>
#include <clang/AST/Expr.h>
#include <clang/AST/OperationKinds.h>
#include <clang/AST/Type.h>
#include <clang/Basic/LangOptions.h>
#include <clang/Basic/SourceLocation.h>
#include <clang/Basic/Specifiers.h>
#include <clang/Frontend/ASTUnit.h>
#include <clang/Sema/Sema.h>
#include <clang/Tooling/Tooling.h>
#include <llvm/ADT/APInt.h>


clang::IdentifierInfo *CreateIdentifier(std::string name, clang::ASTContext& ctx ) {
  std::string str{""};
  for (auto chr : name) {
    str.push_back(std::isalnum(chr) ? chr : '_');
  }
  return &ctx.Idents.get(str);
}


int main(int argc, char *argv[]) {
    auto ast = clang::tooling::buildASTFromCode("");

    auto rdecl = clang::RecordDecl::Create(ast->getASTContext(), clang::TagTypeKind::TTK_Struct, ast->getASTContext().getTranslationUnitDecl(), clang::SourceLocation(), clang::SourceLocation(), CreateIdentifier("test", ast->getASTContext()));
    auto& sema = ast->getSema();
    auto chr_ty = ast->getASTContext().getUnsignedWCharType();
    auto int_sz = clang::IntegerLiteral::Create( ast->getASTContext(), llvm::APInt(64, 1, false), ast->getASTContext().getIntTypeForBitwidth(64, 0),  clang::SourceLocation());
    auto arr_ty = ast->getASTContext().getConstantArrayType(chr_ty, llvm::APInt(64, 1, false), int_sz, clang::ArrayType::ArraySizeModifier::Normal, 0);
    auto fld = sema.CheckFieldDecl(clang::DeclarationName(CreateIdentifier("test_field", ast->getASTContext())), arr_ty, ast->getASTContext().getTrivialTypeSourceInfo(arr_ty), rdecl, clang::SourceLocation(), false, nullptr, clang::ICIS_NoInit, 
        clang::SourceLocation(), clang::AccessSpecifier::AS_none,nullptr);
    rdecl->completeDefinition();
    
    auto record_ty = ast->getASTContext().getRecordType(rdecl);
    clang::CXXScopeSpec ss;
    auto dap{clang::DeclAccessPair::make(fld, fld->getAccess())};
    auto gv = clang::VarDecl::Create(ast->getASTContext(), ast->getASTContext().getTranslationUnitDecl(), clang::SourceLocation(), clang::SourceLocation(), CreateIdentifier("test_gv", ast->getASTContext()),record_ty,ast->getASTContext().getTrivialTypeSourceInfo(record_ty), clang::SC_None);
    
    auto ref = sema.BuildDeclRefExpr(gv, gv->getType(), clang::ExprValueKind::VK_LValue, clang::SourceLocation(), nullptr);
    
    auto fld_ref = sema.BuildFieldReferenceExpr(ref, false, clang::SourceLocation(),ss, fld, dap,clang::DeclarationNameInfo());

    assert(fld_ref.isUsable());

    assert(fld_ref.get()->isFlexibleArrayMemberLike(ast->getASTContext(), clang::LangOptions::StrictFlexArraysLevelKind::Default, true));
}

isFlexibleArrayMemberLike uses the source type info to attempt to determine if the size is the result of a macro. This behavior can lead to a nullptr being passed to dyn_cast if the source range associated with the type info is an empty location.

Unfortunately, CheckArrayAccess uses ignoreTemplate meaning in cases where the API is used for code generation (ie. when source locs will not exist) a crash will occur.

An example patch that treats type info without a location as a non-macro size is available here

@EugeneZelenko EugeneZelenko added clang:frontend Language frontend issues, e.g. anything involving "Sema" crash Prefer [crash-on-valid] or [crash-on-invalid] and removed new issue labels Jun 2, 2023
@llvmbot
Copy link
Collaborator

llvmbot commented Jun 2, 2023

@llvm/issue-subscribers-clang-frontend

@moodyhunter
Copy link

moodyhunter commented Oct 28, 2023

I'm also experiencing this bug when using clangd with the following file content:

typedef whatever_it_is_it_must_be_undefined features_array_t[10];

typedef struct
{
    features_array_t features;
} state_t;

void my_func()
{
    state_t *state;
    state->features[1];
}

cross reference: clangd/clangd#1806

@shafik
Copy link
Collaborator

shafik commented Oct 29, 2023

CC @AaronBallman

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
clang:frontend Language frontend issues, e.g. anything involving "Sema" crash Prefer [crash-on-valid] or [crash-on-invalid]
Projects
None yet
Development

No branches or pull requests

5 participants