As reported by @kees, GCC treats __builtin_object_size of structures
containing flexible array members (aka arrays with incomplete type) not
just as the sizeof the underlying type, but additionally the size of the
members in a designated initializer list.
Details
Diff Detail
- Repository
- rG LLVM Github Monorepo
Unit Tests
Event Timeline
clang/lib/AST/ExprConstant.cpp | ||
---|---|---|
11740 | Isn't this a possible null-deref? |
clang/lib/AST/ExprConstant.cpp | ||
---|---|---|
11740 | I don't think so; in fact, I can use cast and get rather than dyn_cast_or_null and dyn_cast here. Just because we have a pointer doesn't mean it's possibly nullptr; I don't think we can reach this code patch for evaluating the __builtin_object_size of a struct with a flexible array member if the LValue doesn't have a corresponding VarDecl. |
clang/lib/AST/ExprConstant.cpp | ||
---|---|---|
11740 | Of course that is a possibility. You shouldn't use dyn_cast right before a dereference, this should definitely be using cast/get, since they assert. What does the LValue have when the dynamic struct does not have an initializer? Or just an empty one? |
clang/lib/AST/ExprConstant.cpp | ||
---|---|---|
11740 | s/code patch/code path/ |
Added clang-vendors in case this is a breaking change? It also needs a release note (likely both in the potentially breaking changes section, and the bug fix section).
clang/lib/AST/ExprConstant.cpp | ||
---|---|---|
11740 |
Tested: struct foo { int x; int y[]; }; static struct foo instance = { .x = 3, // .y = { 5, 10, 15, }, }; unsigned long foo (void) { return __builtin_object_size(&instance, 1); } With the following values for .y in instance:
|
Thanks for testing those! Can you add them to the object-size.c if they aren't already tested?
clang/docs/ReleaseNotes.rst | ||
---|---|---|
289 | We should probably also release-note in this seciton. |
I'm OK with this, but please give the clang-vendors folks a few days to comment before committing this. Thanks for your patience!
This also changes the behavior of __builtin_dynamic_object_size (see @kees ' full example: https://github.com/llvm/llvm-project/issues/62789#issue-1714764560). s/changes/fixes/. Let me add more tests and notes about that.
clang/lib/AST/ExprConstant.cpp | ||
---|---|---|
11740 | This might have been missed in the discussion here, but what actually ensures we have a VarDecl here? I guess most other LValueBases can't actually have a struct type, but a CompoundLiteralExpr can. (Looking briefly at the code, I can't find any other possibilities at the moment, but in any case, the assumption seems pretty fragile.) |
clang/lib/AST/ExprConstant.cpp | ||
---|---|---|
11740 | I assume that the code works as such: struct foo my_foo; return __builtin_object_size(&foo, 1); foo is a VarDecl otherwise how do you take the address? What other expression could be passed to __builtin_object_size that isn't a reference to a variable? |
clang/lib/AST/ExprConstant.cpp | ||
---|---|---|
11740 | __builtin_object_size(&(struct S){}, 1)? Not really a useful construct, but we don't reject it. |
clang/lib/AST/ExprConstant.cpp | ||
---|---|---|
11740 |
This change causes an assertion failure on the following test case. The memset is important for some reason.
saugustine@saugustine-desktop:~/llvm/build $ cat t.c struct foo { unsigned char x; unsigned char data[]; }; extern void *memset (void *__s, int __c, unsigned long __n); void bar(void) { struct foo bat; memset(&bat, 0, sizeof(bat)); } saugustine@saugustine-desktop:~/llvm/build $ ./bin/clang -c t.c clang: /usr/local/google/home/saugustine/llvm/llvm-project/clang/lib/AST/Decl.cpp:2786: clang::CharUnits clang::VarDecl::getFlexibleArrayInitChars(const clang::ASTContext &) const: Assertion `hasInit() && "Expect initializer to check for flexible array init"' failed. PLEASE submit a bug report to https://github.com/llvm/llvm-project/issues/ and include the crash backtrace, preprocessed source, and associated run script. Stack dump: 0. Program arguments: ./bin/clang -c t.c 1. t.c:11:30: current parser token ')' 2. t.c:9:1: parsing function body 'bar' 3. t.c:9:1: in compound statement ('{}') #0 0x000055bf947c1d7d llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) /usr/local/google/home/saugustine/llvm/llvm-project/llvm/lib/Support/Unix/Signals.inc:602:11 #1 0x000055bf947c21fb PrintStackTraceSignalHandler(void*) /usr/local/google/home/saugustine/llvm/llvm-project/llvm/lib/Support/Unix/Signals.inc:675:1 #2 0x000055bf947c0496 llvm::sys::RunSignalHandlers() /usr/local/google/home/saugustine/llvm/llvm-project/llvm/lib/Support/Signals.cpp:104:5 #3 0x000055bf947c15ee llvm::sys::CleanupOnSignal(unsigned long) /usr/local/google/home/saugustine/llvm/llvm-project/llvm/lib/Support/Unix/Signals.inc:368:1 #4 0x000055bf946ff954 (anonymous namespace)::CrashRecoveryContextImpl::HandleCrash(int, unsigned long) /usr/local/google/home/saugustine/llvm/llvm-project/llvm/lib/Support/CrashRecoveryContext.cpp:0:7 #5 0x000055bf946ffd12 CrashRecoverySignalHandler(int) /usr/local/google/home/saugustine/llvm/llvm-project/llvm/lib/Support/CrashRecoveryContext.cpp:391:1 #6 0x00007f95ab65af90 (/lib/x86_64-linux-gnu/libc.so.6+0x3bf90) #7 0x00007f95ab6a9ccc __pthread_kill_implementation ./nptl/./nptl/pthread_kill.c:44:76 #8 0x00007f95ab65aef2 raise ./signal/../sysdeps/posix/raise.c:27:6 #9 0x00007f95ab645472 abort ./stdlib/./stdlib/abort.c:81:7 #10 0x00007f95ab645395 _nl_load_domain ./intl/./intl/loadmsgcat.c:1177:9 #11 0x00007f95ab653df2 (/lib/x86_64-linux-gnu/libc.so.6+0x34df2) #12 0x000055bf9a6a62cf clang::VarDecl::getFlexibleArrayInitChars(clang::ASTContext const&) const /usr/local/google/home/saugustine/llvm/llvm-project/clang/lib/AST/Decl.cpp:0:3 #13 0x000055bf9a89094b determineEndOffset((anonymous namespace)::EvalInfo&, clang::SourceLocation, unsigned int, (anonymous namespace)::LValue const&, clang::CharUnits&)::$_15::operator()(clang::QualType, clang::CharUnits&) const /usr/local/google/home/saugustine/llvm/llvm-project/clang/lib/AST/ExprConstant.cpp:11741:21 #14 0x000055bf9a89024e determineEndOffset((anonymous namespace)::EvalInfo&, clang::SourceLocation, unsigned int, (anonymous namespace)::LValue const&, clang::CharUnits&) /usr/local/google/home/saugustine/llvm/llvm-project/clang/lib/AST/ExprConstant.cpp:11763:5 #15 0x000055bf9a7dbb62 tryEvaluateBuiltinObjectSize(clang::Expr const*, unsigned int, (anonymous namespace)::EvalInfo&, unsigned long&) /usr/local/google/home/saugustine/llvm/llvm-project/clang/lib/AST/ExprConstant.cpp:11848:7 #16 0x000055bf9a7db953 clang::Expr::tryEvaluateObjectSize(unsigned long&, clang::ASTContext&, unsigned int) const /usr/local/google/home/saugustine/llvm/llvm-project/clang/lib/AST/ExprConstant.cpp:16274:3 #17 0x000055bf98a86e07 clang::Sema::checkFortifiedBuiltinMemoryFunction(clang::FunctionDecl*, clang::CallExpr*)::$_1::operator()(unsigned int) const /usr/local/google/home/saugustine/llvm/llvm-project/clang/lib/Sema/SemaChecking.cpp:1111:9 #18 0x000055bf98a86913 clang::Sema::checkFortifiedBuiltinMemoryFunction(clang::FunctionDecl*, clang::CallExpr*) /usr/local/google/home/saugustine/llvm/llvm-project/clang/lib/Sema/SemaChecking.cpp:1318:21 #19 0x000055bf98fdcb51 clang::Sema::BuildResolvedCallExpr(clang::Expr*, clang::NamedDecl*, clang::SourceLocation, llvm::ArrayRef<clang::Expr*>, clang::SourceLocation, clang::Expr*, bool, clang::CallExpr::ADLCallKind) /usr/local/google/home/saugustine/llvm/llvm-project/clang/lib/Sema/SemaExpr.cpp:7463:9 #20 0x000055bf98fbbf78 clang::Sema::BuildCallExpr(clang::Scope*, clang::Expr*, clang::SourceLocation, llvm::MutableArrayRef<clang::Expr*>, clang::SourceLocation, clang::Expr*, bool, bool) /usr/local/google/home/saugustine/llvm/llvm-project/clang/lib/Sema/SemaExpr.cpp:7112:10 #21 0x000055bf98fda08f clang::Sema::ActOnCallExpr(clang::Scope*, clang::Expr*, clang::SourceLocation, llvm::MutableArrayRef<clang::Expr*>, clang::SourceLocation, clang::Expr*) /usr/local/google/home/saugustine/llvm/llvm-project/clang/lib/Sema/SemaExpr.cpp:6880:7 #22 0x000055bf988f57cf clang::Parser::ParsePostfixExpressionSuffix(clang::ActionResult<clang::Expr*, true>) /usr/local/google/home/saugustine/llvm/llvm-project/clang/lib/Parse/ParseExpr.cpp:2125:23 #23 0x000055bf988fca6f clang::Parser::ParseCastExpression(clang::Parser::CastParseKind, bool, bool&, clang::Parser::TypeCastState, bool, bool*) /usr/local/google/home/saugustine/llvm/llvm-project/clang/lib/Parse/ParseExpr.cpp:1852:9 #24 0x000055bf988f3fe9 clang::Parser::ParseCastExpression(clang::Parser::CastParseKind, bool, clang::Parser::TypeCastState, bool, bool*) /usr/local/google/home/saugustine/llvm/llvm-project/clang/lib/Parse/ParseExpr.cpp:683:20 #25 0x000055bf988f24d8 clang::Parser::ParseAssignmentExpression(clang::Parser::TypeCastState) /usr/local/google/home/saugustine/llvm/llvm-project/clang/lib/Parse/ParseExpr.cpp:175:20 #26 0x000055bf988f238f clang::Parser::ParseExpression(clang::Parser::TypeCastState) /usr/local/google/home/saugustine/llvm/llvm-project/clang/lib/Parse/ParseExpr.cpp:126:18 #27 0x000055bf98981928 clang::Parser::ParseExprStatement(clang::Parser::ParsedStmtContext) /usr/local/google/home/saugustine/llvm/llvm-project/clang/lib/Parse/ParseStmt.cpp:525:19 #28 0x000055bf9897fe5e clang::Parser::ParseStatementOrDeclarationAfterAttributes(llvm::SmallVector<clang::Stmt*, 32u>&, clang::Parser::ParsedStmtContext, clang::SourceLocation*, clang::ParsedAttributes&, clang::ParsedAttributes&) /usr/local/google/home/saugustine/llvm/llvm-project/clang/lib/Parse/ParseStmt.cpp:279:14 #29 0x000055bf9897f4db clang::Parser::ParseStatementOrDeclaration(llvm::SmallVector<clang::Stmt*, 32u>&, clang::Parser::ParsedStmtContext, clang::SourceLocation*) /usr/local/google/home/saugustine/llvm/llvm-project/clang/lib/Parse/ParseStmt.cpp:117:20 #30 0x000055bf9898822e clang::Parser::ParseCompoundStatementBody(bool) /usr/local/google/home/saugustine/llvm/llvm-project/clang/lib/Parse/ParseStmt.cpp:1200:11 #31 0x000055bf98989934 clang::Parser::ParseFunctionStatementBody(clang::Decl*, clang::Parser::ParseScope&) /usr/local/google/home/saugustine/llvm/llvm-project/clang/lib/Parse/ParseStmt.cpp:2464:21 #32 0x000055bf9887db1f clang::Parser::ParseFunctionDefinition(clang::ParsingDeclarator&, clang::Parser::ParsedTemplateInfo const&, clang::Parser::LateParsedAttrList*) /usr/local/google/home/saugustine/llvm/llvm-project/clang/lib/Parse/Parser.cpp:1471:3 #33 0x000055bf9889f2cb clang::Parser::ParseDeclGroup(clang::ParsingDeclSpec&, clang::DeclaratorContext, clang::ParsedAttributes&, clang::SourceLocation*, clang::Parser::ForRangeInit*) /usr/local/google/home/saugustine/llvm/llvm-project/clang/lib/Parse/ParseDecl.cpp:2175:27 #34 0x000055bf9887c99a clang::Parser::ParseDeclOrFunctionDefInternal(clang::ParsedAttributes&, clang::ParsedAttributes&, clang::ParsingDeclSpec&, clang::AccessSpecifier) /usr/local/google/home/saugustine/llvm/llvm-project/clang/lib/Parse/Parser.cpp:1210:10 #35 0x000055bf9887bedf clang::Parser::ParseDeclarationOrFunctionDefinition(clang::ParsedAttributes&, clang::ParsedAttributes&, clang::ParsingDeclSpec*, clang::AccessSpecifier) /usr/local/google/home/saugustine/llvm/llvm-project/clang/lib/Parse/Parser.cpp:1225:12 #36 0x000055bf9887b7a4 clang::Parser::ParseExternalDeclaration(clang::ParsedAttributes&, clang::ParsedAttributes&, clang::ParsingDeclSpec*) /usr/local/google/home/saugustine/llvm/llvm-project/clang/lib/Parse/Parser.cpp:1040:14 #37 0x000055bf9887967c clang::Parser::ParseTopLevelDecl(clang::OpaquePtr<clang::DeclGroupRef>&, clang::Sema::ModuleImportState&) /usr/local/google/home/saugustine/llvm/llvm-project/clang/lib/Parse/Parser.cpp:742:12 #38 0x000055bf988744d7 clang::ParseAST(clang::Sema&, bool, bool) /usr/local/google/home/saugustine/llvm/llvm-project/clang/lib/Parse/ParseAST.cpp:163:16 #39 0x000055bf957d311c clang::ASTFrontendAction::ExecuteAction() /usr/local/google/home/saugustine/llvm/llvm-project/clang/lib/Frontend/FrontendAction.cpp:1168:1 #40 0x000055bf9629da04 clang::CodeGenAction::ExecuteAction() /usr/local/google/home/saugustine/llvm/llvm-project/clang/lib/CodeGen/CodeGenAction.cpp:1174:5 #41 0x000055bf957d2b1c clang::FrontendAction::Execute() /usr/local/google/home/saugustine/llvm/llvm-project/clang/lib/Frontend/FrontendAction.cpp:1060:7 #42 0x000055bf956fbe48 clang::CompilerInstance::ExecuteAction(clang::FrontendAction&) /usr/local/google/home/saugustine/llvm/llvm-project/clang/lib/Frontend/CompilerInstance.cpp:1049:23 #43 0x000055bf9599b5c7 clang::ExecuteCompilerInvocation(clang::CompilerInstance*) /usr/local/google/home/saugustine/llvm/llvm-project/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp:264:8 #44 0x000055bf92b09533 cc1_main(llvm::ArrayRef<char const*>, char const*, void*) /usr/local/google/home/saugustine/llvm/llvm-project/clang/tools/driver/cc1_main.cpp:249:13 #45 0x000055bf92af4f6a ExecuteCC1Tool(llvm::SmallVectorImpl<char const*>&, llvm::ToolContext const&) /usr/local/google/home/saugustine/llvm/llvm-project/clang/tools/driver/driver.cpp:366:5 #46 0x000055bf92af68dd clang_main(int, char**, llvm::ToolContext const&)::$_0::operator()(llvm::SmallVectorImpl<char const*>&) const /usr/local/google/home/saugustine/llvm/llvm-project/clang/tools/driver/driver.cpp:506:7 #47 0x000055bf92af68ad int llvm::function_ref<int (llvm::SmallVectorImpl<char const*>&)>::callback_fn<clang_main(int, char**, llvm::ToolContext const&)::$_0>(long, llvm::SmallVectorImpl<char const*>&) /usr/local/google/home/saugustine/llvm/llvm-project/llvm/include/llvm/ADT/STLFunctionalExtras.h:45:5 #48 0x000055bf955aa499 llvm::function_ref<int (llvm::SmallVectorImpl<char const*>&)>::operator()(llvm::SmallVectorImpl<char const*>&) const /usr/local/google/home/saugustine/llvm/llvm-project/llvm/include/llvm/ADT/STLFunctionalExtras.h:68:5 #49 0x000055bf955a68b8 clang::driver::CC1Command::Execute(llvm::ArrayRef<std::optional<llvm::StringRef> >, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >*, bool*) const::$_1::operator()() const /usr/local/google/home/saugustine/llvm/llvm-project/clang/lib/Driver/Job.cpp:439:34 #50 0x000055bf955a6885 void llvm::function_ref<void ()>::callback_fn<clang::driver::CC1Command::Execute(llvm::ArrayRef<std::optional<llvm::StringRef> >, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >*, bool*) const::$_1>(long) /usr/local/google/home/saugustine/llvm/llvm-project/llvm/include/llvm/ADT/STLFunctionalExtras.h:45:5 #51 0x000055bf9345b379 llvm::function_ref<void ()>::operator()() const /usr/local/google/home/saugustine/llvm/llvm-project/llvm/include/llvm/ADT/STLFunctionalExtras.h:68:5 #52 0x000055bf946ff76a llvm::CrashRecoveryContext::RunSafely(llvm::function_ref<void ()>) /usr/local/google/home/saugustine/llvm/llvm-project/llvm/lib/Support/CrashRecoveryContext.cpp:427:3 #53 0x000055bf955a6017 clang::driver::CC1Command::Execute(llvm::ArrayRef<std::optional<llvm::StringRef> >, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >*, bool*) const /usr/local/google/home/saugustine/llvm/llvm-project/clang/lib/Driver/Job.cpp:439:7 #54 0x000055bf95540bdf clang::driver::Compilation::ExecuteCommand(clang::driver::Command const&, clang::driver::Command const*&, bool) const /usr/local/google/home/saugustine/llvm/llvm-project/clang/lib/Driver/Compilation.cpp:199:15 #55 0x000055bf95540de7 clang::driver::Compilation::ExecuteJobs(clang::driver::JobList const&, llvm::SmallVectorImpl<std::pair<int, clang::driver::Command const*> >&, bool) const /usr/local/google/home/saugustine/llvm/llvm-project/clang/lib/Driver/Compilation.cpp:253:13 #56 0x000055bf9555b4f8 clang::driver::Driver::ExecuteCompilation(clang::driver::Compilation&, llvm::SmallVectorImpl<std::pair<int, clang::driver::Command const*> >&) /usr/local/google/home/saugustine/llvm/llvm-project/clang/lib/Driver/Driver.cpp:1868:7 #57 0x000055bf92af4a28 clang_main(int, char**, llvm::ToolContext const&) /usr/local/google/home/saugustine/llvm/llvm-project/clang/tools/driver/driver.cpp:542:9 #58 0x000055bf92b2ccdd main /usr/local/google/home/saugustine/llvm/build/tools/clang/tools/driver/clang-driver.cpp:15:3 #59 0x00007f95ab64618a __libc_start_call_main ./csu/../sysdeps/nptl/libc_start_call_main.h:74:3 #60 0x00007f95ab646245 call_init ./csu/../csu/libc-start.c:128:20 #61 0x00007f95ab646245 __libc_start_main ./csu/../csu/libc-start.c:368:5 #62 0x000055bf92af36c1 _start (./bin/clang+0x19096c1) clang: error: clang frontend command failed with exit code 134 (use -v to see invocation) clang version 17.0.0 (https://github.com/llvm/llvm-project.git 4faf3aaf28226a4e950c103a14f6fc1d1fdabb1b) Target: x86_64-unknown-linux-gnu Thread model: posix InstalledDir: /usr/local/google/home/saugustine/llvm/build/./bin clang: note: diagnostic msg: ******************** PLEASE ATTACH THE FOLLOWING FILES TO THE BUG REPORT: Preprocessed source(s) and associated run script(s) are located at: clang: note: diagnostic msg: /tmp/t-4b8223.c clang: note: diagnostic msg: /tmp/t-4b8223.sh clang: note: diagnostic msg: ********************
- prefer OBJECT_SIZE_BUILTIN to builtin_object_size to additionally test dynamic_builtin_object_size
We should probably also release-note in this seciton.