llvm-project/llvm/lib/IR
Hans Wennborg 2bc57d85eb Don't override __attribute__((no_stack_protector)) by inlining (PR52886)
Since 26c6a3e736, LLVM's inliner will "upgrade" the caller's stack protector
attribute based on the callee. This lead to surprising results with Clang's
no_stack_protector attribute added in 4fbf84c173 (D46300). Consider the
following code compiled with clang -fstack-protector-strong -Os
(https://godbolt.org/z/7s3rW7a1q).

  extern void h(int* p);

  inline __attribute__((always_inline)) int g() {
    return 0;
  }

  int __attribute__((__no_stack_protector__)) f() {
    int a[1];
    h(a);
    return g();
  }

LLVM will inline g() into f(), and f() would get a stack protector, against the
users explicit wishes, potentially breaking the program e.g. if h() changes the
value of the stack cookie. That's a miscompile.

More recently, bc044a88ee (D91816) addressed this problem by preventing
inlining when the stack protector is disabled in the caller and enabled in the
callee or vice versa. However, the problem remained if the callee is marked
always_inline as in the example above. This affected users, see e.g.
http://crbug.com/1274129 and http://llvm.org/pr52886.

One way to fix this would be to prevent inlining also in the always_inline
case. Despite the name, always_inline does not guarantee inlining, so this
would be legal but potentially surprising to users.

However, I think the better fix is to not enable the stack protector in a
caller based on the callee. The motivation for the old behaviour is unclear, it
seems counter-intuitive, and causes real problems as we've seen.

This commit implements that fix, which means in the example above, g() gets
inlined into f() (also without always_inline), and f() is emitted without stack
protector. I think that matches most developers' expectations, and that's also
what GCC does.

Another effect of this change is that a no_stack_protector function can now be
inlined into a stack protected function, e.g. (https://godbolt.org/z/hafP6W856):

  extern void h(int* p);

  inline int __attribute__((__no_stack_protector__)) __attribute__((always_inline)) g() {
    return 0;
  }

  int f() {
    int a[1];
    h(a);
    return g();
  }

I think that's fine. Such code would be unusual since no_stack_protector is
normally applied to a program entry point which sets up the stack canary. And
even if such code exists, inlining doesn't change the semantics: there is still
no stack cookie setup/check around entry/exit of the g() code region, but there
may be in the surrounding context, as there was before inlining. This also
matches GCC.

See also the discussion at https://gcc.gnu.org/bugzilla/show_bug.cgi?id=94722

Differential revision: https://reviews.llvm.org/D116589
2022-01-13 12:04:49 +01:00
..
AbstractCallSite.cpp [IR] Migrate from getNumArgOperands to arg_size (NFC) 2021-10-04 08:40:25 -07:00
AsmWriter.cpp [llvm][IR] Add no_cfi constant 2021-12-20 12:55:32 -08:00
Assumptions.cpp [Attributor] Introduce AAAssumptionInfo to propagate assumptions 2021-11-09 17:39:18 -05:00
AttributeImpl.h [IR] Split vscale_range interface 2021-12-07 10:38:26 +00:00
Attributes.cpp Don't override __attribute__((no_stack_protector)) by inlining (PR52886) 2022-01-13 12:04:49 +01:00
AutoUpgrade.cpp [X86][MS] Change the alignment of f80 to 16 bytes on Windows 32bits to match with ICC 2022-01-12 17:50:37 +08:00
BasicBlock.cpp [llvm] Use range-based for loops (NFC) 2021-12-08 20:35:39 -08:00
BuiltinGCs.cpp [GC][NFC] Move GCStrategy from CodeGen to IR 2021-05-13 12:31:59 +07:00
CMakeLists.txt Reapply CycleInfo: Introduce cycles as a generalization of loops 2021-12-10 14:36:43 +05:30
Comdat.cpp [IR] Track users of comdats 2022-01-06 09:13:58 +01:00
ConstantFold.cpp [ConstFold] Add missing check for inbounds gep 2022-01-06 09:59:40 +01:00
ConstantFold.h [ConstantFolding] Use ICmpInst::Predicate instead of plain integer 2021-12-30 14:31:44 +07:00
ConstantRange.cpp [ConstantRange] Add exact union/intersect (NFC) 2021-11-07 21:46:06 +01:00
Constants.cpp [ConstantFolding] Use ICmpInst::Predicate instead of plain integer 2021-12-30 14:31:44 +07:00
ConstantsContext.h [IR] Added operator delete to subclasses of User to avoid UB 2021-07-08 11:59:22 +02:00
Core.cpp [llvm] Use nullptr instead of 0 (NFC) 2021-12-28 08:52:25 -08:00
DIBuilder.cpp [clang][CodeGen] Remove the signed version of createExpression 2021-12-27 14:16:08 +08:00
DataLayout.cpp [IR] Extract method to get single GEP index from offset (NFC) 2021-12-10 17:22:46 +01:00
DebugInfo.cpp [clang][CodeGen] Remove the signed version of createExpression 2021-12-27 14:16:08 +08:00
DebugInfoMetadata.cpp [DebugInfo] run clang-format on some unformatted files 2021-11-11 18:59:41 -08:00
DebugLoc.cpp
DiagnosticHandler.cpp [llvm] Replace report_fatal_error(std::string) uses with report_fatal_error(Twine) 2021-10-06 12:04:30 +01:00
DiagnosticInfo.cpp [IR] Fix a few incorrect paths in file header comments. NFC 2021-10-15 09:18:57 -07:00
DiagnosticPrinter.cpp [IR] Fix a few incorrect paths in file header comments. NFC 2021-10-15 09:18:57 -07:00
Dominators.cpp [gvn] Precisely propagate equalities to phi operands 2021-03-08 08:59:00 -08:00
FPEnv.cpp [NFC] Rename functions to match our naming scheme. 2021-10-07 14:12:41 -04:00
Function.cpp Use a sorted array instead of a map to store AttrBuilder string attributes 2022-01-10 14:49:53 +01:00
GCStrategy.cpp [GC][NFC] Make getGCStrategy by name available in IR 2021-08-02 14:26:04 +07:00
GVMaterializer.cpp
Globals.cpp [IR] Track users of comdats 2022-01-06 09:13:58 +01:00
IRBuilder.cpp [IR] Change CreateStepVector to work with element types smaller than i8 2021-11-17 10:47:50 +00:00
IRPrintingPasses.cpp
InlineAsm.cpp [llvm] Use range-based for loops (NFC) 2021-12-09 09:37:29 -08:00
Instruction.cpp Rename doesNotReadMemory to onlyWritesMemory globally [NFC] 2022-01-05 08:52:55 -08:00
Instructions.cpp [NFC] Method for evaluation of FCmpInst for constant operands 2021-12-25 17:37:38 +07:00
IntrinsicInst.cpp [VP] llvm.vp.merge intrinsic and LangRef 2022-01-12 14:06:56 +01:00
LLVMContext.cpp [OpaquePtr] Fix initialization-order-fiasco 2021-11-04 19:29:06 -07:00
LLVMContextImpl.cpp Revert "[DebugInfo] Enforce implicit constraints on `distinct` MDNodes" 2021-11-09 14:27:55 -08:00
LLVMContextImpl.h [llvm][IR] Add no_cfi constant 2021-12-20 12:55:32 -08:00
LLVMRemarkStreamer.cpp [SystemZ][z/OS][Windows] Add new OF_TextWithCRLF flag and use this flag instead of OF_Text 2021-04-06 07:23:31 -04:00
LegacyPassManager.cpp [llvm] Remove redundant member initialization (NFC) 2022-01-07 17:45:09 -08:00
MDBuilder.cpp
Mangler.cpp [Mangler] Calculate the argument list byte count suffix correctly when returning large values 2021-09-29 11:42:28 -07:00
Metadata.cpp [llvm] Use isa instead of dyn_cast (NFC) 2021-11-14 19:40:46 -08:00
MetadataImpl.h
Module.cpp Revert "[llvm] Remove redundant member initialization (NFC)" 2022-01-03 11:28:47 -08:00
ModuleSummaryIndex.cpp [LTO] Ignore unreachable virtual functions in WPD in hybrid LTO. 2021-12-14 20:18:04 +00:00
Operator.cpp [llvm] Construct SmallVector with iterator ranges (NFC) 2021-12-20 23:43:24 -08:00
OptBisect.cpp Delay initialization of OptBisect 2021-08-05 09:04:17 -05:00
Pass.cpp
PassInstrumentation.cpp [NewPM] Handle passes with params in -print-before/-print-after 2021-07-09 09:27:37 +02:00
PassManager.cpp [NewPM] Make eager analysis invalidation per-adaptor 2021-11-04 17:16:11 -07:00
PassRegistry.cpp
PassTimingInfo.cpp [LLVM][NFC]Inclusive language: remove occurances of sanity check/test from llvm 2021-11-24 17:29:55 -05:00
PrintPasses.cpp
ProfileSummary.cpp [NFC] ProfileSummary: const a bunch of members and fields. 2021-10-18 08:55:06 -07:00
PseudoProbe.cpp [IR] Remove addPseudoProbeAttribute (NFC) 2021-08-26 09:02:26 -07:00
ReplaceConstant.cpp [IR] Replace *all* uses of a constant expression by corresponding instruction 2021-11-02 10:01:46 +05:30
SSAContext.cpp Reapply CycleInfo: Introduce cycles as a generalization of loops 2021-12-10 14:36:43 +05:30
SafepointIRVerifier.cpp [LLVM][NFC]Inclusive language: remove occurances of sanity check/test from llvm 2021-11-24 17:29:55 -05:00
Statepoint.cpp [NFC] One more AttributeList::getAttribute(FunctionIndex) -> getFnAttr() 2021-08-13 16:49:05 -07:00
StructuralHash.cpp
SymbolTableListTraitsImpl.h
Type.cpp [OpaquePtr] Fix initialization-order-fiasco 2021-11-04 19:29:06 -07:00
TypeFinder.cpp [TypeFinder] Support opaque pointers 2022-01-10 14:46:45 +01:00
Use.cpp
User.cpp [CSSPGO] Unblock optimizations with pseudo probe instrumentation part 3. 2021-10-12 09:44:12 -07:00
Value.cpp [NFC] Replace some deprecated getAlignment() calls with getAlign() 2021-12-09 08:43:19 -08:00
ValueSymbolTable.cpp PR51018: Remove explicit conversions from SmallString to StringRef to future-proof against C++23 2021-07-08 13:37:57 -07:00
Verifier.cpp [IR] Change vector.splice intrinsic to reject out-of-bounds indices 2022-01-11 09:37:39 +00:00