[PATCH] D69569: isBuiltinFunc() uses StringRef instead of const char*

2019-10-29 Thread Vlad Tsyrklevich via Phabricator via cfe-commits
vlad.tsyrklevich added a comment.

Fix LGTM.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D69569/new/

https://reviews.llvm.org/D69569



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D41569: [Concepts] Constraint enforcement and diagnostics

2019-10-28 Thread Vlad Tsyrklevich via Phabricator via cfe-commits
vlad.tsyrklevich added a comment.

I noticed in Decl.cpp your change deleted some whitespace that belonged there. 
Not a big deal, just try to remember to run clang-format-diff when you're 
submitting for review. Thanks!


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D41569/new/

https://reviews.llvm.org/D41569



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D59254: [RFC] Implementation of Clang randstruct

2019-03-13 Thread Vlad Tsyrklevich via Phabricator via cfe-commits
vlad.tsyrklevich added inline comments.



Comment at: clang/include/clang/AST/RecordFieldReorganizer.h:54
+  std::seed_seq Seq;
+  std::default_random_engine rng;
+};

timpugh wrote:
> connorkuehl wrote:
> > pcc wrote:
> > > I don't think we can use `default_random_engine` for this because the 
> > > behaviour would need to be consistent between C++ standard library 
> > > implementations, and the behaviour of `default_random_engine` is 
> > > implementation defined. Similarly, I don't think that we can use 
> > > `std::shuffle` (see note in 
> > > https://en.cppreference.com/w/cpp/algorithm/random_shuffle ).
> > Sure thing, we'll begin investigating alternatives.
> @pcc  if we were to swap `default_random_engine` for a pre-defined random 
> generator such as `mt19937_64` would this suffice? It is included in the 
> random number library.
> 
> https://en.cppreference.com/w/cpp/numeric/random
In that case the random numbers would be deterministic; however, std::shuffle 
would still vary by implementation (as mentioned in the note Peter linked to.) 
A quick search didn't reveal a deterministic shuffle in the LLVM code so you 
may have to implement one.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D59254/new/

https://reviews.llvm.org/D59254



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D59034: Delete x86_64 ShadowCallStack support

2019-03-07 Thread Vlad Tsyrklevich via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rCRT355624: Delete x86_64 ShadowCallStack support (authored by 
vlad.tsyrklevich, committed by ).

Changed prior to commit:
  https://reviews.llvm.org/D59034?vs=189750=189756#toc

Repository:
  rCRT Compiler Runtime

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D59034/new/

https://reviews.llvm.org/D59034

Files:
  cmake/config-ix.cmake
  test/shadowcallstack/libc_support.h
  test/shadowcallstack/lit.cfg
  test/shadowcallstack/minimal_runtime.h
  test/shadowcallstack/overflow-aarch64.c
  test/shadowcallstack/overflow-x86_64.c
  test/shadowcallstack/overflow.c

Index: cmake/config-ix.cmake
===
--- cmake/config-ix.cmake
+++ cmake/config-ix.cmake
@@ -254,7 +254,7 @@
 else()
 set(ALL_XRAY_SUPPORTED_ARCH ${X86_64} ${ARM32} ${ARM64} ${MIPS32} ${MIPS64} powerpc64le)
 endif()
-set(ALL_SHADOWCALLSTACK_SUPPORTED_ARCH ${X86_64} ${ARM64})
+set(ALL_SHADOWCALLSTACK_SUPPORTED_ARCH ${ARM64})
 
 if(APPLE)
   include(CompilerRTDarwinUtils)
Index: test/shadowcallstack/minimal_runtime.h
===
--- test/shadowcallstack/minimal_runtime.h
+++ test/shadowcallstack/minimal_runtime.h
@@ -4,10 +4,6 @@
 
 #pragma once
 
-#ifdef __x86_64__
-#include 
-int arch_prctl(int code, void *addr);
-#endif
 #include 
 #include 
 #include 
@@ -21,10 +17,7 @@
   if (stack == MAP_FAILED)
 abort();
 
-#if defined(__x86_64__)
-  if (arch_prctl(ARCH_SET_GS, stack))
-abort();
-#elif defined(__aarch64__)
+#if defined(__aarch64__)
   __asm__ __volatile__("mov x18, %0" ::"r"(stack));
 #else
 #error Unsupported platform
Index: test/shadowcallstack/libc_support.h
===
--- test/shadowcallstack/libc_support.h
+++ test/shadowcallstack/libc_support.h
@@ -33,9 +33,5 @@
 }
 
 #else
-
-__attribute__((noinline)) void scs_fputs_stdout(const char *p) {
-  fputs(p, stdout);
-}
-
+#error Unsupported platform
 #endif
Index: test/shadowcallstack/lit.cfg
===
--- test/shadowcallstack/lit.cfg
+++ test/shadowcallstack/lit.cfg
@@ -19,5 +19,5 @@
   scs_arch_cflags += ' -ffixed-x18 '
 config.substitutions.append( ("%clang_scs ", config.clang + ' -O0 -fsanitize=shadow-call-stack ' + scs_arch_cflags + ' ') )
 
-if config.host_os not in ['Linux'] or config.target_arch not in ['x86_64', 'aarch64']:
+if config.host_os not in ['Linux'] or config.target_arch not in ['aarch64']:
config.unsupported = True
Index: test/shadowcallstack/overflow.c
===
--- test/shadowcallstack/overflow.c
+++ test/shadowcallstack/overflow.c
@@ -8,12 +8,10 @@
 // RUN: %clang_scs %s -o %t -DITERATIONS=3
 // RUN: %run %t | FileCheck %s
 
-// The behavioral check for SCS + overflow lives in the tests overflow-x86_64.c
-// and overflow-aarch64.c. This is because the expected behavior is different
-// between the two platforms. On x86_64 we crash because the comparison between
-// the shadow call stack and the regular stack fails. On aarch64 there is no
-// comparison, we just load the return address from the shadow call stack. So we
-// just expect not to see the output from print_and_exit.
+// On aarch64 we just load the return address from the shadow call stack so we
+// do not expect to see the output from print_and_exit.
+// RUN: %clang_scs %s -o %t -DITERATIONS=12
+// RUN: %run %t | FileCheck %S/overflow.c
 
 #include 
 #include 
Index: test/shadowcallstack/overflow-aarch64.c
===
--- test/shadowcallstack/overflow-aarch64.c
+++ test/shadowcallstack/overflow-aarch64.c
@@ -1,5 +0,0 @@
-// See overflow.c for a description.
-
-// REQUIRES: aarch64-target-arch
-// RUN: %clang_scs %S/overflow.c -o %t -DITERATIONS=12
-// RUN: %run %t | FileCheck %S/overflow.c
Index: test/shadowcallstack/overflow-x86_64.c
===
--- test/shadowcallstack/overflow-x86_64.c
+++ test/shadowcallstack/overflow-x86_64.c
@@ -1,5 +0,0 @@
-// See overflow.c for a description.
-
-// REQUIRES: x86_64-target-arch
-// RUN: %clang_scs %S/overflow.c -o %t -DITERATIONS=12
-// RUN: not --crash %run %t
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D59034: Delete x86_64 ShadowCallStack support

2019-03-07 Thread Vlad Tsyrklevich via Phabricator via cfe-commits
vlad.tsyrklevich updated this revision to Diff 189750.
vlad.tsyrklevich added a comment.

- Keep x86_64 doc link


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D59034/new/

https://reviews.llvm.org/D59034

Files:
  clang/docs/ShadowCallStack.rst
  compiler-rt/cmake/config-ix.cmake
  compiler-rt/test/shadowcallstack/libc_support.h
  compiler-rt/test/shadowcallstack/lit.cfg
  compiler-rt/test/shadowcallstack/minimal_runtime.h
  compiler-rt/test/shadowcallstack/overflow-aarch64.c
  compiler-rt/test/shadowcallstack/overflow-x86_64.c
  compiler-rt/test/shadowcallstack/overflow.c
  llvm/lib/Target/X86/CMakeLists.txt
  llvm/lib/Target/X86/ShadowCallStack.cpp
  llvm/lib/Target/X86/X86.h
  llvm/lib/Target/X86/X86TargetMachine.cpp
  llvm/test/CodeGen/X86/O0-pipeline.ll
  llvm/test/CodeGen/X86/O3-pipeline.ll
  llvm/test/CodeGen/X86/shadow-call-stack.mir
  llvm/utils/gn/secondary/llvm/lib/Target/X86/BUILD.gn

Index: llvm/utils/gn/secondary/llvm/lib/Target/X86/BUILD.gn
===
--- llvm/utils/gn/secondary/llvm/lib/Target/X86/BUILD.gn
+++ llvm/utils/gn/secondary/llvm/lib/Target/X86/BUILD.gn
@@ -76,7 +76,6 @@
 deps += [ ":X86GenFoldTables" ]
   }
   sources = [
-"ShadowCallStack.cpp",
 "X86AsmPrinter.cpp",
 "X86AvoidStoreForwardingBlocks.cpp",
 "X86CallFrameOptimization.cpp",
Index: llvm/test/CodeGen/X86/shadow-call-stack.mir
===
--- llvm/test/CodeGen/X86/shadow-call-stack.mir
+++ /dev/null
@@ -1,212 +0,0 @@
-# RUN: llc -mtriple=x86_64-unknown-linux-gnu -run-pass shadow-call-stack -verify-machineinstrs -o - %s | FileCheck %s
 |
-
-  define void @no_return() #0 { ret void }
-  define void @normal_return() #0 { ret void }
-  define void @normal_return_leaf_func() #0 { ret void }
-  define void @short_leaf_func() #0 { ret void }
-  define void @normal_tail_call() #0 { ret void }
-  define void @r11_tail_call() #0 { ret void }
-  define void @conditional_tail_call() #0 { ret void }
-  define void @r10_live_in() #0 { ret void }
-
-  attributes #0 = { shadowcallstack }
-
-...

-# CHECK-LABEL: name: no_return
-name: no_return
-tracksRegLiveness: true
-frameInfo:
-  adjustsStack: true # not a leaf function
-body: |
-  ; CHECK: bb.0:
-  bb.0:
-; CHECK-NEXT: $eax = MOV32ri 13
-$eax = MOV32ri 13
-...

-# CHECK-LABEL: name: normal_return
-name: normal_return
-tracksRegLiveness: true
-frameInfo:
-  adjustsStack: true # not a leaf function
-body: |
-  ; CHECK: bb.0:
-  bb.0:
-; CHECK: $r10 = MOV64rm $rsp, 1, $noreg, 0, $noreg
-; CHECK-NEXT: $r11 = XOR64rr undef $r11, undef $r11, implicit-def $eflags
-; CHECK-NEXT: ADD64mi8 $r11, 1, $noreg, 0, $gs, 8, implicit-def $eflags
-; CHECK-NEXT: $r11 = MOV64rm $r11, 1, $noreg, 0, $gs
-; CHECK-NEXT: MOV64mr $r11, 1, $noreg, 0, $gs, $r10
-; CHECK-NEXT: $eax = MOV32ri 13
-$eax = MOV32ri 13
-
-; CHECK-NEXT: $r11 = XOR64rr undef $r11, undef $r11, implicit-def $eflags
-; CHECK-NEXT: $r10 = MOV64rm $r11, 1, $noreg, 0, $gs
-; CHECK-NEXT: $r10 = MOV64rm $r10, 1, $noreg, 0, $gs
-; CHECK-NEXT: SUB64mi8 $r11, 1, $noreg, 0, $gs, 8, implicit-def $eflags
-; CHECK-NEXT: CMP64mr $rsp, 1, $noreg, 0, $noreg, $r10, implicit-def $eflags
-; CHECK-NEXT: JNE_1 %bb.1, implicit $eflags
-; CHECK-NEXT: RETQ $eax
-RETQ $eax
-
-; CHECK: bb.1:
-; CHECK-NEXT; TRAP
-...

-# CHECK-LABEL: name: normal_return_leaf_func
-name: normal_return_leaf_func
-tracksRegLiveness: true
-frameInfo:
-  adjustsStack: false # leaf function
-body: |
-  ; CHECK: bb.0:
-  ; CHECK: liveins: $rcx
-  bb.0:
-liveins: $rcx
-
-; CHECK: $rdx = MOV64rm $rsp, 1, $noreg, 0, $noreg
-; CHECK-NEXT: $eax = MOV32ri 0
-$eax = MOV32ri 0
-; CHECK-NEXT: CMP64ri8 $rcx, 5, implicit-def $eflags
-CMP64ri8 $rcx, 5, implicit-def $eflags
-; CHECK-NEXT: JA_1 %bb.1, implicit $eflags
-JA_1 %bb.1, implicit $eflags
-; CHECK-NEXT: JMP_1 %bb.2
-JMP_1 %bb.2
-
-  ; CHECK: bb.1
-  ; CHECK: liveins: $eax, $rdx
-  bb.1:
-liveins: $eax
-
-; CHECKT: $eax = MOV32ri 1
-$eax = MOV32ri 1
-
-  ; CHECK: bb.2
-  ; CHECK: liveins: $eax, $rdx
-  bb.2:
-liveins: $eax
-
-; CHECK: CMP64mr $rsp, 1, $noreg, 0, $noreg, $rdx, implicit-def $eflags
-; CHECK-NEXT: JNE_1 %bb.3, implicit $eflags
-; CHECK-NEXT: RETQ $eax
-RETQ $eax
-
-; CHECK: bb.3:
-; CHECK-NEXT; TRAP
-...

-# CHECK-LABEL: name: short_leaf_func
-name: short_leaf_func
-tracksRegLiveness: true
-frameInfo:
-  adjustsStack: false # leaf function
-body: |
-  ; CHECK: bb.0:
-  bb.0:
-; Ensure these are not counted as machine instructions
-CFI_INSTRUCTION 0
-CFI_INSTRUCTION 0
-CFI_INSTRUCTION 0
-DBG_VALUE 0
-DBG_VALUE 0
-DBG_VALUE 0
-
-; CHECK: $eax = MOV32ri 13
-$eax = MOV32ri 13
-
-; CHECK-NEXT: RETQ $eax
-RETQ $eax
-...

-# CHECK-LABEL: 

[PATCH] D59034: Delete x86_64 ShadowCallStack support

2019-03-06 Thread Vlad Tsyrklevich via Phabricator via cfe-commits
vlad.tsyrklevich created this revision.
vlad.tsyrklevich added a reviewer: pcc.
Herald added subscribers: llvm-commits, Sanitizers, cfe-commits, jdoerfert, 
hiraditya, javed.absar, mgorny.
Herald added projects: clang, Sanitizers, LLVM.

ShadowCallStack on x86_64 suffered from the same racy security issues as
Return Flow Guard and had performance overhead as high as 13% depending
on the benchmark. x86_64 ShadowCallStack was always an experimental
feature and never shipped a runtime required to support it, as such
there are no expected downstream users.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D59034

Files:
  clang/docs/ShadowCallStack.rst
  compiler-rt/cmake/config-ix.cmake
  compiler-rt/test/shadowcallstack/libc_support.h
  compiler-rt/test/shadowcallstack/lit.cfg
  compiler-rt/test/shadowcallstack/minimal_runtime.h
  compiler-rt/test/shadowcallstack/overflow-aarch64.c
  compiler-rt/test/shadowcallstack/overflow-x86_64.c
  compiler-rt/test/shadowcallstack/overflow.c
  llvm/lib/Target/X86/CMakeLists.txt
  llvm/lib/Target/X86/ShadowCallStack.cpp
  llvm/lib/Target/X86/X86.h
  llvm/lib/Target/X86/X86TargetMachine.cpp
  llvm/test/CodeGen/X86/O0-pipeline.ll
  llvm/test/CodeGen/X86/O3-pipeline.ll
  llvm/test/CodeGen/X86/shadow-call-stack.mir
  llvm/utils/gn/secondary/llvm/lib/Target/X86/BUILD.gn

Index: llvm/utils/gn/secondary/llvm/lib/Target/X86/BUILD.gn
===
--- llvm/utils/gn/secondary/llvm/lib/Target/X86/BUILD.gn
+++ llvm/utils/gn/secondary/llvm/lib/Target/X86/BUILD.gn
@@ -76,7 +76,6 @@
 deps += [ ":X86GenFoldTables" ]
   }
   sources = [
-"ShadowCallStack.cpp",
 "X86AsmPrinter.cpp",
 "X86AvoidStoreForwardingBlocks.cpp",
 "X86CallFrameOptimization.cpp",
Index: llvm/test/CodeGen/X86/shadow-call-stack.mir
===
--- llvm/test/CodeGen/X86/shadow-call-stack.mir
+++ /dev/null
@@ -1,212 +0,0 @@
-# RUN: llc -mtriple=x86_64-unknown-linux-gnu -run-pass shadow-call-stack -verify-machineinstrs -o - %s | FileCheck %s
 |
-
-  define void @no_return() #0 { ret void }
-  define void @normal_return() #0 { ret void }
-  define void @normal_return_leaf_func() #0 { ret void }
-  define void @short_leaf_func() #0 { ret void }
-  define void @normal_tail_call() #0 { ret void }
-  define void @r11_tail_call() #0 { ret void }
-  define void @conditional_tail_call() #0 { ret void }
-  define void @r10_live_in() #0 { ret void }
-
-  attributes #0 = { shadowcallstack }
-
-...

-# CHECK-LABEL: name: no_return
-name: no_return
-tracksRegLiveness: true
-frameInfo:
-  adjustsStack: true # not a leaf function
-body: |
-  ; CHECK: bb.0:
-  bb.0:
-; CHECK-NEXT: $eax = MOV32ri 13
-$eax = MOV32ri 13
-...

-# CHECK-LABEL: name: normal_return
-name: normal_return
-tracksRegLiveness: true
-frameInfo:
-  adjustsStack: true # not a leaf function
-body: |
-  ; CHECK: bb.0:
-  bb.0:
-; CHECK: $r10 = MOV64rm $rsp, 1, $noreg, 0, $noreg
-; CHECK-NEXT: $r11 = XOR64rr undef $r11, undef $r11, implicit-def $eflags
-; CHECK-NEXT: ADD64mi8 $r11, 1, $noreg, 0, $gs, 8, implicit-def $eflags
-; CHECK-NEXT: $r11 = MOV64rm $r11, 1, $noreg, 0, $gs
-; CHECK-NEXT: MOV64mr $r11, 1, $noreg, 0, $gs, $r10
-; CHECK-NEXT: $eax = MOV32ri 13
-$eax = MOV32ri 13
-
-; CHECK-NEXT: $r11 = XOR64rr undef $r11, undef $r11, implicit-def $eflags
-; CHECK-NEXT: $r10 = MOV64rm $r11, 1, $noreg, 0, $gs
-; CHECK-NEXT: $r10 = MOV64rm $r10, 1, $noreg, 0, $gs
-; CHECK-NEXT: SUB64mi8 $r11, 1, $noreg, 0, $gs, 8, implicit-def $eflags
-; CHECK-NEXT: CMP64mr $rsp, 1, $noreg, 0, $noreg, $r10, implicit-def $eflags
-; CHECK-NEXT: JNE_1 %bb.1, implicit $eflags
-; CHECK-NEXT: RETQ $eax
-RETQ $eax
-
-; CHECK: bb.1:
-; CHECK-NEXT; TRAP
-...

-# CHECK-LABEL: name: normal_return_leaf_func
-name: normal_return_leaf_func
-tracksRegLiveness: true
-frameInfo:
-  adjustsStack: false # leaf function
-body: |
-  ; CHECK: bb.0:
-  ; CHECK: liveins: $rcx
-  bb.0:
-liveins: $rcx
-
-; CHECK: $rdx = MOV64rm $rsp, 1, $noreg, 0, $noreg
-; CHECK-NEXT: $eax = MOV32ri 0
-$eax = MOV32ri 0
-; CHECK-NEXT: CMP64ri8 $rcx, 5, implicit-def $eflags
-CMP64ri8 $rcx, 5, implicit-def $eflags
-; CHECK-NEXT: JA_1 %bb.1, implicit $eflags
-JA_1 %bb.1, implicit $eflags
-; CHECK-NEXT: JMP_1 %bb.2
-JMP_1 %bb.2
-
-  ; CHECK: bb.1
-  ; CHECK: liveins: $eax, $rdx
-  bb.1:
-liveins: $eax
-
-; CHECKT: $eax = MOV32ri 1
-$eax = MOV32ri 1
-
-  ; CHECK: bb.2
-  ; CHECK: liveins: $eax, $rdx
-  bb.2:
-liveins: $eax
-
-; CHECK: CMP64mr $rsp, 1, $noreg, 0, $noreg, $rdx, implicit-def $eflags
-; CHECK-NEXT: JNE_1 %bb.3, implicit $eflags
-; CHECK-NEXT: RETQ $eax
-RETQ $eax
-
-; CHECK: bb.3:
-; CHECK-NEXT; TRAP
-...

-# CHECK-LABEL: name: short_leaf_func
-name: short_leaf_func
-tracksRegLiveness: true
-frameInfo:
-  

[PATCH] D56818: TLS: Respect visibility for thread_local variables on Darwin (PR40327)

2019-01-17 Thread Vlad Tsyrklevich via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rC351457: TLS: Respect visibility for thread_local variables 
on Darwin (PR40327) (authored by vlad.tsyrklevich, committed by ).
Herald added a subscriber: cfe-commits.

Changed prior to commit:
  https://reviews.llvm.org/D56818?vs=182171=182327#toc

Repository:
  rC Clang

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D56818/new/

https://reviews.llvm.org/D56818

Files:
  lib/CodeGen/ItaniumCXXABI.cpp
  test/CodeGenCXX/cxx11-thread-local-visibility.cpp
  test/CodeGenCXX/cxx11-thread-local.cpp


Index: lib/CodeGen/ItaniumCXXABI.cpp
===
--- lib/CodeGen/ItaniumCXXABI.cpp
+++ lib/CodeGen/ItaniumCXXABI.cpp
@@ -2463,10 +2463,12 @@
 CGM.SetLLVMFunctionAttributesForDefinition(nullptr, Wrapper);
 
   // Always resolve references to the wrapper at link time.
-  if (!Wrapper->hasLocalLinkage() && !(isThreadWrapperReplaceable(VD, CGM) &&
-  !llvm::GlobalVariable::isLinkOnceLinkage(Wrapper->getLinkage()) &&
-  !llvm::GlobalVariable::isWeakODRLinkage(Wrapper->getLinkage(
-Wrapper->setVisibility(llvm::GlobalValue::HiddenVisibility);
+  if (!Wrapper->hasLocalLinkage())
+if (!isThreadWrapperReplaceable(VD, CGM) ||
+llvm::GlobalVariable::isLinkOnceLinkage(Wrapper->getLinkage()) ||
+llvm::GlobalVariable::isWeakODRLinkage(Wrapper->getLinkage()) ||
+VD->getVisibility() == HiddenVisibility)
+  Wrapper->setVisibility(llvm::GlobalValue::HiddenVisibility);
 
   if (isThreadWrapperReplaceable(VD, CGM)) {
 Wrapper->setCallingConv(llvm::CallingConv::CXX_FAST_TLS);
Index: test/CodeGenCXX/cxx11-thread-local.cpp
===
--- test/CodeGenCXX/cxx11-thread-local.cpp
+++ test/CodeGenCXX/cxx11-thread-local.cpp
@@ -318,7 +318,7 @@
 // CHECK-NOT: call void @[[V_M_INIT]]()
 
 
-// LIUNX: define weak_odr hidden i32* @_ZTW1a() {
+// LINUX: define weak_odr hidden i32* @_ZTW1a()
 // DARWIN: define cxx_fast_tlscc i32* @_ZTW1a()
 // LINUX:   call void @_ZTH1a()
 // DARWIN: call cxx_fast_tlscc void @_ZTH1a()
Index: test/CodeGenCXX/cxx11-thread-local-visibility.cpp
===
--- test/CodeGenCXX/cxx11-thread-local-visibility.cpp
+++ test/CodeGenCXX/cxx11-thread-local-visibility.cpp
@@ -0,0 +1,17 @@
+// RUN: %clang_cc1 -std=c++11 -emit-llvm %s -o - -triple x86_64-linux-gnu | 
FileCheck --check-prefix=LINUX %s
+// RUN: %clang_cc1 -std=c++11 -emit-llvm %s -o - -triple x86_64-apple-darwin12 
| FileCheck --check-prefix=DARWIN %s
+
+// Regression test for PR40327
+
+// LINUX: @default_tls = thread_local global i32
+// LINUX: @hidden_tls = hidden thread_local global i32
+// LINUX: define weak_odr hidden i32* @_ZTW11default_tls()
+// LINUX: define weak_odr hidden i32* @_ZTW10hidden_tls()
+//
+// DARWIN: @default_tls = internal thread_local global i32
+// DARWIN: @hidden_tls = internal thread_local global i32
+// DARWIN: define cxx_fast_tlscc i32* @_ZTW11default_tls()
+// DARWIN: define hidden cxx_fast_tlscc i32* @_ZTW10hidden_tls()
+
+__attribute__((visibility("default"))) thread_local int default_tls;
+__attribute__((visibility("hidden"))) thread_local int hidden_tls;


Index: lib/CodeGen/ItaniumCXXABI.cpp
===
--- lib/CodeGen/ItaniumCXXABI.cpp
+++ lib/CodeGen/ItaniumCXXABI.cpp
@@ -2463,10 +2463,12 @@
 CGM.SetLLVMFunctionAttributesForDefinition(nullptr, Wrapper);
 
   // Always resolve references to the wrapper at link time.
-  if (!Wrapper->hasLocalLinkage() && !(isThreadWrapperReplaceable(VD, CGM) &&
-  !llvm::GlobalVariable::isLinkOnceLinkage(Wrapper->getLinkage()) &&
-  !llvm::GlobalVariable::isWeakODRLinkage(Wrapper->getLinkage(
-Wrapper->setVisibility(llvm::GlobalValue::HiddenVisibility);
+  if (!Wrapper->hasLocalLinkage())
+if (!isThreadWrapperReplaceable(VD, CGM) ||
+llvm::GlobalVariable::isLinkOnceLinkage(Wrapper->getLinkage()) ||
+llvm::GlobalVariable::isWeakODRLinkage(Wrapper->getLinkage()) ||
+VD->getVisibility() == HiddenVisibility)
+  Wrapper->setVisibility(llvm::GlobalValue::HiddenVisibility);
 
   if (isThreadWrapperReplaceable(VD, CGM)) {
 Wrapper->setCallingConv(llvm::CallingConv::CXX_FAST_TLS);
Index: test/CodeGenCXX/cxx11-thread-local.cpp
===
--- test/CodeGenCXX/cxx11-thread-local.cpp
+++ test/CodeGenCXX/cxx11-thread-local.cpp
@@ -318,7 +318,7 @@
 // CHECK-NOT: call void @[[V_M_INIT]]()
 
 
-// LIUNX: define weak_odr hidden i32* @_ZTW1a() {
+// LINUX: define weak_odr hidden i32* @_ZTW1a()
 // DARWIN: define cxx_fast_tlscc i32* @_ZTW1a()
 // LINUX:   call void @_ZTH1a()
 // DARWIN: call cxx_fast_tlscc void @_ZTH1a()
Index: test/CodeGenCXX/cxx11-thread-local-visibility.cpp

[PATCH] D51905: Front-end of the implementation of the interleaving algorithm

2018-09-14 Thread Vlad Tsyrklevich via Phabricator via cfe-commits
vlad.tsyrklevich added a comment.

In https://reviews.llvm.org/D51905#1234308, @zhaomo wrote:

> In https://reviews.llvm.org/D51905#1231383, @vlad.tsyrklevich wrote:
>
> > This change causes all compiler-rt cfi tests to be UNSUPPORTED for me 
> > locally, do you have any idea why that might be? The lit changes don't make 
> > it immediately clear.
>
>
> Not sure why that happened. How did you run the compiler-rt tests? Did you 
> use ninja check-cfi?


I ran them with llvm-lit against the tests under test/cfi. It looks like 
something caused the default test suite to change where all of the tests were 
marked unsupported (the test suite ran without lld and my default linker 
otherwise is bfd so LTO was unsupported.) Not a problem with the change.




Comment at: clang/lib/CodeGen/ItaniumCXXABI.cpp:939
 
+/// We should only interleave vtables when the module has the hidden
+/// LTO visibility, cfi-vcall is enabled and EnableVTableInterleaving

zhaomo wrote:
> vlad.tsyrklevich wrote:
> > doxygen comments normally go in the corresponding header file.
> I just followed the style of the rest of the file. All the comments above 
> functions use ///. Do I need to change them?
Disregard that, I hadn't realized that was the style elsewhere.


https://reviews.llvm.org/D51905



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D51905: Front-end of the implementation of the interleaving algorithm

2018-09-11 Thread Vlad Tsyrklevich via Phabricator via cfe-commits
vlad.tsyrklevich added a comment.

This change causes all compiler-rt cfi tests to be UNSUPPORTED for me locally, 
do you have any idea why that might be? The lit changes don't make it 
immediately clear.




Comment at: clang/lib/CodeGen/CGVTables.cpp:1055
+// When vtable interleaving is enabled, we don't emit type metadata for
+// function pointers.
+if (ABI->getEnableVTableInterleaving())

member function pointers*



Comment at: clang/lib/CodeGen/ItaniumCXXABI.cpp:939
 
+/// We should only interleave vtables when the module has the hidden
+/// LTO visibility, cfi-vcall is enabled and EnableVTableInterleaving

doxygen comments normally go in the corresponding header file.



Comment at: compiler-rt/test/cfi/CMakeLists.txt:62
+add_cfi_test_suites(True False False False)
+   add_cfi_test_suites(True True False False)
+   add_cfi_test_suites(True False False True)

nit: spacing



Comment at: compiler-rt/test/cfi/cross-dso-diagnostic.cpp:7
 
-// UNSUPPORTED: windows-msvc
+// UNSUPPORTED: windows-msvc, interleaving
 // REQUIRES: cxxabi

Why? This test has to do with error printing to do with vcalls across DSOs, not 
cross-DSO CFI, so I wouldn't expect that this should be affected by this change.



Comment at: compiler-rt/test/cfi/lit.cfg:33
   dso = '-fsanitize-cfi-cross-dso -fvisibility=default '
+  interleave = '-Xclang -enable-vtable-interleaving 
-Wl,-plugin-opt,-enable-vtable-interleaving -Wl,-plugin-opt=save-temps 
-fno-sanitize=cfi-mfcall '
   if config.android:

Can get rid of at least save-temps here, do we need to pass 
-enable-vtable-interleaving to the linker?


https://reviews.llvm.org/D51905



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D50724: SafeStack: Disable Darwin support

2018-08-14 Thread Vlad Tsyrklevich via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rL339720: SafeStack: Disable Darwin support (authored by 
vlad.tsyrklevich, committed by ).
Herald added a subscriber: llvm-commits.

Repository:
  rL LLVM

https://reviews.llvm.org/D50724

Files:
  cfe/trunk/lib/Driver/ToolChains/Darwin.cpp


Index: cfe/trunk/lib/Driver/ToolChains/Darwin.cpp
===
--- cfe/trunk/lib/Driver/ToolChains/Darwin.cpp
+++ cfe/trunk/lib/Driver/ToolChains/Darwin.cpp
@@ -509,15 +509,6 @@
   if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles))
 getMachOToolChain().addStartObjectFileArgs(Args, CmdArgs);
 
-  // SafeStack requires its own runtime libraries
-  // These libraries should be linked first, to make sure the
-  // __safestack_init constructor executes before everything else
-  if (getToolChain().getSanitizerArgs().needsSafeStackRt()) {
-getMachOToolChain().AddLinkRuntimeLib(Args, CmdArgs,
-  "libclang_rt.safestack_osx.a",
-  toolchains::Darwin::RLO_AlwaysLink);
-  }
-
   Args.AddAllArgs(CmdArgs, options::OPT_L);
 
   AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs, JA);
@@ -2297,7 +2288,6 @@
   if (isTargetMacOS()) {
 if (!isMacosxVersionLT(10, 9))
   Res |= SanitizerKind::Vptr;
-Res |= SanitizerKind::SafeStack;
 if (IsX86_64)
   Res |= SanitizerKind::Thread;
   } else if (isTargetIOSSimulator() || isTargetTvOSSimulator()) {


Index: cfe/trunk/lib/Driver/ToolChains/Darwin.cpp
===
--- cfe/trunk/lib/Driver/ToolChains/Darwin.cpp
+++ cfe/trunk/lib/Driver/ToolChains/Darwin.cpp
@@ -509,15 +509,6 @@
   if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles))
 getMachOToolChain().addStartObjectFileArgs(Args, CmdArgs);
 
-  // SafeStack requires its own runtime libraries
-  // These libraries should be linked first, to make sure the
-  // __safestack_init constructor executes before everything else
-  if (getToolChain().getSanitizerArgs().needsSafeStackRt()) {
-getMachOToolChain().AddLinkRuntimeLib(Args, CmdArgs,
-  "libclang_rt.safestack_osx.a",
-  toolchains::Darwin::RLO_AlwaysLink);
-  }
-
   Args.AddAllArgs(CmdArgs, options::OPT_L);
 
   AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs, JA);
@@ -2297,7 +2288,6 @@
   if (isTargetMacOS()) {
 if (!isMacosxVersionLT(10, 9))
   Res |= SanitizerKind::Vptr;
-Res |= SanitizerKind::SafeStack;
 if (IsX86_64)
   Res |= SanitizerKind::Thread;
   } else if (isTargetIOSSimulator() || isTargetTvOSSimulator()) {
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D50724: SafeStack: Disable Darwin support

2018-08-14 Thread Vlad Tsyrklevich via Phabricator via cfe-commits
vlad.tsyrklevich added a comment.

In https://reviews.llvm.org/D50724#1199345, @kubamracek wrote:

> Doesn't this need any tests to be updated? Otherwise, LGTM.


There were no Darwin-specific safestack driver tests. I ran check-clang just to 
make sure and it passes.


Repository:
  rC Clang

https://reviews.llvm.org/D50724



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D50724: SafeStack: Disable Darwin support

2018-08-14 Thread Vlad Tsyrklevich via Phabricator via cfe-commits
vlad.tsyrklevich created this revision.
vlad.tsyrklevich added reviewers: pcc, kubamracek.
Herald added a subscriber: cfe-commits.

Darwin support does not appear to be used as evidenced by the fact that
the runtime has never supported non-trivial programs.


Repository:
  rC Clang

https://reviews.llvm.org/D50724

Files:
  lib/Driver/ToolChains/Darwin.cpp


Index: lib/Driver/ToolChains/Darwin.cpp
===
--- lib/Driver/ToolChains/Darwin.cpp
+++ lib/Driver/ToolChains/Darwin.cpp
@@ -509,15 +509,6 @@
   if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles))
 getMachOToolChain().addStartObjectFileArgs(Args, CmdArgs);
 
-  // SafeStack requires its own runtime libraries
-  // These libraries should be linked first, to make sure the
-  // __safestack_init constructor executes before everything else
-  if (getToolChain().getSanitizerArgs().needsSafeStackRt()) {
-getMachOToolChain().AddLinkRuntimeLib(Args, CmdArgs,
-  "libclang_rt.safestack_osx.a",
-  toolchains::Darwin::RLO_AlwaysLink);
-  }
-
   Args.AddAllArgs(CmdArgs, options::OPT_L);
 
   AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs, JA);
@@ -2297,7 +2288,6 @@
   if (isTargetMacOS()) {
 if (!isMacosxVersionLT(10, 9))
   Res |= SanitizerKind::Vptr;
-Res |= SanitizerKind::SafeStack;
 if (IsX86_64)
   Res |= SanitizerKind::Thread;
   } else if (isTargetIOSSimulator() || isTargetTvOSSimulator()) {


Index: lib/Driver/ToolChains/Darwin.cpp
===
--- lib/Driver/ToolChains/Darwin.cpp
+++ lib/Driver/ToolChains/Darwin.cpp
@@ -509,15 +509,6 @@
   if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles))
 getMachOToolChain().addStartObjectFileArgs(Args, CmdArgs);
 
-  // SafeStack requires its own runtime libraries
-  // These libraries should be linked first, to make sure the
-  // __safestack_init constructor executes before everything else
-  if (getToolChain().getSanitizerArgs().needsSafeStackRt()) {
-getMachOToolChain().AddLinkRuntimeLib(Args, CmdArgs,
-  "libclang_rt.safestack_osx.a",
-  toolchains::Darwin::RLO_AlwaysLink);
-  }
-
   Args.AddAllArgs(CmdArgs, options::OPT_L);
 
   AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs, JA);
@@ -2297,7 +2288,6 @@
   if (isTargetMacOS()) {
 if (!isMacosxVersionLT(10, 9))
   Res |= SanitizerKind::Vptr;
-Res |= SanitizerKind::SafeStack;
 if (IsX86_64)
   Res |= SanitizerKind::Thread;
   } else if (isTargetIOSSimulator() || isTargetTvOSSimulator()) {
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D50372: Introduce the VTable interleaving scheme to the CFI design documentation

2018-08-07 Thread Vlad Tsyrklevich via Phabricator via cfe-commits
vlad.tsyrklevich added inline comments.



Comment at: clang/docs/ControlFlowIntegrityDesign.rst:283
+At the same time, it is also more efficient in terms of performance because in 
the interleaved virtual 
+table address points are consecutive, thus the validity check of a virtual 
vtable pointer is simplified 
+to a range check. 

simplified to a range check -> always a range check


Repository:
  rC Clang

https://reviews.llvm.org/D50372



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D50163: [AST] Remove the static_assert check in ObjCMethodDecl::ObjCMethodDecl

2018-08-01 Thread Vlad Tsyrklevich via Phabricator via cfe-commits
This revision was not accepted when it landed; it landed in state "Needs 
Review".
This revision was automatically updated to reflect the committed changes.
Closed by commit rC338648: [AST] Remove the static_assert check in 
ObjCMethodDecl::ObjCMethodDecl (authored by vlad.tsyrklevich, committed by ).

Repository:
  rC Clang

https://reviews.llvm.org/D50163

Files:
  lib/AST/DeclObjC.cpp


Index: lib/AST/DeclObjC.cpp
===
--- lib/AST/DeclObjC.cpp
+++ lib/AST/DeclObjC.cpp
@@ -787,13 +787,6 @@
 : NamedDecl(ObjCMethod, contextDecl, beginLoc, SelInfo),
   DeclContext(ObjCMethod), MethodDeclType(T), ReturnTInfo(ReturnTInfo),
   DeclEndLoc(endLoc) {
-  // See the comment in ObjCMethodFamilyBitfields about
-  // ObjCMethodFamilyBitWidth for why we check this.
-  static_assert(
-  static_cast(ObjCMethodDeclBits.ObjCMethodFamilyBitWidth) ==
-  static_cast(ObjCMethodFamilyBitWidth),
-  "ObjCMethodDeclBitfields::ObjCMethodFamilyBitWidth and "
-  "ObjCMethodFamilyBitWidth do not match!");
 
   // Initialized the bits stored in DeclContext.
   ObjCMethodDeclBits.Family =


Index: lib/AST/DeclObjC.cpp
===
--- lib/AST/DeclObjC.cpp
+++ lib/AST/DeclObjC.cpp
@@ -787,13 +787,6 @@
 : NamedDecl(ObjCMethod, contextDecl, beginLoc, SelInfo),
   DeclContext(ObjCMethod), MethodDeclType(T), ReturnTInfo(ReturnTInfo),
   DeclEndLoc(endLoc) {
-  // See the comment in ObjCMethodFamilyBitfields about
-  // ObjCMethodFamilyBitWidth for why we check this.
-  static_assert(
-  static_cast(ObjCMethodDeclBits.ObjCMethodFamilyBitWidth) ==
-  static_cast(ObjCMethodFamilyBitWidth),
-  "ObjCMethodDeclBitfields::ObjCMethodFamilyBitWidth and "
-  "ObjCMethodFamilyBitWidth do not match!");
 
   // Initialized the bits stored in DeclContext.
   ObjCMethodDeclBits.Family =
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D47567: Implement CFI for indirect calls via a member function pointer.

2018-06-25 Thread Vlad Tsyrklevich via Phabricator via cfe-commits
vlad.tsyrklevich accepted this revision.
vlad.tsyrklevich added a comment.
This revision is now accepted and ready to land.

I think it would be clearer to replace uses of 'member function pointer' with 
'pointer to member function'; however, a google search shows that the usage of 
both terms is basically the same so not this might be just be my own bias 
coming through.




Comment at: clang/lib/CodeGen/CodeGenModule.cpp:1413
+  FD->getType(), Context.getRecordType(Base).getTypePtr()));
+  F->addTypeMetadata(0, Id);
+}

It'd be nice to have a test that reaches this.



Comment at: clang/lib/CodeGen/CodeGenModule.h:1256
 
+  std::vector
+  getMostBaseClasses(const CXXRecordDecl *RD);

Could be helpful to have a comment here to ensure there is no confusion 
interpreting this as 'the most-base classes' and not 'most of the base classes'.



Comment at: clang/lib/Driver/SanitizerArgs.cpp:233
+ options::OPT_fno_sanitize_cfi_cross_dso, false);
+  if (CfiCrossDso)
+Supported &= ~CFIMFCall;

This will cause supplying both options to fail with `clang: error: unsupported 
option '-fsanitize=cfi-mfcall' for target ...`. Having it error out the same 
way as type generalization below where it states that cfi-cross-dso is 
unsupported with cfi-mfcall seems like a more helpful error.



Comment at: clang/test/CodeGenCXX/type-metadata.cpp:281
 // ITANIUM: [[FA_ID]] = distinct !{}
 
 // MS: [[A8]] = !{i64 8, !"?AUA@@"}

Any reason not to include AF64/CF64/FAF16 here?



Comment at: compiler-rt/lib/ubsan/ubsan_handlers.cc:645
+  const char *CheckKindStr = Data->CheckKind == CFITCK_NVMFCall
+ ? "non-virtual member function call"
+ : "indirect function call";

s/member/pointer to member/ ?



Comment at: compiler-rt/lib/ubsan/ubsan_handlers_cxx.cc:126
+  case CFITCK_VMFCall:
+CheckKindStr = "virtual member function call";
+break;

s/member/pointer to member/ ?


https://reviews.llvm.org/D47567



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D34156: [LTO] Enable module summary emission by default for regular LTO

2018-06-07 Thread Vlad Tsyrklevich via Phabricator via cfe-commits
vlad.tsyrklevich added a comment.
Herald added a subscriber: steven_wu.

Hi Tobias, I tracked down the failure self-hosting LLVM with LTO with this 
revision to https://bugs.llvm.org/show_bug.cgi?id=37684#c2 and have a fix under 
review in https://reviews.llvm.org/D47898. This revision needs to be updated to 
include the following trivial EmitSummaryIndex->PrepareForThinLTO renames to 
build:

  --- a/lib/CodeGen/BackendUtil.cpp
  +++ b/lib/CodeGen/BackendUtil.cpp
  @@ -944,7 +944,7 @@ void EmitAssemblyHelper::EmitAssemblyWithNewPassManager(
 ModulePassManager MPM(CodeGenOpts.DebugPassManager);
   
 if (!CodeGenOpts.DisableLLVMPasses) {
  -bool IsThinLTO = CodeGenOpts.EmitSummaryIndex;
  +bool IsThinLTO = CodeGenOpts.PrepareForThinLTO;
   bool IsLTO = CodeGenOpts.PrepareForLTO;
   
   if (CodeGenOpts.OptimizationLevel == 0) {
  diff --git a/lib/CodeGen/CGDebugInfo.cpp b/lib/CodeGen/CGDebugInfo.cpp
  index db6a82b415..91f80e5739 100644
  --- a/lib/CodeGen/CGDebugInfo.cpp
  +++ b/lib/CodeGen/CGDebugInfo.cpp
  @@ -578,7 +578,7 @@ void CGDebugInfo::CreateCompileUnit() {
 CSInfo,
 getSource(SM, SM.getMainFileID())),
 CGOpts.EmitVersionIdentMetadata ? Producer : "",
  -  LO.Optimize || CGOpts.PrepareForLTO || CGOpts.EmitSummaryIndex,
  +  LO.Optimize || CGOpts.PrepareForLTO || CGOpts.PrepareForThinLTO,
 CGOpts.DwarfDebugFlags, RuntimeVers,
 CGOpts.EnableSplitDwarf ? "" : CGOpts.SplitDwarfFile, EmissionKind,
 0 /* DWOid */, CGOpts.SplitDwarfInlining, CGOpts.DebugInfoForProfiling,

Are you still interested in landing this?


https://reviews.llvm.org/D34156



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D47726: [Analyzer][Z3] Test fixes for Z3 constraint manager

2018-06-06 Thread Vlad Tsyrklevich via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rC334067: [Analyzer][Z3] Test fixes for Z3 constraint manager 
(authored by vlad.tsyrklevich, committed by ).

Changed prior to commit:
  https://reviews.llvm.org/D47726?vs=149786=150076#toc

Repository:
  rC Clang

https://reviews.llvm.org/D47726

Files:
  test/Analysis/PR24184.cpp
  test/Analysis/constant-folding.c
  test/Analysis/loop-unrolling.cpp
  test/Analysis/z3/enabled.c


Index: test/Analysis/PR24184.cpp
===
--- test/Analysis/PR24184.cpp
+++ test/Analysis/PR24184.cpp
@@ -1,3 +1,4 @@
+// UNSUPPORTED: z3
 // RUN: %clang_analyze_cc1 -w -analyzer-eagerly-assume -fcxx-exceptions 
-analyzer-checker=core 
-analyzer-checker=alpha.core.PointerArithm,alpha.core.CastToStruct 
-analyzer-max-loop 64 -verify %s
 // RUN: %clang_analyze_cc1 -w -analyzer-checker=core 
-analyzer-checker=cplusplus -fcxx-exceptions -analyzer-checker 
alpha.core.PointerArithm,alpha.core.CastToStruct -analyzer-max-loop 63 -verify 
%s
 
Index: test/Analysis/z3/enabled.c
===
--- test/Analysis/z3/enabled.c
+++ test/Analysis/z3/enabled.c
@@ -0,0 +1,3 @@
+// REQUIRES: z3
+// RUN: echo %clang_analyze_cc1 | FileCheck %s
+// CHECK: -analyzer-constraints=z3
Index: test/Analysis/constant-folding.c
===
--- test/Analysis/constant-folding.c
+++ test/Analysis/constant-folding.c
@@ -108,7 +108,11 @@
   clang_analyzer_eval((b | -2) == 0); // expected-warning{{FALSE}}
   clang_analyzer_eval((b | 10) == 0); // expected-warning{{FALSE}}
   clang_analyzer_eval((b | 0) == 0); // expected-warning{{UNKNOWN}}
+#ifdef ANALYZER_CM_Z3
+  clang_analyzer_eval((b | -2) >= 0); // expected-warning{{FALSE}}
+#else
   clang_analyzer_eval((b | -2) >= 0); // expected-warning{{UNKNOWN}}
+#endif
 
   // Check that dynamically computed constants also work.
   int constant = 1 << 3;
Index: test/Analysis/loop-unrolling.cpp
===
--- test/Analysis/loop-unrolling.cpp
+++ test/Analysis/loop-unrolling.cpp
@@ -368,7 +368,11 @@
 int nested_inlined_no_unroll1() {
   int k;
   for (int i = 0; i < 9; i++) {
+#ifdef ANALYZER_CM_Z3
+clang_analyzer_numTimesReached(); // expected-warning {{13}}
+#else
 clang_analyzer_numTimesReached(); // expected-warning {{15}}
+#endif
 k = simple_unknown_bound_loop();  // reevaluation without inlining, splits 
the state as well
   }
   int a = 22 / k; // no-warning


Index: test/Analysis/PR24184.cpp
===
--- test/Analysis/PR24184.cpp
+++ test/Analysis/PR24184.cpp
@@ -1,3 +1,4 @@
+// UNSUPPORTED: z3
 // RUN: %clang_analyze_cc1 -w -analyzer-eagerly-assume -fcxx-exceptions -analyzer-checker=core -analyzer-checker=alpha.core.PointerArithm,alpha.core.CastToStruct -analyzer-max-loop 64 -verify %s
 // RUN: %clang_analyze_cc1 -w -analyzer-checker=core -analyzer-checker=cplusplus -fcxx-exceptions -analyzer-checker alpha.core.PointerArithm,alpha.core.CastToStruct -analyzer-max-loop 63 -verify %s
 
Index: test/Analysis/z3/enabled.c
===
--- test/Analysis/z3/enabled.c
+++ test/Analysis/z3/enabled.c
@@ -0,0 +1,3 @@
+// REQUIRES: z3
+// RUN: echo %clang_analyze_cc1 | FileCheck %s
+// CHECK: -analyzer-constraints=z3
Index: test/Analysis/constant-folding.c
===
--- test/Analysis/constant-folding.c
+++ test/Analysis/constant-folding.c
@@ -108,7 +108,11 @@
   clang_analyzer_eval((b | -2) == 0); // expected-warning{{FALSE}}
   clang_analyzer_eval((b | 10) == 0); // expected-warning{{FALSE}}
   clang_analyzer_eval((b | 0) == 0); // expected-warning{{UNKNOWN}}
+#ifdef ANALYZER_CM_Z3
+  clang_analyzer_eval((b | -2) >= 0); // expected-warning{{FALSE}}
+#else
   clang_analyzer_eval((b | -2) >= 0); // expected-warning{{UNKNOWN}}
+#endif
 
   // Check that dynamically computed constants also work.
   int constant = 1 << 3;
Index: test/Analysis/loop-unrolling.cpp
===
--- test/Analysis/loop-unrolling.cpp
+++ test/Analysis/loop-unrolling.cpp
@@ -368,7 +368,11 @@
 int nested_inlined_no_unroll1() {
   int k;
   for (int i = 0; i < 9; i++) {
+#ifdef ANALYZER_CM_Z3
+clang_analyzer_numTimesReached(); // expected-warning {{13}}
+#else
 clang_analyzer_numTimesReached(); // expected-warning {{15}}
+#endif
 k = simple_unknown_bound_loop();  // reevaluation without inlining, splits the state as well
   }
   int a = 22 / k; // no-warning
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D47726: [Analyzer][Z3] Test fixes for Z3 constraint manager

2018-06-06 Thread Vlad Tsyrklevich via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rL334067: [Analyzer][Z3] Test fixes for Z3 constraint manager 
(authored by vlad.tsyrklevich, committed by ).
Herald added a subscriber: llvm-commits.

Repository:
  rL LLVM

https://reviews.llvm.org/D47726

Files:
  cfe/trunk/test/Analysis/PR24184.cpp
  cfe/trunk/test/Analysis/constant-folding.c
  cfe/trunk/test/Analysis/loop-unrolling.cpp
  cfe/trunk/test/Analysis/z3/enabled.c


Index: cfe/trunk/test/Analysis/PR24184.cpp
===
--- cfe/trunk/test/Analysis/PR24184.cpp
+++ cfe/trunk/test/Analysis/PR24184.cpp
@@ -1,3 +1,4 @@
+// UNSUPPORTED: z3
 // RUN: %clang_analyze_cc1 -w -analyzer-eagerly-assume -fcxx-exceptions 
-analyzer-checker=core 
-analyzer-checker=alpha.core.PointerArithm,alpha.core.CastToStruct 
-analyzer-max-loop 64 -verify %s
 // RUN: %clang_analyze_cc1 -w -analyzer-checker=core 
-analyzer-checker=cplusplus -fcxx-exceptions -analyzer-checker 
alpha.core.PointerArithm,alpha.core.CastToStruct -analyzer-max-loop 63 -verify 
%s
 
Index: cfe/trunk/test/Analysis/z3/enabled.c
===
--- cfe/trunk/test/Analysis/z3/enabled.c
+++ cfe/trunk/test/Analysis/z3/enabled.c
@@ -0,0 +1,3 @@
+// REQUIRES: z3
+// RUN: echo %clang_analyze_cc1 | FileCheck %s
+// CHECK: -analyzer-constraints=z3
Index: cfe/trunk/test/Analysis/constant-folding.c
===
--- cfe/trunk/test/Analysis/constant-folding.c
+++ cfe/trunk/test/Analysis/constant-folding.c
@@ -108,7 +108,11 @@
   clang_analyzer_eval((b | -2) == 0); // expected-warning{{FALSE}}
   clang_analyzer_eval((b | 10) == 0); // expected-warning{{FALSE}}
   clang_analyzer_eval((b | 0) == 0); // expected-warning{{UNKNOWN}}
+#ifdef ANALYZER_CM_Z3
+  clang_analyzer_eval((b | -2) >= 0); // expected-warning{{FALSE}}
+#else
   clang_analyzer_eval((b | -2) >= 0); // expected-warning{{UNKNOWN}}
+#endif
 
   // Check that dynamically computed constants also work.
   int constant = 1 << 3;
Index: cfe/trunk/test/Analysis/loop-unrolling.cpp
===
--- cfe/trunk/test/Analysis/loop-unrolling.cpp
+++ cfe/trunk/test/Analysis/loop-unrolling.cpp
@@ -368,7 +368,11 @@
 int nested_inlined_no_unroll1() {
   int k;
   for (int i = 0; i < 9; i++) {
+#ifdef ANALYZER_CM_Z3
+clang_analyzer_numTimesReached(); // expected-warning {{13}}
+#else
 clang_analyzer_numTimesReached(); // expected-warning {{15}}
+#endif
 k = simple_unknown_bound_loop();  // reevaluation without inlining, splits 
the state as well
   }
   int a = 22 / k; // no-warning


Index: cfe/trunk/test/Analysis/PR24184.cpp
===
--- cfe/trunk/test/Analysis/PR24184.cpp
+++ cfe/trunk/test/Analysis/PR24184.cpp
@@ -1,3 +1,4 @@
+// UNSUPPORTED: z3
 // RUN: %clang_analyze_cc1 -w -analyzer-eagerly-assume -fcxx-exceptions -analyzer-checker=core -analyzer-checker=alpha.core.PointerArithm,alpha.core.CastToStruct -analyzer-max-loop 64 -verify %s
 // RUN: %clang_analyze_cc1 -w -analyzer-checker=core -analyzer-checker=cplusplus -fcxx-exceptions -analyzer-checker alpha.core.PointerArithm,alpha.core.CastToStruct -analyzer-max-loop 63 -verify %s
 
Index: cfe/trunk/test/Analysis/z3/enabled.c
===
--- cfe/trunk/test/Analysis/z3/enabled.c
+++ cfe/trunk/test/Analysis/z3/enabled.c
@@ -0,0 +1,3 @@
+// REQUIRES: z3
+// RUN: echo %clang_analyze_cc1 | FileCheck %s
+// CHECK: -analyzer-constraints=z3
Index: cfe/trunk/test/Analysis/constant-folding.c
===
--- cfe/trunk/test/Analysis/constant-folding.c
+++ cfe/trunk/test/Analysis/constant-folding.c
@@ -108,7 +108,11 @@
   clang_analyzer_eval((b | -2) == 0); // expected-warning{{FALSE}}
   clang_analyzer_eval((b | 10) == 0); // expected-warning{{FALSE}}
   clang_analyzer_eval((b | 0) == 0); // expected-warning{{UNKNOWN}}
+#ifdef ANALYZER_CM_Z3
+  clang_analyzer_eval((b | -2) >= 0); // expected-warning{{FALSE}}
+#else
   clang_analyzer_eval((b | -2) >= 0); // expected-warning{{UNKNOWN}}
+#endif
 
   // Check that dynamically computed constants also work.
   int constant = 1 << 3;
Index: cfe/trunk/test/Analysis/loop-unrolling.cpp
===
--- cfe/trunk/test/Analysis/loop-unrolling.cpp
+++ cfe/trunk/test/Analysis/loop-unrolling.cpp
@@ -368,7 +368,11 @@
 int nested_inlined_no_unroll1() {
   int k;
   for (int i = 0; i < 9; i++) {
+#ifdef ANALYZER_CM_Z3
+clang_analyzer_numTimesReached(); // expected-warning {{13}}
+#else
 clang_analyzer_numTimesReached(); // expected-warning {{15}}
+#endif
 k = simple_unknown_bound_loop();  // reevaluation without inlining, splits the state as well
   }
   int a = 22 / k; // no-warning

[PATCH] D47617: [Analyzer] Fix Z3ConstraintManager crash (PR37646)

2018-06-06 Thread Vlad Tsyrklevich via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rC334065: [Analyzer] Fix Z3ConstraintManager crash (PR37646) 
(authored by vlad.tsyrklevich, committed by ).

Changed prior to commit:
  https://reviews.llvm.org/D47617?vs=149796=150074#toc

Repository:
  rC Clang

https://reviews.llvm.org/D47617

Files:
  lib/StaticAnalyzer/Core/Z3ConstraintManager.cpp
  test/Analysis/apsint.c
  test/Analysis/z3/apsint.c


Index: lib/StaticAnalyzer/Core/Z3ConstraintManager.cpp
===
--- lib/StaticAnalyzer/Core/Z3ConstraintManager.cpp
+++ lib/StaticAnalyzer/Core/Z3ConstraintManager.cpp
@@ -1231,8 +1231,10 @@
 if (!LHS || !RHS)
   return nullptr;
 
-llvm::APSInt ConvertedLHS = *LHS, ConvertedRHS = *RHS;
-QualType LTy = getAPSIntType(*LHS), RTy = getAPSIntType(*RHS);
+llvm::APSInt ConvertedLHS, ConvertedRHS;
+QualType LTy, RTy;
+std::tie(ConvertedLHS, LTy) = fixAPSInt(*LHS);
+std::tie(ConvertedRHS, RTy) = fixAPSInt(*RHS);
 doIntTypeConversion(
 ConvertedLHS, LTy, ConvertedRHS, RTy);
 return BVF.evalAPSInt(BSE->getOpcode(), ConvertedLHS, ConvertedRHS);
Index: test/Analysis/z3/apsint.c
===
--- test/Analysis/z3/apsint.c
+++ test/Analysis/z3/apsint.c
@@ -0,0 +1,16 @@
+// RUN: %clang_analyze_cc1 -triple x86_64-unknown-linux-gnu 
-analyzer-checker=core -verify %s
+// expected-no-diagnostics
+
+// https://bugs.llvm.org/show_bug.cgi?id=37622
+_Bool a() {
+  return !({ a(); });
+}
+
+// https://bugs.llvm.org/show_bug.cgi?id=37646
+_Bool b;
+void c() {
+  _Bool a = b | 0;
+  for (;;)
+if (a)
+  ;
+}
Index: test/Analysis/apsint.c
===
--- test/Analysis/apsint.c
+++ test/Analysis/apsint.c
@@ -1,7 +0,0 @@
-// REQUIRES: z3
-// RUN: %clang_analyze_cc1 -triple x86_64-unknown-linux-gnu 
-analyzer-checker=core -verify %s
-// expected-no-diagnostics
-
-_Bool a() {
-  return !({ a(); });
-}


Index: lib/StaticAnalyzer/Core/Z3ConstraintManager.cpp
===
--- lib/StaticAnalyzer/Core/Z3ConstraintManager.cpp
+++ lib/StaticAnalyzer/Core/Z3ConstraintManager.cpp
@@ -1231,8 +1231,10 @@
 if (!LHS || !RHS)
   return nullptr;
 
-llvm::APSInt ConvertedLHS = *LHS, ConvertedRHS = *RHS;
-QualType LTy = getAPSIntType(*LHS), RTy = getAPSIntType(*RHS);
+llvm::APSInt ConvertedLHS, ConvertedRHS;
+QualType LTy, RTy;
+std::tie(ConvertedLHS, LTy) = fixAPSInt(*LHS);
+std::tie(ConvertedRHS, RTy) = fixAPSInt(*RHS);
 doIntTypeConversion(
 ConvertedLHS, LTy, ConvertedRHS, RTy);
 return BVF.evalAPSInt(BSE->getOpcode(), ConvertedLHS, ConvertedRHS);
Index: test/Analysis/z3/apsint.c
===
--- test/Analysis/z3/apsint.c
+++ test/Analysis/z3/apsint.c
@@ -0,0 +1,16 @@
+// RUN: %clang_analyze_cc1 -triple x86_64-unknown-linux-gnu -analyzer-checker=core -verify %s
+// expected-no-diagnostics
+
+// https://bugs.llvm.org/show_bug.cgi?id=37622
+_Bool a() {
+  return !({ a(); });
+}
+
+// https://bugs.llvm.org/show_bug.cgi?id=37646
+_Bool b;
+void c() {
+  _Bool a = b | 0;
+  for (;;)
+if (a)
+  ;
+}
Index: test/Analysis/apsint.c
===
--- test/Analysis/apsint.c
+++ test/Analysis/apsint.c
@@ -1,7 +0,0 @@
-// REQUIRES: z3
-// RUN: %clang_analyze_cc1 -triple x86_64-unknown-linux-gnu -analyzer-checker=core -verify %s
-// expected-no-diagnostics
-
-_Bool a() {
-  return !({ a(); });
-}
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D47617: [Analyzer] Fix Z3ConstraintManager crash (PR37646)

2018-06-04 Thread Vlad Tsyrklevich via Phabricator via cfe-commits
vlad.tsyrklevich updated this revision to Diff 149796.
vlad.tsyrklevich added a comment.

- Merge test with apsint.c and move to z3/apsint.c


Repository:
  rC Clang

https://reviews.llvm.org/D47617

Files:
  lib/StaticAnalyzer/Core/Z3ConstraintManager.cpp
  test/Analysis/apsint.c
  test/Analysis/z3/apsint.c


Index: test/Analysis/z3/apsint.c
===
--- /dev/null
+++ test/Analysis/z3/apsint.c
@@ -0,0 +1,16 @@
+// RUN: %clang_analyze_cc1 -triple x86_64-unknown-linux-gnu 
-analyzer-checker=core -verify %s
+// expected-no-diagnostics
+
+// https://bugs.llvm.org/show_bug.cgi?id=37622
+_Bool a() {
+  return !({ a(); });
+}
+
+// https://bugs.llvm.org/show_bug.cgi?id=37646
+_Bool b;
+void c() {
+  _Bool a = b | 0;
+  for (;;)
+if (a)
+  ;
+}
Index: test/Analysis/apsint.c
===
--- test/Analysis/apsint.c
+++ /dev/null
@@ -1,7 +0,0 @@
-// REQUIRES: z3
-// RUN: %clang_analyze_cc1 -triple x86_64-unknown-linux-gnu 
-analyzer-checker=core -verify %s
-// expected-no-diagnostics
-
-_Bool a() {
-  return !({ a(); });
-}
Index: lib/StaticAnalyzer/Core/Z3ConstraintManager.cpp
===
--- lib/StaticAnalyzer/Core/Z3ConstraintManager.cpp
+++ lib/StaticAnalyzer/Core/Z3ConstraintManager.cpp
@@ -1231,8 +1231,10 @@
 if (!LHS || !RHS)
   return nullptr;
 
-llvm::APSInt ConvertedLHS = *LHS, ConvertedRHS = *RHS;
-QualType LTy = getAPSIntType(*LHS), RTy = getAPSIntType(*RHS);
+llvm::APSInt ConvertedLHS, ConvertedRHS;
+QualType LTy, RTy;
+std::tie(ConvertedLHS, LTy) = fixAPSInt(*LHS);
+std::tie(ConvertedRHS, RTy) = fixAPSInt(*RHS);
 doIntTypeConversion(
 ConvertedLHS, LTy, ConvertedRHS, RTy);
 return BVF.evalAPSInt(BSE->getOpcode(), ConvertedLHS, ConvertedRHS);


Index: test/Analysis/z3/apsint.c
===
--- /dev/null
+++ test/Analysis/z3/apsint.c
@@ -0,0 +1,16 @@
+// RUN: %clang_analyze_cc1 -triple x86_64-unknown-linux-gnu -analyzer-checker=core -verify %s
+// expected-no-diagnostics
+
+// https://bugs.llvm.org/show_bug.cgi?id=37622
+_Bool a() {
+  return !({ a(); });
+}
+
+// https://bugs.llvm.org/show_bug.cgi?id=37646
+_Bool b;
+void c() {
+  _Bool a = b | 0;
+  for (;;)
+if (a)
+  ;
+}
Index: test/Analysis/apsint.c
===
--- test/Analysis/apsint.c
+++ /dev/null
@@ -1,7 +0,0 @@
-// REQUIRES: z3
-// RUN: %clang_analyze_cc1 -triple x86_64-unknown-linux-gnu -analyzer-checker=core -verify %s
-// expected-no-diagnostics
-
-_Bool a() {
-  return !({ a(); });
-}
Index: lib/StaticAnalyzer/Core/Z3ConstraintManager.cpp
===
--- lib/StaticAnalyzer/Core/Z3ConstraintManager.cpp
+++ lib/StaticAnalyzer/Core/Z3ConstraintManager.cpp
@@ -1231,8 +1231,10 @@
 if (!LHS || !RHS)
   return nullptr;
 
-llvm::APSInt ConvertedLHS = *LHS, ConvertedRHS = *RHS;
-QualType LTy = getAPSIntType(*LHS), RTy = getAPSIntType(*RHS);
+llvm::APSInt ConvertedLHS, ConvertedRHS;
+QualType LTy, RTy;
+std::tie(ConvertedLHS, LTy) = fixAPSInt(*LHS);
+std::tie(ConvertedRHS, RTy) = fixAPSInt(*RHS);
 doIntTypeConversion(
 ConvertedLHS, LTy, ConvertedRHS, RTy);
 return BVF.evalAPSInt(BSE->getOpcode(), ConvertedLHS, ConvertedRHS);
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D47726: [Analyzer][Z3] Test fixes for Z3 constraint manager

2018-06-04 Thread Vlad Tsyrklevich via Phabricator via cfe-commits
vlad.tsyrklevich created this revision.
vlad.tsyrklevich added reviewers: george.karpenkov, NoQ, ddcc.
Herald added subscribers: cfe-commits, a.sidorin, zzheng, szepet, xazax.hun.

Since Z3 tests have been not been running [1] some tests needed to be
updated. I also added a regression test for [1].

[1] https://reviews.llvm.org/D47722


Repository:
  rC Clang

https://reviews.llvm.org/D47726

Files:
  test/Analysis/PR24184.cpp
  test/Analysis/constant-folding.c
  test/Analysis/loop-unrolling.cpp
  test/Analysis/z3/enabled.c


Index: test/Analysis/z3/enabled.c
===
--- /dev/null
+++ test/Analysis/z3/enabled.c
@@ -0,0 +1,3 @@
+// REQUIRES: z3
+// RUN: echo %clang_analyze_cc1 | FileCheck %s
+// CHECK: -analyzer-constraints=z3
Index: test/Analysis/loop-unrolling.cpp
===
--- test/Analysis/loop-unrolling.cpp
+++ test/Analysis/loop-unrolling.cpp
@@ -368,7 +368,11 @@
 int nested_inlined_no_unroll1() {
   int k;
   for (int i = 0; i < 9; i++) {
+#ifdef ANALYZER_CM_Z3
+clang_analyzer_numTimesReached(); // expected-warning {{13}}
+#else
 clang_analyzer_numTimesReached(); // expected-warning {{15}}
+#endif
 k = simple_unknown_bound_loop();  // reevaluation without inlining, splits 
the state as well
   }
   int a = 22 / k; // no-warning
Index: test/Analysis/constant-folding.c
===
--- test/Analysis/constant-folding.c
+++ test/Analysis/constant-folding.c
@@ -108,7 +108,11 @@
   clang_analyzer_eval((b | -2) == 0); // expected-warning{{FALSE}}
   clang_analyzer_eval((b | 10) == 0); // expected-warning{{FALSE}}
   clang_analyzer_eval((b | 0) == 0); // expected-warning{{UNKNOWN}}
+#ifdef ANALYZER_CM_Z3
+  clang_analyzer_eval((b | -2) >= 0); // expected-warning{{FALSE}}
+#else
   clang_analyzer_eval((b | -2) >= 0); // expected-warning{{UNKNOWN}}
+#endif
 
   // Check that dynamically computed constants also work.
   int constant = 1 << 3;
Index: test/Analysis/PR24184.cpp
===
--- test/Analysis/PR24184.cpp
+++ test/Analysis/PR24184.cpp
@@ -1,3 +1,4 @@
+// UNSUPPORTED: z3
 // RUN: %clang_analyze_cc1 -w -analyzer-eagerly-assume -fcxx-exceptions 
-analyzer-checker=core 
-analyzer-checker=alpha.core.PointerArithm,alpha.core.CastToStruct 
-analyzer-max-loop 64 -verify %s
 // RUN: %clang_analyze_cc1 -w -analyzer-checker=core 
-analyzer-checker=cplusplus -fcxx-exceptions -analyzer-checker 
alpha.core.PointerArithm,alpha.core.CastToStruct -analyzer-max-loop 63 -verify 
%s
 


Index: test/Analysis/z3/enabled.c
===
--- /dev/null
+++ test/Analysis/z3/enabled.c
@@ -0,0 +1,3 @@
+// REQUIRES: z3
+// RUN: echo %clang_analyze_cc1 | FileCheck %s
+// CHECK: -analyzer-constraints=z3
Index: test/Analysis/loop-unrolling.cpp
===
--- test/Analysis/loop-unrolling.cpp
+++ test/Analysis/loop-unrolling.cpp
@@ -368,7 +368,11 @@
 int nested_inlined_no_unroll1() {
   int k;
   for (int i = 0; i < 9; i++) {
+#ifdef ANALYZER_CM_Z3
+clang_analyzer_numTimesReached(); // expected-warning {{13}}
+#else
 clang_analyzer_numTimesReached(); // expected-warning {{15}}
+#endif
 k = simple_unknown_bound_loop();  // reevaluation without inlining, splits the state as well
   }
   int a = 22 / k; // no-warning
Index: test/Analysis/constant-folding.c
===
--- test/Analysis/constant-folding.c
+++ test/Analysis/constant-folding.c
@@ -108,7 +108,11 @@
   clang_analyzer_eval((b | -2) == 0); // expected-warning{{FALSE}}
   clang_analyzer_eval((b | 10) == 0); // expected-warning{{FALSE}}
   clang_analyzer_eval((b | 0) == 0); // expected-warning{{UNKNOWN}}
+#ifdef ANALYZER_CM_Z3
+  clang_analyzer_eval((b | -2) >= 0); // expected-warning{{FALSE}}
+#else
   clang_analyzer_eval((b | -2) >= 0); // expected-warning{{UNKNOWN}}
+#endif
 
   // Check that dynamically computed constants also work.
   int constant = 1 << 3;
Index: test/Analysis/PR24184.cpp
===
--- test/Analysis/PR24184.cpp
+++ test/Analysis/PR24184.cpp
@@ -1,3 +1,4 @@
+// UNSUPPORTED: z3
 // RUN: %clang_analyze_cc1 -w -analyzer-eagerly-assume -fcxx-exceptions -analyzer-checker=core -analyzer-checker=alpha.core.PointerArithm,alpha.core.CastToStruct -analyzer-max-loop 64 -verify %s
 // RUN: %clang_analyze_cc1 -w -analyzer-checker=core -analyzer-checker=cplusplus -fcxx-exceptions -analyzer-checker alpha.core.PointerArithm,alpha.core.CastToStruct -analyzer-max-loop 63 -verify %s
 
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D47617: [Analyzer] Fix Z3ConstraintManager crash (PR37646)

2018-06-04 Thread Vlad Tsyrklevich via Phabricator via cfe-commits
vlad.tsyrklevich added a comment.

In https://reviews.llvm.org/D47617#1119268, @NoQ wrote:

> Also does this test need to be z3-specific? We would also not like to crash 
> here without z3.


I originally did that so I could specify enabling and testing the z3 backend; 
however, looking at the testing infra more I realize that z3 is supposed to be 
run on the analyzer tests but it seems like z3 tests have been broken since 
October when r315627 landed. I submitted a fix in 
https://reviews.llvm.org/D47722


Repository:
  rC Clang

https://reviews.llvm.org/D47617



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D47617: [Analyzer] Fix Z3 crash (PR37646)

2018-05-31 Thread Vlad Tsyrklevich via Phabricator via cfe-commits
vlad.tsyrklevich created this revision.
vlad.tsyrklevich added reviewers: george.karpenkov, NoQ, ddcc.
Herald added subscribers: cfe-commits, a.sidorin, szepet, xazax.hun.

Fix another Z3ConstraintManager crash, use fixAPSInt() to extend a
boolean APSInt.


Repository:
  rC Clang

https://reviews.llvm.org/D47617

Files:
  lib/StaticAnalyzer/Core/Z3ConstraintManager.cpp
  test/Analysis/pr37646.c


Index: test/Analysis/pr37646.c
===
--- /dev/null
+++ test/Analysis/pr37646.c
@@ -0,0 +1,11 @@
+// REQUIRES: z3
+// RUN: %clang_analyze_cc1 -triple x86_64-apple-darwin9 -analyzer-checker=core 
-analyzer-store=region -analyzer-constraints=z3 -verify %s
+// expected-no-diagnostics
+
+_Bool b;
+void c() {
+  _Bool a = b | 0;
+  for (;;)
+if (a)
+  ;
+}
Index: lib/StaticAnalyzer/Core/Z3ConstraintManager.cpp
===
--- lib/StaticAnalyzer/Core/Z3ConstraintManager.cpp
+++ lib/StaticAnalyzer/Core/Z3ConstraintManager.cpp
@@ -1211,8 +1211,10 @@
 if (!LHS || !RHS)
   return nullptr;
 
-llvm::APSInt ConvertedLHS = *LHS, ConvertedRHS = *RHS;
-QualType LTy = getAPSIntType(*LHS), RTy = getAPSIntType(*RHS);
+llvm::APSInt ConvertedLHS, ConvertedRHS;
+QualType LTy, RTy;
+std::tie(ConvertedLHS, LTy) = fixAPSInt(*LHS);
+std::tie(ConvertedRHS, RTy) = fixAPSInt(*RHS);
 doIntTypeConversion(
 ConvertedLHS, LTy, ConvertedRHS, RTy);
 return BV.evalAPSInt(BSE->getOpcode(), ConvertedLHS, ConvertedRHS);


Index: test/Analysis/pr37646.c
===
--- /dev/null
+++ test/Analysis/pr37646.c
@@ -0,0 +1,11 @@
+// REQUIRES: z3
+// RUN: %clang_analyze_cc1 -triple x86_64-apple-darwin9 -analyzer-checker=core -analyzer-store=region -analyzer-constraints=z3 -verify %s
+// expected-no-diagnostics
+
+_Bool b;
+void c() {
+  _Bool a = b | 0;
+  for (;;)
+if (a)
+  ;
+}
Index: lib/StaticAnalyzer/Core/Z3ConstraintManager.cpp
===
--- lib/StaticAnalyzer/Core/Z3ConstraintManager.cpp
+++ lib/StaticAnalyzer/Core/Z3ConstraintManager.cpp
@@ -1211,8 +1211,10 @@
 if (!LHS || !RHS)
   return nullptr;
 
-llvm::APSInt ConvertedLHS = *LHS, ConvertedRHS = *RHS;
-QualType LTy = getAPSIntType(*LHS), RTy = getAPSIntType(*RHS);
+llvm::APSInt ConvertedLHS, ConvertedRHS;
+QualType LTy, RTy;
+std::tie(ConvertedLHS, LTy) = fixAPSInt(*LHS);
+std::tie(ConvertedRHS, RTy) = fixAPSInt(*RHS);
 doIntTypeConversion(
 ConvertedLHS, LTy, ConvertedRHS, RTy);
 return BV.evalAPSInt(BSE->getOpcode(), ConvertedLHS, ConvertedRHS);
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D47603: [analyzer] fix bug with 1-bit APSInt types in Z3ConstraintManager

2018-05-31 Thread Vlad Tsyrklevich via Phabricator via cfe-commits
vlad.tsyrklevich added a comment.

In https://reviews.llvm.org/D47603#1118106, @george.karpenkov wrote:

> Would it be possible to add tests? I know we have very few unit tests, but I 
> assume you could actually use an integration test to exercise this path?


I tested this change and it fixes PR37622. There's a simple crash reproducer 
included there.


Repository:
  rC Clang

https://reviews.llvm.org/D47603



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D45611: [analyzer] Fix filename in cross-file HTML report

2018-04-18 Thread Vlad Tsyrklevich via Phabricator via cfe-commits
vlad.tsyrklevich accepted this revision.
vlad.tsyrklevich added a comment.
This revision is now accepted and ready to land.

This LGTM, but 1) you should add a test, probably just need to another CHECK to 
test/Coverage/html-multifile-diagnostics.c from 
https://reviews.llvm.org/D30406, and 2) someone from the analyzer team should 
sign off on it too.


Repository:
  rC Clang

https://reviews.llvm.org/D45611



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D45455: [CFI] Disable CFI checks for __cxa_decrement_exception_refcount

2018-04-09 Thread Vlad Tsyrklevich via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rL329629: [CFI] Disable CFI checks for 
__cxa_decrement_exception_refcount (authored by vlad.tsyrklevich, committed by 
).
Herald added a subscriber: llvm-commits.

Repository:
  rL LLVM

https://reviews.llvm.org/D45455

Files:
  libcxxabi/trunk/include/__cxxabi_config.h
  libcxxabi/trunk/src/cxa_exception.cpp


Index: libcxxabi/trunk/src/cxa_exception.cpp
===
--- libcxxabi/trunk/src/cxa_exception.cpp
+++ libcxxabi/trunk/src/cxa_exception.cpp
@@ -630,8 +630,8 @@
 
 Requires:  If thrown_object is not NULL, it is a native exception.
 */
-void
-__cxa_decrement_exception_refcount(void *thrown_object) throw() {
+_LIBCXXABI_NO_CFI
+void __cxa_decrement_exception_refcount(void *thrown_object) throw() {
 if (thrown_object != NULL )
 {
 __cxa_exception* exception_header = 
cxa_exception_from_thrown_object(thrown_object);
Index: libcxxabi/trunk/include/__cxxabi_config.h
===
--- libcxxabi/trunk/include/__cxxabi_config.h
+++ libcxxabi/trunk/include/__cxxabi_config.h
@@ -60,4 +60,14 @@
 #define _LIBCXXABI_WEAK __attribute__((__weak__))
 #endif
 
+#if defined(__clang__)
+#define _LIBCXXABI_COMPILER_CLANG
+#endif
+
+#if __has_attribute(__no_sanitize__) && defined(_LIBCXXABI_COMPILER_CLANG)
+#define _LIBCXXABI_NO_CFI __attribute__((__no_sanitize__("cfi")))
+#else
+#define _LIBCXXABI_NO_CFI
+#endif
+
 #endif // CXXABI_CONFIG_H


Index: libcxxabi/trunk/src/cxa_exception.cpp
===
--- libcxxabi/trunk/src/cxa_exception.cpp
+++ libcxxabi/trunk/src/cxa_exception.cpp
@@ -630,8 +630,8 @@
 
 Requires:  If thrown_object is not NULL, it is a native exception.
 */
-void
-__cxa_decrement_exception_refcount(void *thrown_object) throw() {
+_LIBCXXABI_NO_CFI
+void __cxa_decrement_exception_refcount(void *thrown_object) throw() {
 if (thrown_object != NULL )
 {
 __cxa_exception* exception_header = cxa_exception_from_thrown_object(thrown_object);
Index: libcxxabi/trunk/include/__cxxabi_config.h
===
--- libcxxabi/trunk/include/__cxxabi_config.h
+++ libcxxabi/trunk/include/__cxxabi_config.h
@@ -60,4 +60,14 @@
 #define _LIBCXXABI_WEAK __attribute__((__weak__))
 #endif
 
+#if defined(__clang__)
+#define _LIBCXXABI_COMPILER_CLANG
+#endif
+
+#if __has_attribute(__no_sanitize__) && defined(_LIBCXXABI_COMPILER_CLANG)
+#define _LIBCXXABI_NO_CFI __attribute__((__no_sanitize__("cfi")))
+#else
+#define _LIBCXXABI_NO_CFI
+#endif
+
 #endif // CXXABI_CONFIG_H
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D45455: [CFI] Disable CFI checks for __cxa_decrement_exception_refcount

2018-04-09 Thread Vlad Tsyrklevich via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rCXXA329629: [CFI] Disable CFI checks for 
__cxa_decrement_exception_refcount (authored by vlad.tsyrklevich, committed by 
).

Changed prior to commit:
  https://reviews.llvm.org/D45455?vs=141733=141752#toc

Repository:
  rL LLVM

https://reviews.llvm.org/D45455

Files:
  include/__cxxabi_config.h
  src/cxa_exception.cpp


Index: src/cxa_exception.cpp
===
--- src/cxa_exception.cpp
+++ src/cxa_exception.cpp
@@ -630,8 +630,8 @@
 
 Requires:  If thrown_object is not NULL, it is a native exception.
 */
-void
-__cxa_decrement_exception_refcount(void *thrown_object) throw() {
+_LIBCXXABI_NO_CFI
+void __cxa_decrement_exception_refcount(void *thrown_object) throw() {
 if (thrown_object != NULL )
 {
 __cxa_exception* exception_header = 
cxa_exception_from_thrown_object(thrown_object);
Index: include/__cxxabi_config.h
===
--- include/__cxxabi_config.h
+++ include/__cxxabi_config.h
@@ -60,4 +60,14 @@
 #define _LIBCXXABI_WEAK __attribute__((__weak__))
 #endif
 
+#if defined(__clang__)
+#define _LIBCXXABI_COMPILER_CLANG
+#endif
+
+#if __has_attribute(__no_sanitize__) && defined(_LIBCXXABI_COMPILER_CLANG)
+#define _LIBCXXABI_NO_CFI __attribute__((__no_sanitize__("cfi")))
+#else
+#define _LIBCXXABI_NO_CFI
+#endif
+
 #endif // CXXABI_CONFIG_H


Index: src/cxa_exception.cpp
===
--- src/cxa_exception.cpp
+++ src/cxa_exception.cpp
@@ -630,8 +630,8 @@
 
 Requires:  If thrown_object is not NULL, it is a native exception.
 */
-void
-__cxa_decrement_exception_refcount(void *thrown_object) throw() {
+_LIBCXXABI_NO_CFI
+void __cxa_decrement_exception_refcount(void *thrown_object) throw() {
 if (thrown_object != NULL )
 {
 __cxa_exception* exception_header = cxa_exception_from_thrown_object(thrown_object);
Index: include/__cxxabi_config.h
===
--- include/__cxxabi_config.h
+++ include/__cxxabi_config.h
@@ -60,4 +60,14 @@
 #define _LIBCXXABI_WEAK __attribute__((__weak__))
 #endif
 
+#if defined(__clang__)
+#define _LIBCXXABI_COMPILER_CLANG
+#endif
+
+#if __has_attribute(__no_sanitize__) && defined(_LIBCXXABI_COMPILER_CLANG)
+#define _LIBCXXABI_NO_CFI __attribute__((__no_sanitize__("cfi")))
+#else
+#define _LIBCXXABI_NO_CFI
+#endif
+
 #endif // CXXABI_CONFIG_H
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D45455: [CFI] Disable CFI checks for __cxa_decrement_exception_refcount

2018-04-09 Thread Vlad Tsyrklevich via Phabricator via cfe-commits
vlad.tsyrklevich created this revision.
Herald added subscribers: cfe-commits, christof.

exception_header->exceptionDestructor is a void(*)(void*) function
pointer; however, it can point to destructors like std::
exception::~exception that don't match that type signature.


Repository:
  rCXXA libc++abi

https://reviews.llvm.org/D45455

Files:
  include/__cxxabi_config.h
  src/cxa_exception.cpp


Index: src/cxa_exception.cpp
===
--- src/cxa_exception.cpp
+++ src/cxa_exception.cpp
@@ -630,8 +630,8 @@
 
 Requires:  If thrown_object is not NULL, it is a native exception.
 */
-void
-__cxa_decrement_exception_refcount(void *thrown_object) throw() {
+_LIBCXXABI_NO_CFI
+void __cxa_decrement_exception_refcount(void *thrown_object) throw() {
 if (thrown_object != NULL )
 {
 __cxa_exception* exception_header = 
cxa_exception_from_thrown_object(thrown_object);
Index: include/__cxxabi_config.h
===
--- include/__cxxabi_config.h
+++ include/__cxxabi_config.h
@@ -60,4 +60,14 @@
 #define _LIBCXXABI_WEAK __attribute__((__weak__))
 #endif
 
+#if defined(__clang__)
+#define _LIBCXXABI_COMPILER_CLANG
+#endif
+
+#if __has_attribute(__no_sanitize__) && defined(_LIBCXXABI_COMPILER_CLANG)
+#define _LIBCXXABI_NO_CFI __attribute__((__no_sanitize__("cfi")))
+#else
+#define _LIBCXXABI_NO_CFI
+#endif
+
 #endif // CXXABI_CONFIG_H


Index: src/cxa_exception.cpp
===
--- src/cxa_exception.cpp
+++ src/cxa_exception.cpp
@@ -630,8 +630,8 @@
 
 Requires:  If thrown_object is not NULL, it is a native exception.
 */
-void
-__cxa_decrement_exception_refcount(void *thrown_object) throw() {
+_LIBCXXABI_NO_CFI
+void __cxa_decrement_exception_refcount(void *thrown_object) throw() {
 if (thrown_object != NULL )
 {
 __cxa_exception* exception_header = cxa_exception_from_thrown_object(thrown_object);
Index: include/__cxxabi_config.h
===
--- include/__cxxabi_config.h
+++ include/__cxxabi_config.h
@@ -60,4 +60,14 @@
 #define _LIBCXXABI_WEAK __attribute__((__weak__))
 #endif
 
+#if defined(__clang__)
+#define _LIBCXXABI_COMPILER_CLANG
+#endif
+
+#if __has_attribute(__no_sanitize__) && defined(_LIBCXXABI_COMPILER_CLANG)
+#define _LIBCXXABI_NO_CFI __attribute__((__no_sanitize__("cfi")))
+#else
+#define _LIBCXXABI_NO_CFI
+#endif
+
 #endif // CXXABI_CONFIG_H
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D45357: [XRay][llvm+clang] Consolidate attribute list files

2018-04-06 Thread Vlad Tsyrklevich via Phabricator via cfe-commits
vlad.tsyrklevich accepted this revision.
vlad.tsyrklevich added inline comments.
This revision is now accepted and ready to land.



Comment at: llvm/docs/XRayExample.rst:196
+``-fxray-attr-list=`` flag to clang. You can have multiple files, each defining
+different sets of attribute sets, to be cobined into a single list by clang.
 

combined*


https://reviews.llvm.org/D45357



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D45239: AArch64: Implement support for the shadowcallstack attribute.

2018-04-04 Thread Vlad Tsyrklevich via Phabricator via cfe-commits
vlad.tsyrklevich accepted this revision.
vlad.tsyrklevich added inline comments.
This revision is now accepted and ready to land.



Comment at: clang/docs/ShadowCallStack.rst:12
 ShadowCallStack is an **experimental** instrumentation pass, currently only
 implemented for x86_64, that protects programs against return address
 overwrites (e.g. stack buffer overflows.) It works by saving a function's 
return

Should also mention aarch64 here.



Comment at: llvm/lib/Target/AArch64/AArch64RegisterInfo.cpp:78
   CallingConv::ID CC) const {
+  bool SCS = MF.getFunction().hasFnAttribute(Attribute::ShadowCallStack);
   if (CC == CallingConv::GHC)

It's sort of a stretch to construct a scenario where this is likely to happen, 
but is it possible that a runtime function marked with 
`__attribute__((no_sanitize("shadowcallstack")))` would spill x18 across a 
function call because of this mask if it's referenced before and after? If that 
was a concern, we could make this test `hasAttr(SCS) || hasFlag(fFixedx18)`


https://reviews.llvm.org/D45239



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D44801: Add the -fsanitize=shadow-call-stack flag

2018-04-03 Thread Vlad Tsyrklevich via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rL329122: Add the -fsanitize=shadow-call-stack flag (authored 
by vlad.tsyrklevich, committed by ).
Herald added a subscriber: llvm-commits.

Repository:
  rL LLVM

https://reviews.llvm.org/D44801

Files:
  cfe/trunk/docs/ShadowCallStack.rst
  cfe/trunk/docs/index.rst
  cfe/trunk/include/clang/Basic/Sanitizers.def
  cfe/trunk/lib/CodeGen/CGDeclCXX.cpp
  cfe/trunk/lib/CodeGen/CodeGenFunction.cpp
  cfe/trunk/lib/Driver/SanitizerArgs.cpp
  cfe/trunk/lib/Driver/ToolChain.cpp
  cfe/trunk/lib/Lex/PPMacroExpansion.cpp
  cfe/trunk/test/CodeGen/shadowcallstack-attr.c
  cfe/trunk/test/Driver/sanitizer-ld.c

Index: cfe/trunk/docs/ShadowCallStack.rst
===
--- cfe/trunk/docs/ShadowCallStack.rst
+++ cfe/trunk/docs/ShadowCallStack.rst
@@ -0,0 +1,150 @@
+===
+ShadowCallStack
+===
+
+.. contents::
+   :local:
+
+Introduction
+
+
+ShadowCallStack is an **experimental** instrumentation pass, currently only
+implemented for x86_64, that protects programs against return address
+overwrites (e.g. stack buffer overflows.) It works by saving a function's return
+address to a separately allocated 'shadow call stack' in the function prolog and
+checking the return address on the stack against the shadow call stack in the
+function epilog.
+
+Comparison
+--
+
+To optimize for memory consumption and cache locality, the shadow call stack
+stores an index followed by an array of return addresses. This is in contrast
+to other schemes, like :doc:`SafeStack`, that mirror the entire stack and
+trade-off consuming more memory for shorter function prologs and epilogs with
+fewer memory accesses. Similarly, `Return Flow Guard`_ consumes more memory with
+shorter function prologs and epilogs than ShadowCallStack but suffers from the
+same race conditions (see `Security`_). Intel `Control-flow Enforcement Technology`_
+(CET) is a proposed hardware extension that would add native support to
+use a shadow stack to store/check return addresses at call/return time. It
+would not suffer from race conditions at calls and returns and not incur the
+overhead of function instrumentation, but it does require operating system
+support.
+
+.. _`Return Flow Guard`: https://xlab.tencent.com/en/2016/11/02/return-flow-guard/
+.. _`Control-flow Enforcement Technology`: https://software.intel.com/sites/default/files/managed/4d/2a/control-flow-enforcement-technology-preview.pdf
+
+Compatibility
+-
+
+ShadowCallStack currently only supports x86_64. A runtime is not currently
+provided in compiler-rt so one must be provided by the compiled application.
+
+Security
+
+
+ShadowCallStack is intended to be a stronger alternative to
+``-fstack-protector``. It protects from non-linear overflows and arbitrary
+memory writes to the return address slot; however, similarly to
+``-fstack-protector`` this protection suffers from race conditions because of
+the call-return semantics on x86_64. There is a short race between the call
+instruction and the first instruction in the function that reads the return
+address where an attacker could overwrite the return address and bypass
+ShadowCallStack. Similarly, there is a time-of-check-to-time-of-use race in the
+function epilog where an attacker could overwrite the return address after it
+has been checked and before it has been returned to. Modifying the call-return
+semantics to fix this on x86_64 would incur an unacceptable performance overhead
+due to return branch prediction.
+
+The instrumentation makes use of the ``gs`` segment register to reference the
+shadow call stack meaning that references to the shadow call stack do not have
+to be stored in memory. This makes it possible to implement a runtime that
+avoids exposing the address of the shadow call stack to attackers that can read
+arbitrary memory. However, attackers could still try to exploit side channels
+exposed by the operating system `[1]`_ `[2]`_ or processor `[3]`_ to discover
+the address of the shadow call stack.
+
+.. _`[1]`: https://eyalitkin.wordpress.com/2017/09/01/cartography-lighting-up-the-shadows/
+.. _`[2]`: https://www.blackhat.com/docs/eu-16/materials/eu-16-Goktas-Bypassing-Clangs-SafeStack.pdf
+.. _`[3]`: https://www.vusec.net/projects/anc/
+
+Leaf functions are optimized to store the return address in a free register
+and avoid writing to the shadow call stack if a register is available. Very
+short leaf functions are uninstrumented if their execution is judged to be
+shorter than the race condition window intrinsic to the instrumentation.
+
+Usage
+=
+
+To enable ShadowCallStack, just pass the ``-fsanitize=shadow-call-stack`` flag
+to both compile and link command lines.
+
+Low-level API
+-
+
+``__has_feature(shadow_call_stack)``
+
+
+In some cases one may need to execute 

[PATCH] D44801: Add the -fsanitize=shadow-call-stack flag

2018-04-03 Thread Vlad Tsyrklevich via Phabricator via cfe-commits
vlad.tsyrklevich updated this revision to Diff 140868.
vlad.tsyrklevich added a comment.

- Small test, doc updates


Repository:
  rC Clang

https://reviews.llvm.org/D44801

Files:
  docs/ShadowCallStack.rst
  docs/index.rst
  include/clang/Basic/Sanitizers.def
  lib/CodeGen/CGDeclCXX.cpp
  lib/CodeGen/CodeGenFunction.cpp
  lib/Driver/SanitizerArgs.cpp
  lib/Driver/ToolChain.cpp
  lib/Lex/PPMacroExpansion.cpp
  test/CodeGen/shadowcallstack-attr.c
  test/Driver/sanitizer-ld.c

Index: test/Driver/sanitizer-ld.c
===
--- test/Driver/sanitizer-ld.c
+++ test/Driver/sanitizer-ld.c
@@ -557,6 +557,21 @@
 // CHECK-SAFESTACK-LINUX: "-lpthread"
 // CHECK-SAFESTACK-LINUX: "-ldl"
 
+// RUN: %clang -fsanitize=shadow-call-stack %s -### -o %t.o 2>&1 \
+// RUN: -target x86_64-unknown-linux -fuse-ld=ld \
+// RUN:   | FileCheck --check-prefix=CHECK-SHADOWCALLSTACK-LINUX-X86-64 %s
+// CHECK-SHADOWCALLSTACK-LINUX-X86-64-NOT: error:
+
+// RUN: %clang -fsanitize=shadow-call-stack %s -### -o %t.o 2>&1 \
+// RUN: -target x86-unknown-linux -fuse-ld=ld \
+// RUN:   | FileCheck --check-prefix=CHECK-SHADOWCALLSTACK-LINUX-X86 %s
+// CHECK-SHADOWCALLSTACK-LINUX-X86: error: unsupported option '-fsanitize=shadow-call-stack' for target 'x86-unknown-linux'
+
+// RUN: %clang -fsanitize=shadow-call-stack %s -### -o %t.o 2>&1 \
+// RUN: -fsanitize=safe-stack -target x86_64-unknown-linux -fuse-ld=ld \
+// RUN:   | FileCheck --check-prefix=CHECK-SHADOWCALLSTACK-SAFESTACK %s
+// CHECK-SHADOWCALLSTACK-SAFESTACK: error: invalid argument '-fsanitize=shadow-call-stack' not allowed with '-fsanitize=safe-stack'
+
 // RUN: %clang -fsanitize=cfi -fsanitize-stats %s -### -o %t.o 2>&1 \
 // RUN: -target x86_64-unknown-linux -fuse-ld=ld \
 // RUN: --sysroot=%S/Inputs/basic_linux_tree \
Index: test/CodeGen/shadowcallstack-attr.c
===
--- /dev/null
+++ test/CodeGen/shadowcallstack-attr.c
@@ -0,0 +1,16 @@
+// RUN: %clang_cc1 -triple x86_64-linux-unknown -emit-llvm -o - %s -fsanitize=shadow-call-stack | FileCheck -check-prefix=UNBLACKLISTED %s
+
+// RUN: %clang_cc1 -D ATTR -triple x86_64-linux-unknown -emit-llvm -o - %s -fsanitize=shadow-call-stack | FileCheck -check-prefix=BLACKLISTED %s
+
+// RUN: echo -e "[shadow-call-stack]\nfun:foo" > %t
+// RUN: %clang_cc1 -fsanitize-blacklist=%t -triple x86_64-linux-unknown -emit-llvm -o - %s -fsanitize=shadow-call-stack | FileCheck -check-prefix=BLACKLISTED %s
+
+#ifdef ATTR
+__attribute__((no_sanitize("shadow-call-stack")))
+#endif
+int foo(int *a) { return *a; }
+
+// CHECK: define i32 @foo(i32* %a)
+
+// BLACKLISTED-NOT: attributes {{.*}}shadowcallstack{{.*}}
+// UNBLACKLISTED: attributes {{.*}}shadowcallstack{{.*}}
Index: lib/Lex/PPMacroExpansion.cpp
===
--- lib/Lex/PPMacroExpansion.cpp
+++ lib/Lex/PPMacroExpansion.cpp
@@ -1275,6 +1275,8 @@
   .Case("is_union", LangOpts.CPlusPlus)
   .Case("modules", LangOpts.Modules)
   .Case("safe_stack", LangOpts.Sanitize.has(SanitizerKind::SafeStack))
+  .Case("shadow_call_stack",
+LangOpts.Sanitize.has(SanitizerKind::ShadowCallStack))
   .Case("tls", PP.getTargetInfo().isTLSSupported())
   .Case("underlying_type", LangOpts.CPlusPlus)
   .Default(false);
Index: lib/Driver/ToolChain.cpp
===
--- lib/Driver/ToolChain.cpp
+++ lib/Driver/ToolChain.cpp
@@ -814,6 +814,8 @@
   getTriple().getArch() == llvm::Triple::wasm32 ||
   getTriple().getArch() == llvm::Triple::wasm64)
 Res |= CFIICall;
+  if (getTriple().getArch() == llvm::Triple::x86_64)
+Res |= ShadowCallStack;
   return Res;
 }
 
Index: lib/Driver/SanitizerArgs.cpp
===
--- lib/Driver/SanitizerArgs.cpp
+++ lib/Driver/SanitizerArgs.cpp
@@ -343,7 +343,10 @@
   std::make_pair(Scudo, Address | HWAddress | Leak | Thread | Memory |
 KernelAddress | Efficiency),
   std::make_pair(SafeStack, Address | HWAddress | Leak | Thread | Memory |
-KernelAddress | Efficiency)};
+KernelAddress | Efficiency),
+  std::make_pair(ShadowCallStack, Address | HWAddress | Leak | Thread |
+  Memory | KernelAddress | Efficiency |
+  SafeStack)};
 
   // Enable toolchain specific default sanitizers if not explicitly disabled.
   SanitizerMask Default = TC.getDefaultSanitizers() & ~AllRemove;
Index: lib/CodeGen/CodeGenFunction.cpp
===
--- lib/CodeGen/CodeGenFunction.cpp
+++ lib/CodeGen/CodeGenFunction.cpp
@@ -861,6 +861,8 @@
 Fn->addFnAttr(llvm::Attribute::SanitizeMemory);
   if 

[PATCH] D44801: Add the -fsanitize=shadow-call-stack flag

2018-03-28 Thread Vlad Tsyrklevich via Phabricator via cfe-commits
vlad.tsyrklevich added inline comments.



Comment at: docs/ShadowCallStack.rst:14
+buffer overflows. It works by saving a function's return address to a
+separately allocated 'shadow call stack' in the function prolog and checking 
the
+return address on the stack against the shadow call stack in the function

kcc wrote:
> kcc wrote:
> > prologue/epilogue? 
> > (it's your native tongue, not mine, though)
> PTAL
Forgot to submit this comment: It's used both ways across LLVM but I chose to 
go with this one just because that's how the PrologEpilogInserter pass wrote it.


Repository:
  rC Clang

https://reviews.llvm.org/D44801



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D44801: Add the -fsanitize=shadow-call-stack flag

2018-03-23 Thread Vlad Tsyrklevich via Phabricator via cfe-commits
vlad.tsyrklevich updated this revision to Diff 139652.
vlad.tsyrklevich marked 6 inline comments as done.
vlad.tsyrklevich added a comment.

- Address Kostya's documentation feedback


Repository:
  rC Clang

https://reviews.llvm.org/D44801

Files:
  docs/ShadowCallStack.rst
  docs/index.rst
  include/clang/Basic/Sanitizers.def
  lib/CodeGen/CGDeclCXX.cpp
  lib/CodeGen/CodeGenFunction.cpp
  lib/Driver/SanitizerArgs.cpp
  lib/Driver/ToolChain.cpp
  lib/Lex/PPMacroExpansion.cpp
  test/CodeGen/shadowcallstack-attr.c
  test/Driver/sanitizer-ld.c

Index: test/Driver/sanitizer-ld.c
===
--- test/Driver/sanitizer-ld.c
+++ test/Driver/sanitizer-ld.c
@@ -557,6 +557,21 @@
 // CHECK-SAFESTACK-LINUX: "-lpthread"
 // CHECK-SAFESTACK-LINUX: "-ldl"
 
+// RUN: %clang -fsanitize=shadow-call-stack %s -### -o %t.o 2>&1 \
+// RUN: -target x86_64-unknown-linux -fuse-ld=ld \
+// RUN:   | FileCheck --check-prefix=CHECK-SHADOWCALLSTACK-LINUX-X86-64 %s
+// CHECK-SHADOWCALLSTACK-LINUX-X86-64-NOT: error:
+
+// RUN: %clang -fsanitize=shadow-call-stack %s -### -o %t.o 2>&1 \
+// RUN: -target x86-unknown-linux -fuse-ld=ld \
+// RUN:   | FileCheck --check-prefix=CHECK-SHADOWCALLSTACK-LINUX-X86 %s
+// CHECK-SHADOWCALLSTACK-LINUX-X86: error: unsupported option '-fsanitize=shadow-call-stack' for target 'x86-unknown-linux'
+
+// RUN: %clang -fsanitize=shadow-call-stack %s -### -o %t.o 2>&1 \
+// RUN: -fsanitize=safe-stack -target x86_64-unknown-linux -fuse-ld=ld \
+// RUN:   | FileCheck --check-prefix=CHECK-SHADOWCALLSTACK-SAFESTACK %s
+// CHECK-SHADOWCALLSTACK-SAFESTACK: error: invalid argument '-fsanitize=shadow-call-stack' not allowed with '-fsanitize=safe-stack'
+
 // RUN: %clang -fsanitize=cfi -fsanitize-stats %s -### -o %t.o 2>&1 \
 // RUN: -target x86_64-unknown-linux -fuse-ld=ld \
 // RUN: --sysroot=%S/Inputs/basic_linux_tree \
Index: test/CodeGen/shadowcallstack-attr.c
===
--- /dev/null
+++ test/CodeGen/shadowcallstack-attr.c
@@ -0,0 +1,12 @@
+// RUN: %clang_cc1 -triple x86_64-linux-unknown -emit-llvm -o - %s -fsanitize=shadow-call-stack | FileCheck %s
+
+__attribute__((no_sanitize("shadow-call-stack")))
+int foo(int *a) { return *a; }
+
+ int bar(int *a) { return *a; }
+
+// CHECK: define i32 @foo(i32* %a) #[[FOO_ATTR:[0-9]+]] {
+// CHECK: define i32 @bar(i32* %a) #[[BAR_ATTR:[0-9]+]] {
+
+// CHECK-NOT: attributes #[[FOO_ATTR]] = { {{.*}}shadowcallstack{{.*}} }
+// CHECK: attributes #[[BAR_ATTR]] = { {{.*}}shadowcallstack{{.*}} }
Index: lib/Lex/PPMacroExpansion.cpp
===
--- lib/Lex/PPMacroExpansion.cpp
+++ lib/Lex/PPMacroExpansion.cpp
@@ -1275,6 +1275,8 @@
   .Case("is_union", LangOpts.CPlusPlus)
   .Case("modules", LangOpts.Modules)
   .Case("safe_stack", LangOpts.Sanitize.has(SanitizerKind::SafeStack))
+  .Case("shadow_call_stack",
+LangOpts.Sanitize.has(SanitizerKind::ShadowCallStack))
   .Case("tls", PP.getTargetInfo().isTLSSupported())
   .Case("underlying_type", LangOpts.CPlusPlus)
   .Default(false);
Index: lib/Driver/ToolChain.cpp
===
--- lib/Driver/ToolChain.cpp
+++ lib/Driver/ToolChain.cpp
@@ -814,6 +814,8 @@
   getTriple().getArch() == llvm::Triple::wasm32 ||
   getTriple().getArch() == llvm::Triple::wasm64)
 Res |= CFIICall;
+  if (getTriple().getArch() == llvm::Triple::x86_64)
+Res |= ShadowCallStack;
   return Res;
 }
 
Index: lib/Driver/SanitizerArgs.cpp
===
--- lib/Driver/SanitizerArgs.cpp
+++ lib/Driver/SanitizerArgs.cpp
@@ -343,7 +343,10 @@
   std::make_pair(Scudo, Address | HWAddress | Leak | Thread | Memory |
 KernelAddress | Efficiency),
   std::make_pair(SafeStack, Address | HWAddress | Leak | Thread | Memory |
-KernelAddress | Efficiency)};
+KernelAddress | Efficiency),
+  std::make_pair(ShadowCallStack, Address | HWAddress | Leak | Thread |
+  Memory | KernelAddress | Efficiency |
+  SafeStack)};
 
   // Enable toolchain specific default sanitizers if not explicitly disabled.
   SanitizerMask Default = TC.getDefaultSanitizers() & ~AllRemove;
Index: lib/CodeGen/CodeGenFunction.cpp
===
--- lib/CodeGen/CodeGenFunction.cpp
+++ lib/CodeGen/CodeGenFunction.cpp
@@ -861,6 +861,8 @@
 Fn->addFnAttr(llvm::Attribute::SanitizeMemory);
   if (SanOpts.has(SanitizerKind::SafeStack))
 Fn->addFnAttr(llvm::Attribute::SafeStack);
+  if (SanOpts.has(SanitizerKind::ShadowCallStack))
+Fn->addFnAttr(llvm::Attribute::ShadowCallStack);
 
   // Ignore TSan memory acesses from 

[PATCH] D44801: Add the -fsanitize=shadow-call-stack flag

2018-03-22 Thread Vlad Tsyrklevich via Phabricator via cfe-commits
vlad.tsyrklevich updated this revision to Diff 139554.
vlad.tsyrklevich added a comment.

- Add Driver tests


Repository:
  rC Clang

https://reviews.llvm.org/D44801

Files:
  docs/ShadowCallStack.rst
  docs/index.rst
  include/clang/Basic/Sanitizers.def
  lib/CodeGen/CGDeclCXX.cpp
  lib/CodeGen/CodeGenFunction.cpp
  lib/Driver/SanitizerArgs.cpp
  lib/Driver/ToolChain.cpp
  lib/Lex/PPMacroExpansion.cpp
  test/CodeGen/shadowcallstack-attr.c
  test/Driver/sanitizer-ld.c

Index: test/Driver/sanitizer-ld.c
===
--- test/Driver/sanitizer-ld.c
+++ test/Driver/sanitizer-ld.c
@@ -557,6 +557,21 @@
 // CHECK-SAFESTACK-LINUX: "-lpthread"
 // CHECK-SAFESTACK-LINUX: "-ldl"
 
+// RUN: %clang -fsanitize=shadow-call-stack %s -### -o %t.o 2>&1 \
+// RUN: -target x86_64-unknown-linux -fuse-ld=ld \
+// RUN:   | FileCheck --check-prefix=CHECK-SHADOWCALLSTACK-LINUX-X86-64 %s
+// CHECK-SHADOWCALLSTACK-LINUX-X86-64-NOT: error:
+
+// RUN: %clang -fsanitize=shadow-call-stack %s -### -o %t.o 2>&1 \
+// RUN: -target x86-unknown-linux -fuse-ld=ld \
+// RUN:   | FileCheck --check-prefix=CHECK-SHADOWCALLSTACK-LINUX-X86 %s
+// CHECK-SHADOWCALLSTACK-LINUX-X86: error: unsupported option '-fsanitize=shadow-call-stack' for target 'x86-unknown-linux'
+
+// RUN: %clang -fsanitize=shadow-call-stack %s -### -o %t.o 2>&1 \
+// RUN: -fsanitize=safe-stack -target x86_64-unknown-linux -fuse-ld=ld \
+// RUN:   | FileCheck --check-prefix=CHECK-SHADOWCALLSTACK-SAFESTACK %s
+// CHECK-SHADOWCALLSTACK-SAFESTACK: error: invalid argument '-fsanitize=shadow-call-stack' not allowed with '-fsanitize=safe-stack'
+
 // RUN: %clang -fsanitize=cfi -fsanitize-stats %s -### -o %t.o 2>&1 \
 // RUN: -target x86_64-unknown-linux -fuse-ld=ld \
 // RUN: --sysroot=%S/Inputs/basic_linux_tree \
Index: test/CodeGen/shadowcallstack-attr.c
===
--- /dev/null
+++ test/CodeGen/shadowcallstack-attr.c
@@ -0,0 +1,12 @@
+// RUN: %clang_cc1 -triple x86_64-linux-unknown -emit-llvm -o - %s -fsanitize=shadow-call-stack | FileCheck %s
+
+__attribute__((no_sanitize("shadow-call-stack")))
+int foo(int *a) { return *a; }
+
+ int bar(int *a) { return *a; }
+
+// CHECK: define i32 @foo(i32* %a) #[[FOO_ATTR:[0-9]+]] {
+// CHECK: define i32 @bar(i32* %a) #[[BAR_ATTR:[0-9]+]] {
+
+// CHECK-NOT: attributes #[[FOO_ATTR]] = { {{.*}}shadowcallstack{{.*}} }
+// CHECK: attributes #[[BAR_ATTR]] = { {{.*}}shadowcallstack{{.*}} }
Index: lib/Lex/PPMacroExpansion.cpp
===
--- lib/Lex/PPMacroExpansion.cpp
+++ lib/Lex/PPMacroExpansion.cpp
@@ -1275,6 +1275,8 @@
   .Case("is_union", LangOpts.CPlusPlus)
   .Case("modules", LangOpts.Modules)
   .Case("safe_stack", LangOpts.Sanitize.has(SanitizerKind::SafeStack))
+  .Case("shadow_call_stack",
+LangOpts.Sanitize.has(SanitizerKind::ShadowCallStack))
   .Case("tls", PP.getTargetInfo().isTLSSupported())
   .Case("underlying_type", LangOpts.CPlusPlus)
   .Default(false);
Index: lib/Driver/ToolChain.cpp
===
--- lib/Driver/ToolChain.cpp
+++ lib/Driver/ToolChain.cpp
@@ -814,6 +814,8 @@
   getTriple().getArch() == llvm::Triple::wasm32 ||
   getTriple().getArch() == llvm::Triple::wasm64)
 Res |= CFIICall;
+  if (getTriple().getArch() == llvm::Triple::x86_64)
+Res |= ShadowCallStack;
   return Res;
 }
 
Index: lib/Driver/SanitizerArgs.cpp
===
--- lib/Driver/SanitizerArgs.cpp
+++ lib/Driver/SanitizerArgs.cpp
@@ -343,7 +343,10 @@
   std::make_pair(Scudo, Address | HWAddress | Leak | Thread | Memory |
 KernelAddress | Efficiency),
   std::make_pair(SafeStack, Address | HWAddress | Leak | Thread | Memory |
-KernelAddress | Efficiency)};
+KernelAddress | Efficiency),
+  std::make_pair(ShadowCallStack, Address | HWAddress | Leak | Thread |
+  Memory | KernelAddress | Efficiency |
+  SafeStack)};
 
   // Enable toolchain specific default sanitizers if not explicitly disabled.
   SanitizerMask Default = TC.getDefaultSanitizers() & ~AllRemove;
Index: lib/CodeGen/CodeGenFunction.cpp
===
--- lib/CodeGen/CodeGenFunction.cpp
+++ lib/CodeGen/CodeGenFunction.cpp
@@ -861,6 +861,8 @@
 Fn->addFnAttr(llvm::Attribute::SanitizeMemory);
   if (SanOpts.has(SanitizerKind::SafeStack))
 Fn->addFnAttr(llvm::Attribute::SafeStack);
+  if (SanOpts.has(SanitizerKind::ShadowCallStack))
+Fn->addFnAttr(llvm::Attribute::ShadowCallStack);
 
   // Ignore TSan memory acesses from within ObjC/ObjC++ dealloc, initialize,
   // .cxx_destruct, 

[PATCH] D44801: Add the -fsanitize=shadow-call-stack flag

2018-03-22 Thread Vlad Tsyrklevich via Phabricator via cfe-commits
vlad.tsyrklevich created this revision.
vlad.tsyrklevich added a reviewer: pcc.
Herald added a subscriber: cfe-commits.

Add support for the -fsanitize=shadow-call-stack flag which causes clang
to add ShadowCallStack attribute to functions compiled with that flag
enabled.


Repository:
  rC Clang

https://reviews.llvm.org/D44801

Files:
  docs/ShadowCallStack.rst
  docs/index.rst
  include/clang/Basic/Sanitizers.def
  lib/CodeGen/CGDeclCXX.cpp
  lib/CodeGen/CodeGenFunction.cpp
  lib/Driver/SanitizerArgs.cpp
  lib/Driver/ToolChain.cpp
  lib/Lex/PPMacroExpansion.cpp
  test/CodeGen/shadowcallstack-attr.c

Index: test/CodeGen/shadowcallstack-attr.c
===
--- /dev/null
+++ test/CodeGen/shadowcallstack-attr.c
@@ -0,0 +1,12 @@
+// RUN: %clang_cc1 -triple x86_64-linux-unknown -emit-llvm -o - %s -fsanitize=shadow-call-stack | FileCheck %s
+
+__attribute__((no_sanitize("shadow-call-stack")))
+int foo(int *a) { return *a; }
+
+ int bar(int *a) { return *a; }
+
+// CHECK: define i32 @foo(i32* %a) #[[FOO_ATTR:[0-9]+]] {
+// CHECK: define i32 @bar(i32* %a) #[[BAR_ATTR:[0-9]+]] {
+
+// CHECK-NOT: attributes #[[FOO_ATTR]] = { {{.*}}shadowcallstack{{.*}} }
+// CHECK: attributes #[[BAR_ATTR]] = { {{.*}}shadowcallstack{{.*}} }
Index: lib/Lex/PPMacroExpansion.cpp
===
--- lib/Lex/PPMacroExpansion.cpp
+++ lib/Lex/PPMacroExpansion.cpp
@@ -1275,6 +1275,8 @@
   .Case("is_union", LangOpts.CPlusPlus)
   .Case("modules", LangOpts.Modules)
   .Case("safe_stack", LangOpts.Sanitize.has(SanitizerKind::SafeStack))
+  .Case("shadow_call_stack",
+LangOpts.Sanitize.has(SanitizerKind::ShadowCallStack))
   .Case("tls", PP.getTargetInfo().isTLSSupported())
   .Case("underlying_type", LangOpts.CPlusPlus)
   .Default(false);
Index: lib/Driver/ToolChain.cpp
===
--- lib/Driver/ToolChain.cpp
+++ lib/Driver/ToolChain.cpp
@@ -814,6 +814,8 @@
   getTriple().getArch() == llvm::Triple::wasm32 ||
   getTriple().getArch() == llvm::Triple::wasm64)
 Res |= CFIICall;
+  if (getTriple().getArch() == llvm::Triple::x86_64)
+Res |= ShadowCallStack;
   return Res;
 }
 
Index: lib/Driver/SanitizerArgs.cpp
===
--- lib/Driver/SanitizerArgs.cpp
+++ lib/Driver/SanitizerArgs.cpp
@@ -343,7 +343,10 @@
   std::make_pair(Scudo, Address | HWAddress | Leak | Thread | Memory |
 KernelAddress | Efficiency),
   std::make_pair(SafeStack, Address | HWAddress | Leak | Thread | Memory |
-KernelAddress | Efficiency)};
+KernelAddress | Efficiency),
+  std::make_pair(ShadowCallStack, Address | HWAddress | Leak | Thread |
+  Memory | KernelAddress | Efficiency |
+  SafeStack)};
 
   // Enable toolchain specific default sanitizers if not explicitly disabled.
   SanitizerMask Default = TC.getDefaultSanitizers() & ~AllRemove;
Index: lib/CodeGen/CodeGenFunction.cpp
===
--- lib/CodeGen/CodeGenFunction.cpp
+++ lib/CodeGen/CodeGenFunction.cpp
@@ -861,6 +861,8 @@
 Fn->addFnAttr(llvm::Attribute::SanitizeMemory);
   if (SanOpts.has(SanitizerKind::SafeStack))
 Fn->addFnAttr(llvm::Attribute::SafeStack);
+  if (SanOpts.has(SanitizerKind::ShadowCallStack))
+Fn->addFnAttr(llvm::Attribute::ShadowCallStack);
 
   // Ignore TSan memory acesses from within ObjC/ObjC++ dealloc, initialize,
   // .cxx_destruct, __destroy_helper_block_ and all of their calees at run time.
Index: lib/CodeGen/CGDeclCXX.cpp
===
--- lib/CodeGen/CGDeclCXX.cpp
+++ lib/CodeGen/CGDeclCXX.cpp
@@ -343,6 +343,10 @@
   !isInSanitizerBlacklist(SanitizerKind::SafeStack, Fn, Loc))
 Fn->addFnAttr(llvm::Attribute::SafeStack);
 
+  if (getLangOpts().Sanitize.has(SanitizerKind::ShadowCallStack) &&
+  !isInSanitizerBlacklist(SanitizerKind::ShadowCallStack, Fn, Loc))
+Fn->addFnAttr(llvm::Attribute::ShadowCallStack);
+
   return Fn;
 }
 
Index: include/clang/Basic/Sanitizers.def
===
--- include/clang/Basic/Sanitizers.def
+++ include/clang/Basic/Sanitizers.def
@@ -110,6 +110,9 @@
 // Safe Stack
 SANITIZER("safe-stack", SafeStack)
 
+// Shadow Call Stack
+SANITIZER("shadow-call-stack", ShadowCallStack)
+
 // -fsanitize=undefined includes all the sanitizers which have low overhead, no
 // ABI or address space layout implications, and only catch undefined behavior.
 SANITIZER_GROUP("undefined", Undefined,
Index: docs/index.rst
===
--- docs/index.rst
+++ docs/index.rst
@@ 

[PATCH] D37925: Allow specifying sanitizers in blacklists

2017-09-21 Thread Vlad Tsyrklevich via Phabricator via cfe-commits
vlad.tsyrklevich added inline comments.



Comment at: lib/AST/Decl.cpp:3953
 ReasonToReject = 5;  // is standard layout.
-  else if (Blacklist.isBlacklistedLocation(getLocation(), "field-padding"))
+  else if (Blacklist.isBlacklistedLocation(ASanMask, getLocation(),
+   "field-padding"))

eugenis wrote:
> Looks like this is another case of missing "& LangOpts.Sanitize.Mask" ?
Indeed.



Comment at: lib/Basic/XRayLists.cpp:29
   // whether it's treated as a "never" instrument function.
-  if (AlwaysInstrument->inSection("fun", FunctionName, "arg1"))
+  if (AlwaysInstrument->inSection("xray_always_instrument", "fun", 
FunctionName,
+  "arg1"))

eugenis wrote:
> It feels redundant to have AlwaysInstrument and NeverInstrument lists, and 
> then the same distinction in section names. Maybe sections could be named 
> "xray" in  both cases? Or, better, the lists could be merged into a single 
> list with always and never sections? There is also an issue of backward 
> compatibility. Anyway, that's for xray devs to decide. @dberris 
I chose this approach for backwards compatibility, but I'd defer to what 
@dberris thinks is best.


https://reviews.llvm.org/D37925



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D37925: Allow specifying sanitizers in blacklists

2017-09-21 Thread Vlad Tsyrklevich via Phabricator via cfe-commits
vlad.tsyrklevich updated this revision to Diff 116213.
vlad.tsyrklevich marked 5 inline comments as done.
vlad.tsyrklevich added a comment.

- sanitizerCompile -> createSanitizerSections
- ASanMask -> AsanMask and fix another bug relating to ANDing with 
LangOpts.Sanitize.Mask


https://reviews.llvm.org/D37925

Files:
  docs/ControlFlowIntegrity.rst
  docs/SanitizerSpecialCaseList.rst
  include/clang/Basic/SanitizerBlacklist.h
  include/clang/Basic/SanitizerSpecialCaseList.h
  lib/AST/Decl.cpp
  lib/Basic/CMakeLists.txt
  lib/Basic/SanitizerBlacklist.cpp
  lib/Basic/SanitizerSpecialCaseList.cpp
  lib/Basic/XRayLists.cpp
  lib/CodeGen/CGClass.cpp
  lib/CodeGen/CGDeclCXX.cpp
  lib/CodeGen/CGExpr.cpp
  lib/CodeGen/CodeGenFunction.cpp
  lib/CodeGen/CodeGenModule.cpp
  lib/CodeGen/CodeGenModule.h
  test/CodeGen/Inputs/sanitizer-special-case-list.sanitized.txt
  test/CodeGen/Inputs/sanitizer-special-case-list.unsanitized1.txt
  test/CodeGen/Inputs/sanitizer-special-case-list.unsanitized2.txt
  test/CodeGen/Inputs/sanitizer-special-case-list.unsanitized3.txt
  test/CodeGen/Inputs/sanitizer-special-case-list.unsanitized4.txt
  test/CodeGen/sanitizer-special-case-list.c
  test/CodeGenCXX/cfi-blacklist.cpp

Index: test/CodeGenCXX/cfi-blacklist.cpp
===
--- test/CodeGenCXX/cfi-blacklist.cpp
+++ test/CodeGenCXX/cfi-blacklist.cpp
@@ -1,6 +1,18 @@
 // RUN: %clang_cc1 -triple %itanium_abi_triple -fvisibility hidden -fms-extensions -fsanitize=cfi-vcall -emit-llvm -o - %s | FileCheck --check-prefix=CHECK --check-prefix=NOBL %s
-// RUN: echo "type:std::*" > %t.txt
-// RUN: %clang_cc1 -triple %itanium_abi_triple -fvisibility hidden -fms-extensions -fsanitize=cfi-vcall -fsanitize-blacklist=%t.txt -emit-llvm -o - %s | FileCheck --check-prefix=CHECK --check-prefix=NOSTD %s
+
+// Check that blacklisting cfi and cfi-vcall work correctly
+// RUN: echo "[cfi-vcall]" > %t.vcall.txt
+// RUN: echo "type:std::*" >> %t.vcall.txt
+// RUN: %clang_cc1 -triple %itanium_abi_triple -fvisibility hidden -fms-extensions -fsanitize=cfi-vcall -fsanitize-blacklist=%t.vcall.txt -emit-llvm -o - %s | FileCheck --check-prefix=CHECK --check-prefix=NOSTD %s
+//
+// RUN: echo "[cfi]" > %t.cfi.txt
+// RUN: echo "type:std::*" >> %t.cfi.txt
+// RUN: %clang_cc1 -triple %itanium_abi_triple -fvisibility hidden -fms-extensions -fsanitize=cfi-vcall -fsanitize-blacklist=%t.cfi.txt -emit-llvm -o - %s | FileCheck --check-prefix=CHECK --check-prefix=NOSTD %s
+
+// Check that blacklisting non-vcall modes does not affect vcalls
+// RUN: echo "[cfi-icall|cfi-nvcall|cfi-cast-strict|cfi-derived-cast|cfi-unrelated-cast]" > %t.other.txt
+// RUN: echo "type:std::*" >> %t.other.txt
+// RUN: %clang_cc1 -triple %itanium_abi_triple -fvisibility hidden -fms-extensions -fsanitize=cfi-vcall -fsanitize-blacklist=%t.other.txt -emit-llvm -o - %s | FileCheck --check-prefix=CHECK --check-prefix=NOBL %s
 
 struct S1 {
   virtual void f();
Index: test/CodeGen/sanitizer-special-case-list.c
===
--- /dev/null
+++ test/CodeGen/sanitizer-special-case-list.c
@@ -0,0 +1,26 @@
+// Verify that blacklist sections correctly select sanitizers to apply blacklist entries to.
+//
+// RUN: %clang_cc1 -fsanitize=unsigned-integer-overflow,cfi-icall -fsanitize-blacklist=%S/Inputs/sanitizer-special-case-list.unsanitized1.txt -emit-llvm %s -o - | FileCheck %s --check-prefix=UNSANITIZED
+// RUN: %clang_cc1 -fsanitize=unsigned-integer-overflow,cfi-icall -fsanitize-blacklist=%S/Inputs/sanitizer-special-case-list.unsanitized2.txt -emit-llvm %s -o - | FileCheck %s --check-prefix=UNSANITIZED
+// RUN: %clang_cc1 -fsanitize=unsigned-integer-overflow,cfi-icall -fsanitize-blacklist=%S/Inputs/sanitizer-special-case-list.unsanitized3.txt -emit-llvm %s -o - | FileCheck %s --check-prefix=UNSANITIZED
+// RUN: %clang_cc1 -fsanitize=unsigned-integer-overflow,cfi-icall -fsanitize-blacklist=%S/Inputs/sanitizer-special-case-list.unsanitized4.txt -emit-llvm %s -o - | FileCheck %s --check-prefix=UNSANITIZED
+//
+// RUN: %clang_cc1 -fsanitize=unsigned-integer-overflow,cfi-icall -fsanitize-blacklist=%S/Inputs/sanitizer-special-case-list.sanitized.txt -emit-llvm %s -o - | FileCheck %s --check-prefix=SANITIZED
+
+unsigned i;
+
+// SANITIZED: @overflow
+// UNSANITIZED: @overflow
+unsigned overflow() {
+  // SANITIZED: call {{.*}}void @__ubsan
+  // UNSANITIZED-NOT: call {{.*}}void @__ubsan
+  return i * 37;
+}
+
+// SANITIZED: @cfi
+// UNSANITIZED: @cfi
+void cfi(void (*fp)()) {
+  // SANITIZED: llvm.type.test
+  // UNSANITIZED-NOT: llvm.type.test
+  fp();
+}
Index: test/CodeGen/Inputs/sanitizer-special-case-list.unsanitized4.txt
===
--- /dev/null
+++ test/CodeGen/Inputs/sanitizer-special-case-list.unsanitized4.txt
@@ -0,0 +1,4 @@
+[c*]
+fun:*cfi*
+[u*]
+fun:*overflow*
Index: test/CodeGen/Inputs/sanitizer-special-case-list.unsanitized3.txt

[PATCH] D37925: Allow specifying sanitizers in blacklists

2017-09-19 Thread Vlad Tsyrklevich via Phabricator via cfe-commits
vlad.tsyrklevich marked an inline comment as done.
vlad.tsyrklevich added inline comments.



Comment at: docs/SanitizerSpecialCaseList.rst:57
+
+Sections are regular expressions written in square brackets that denote which
+sanitizer the following entries apply to. For example, ``[address]`` specifies

eugenis wrote:
> Section names are regular expressions
> 
> also, not really a regular expression, more like a wildcard; I don't know 
> what's the right term for this
They are not just wildcards in the sense that `cfi-vcall|cfi-icall` is more 
than just wildcard matching. I could add a line that explains how `*` behaves 
here as well? (similarly to what we have in the entries paragraph)



Comment at: lib/CodeGen/CGDeclCXX.cpp:322
+  if (getLangOpts().Sanitize.hasOneOf(ASanMask))
+if (!isInSanitizerBlacklist(ASanMask, Fn, Loc))
   Fn->addFnAttr(llvm::Attribute::SanitizeAddress);

eugenis wrote:
> vlad.tsyrklevich wrote:
> > This use of ASanMask could also confound address & kernel-address as 
> > @eugenis pointed out.
> It would be more readable to split it in two if-s, IMHO: one for asan, one 
> for kernel-asan.
> 
Agreed.


https://reviews.llvm.org/D37925



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D37925: Allow specifying sanitizers in blacklists

2017-09-19 Thread Vlad Tsyrklevich via Phabricator via cfe-commits
vlad.tsyrklevich updated this revision to Diff 115849.
vlad.tsyrklevich added a comment.

- Refactor to make compile() not virtual again
- Refactor a confusing use of ASanMask into individual uses of 
SanitizerKind::{Address,KernelAddress}
- 'Sections' -> 'Section names'


https://reviews.llvm.org/D37925

Files:
  docs/ControlFlowIntegrity.rst
  docs/SanitizerSpecialCaseList.rst
  include/clang/Basic/SanitizerBlacklist.h
  include/clang/Basic/SanitizerSpecialCaseList.h
  lib/AST/Decl.cpp
  lib/Basic/CMakeLists.txt
  lib/Basic/SanitizerBlacklist.cpp
  lib/Basic/SanitizerSpecialCaseList.cpp
  lib/Basic/XRayLists.cpp
  lib/CodeGen/CGClass.cpp
  lib/CodeGen/CGDeclCXX.cpp
  lib/CodeGen/CGExpr.cpp
  lib/CodeGen/CodeGenFunction.cpp
  lib/CodeGen/CodeGenModule.cpp
  lib/CodeGen/CodeGenModule.h
  test/CodeGen/Inputs/sanitizer-special-case-list.sanitized.txt
  test/CodeGen/Inputs/sanitizer-special-case-list.unsanitized1.txt
  test/CodeGen/Inputs/sanitizer-special-case-list.unsanitized2.txt
  test/CodeGen/Inputs/sanitizer-special-case-list.unsanitized3.txt
  test/CodeGen/Inputs/sanitizer-special-case-list.unsanitized4.txt
  test/CodeGen/sanitizer-special-case-list.c
  test/CodeGenCXX/cfi-blacklist.cpp

Index: test/CodeGenCXX/cfi-blacklist.cpp
===
--- test/CodeGenCXX/cfi-blacklist.cpp
+++ test/CodeGenCXX/cfi-blacklist.cpp
@@ -1,6 +1,18 @@
 // RUN: %clang_cc1 -triple %itanium_abi_triple -fvisibility hidden -fms-extensions -fsanitize=cfi-vcall -emit-llvm -o - %s | FileCheck --check-prefix=CHECK --check-prefix=NOBL %s
-// RUN: echo "type:std::*" > %t.txt
-// RUN: %clang_cc1 -triple %itanium_abi_triple -fvisibility hidden -fms-extensions -fsanitize=cfi-vcall -fsanitize-blacklist=%t.txt -emit-llvm -o - %s | FileCheck --check-prefix=CHECK --check-prefix=NOSTD %s
+
+// Check that blacklisting cfi and cfi-vcall work correctly
+// RUN: echo "[cfi-vcall]" > %t.vcall.txt
+// RUN: echo "type:std::*" >> %t.vcall.txt
+// RUN: %clang_cc1 -triple %itanium_abi_triple -fvisibility hidden -fms-extensions -fsanitize=cfi-vcall -fsanitize-blacklist=%t.vcall.txt -emit-llvm -o - %s | FileCheck --check-prefix=CHECK --check-prefix=NOSTD %s
+//
+// RUN: echo "[cfi]" > %t.cfi.txt
+// RUN: echo "type:std::*" >> %t.cfi.txt
+// RUN: %clang_cc1 -triple %itanium_abi_triple -fvisibility hidden -fms-extensions -fsanitize=cfi-vcall -fsanitize-blacklist=%t.cfi.txt -emit-llvm -o - %s | FileCheck --check-prefix=CHECK --check-prefix=NOSTD %s
+
+// Check that blacklisting non-vcall modes does not affect vcalls
+// RUN: echo "[cfi-icall|cfi-nvcall|cfi-cast-strict|cfi-derived-cast|cfi-unrelated-cast]" > %t.other.txt
+// RUN: echo "type:std::*" >> %t.other.txt
+// RUN: %clang_cc1 -triple %itanium_abi_triple -fvisibility hidden -fms-extensions -fsanitize=cfi-vcall -fsanitize-blacklist=%t.other.txt -emit-llvm -o - %s | FileCheck --check-prefix=CHECK --check-prefix=NOBL %s
 
 struct S1 {
   virtual void f();
Index: test/CodeGen/sanitizer-special-case-list.c
===
--- /dev/null
+++ test/CodeGen/sanitizer-special-case-list.c
@@ -0,0 +1,26 @@
+// Verify that blacklist sections correctly select sanitizers to apply blacklist entries to.
+//
+// RUN: %clang_cc1 -fsanitize=unsigned-integer-overflow,cfi-icall -fsanitize-blacklist=%S/Inputs/sanitizer-special-case-list.unsanitized1.txt -emit-llvm %s -o - | FileCheck %s --check-prefix=UNSANITIZED
+// RUN: %clang_cc1 -fsanitize=unsigned-integer-overflow,cfi-icall -fsanitize-blacklist=%S/Inputs/sanitizer-special-case-list.unsanitized2.txt -emit-llvm %s -o - | FileCheck %s --check-prefix=UNSANITIZED
+// RUN: %clang_cc1 -fsanitize=unsigned-integer-overflow,cfi-icall -fsanitize-blacklist=%S/Inputs/sanitizer-special-case-list.unsanitized3.txt -emit-llvm %s -o - | FileCheck %s --check-prefix=UNSANITIZED
+// RUN: %clang_cc1 -fsanitize=unsigned-integer-overflow,cfi-icall -fsanitize-blacklist=%S/Inputs/sanitizer-special-case-list.unsanitized4.txt -emit-llvm %s -o - | FileCheck %s --check-prefix=UNSANITIZED
+//
+// RUN: %clang_cc1 -fsanitize=unsigned-integer-overflow,cfi-icall -fsanitize-blacklist=%S/Inputs/sanitizer-special-case-list.sanitized.txt -emit-llvm %s -o - | FileCheck %s --check-prefix=SANITIZED
+
+unsigned i;
+
+// SANITIZED: @overflow
+// UNSANITIZED: @overflow
+unsigned overflow() {
+  // SANITIZED: call {{.*}}void @__ubsan
+  // UNSANITIZED-NOT: call {{.*}}void @__ubsan
+  return i * 37;
+}
+
+// SANITIZED: @cfi
+// UNSANITIZED: @cfi
+void cfi(void (*fp)()) {
+  // SANITIZED: llvm.type.test
+  // UNSANITIZED-NOT: llvm.type.test
+  fp();
+}
Index: test/CodeGen/Inputs/sanitizer-special-case-list.unsanitized4.txt
===
--- /dev/null
+++ test/CodeGen/Inputs/sanitizer-special-case-list.unsanitized4.txt
@@ -0,0 +1,4 @@
+[c*]
+fun:*cfi*
+[u*]
+fun:*overflow*
Index: test/CodeGen/Inputs/sanitizer-special-case-list.unsanitized3.txt

[PATCH] D37925: Allow specifying sanitizers in blacklists

2017-09-18 Thread Vlad Tsyrklevich via Phabricator via cfe-commits
vlad.tsyrklevich updated this revision to Diff 115751.
vlad.tsyrklevich added a comment.

Update for SectionsMap refactor in LLVM


https://reviews.llvm.org/D37925

Files:
  docs/ControlFlowIntegrity.rst
  docs/SanitizerSpecialCaseList.rst
  include/clang/Basic/SanitizerBlacklist.h
  include/clang/Basic/SanitizerSpecialCaseList.h
  lib/AST/Decl.cpp
  lib/Basic/CMakeLists.txt
  lib/Basic/SanitizerBlacklist.cpp
  lib/Basic/SanitizerSpecialCaseList.cpp
  lib/Basic/XRayLists.cpp
  lib/CodeGen/CGClass.cpp
  lib/CodeGen/CGDeclCXX.cpp
  lib/CodeGen/CGExpr.cpp
  lib/CodeGen/CodeGenFunction.cpp
  lib/CodeGen/CodeGenModule.cpp
  lib/CodeGen/CodeGenModule.h
  test/CodeGen/Inputs/sanitizer-special-case-list.sanitized.txt
  test/CodeGen/Inputs/sanitizer-special-case-list.unsanitized1.txt
  test/CodeGen/Inputs/sanitizer-special-case-list.unsanitized2.txt
  test/CodeGen/Inputs/sanitizer-special-case-list.unsanitized3.txt
  test/CodeGen/Inputs/sanitizer-special-case-list.unsanitized4.txt
  test/CodeGen/sanitizer-special-case-list.c
  test/CodeGenCXX/cfi-blacklist.cpp

Index: test/CodeGenCXX/cfi-blacklist.cpp
===
--- test/CodeGenCXX/cfi-blacklist.cpp
+++ test/CodeGenCXX/cfi-blacklist.cpp
@@ -1,6 +1,18 @@
 // RUN: %clang_cc1 -triple %itanium_abi_triple -fvisibility hidden -fms-extensions -fsanitize=cfi-vcall -emit-llvm -o - %s | FileCheck --check-prefix=CHECK --check-prefix=NOBL %s
-// RUN: echo "type:std::*" > %t.txt
-// RUN: %clang_cc1 -triple %itanium_abi_triple -fvisibility hidden -fms-extensions -fsanitize=cfi-vcall -fsanitize-blacklist=%t.txt -emit-llvm -o - %s | FileCheck --check-prefix=CHECK --check-prefix=NOSTD %s
+
+// Check that blacklisting cfi and cfi-vcall work correctly
+// RUN: echo "[cfi-vcall]" > %t.vcall.txt
+// RUN: echo "type:std::*" >> %t.vcall.txt
+// RUN: %clang_cc1 -triple %itanium_abi_triple -fvisibility hidden -fms-extensions -fsanitize=cfi-vcall -fsanitize-blacklist=%t.vcall.txt -emit-llvm -o - %s | FileCheck --check-prefix=CHECK --check-prefix=NOSTD %s
+//
+// RUN: echo "[cfi]" > %t.cfi.txt
+// RUN: echo "type:std::*" >> %t.cfi.txt
+// RUN: %clang_cc1 -triple %itanium_abi_triple -fvisibility hidden -fms-extensions -fsanitize=cfi-vcall -fsanitize-blacklist=%t.cfi.txt -emit-llvm -o - %s | FileCheck --check-prefix=CHECK --check-prefix=NOSTD %s
+
+// Check that blacklisting non-vcall modes does not affect vcalls
+// RUN: echo "[cfi-icall|cfi-nvcall|cfi-cast-strict|cfi-derived-cast|cfi-unrelated-cast]" > %t.other.txt
+// RUN: echo "type:std::*" >> %t.other.txt
+// RUN: %clang_cc1 -triple %itanium_abi_triple -fvisibility hidden -fms-extensions -fsanitize=cfi-vcall -fsanitize-blacklist=%t.other.txt -emit-llvm -o - %s | FileCheck --check-prefix=CHECK --check-prefix=NOBL %s
 
 struct S1 {
   virtual void f();
Index: test/CodeGen/sanitizer-special-case-list.c
===
--- /dev/null
+++ test/CodeGen/sanitizer-special-case-list.c
@@ -0,0 +1,26 @@
+// Verify that blacklist sections correctly select sanitizers to apply blacklist entries to.
+//
+// RUN: %clang_cc1 -fsanitize=unsigned-integer-overflow,cfi-icall -fsanitize-blacklist=%S/Inputs/sanitizer-special-case-list.unsanitized1.txt -emit-llvm %s -o - | FileCheck %s --check-prefix=UNSANITIZED
+// RUN: %clang_cc1 -fsanitize=unsigned-integer-overflow,cfi-icall -fsanitize-blacklist=%S/Inputs/sanitizer-special-case-list.unsanitized2.txt -emit-llvm %s -o - | FileCheck %s --check-prefix=UNSANITIZED
+// RUN: %clang_cc1 -fsanitize=unsigned-integer-overflow,cfi-icall -fsanitize-blacklist=%S/Inputs/sanitizer-special-case-list.unsanitized3.txt -emit-llvm %s -o - | FileCheck %s --check-prefix=UNSANITIZED
+// RUN: %clang_cc1 -fsanitize=unsigned-integer-overflow,cfi-icall -fsanitize-blacklist=%S/Inputs/sanitizer-special-case-list.unsanitized4.txt -emit-llvm %s -o - | FileCheck %s --check-prefix=UNSANITIZED
+//
+// RUN: %clang_cc1 -fsanitize=unsigned-integer-overflow,cfi-icall -fsanitize-blacklist=%S/Inputs/sanitizer-special-case-list.sanitized.txt -emit-llvm %s -o - | FileCheck %s --check-prefix=SANITIZED
+
+unsigned i;
+
+// SANITIZED: @overflow
+// UNSANITIZED: @overflow
+unsigned overflow() {
+  // SANITIZED: call {{.*}}void @__ubsan
+  // UNSANITIZED-NOT: call {{.*}}void @__ubsan
+  return i * 37;
+}
+
+// SANITIZED: @cfi
+// UNSANITIZED: @cfi
+void cfi(void (*fp)()) {
+  // SANITIZED: llvm.type.test
+  // UNSANITIZED-NOT: llvm.type.test
+  fp();
+}
Index: test/CodeGen/Inputs/sanitizer-special-case-list.unsanitized4.txt
===
--- /dev/null
+++ test/CodeGen/Inputs/sanitizer-special-case-list.unsanitized4.txt
@@ -0,0 +1,4 @@
+[c*]
+fun:*cfi*
+[u*]
+fun:*overflow*
Index: test/CodeGen/Inputs/sanitizer-special-case-list.unsanitized3.txt
===
--- /dev/null
+++ test/CodeGen/Inputs/sanitizer-special-case-list.unsanitized3.txt
@@ 

[PATCH] D37925: Allow specifying sanitizers in blacklists

2017-09-18 Thread Vlad Tsyrklevich via Phabricator via cfe-commits
vlad.tsyrklevich updated this revision to Diff 115703.
vlad.tsyrklevich added a comment.

Update documentation to mention sections in the blacklist documentation and in 
the CFI documentation (where it's most useful)


https://reviews.llvm.org/D37925

Files:
  docs/ControlFlowIntegrity.rst
  docs/SanitizerSpecialCaseList.rst
  include/clang/Basic/SanitizerBlacklist.h
  include/clang/Basic/SanitizerSpecialCaseList.h
  lib/AST/Decl.cpp
  lib/Basic/CMakeLists.txt
  lib/Basic/SanitizerBlacklist.cpp
  lib/Basic/SanitizerSpecialCaseList.cpp
  lib/Basic/XRayLists.cpp
  lib/CodeGen/CGClass.cpp
  lib/CodeGen/CGDeclCXX.cpp
  lib/CodeGen/CGExpr.cpp
  lib/CodeGen/CodeGenFunction.cpp
  lib/CodeGen/CodeGenModule.cpp
  lib/CodeGen/CodeGenModule.h
  test/CodeGen/Inputs/sanitizer-special-case-list.sanitized.txt
  test/CodeGen/Inputs/sanitizer-special-case-list.unsanitized1.txt
  test/CodeGen/Inputs/sanitizer-special-case-list.unsanitized2.txt
  test/CodeGen/Inputs/sanitizer-special-case-list.unsanitized3.txt
  test/CodeGen/Inputs/sanitizer-special-case-list.unsanitized4.txt
  test/CodeGen/sanitizer-special-case-list.c
  test/CodeGenCXX/cfi-blacklist.cpp

Index: test/CodeGenCXX/cfi-blacklist.cpp
===
--- test/CodeGenCXX/cfi-blacklist.cpp
+++ test/CodeGenCXX/cfi-blacklist.cpp
@@ -1,6 +1,18 @@
 // RUN: %clang_cc1 -triple %itanium_abi_triple -fvisibility hidden -fms-extensions -fsanitize=cfi-vcall -emit-llvm -o - %s | FileCheck --check-prefix=CHECK --check-prefix=NOBL %s
-// RUN: echo "type:std::*" > %t.txt
-// RUN: %clang_cc1 -triple %itanium_abi_triple -fvisibility hidden -fms-extensions -fsanitize=cfi-vcall -fsanitize-blacklist=%t.txt -emit-llvm -o - %s | FileCheck --check-prefix=CHECK --check-prefix=NOSTD %s
+
+// Check that blacklisting cfi and cfi-vcall work correctly
+// RUN: echo "[cfi-vcall]" > %t.vcall.txt
+// RUN: echo "type:std::*" >> %t.vcall.txt
+// RUN: %clang_cc1 -triple %itanium_abi_triple -fvisibility hidden -fms-extensions -fsanitize=cfi-vcall -fsanitize-blacklist=%t.vcall.txt -emit-llvm -o - %s | FileCheck --check-prefix=CHECK --check-prefix=NOSTD %s
+//
+// RUN: echo "[cfi]" > %t.cfi.txt
+// RUN: echo "type:std::*" >> %t.cfi.txt
+// RUN: %clang_cc1 -triple %itanium_abi_triple -fvisibility hidden -fms-extensions -fsanitize=cfi-vcall -fsanitize-blacklist=%t.cfi.txt -emit-llvm -o - %s | FileCheck --check-prefix=CHECK --check-prefix=NOSTD %s
+
+// Check that blacklisting non-vcall modes does not affect vcalls
+// RUN: echo "[cfi-icall|cfi-nvcall|cfi-cast-strict|cfi-derived-cast|cfi-unrelated-cast]" > %t.other.txt
+// RUN: echo "type:std::*" >> %t.other.txt
+// RUN: %clang_cc1 -triple %itanium_abi_triple -fvisibility hidden -fms-extensions -fsanitize=cfi-vcall -fsanitize-blacklist=%t.other.txt -emit-llvm -o - %s | FileCheck --check-prefix=CHECK --check-prefix=NOBL %s
 
 struct S1 {
   virtual void f();
Index: test/CodeGen/sanitizer-special-case-list.c
===
--- /dev/null
+++ test/CodeGen/sanitizer-special-case-list.c
@@ -0,0 +1,26 @@
+// Verify that blacklist sections correctly select sanitizers to apply blacklist entries to.
+//
+// RUN: %clang_cc1 -fsanitize=unsigned-integer-overflow,cfi-icall -fsanitize-blacklist=%S/Inputs/sanitizer-special-case-list.unsanitized1.txt -emit-llvm %s -o - | FileCheck %s --check-prefix=UNSANITIZED
+// RUN: %clang_cc1 -fsanitize=unsigned-integer-overflow,cfi-icall -fsanitize-blacklist=%S/Inputs/sanitizer-special-case-list.unsanitized2.txt -emit-llvm %s -o - | FileCheck %s --check-prefix=UNSANITIZED
+// RUN: %clang_cc1 -fsanitize=unsigned-integer-overflow,cfi-icall -fsanitize-blacklist=%S/Inputs/sanitizer-special-case-list.unsanitized3.txt -emit-llvm %s -o - | FileCheck %s --check-prefix=UNSANITIZED
+// RUN: %clang_cc1 -fsanitize=unsigned-integer-overflow,cfi-icall -fsanitize-blacklist=%S/Inputs/sanitizer-special-case-list.unsanitized4.txt -emit-llvm %s -o - | FileCheck %s --check-prefix=UNSANITIZED
+//
+// RUN: %clang_cc1 -fsanitize=unsigned-integer-overflow,cfi-icall -fsanitize-blacklist=%S/Inputs/sanitizer-special-case-list.sanitized.txt -emit-llvm %s -o - | FileCheck %s --check-prefix=SANITIZED
+
+unsigned i;
+
+// SANITIZED: @overflow
+// UNSANITIZED: @overflow
+unsigned overflow() {
+  // SANITIZED: call {{.*}}void @__ubsan
+  // UNSANITIZED-NOT: call {{.*}}void @__ubsan
+  return i * 37;
+}
+
+// SANITIZED: @cfi
+// UNSANITIZED: @cfi
+void cfi(void (*fp)()) {
+  // SANITIZED: llvm.type.test
+  // UNSANITIZED-NOT: llvm.type.test
+  fp();
+}
Index: test/CodeGen/Inputs/sanitizer-special-case-list.unsanitized4.txt
===
--- /dev/null
+++ test/CodeGen/Inputs/sanitizer-special-case-list.unsanitized4.txt
@@ -0,0 +1,4 @@
+[c*]
+fun:*cfi*
+[u*]
+fun:*overflow*
Index: test/CodeGen/Inputs/sanitizer-special-case-list.unsanitized3.txt
===

[PATCH] D37925: Allow specifying sanitizers in blacklists

2017-09-15 Thread Vlad Tsyrklevich via Phabricator via cfe-commits
vlad.tsyrklevich updated this revision to Diff 115528.
vlad.tsyrklevich added a comment.

Address @eugenis' comments


https://reviews.llvm.org/D37925

Files:
  include/clang/Basic/SanitizerBlacklist.h
  include/clang/Basic/SanitizerSpecialCaseList.h
  lib/AST/Decl.cpp
  lib/Basic/CMakeLists.txt
  lib/Basic/SanitizerBlacklist.cpp
  lib/Basic/SanitizerSpecialCaseList.cpp
  lib/Basic/XRayLists.cpp
  lib/CodeGen/CGClass.cpp
  lib/CodeGen/CGDeclCXX.cpp
  lib/CodeGen/CGExpr.cpp
  lib/CodeGen/CodeGenFunction.cpp
  lib/CodeGen/CodeGenModule.cpp
  lib/CodeGen/CodeGenModule.h
  test/CodeGen/Inputs/sanitizer-special-case-list.sanitized.txt
  test/CodeGen/Inputs/sanitizer-special-case-list.unsanitized1.txt
  test/CodeGen/Inputs/sanitizer-special-case-list.unsanitized2.txt
  test/CodeGen/Inputs/sanitizer-special-case-list.unsanitized3.txt
  test/CodeGen/Inputs/sanitizer-special-case-list.unsanitized4.txt
  test/CodeGen/sanitizer-special-case-list.c
  test/CodeGenCXX/cfi-blacklist.cpp

Index: test/CodeGenCXX/cfi-blacklist.cpp
===
--- test/CodeGenCXX/cfi-blacklist.cpp
+++ test/CodeGenCXX/cfi-blacklist.cpp
@@ -1,6 +1,18 @@
 // RUN: %clang_cc1 -triple %itanium_abi_triple -fvisibility hidden -fms-extensions -fsanitize=cfi-vcall -emit-llvm -o - %s | FileCheck --check-prefix=CHECK --check-prefix=NOBL %s
-// RUN: echo "type:std::*" > %t.txt
-// RUN: %clang_cc1 -triple %itanium_abi_triple -fvisibility hidden -fms-extensions -fsanitize=cfi-vcall -fsanitize-blacklist=%t.txt -emit-llvm -o - %s | FileCheck --check-prefix=CHECK --check-prefix=NOSTD %s
+
+// Check that blacklisting cfi and cfi-vcall work correctly
+// RUN: echo "[cfi-vcall]" > %t.vcall.txt
+// RUN: echo "type:std::*" >> %t.vcall.txt
+// RUN: %clang_cc1 -triple %itanium_abi_triple -fvisibility hidden -fms-extensions -fsanitize=cfi-vcall -fsanitize-blacklist=%t.vcall.txt -emit-llvm -o - %s | FileCheck --check-prefix=CHECK --check-prefix=NOSTD %s
+//
+// RUN: echo "[cfi]" > %t.cfi.txt
+// RUN: echo "type:std::*" >> %t.cfi.txt
+// RUN: %clang_cc1 -triple %itanium_abi_triple -fvisibility hidden -fms-extensions -fsanitize=cfi-vcall -fsanitize-blacklist=%t.cfi.txt -emit-llvm -o - %s | FileCheck --check-prefix=CHECK --check-prefix=NOSTD %s
+
+// Check that blacklisting non-vcall modes does not affect vcalls
+// RUN: echo "[cfi-icall|cfi-nvcall|cfi-cast-strict|cfi-derived-cast|cfi-unrelated-cast]" > %t.other.txt
+// RUN: echo "type:std::*" >> %t.other.txt
+// RUN: %clang_cc1 -triple %itanium_abi_triple -fvisibility hidden -fms-extensions -fsanitize=cfi-vcall -fsanitize-blacklist=%t.other.txt -emit-llvm -o - %s | FileCheck --check-prefix=CHECK --check-prefix=NOBL %s
 
 struct S1 {
   virtual void f();
Index: test/CodeGen/sanitizer-special-case-list.c
===
--- /dev/null
+++ test/CodeGen/sanitizer-special-case-list.c
@@ -0,0 +1,26 @@
+// Verify that blacklist sections correctly select sanitizers to apply blacklist entries to.
+//
+// RUN: %clang_cc1 -fsanitize=unsigned-integer-overflow,cfi-icall -fsanitize-blacklist=%S/Inputs/sanitizer-special-case-list.unsanitized1.txt -emit-llvm %s -o - | FileCheck %s --check-prefix=UNSANITIZED
+// RUN: %clang_cc1 -fsanitize=unsigned-integer-overflow,cfi-icall -fsanitize-blacklist=%S/Inputs/sanitizer-special-case-list.unsanitized2.txt -emit-llvm %s -o - | FileCheck %s --check-prefix=UNSANITIZED
+// RUN: %clang_cc1 -fsanitize=unsigned-integer-overflow,cfi-icall -fsanitize-blacklist=%S/Inputs/sanitizer-special-case-list.unsanitized3.txt -emit-llvm %s -o - | FileCheck %s --check-prefix=UNSANITIZED
+// RUN: %clang_cc1 -fsanitize=unsigned-integer-overflow,cfi-icall -fsanitize-blacklist=%S/Inputs/sanitizer-special-case-list.unsanitized4.txt -emit-llvm %s -o - | FileCheck %s --check-prefix=UNSANITIZED
+//
+// RUN: %clang_cc1 -fsanitize=unsigned-integer-overflow,cfi-icall -fsanitize-blacklist=%S/Inputs/sanitizer-special-case-list.sanitized.txt -emit-llvm %s -o - | FileCheck %s --check-prefix=SANITIZED
+
+unsigned i;
+
+// SANITIZED: @overflow
+// UNSANITIZED: @overflow
+unsigned overflow() {
+  // SANITIZED: call {{.*}}void @__ubsan
+  // UNSANITIZED-NOT: call {{.*}}void @__ubsan
+  return i * 37;
+}
+
+// SANITIZED: @cfi
+// UNSANITIZED: @cfi
+void cfi(void (*fp)()) {
+  // SANITIZED: llvm.type.test
+  // UNSANITIZED-NOT: llvm.type.test
+  fp();
+}
Index: test/CodeGen/Inputs/sanitizer-special-case-list.unsanitized4.txt
===
--- /dev/null
+++ test/CodeGen/Inputs/sanitizer-special-case-list.unsanitized4.txt
@@ -0,0 +1,4 @@
+[c*]
+fun:*cfi*
+[u*]
+fun:*overflow*
Index: test/CodeGen/Inputs/sanitizer-special-case-list.unsanitized3.txt
===
--- /dev/null
+++ test/CodeGen/Inputs/sanitizer-special-case-list.unsanitized3.txt
@@ -0,0 +1,4 @@
+[cfi-icall]
+fun:*cfi*
+[unsigned-integer-overflow]
+fun:*overflow*

[PATCH] D37925: Allow specifying sanitizers in blacklists

2017-09-15 Thread Vlad Tsyrklevich via Phabricator via cfe-commits
vlad.tsyrklevich added inline comments.



Comment at: include/clang/Basic/SanitizerSpecialCaseList.h:33
+
+  bool inSection(SanitizerMask Mask, StringRef Prefix, StringRef Query,
+ StringRef Category = StringRef()) const;

eugenis wrote:
> Please add  a comment on the meaning of Mask. I assume it's any-of?
Correct, I'll add a comment regarding this.



Comment at: lib/CodeGen/CGDeclCXX.cpp:322
+  if (getLangOpts().Sanitize.hasOneOf(ASanMask))
+if (!isInSanitizerBlacklist(ASanMask, Fn, Loc))
   Fn->addFnAttr(llvm::Attribute::SanitizeAddress);

This use of ASanMask could also confound address & kernel-address as @eugenis 
pointed out.



Comment at: lib/CodeGen/CodeGenModule.cpp:1569
   const auto  = getContext().getSanitizerBlacklist();
-  if (SanitizerBL.isBlacklistedGlobal(GV->getName(), Category))
+  if (SanitizerBL.isBlacklistedGlobal(ASanMask, GV->getName(), Category))
 return true;

eugenis wrote:
> would this blacklist [address] when compiling for kernel-address, and vice 
> versa?
Yes, it would. We should pass the actual sanitizer option mask ANDed with the 
ASanMask here. Thanks!


https://reviews.llvm.org/D37925



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D37925: Allow specifying sanitizers in blacklists

2017-09-15 Thread Vlad Tsyrklevich via Phabricator via cfe-commits
vlad.tsyrklevich updated this revision to Diff 115509.
vlad.tsyrklevich added a comment.

Run clang-format.


https://reviews.llvm.org/D37925

Files:
  include/clang/Basic/SanitizerBlacklist.h
  include/clang/Basic/SanitizerSpecialCaseList.h
  lib/AST/Decl.cpp
  lib/Basic/CMakeLists.txt
  lib/Basic/SanitizerBlacklist.cpp
  lib/Basic/SanitizerSpecialCaseList.cpp
  lib/Basic/XRayLists.cpp
  lib/CodeGen/CGClass.cpp
  lib/CodeGen/CGDeclCXX.cpp
  lib/CodeGen/CGExpr.cpp
  lib/CodeGen/CodeGenFunction.cpp
  lib/CodeGen/CodeGenModule.cpp
  lib/CodeGen/CodeGenModule.h
  test/CodeGen/sanitizer-special-case-list.c
  test/CodeGenCXX/cfi-blacklist.cpp

Index: test/CodeGenCXX/cfi-blacklist.cpp
===
--- test/CodeGenCXX/cfi-blacklist.cpp
+++ test/CodeGenCXX/cfi-blacklist.cpp
@@ -1,6 +1,18 @@
 // RUN: %clang_cc1 -triple %itanium_abi_triple -fvisibility hidden -fms-extensions -fsanitize=cfi-vcall -emit-llvm -o - %s | FileCheck --check-prefix=CHECK --check-prefix=NOBL %s
-// RUN: echo "type:std::*" > %t.txt
-// RUN: %clang_cc1 -triple %itanium_abi_triple -fvisibility hidden -fms-extensions -fsanitize=cfi-vcall -fsanitize-blacklist=%t.txt -emit-llvm -o - %s | FileCheck --check-prefix=CHECK --check-prefix=NOSTD %s
+
+// Check that blacklisting cfi and cfi-vcall work correctly
+// RUN: echo "[cfi-vcall]" > %t.vcall.txt
+// RUN: echo "type:std::*" >> %t.vcall.txt
+// RUN: %clang_cc1 -triple %itanium_abi_triple -fvisibility hidden -fms-extensions -fsanitize=cfi-vcall -fsanitize-blacklist=%t.vcall.txt -emit-llvm -o - %s | FileCheck --check-prefix=CHECK --check-prefix=NOSTD %s
+//
+// RUN: echo "[cfi]" > %t.cfi.txt
+// RUN: echo "type:std::*" >> %t.cfi.txt
+// RUN: %clang_cc1 -triple %itanium_abi_triple -fvisibility hidden -fms-extensions -fsanitize=cfi-vcall -fsanitize-blacklist=%t.cfi.txt -emit-llvm -o - %s | FileCheck --check-prefix=CHECK --check-prefix=NOSTD %s
+
+// Check that blacklisting non-vcall modes does not affect vcalls
+// RUN: echo "[cfi-icall|cfi-nvcall|cfi-cast-strict|cfi-derived-cast|cfi-unrelated-cast]" > %t.other.txt
+// RUN: echo "type:std::*" >> %t.other.txt
+// RUN: %clang_cc1 -triple %itanium_abi_triple -fvisibility hidden -fms-extensions -fsanitize=cfi-vcall -fsanitize-blacklist=%t.other.txt -emit-llvm -o - %s | FileCheck --check-prefix=CHECK --check-prefix=NOBL %s
 
 struct S1 {
   virtual void f();
Index: test/CodeGen/sanitizer-special-case-list.c
===
--- /dev/null
+++ test/CodeGen/sanitizer-special-case-list.c
@@ -0,0 +1,47 @@
+// Verify that blacklist sections correctly select sanitizers to apply blacklist entries to.
+//
+// RUN: echo "fun:*cfi*" > %t.unsanitized1
+// RUN: echo "fun:*overflow*" >> %t.unsanitized1
+// RUN: %clang_cc1 -fsanitize=unsigned-integer-overflow,cfi-icall -fsanitize-blacklist=%t.unsanitized1 -emit-llvm %s -o - | FileCheck %s --check-prefix=UNSANITIZED
+//
+// RUN: echo "[cfi]" > %t.unsanitized2
+// RUN: echo "fun:*cfi*" >> %t.unsanitized2
+// RUN: echo "[unsigned-integer-overflow]" >> %t.unsanitized2
+// RUN: echo "fun:*overflow*" >> %t.unsanitized2
+// RUN: %clang_cc1 -fsanitize=unsigned-integer-overflow,cfi-icall -fsanitize-blacklist=%t.unsanitized2 -emit-llvm %s -o - | FileCheck %s --check-prefix=UNSANITIZED
+//
+// RUN: echo "[cfi-icall]" > %t.unsanitized3
+// RUN: echo "fun:*cfi*" >> %t.unsanitized3
+// RUN: echo "[unsigned-integer-overflow]" >> %t.unsanitized3
+// RUN: echo "fun:*overflow*" >> %t.unsanitized3
+// RUN: %clang_cc1 -fsanitize=unsigned-integer-overflow,cfi-icall -fsanitize-blacklist=%t.unsanitized3 -emit-llvm %s -o - | FileCheck %s --check-prefix=UNSANITIZED
+//
+// RUN: echo "[c*]" > %t.unsanitized4
+// RUN: echo "fun:*cfi*" >> %t.unsanitized4
+// RUN: echo "[u*]" >> %t.unsanitized4
+// RUN: echo "fun:*overflow*" >> %t.unsanitized4
+// RUN: %clang_cc1 -fsanitize=unsigned-integer-overflow,cfi-icall -fsanitize-blacklist=%t.unsanitized4 -emit-llvm %s -o - | FileCheck %s --check-prefix=UNSANITIZED
+//
+// RUN: echo "[unsigned-integer-overflow]" > %t.sanitized
+// RUN: echo "fun:*cfi*" >> %t.sanitized
+// RUN: echo "[cfi]" >> %t.sanitized
+// RUN: echo "fun:*overflow*" >> %t.sanitized
+// RUN: %clang_cc1 -fsanitize=unsigned-integer-overflow,cfi-icall -fsanitize-blacklist=%t.sanitized -emit-llvm %s -o - | FileCheck %s --check-prefix=SANITIZED
+
+unsigned i;
+
+// SANITIZED: @overflow
+// UNSANITIZED: @overflow
+unsigned overflow() {
+  // SANITIZED: call {{.*}}void @__ubsan
+  // UNSANITIZED-NOT: call {{.*}}void @__ubsan
+  return i * 37;
+}
+
+// SANITIZED: @cfi
+// UNSANITIZED: @cfi
+void cfi(void (*fp)()) {
+  // SANITIZED: llvm.type.test
+  // UNSANITIZED-NOT: llvm.type.test
+  fp();
+}
Index: lib/CodeGen/CodeGenModule.h
===
--- lib/CodeGen/CodeGenModule.h
+++ lib/CodeGen/CodeGenModule.h
@@ -1106,7 +1106,8 @@
   /// annotations are emitted during finalization of the LLVM 

[PATCH] D37925: Allow specifying sanitizers in blacklists

2017-09-15 Thread Vlad Tsyrklevich via Phabricator via cfe-commits
vlad.tsyrklevich added a comment.

Not included in this change:

- Updating the sanitizer documentation to use section headers. It's worth doing 
for the CFI documentation to let people know they can break down blacklist 
entries by CFI mode, but is it worth pushing users to specify '[address]', 
'[memory]', etc. sections for the other sanitizers as well?
- Merging the various sanitizer blacklists into a single blacklist. I'd like to 
pursue this in a later change where I also plan to break down the cfi blacklist 
by the specific CFI mode they should be blacklisted by.


https://reviews.llvm.org/D37925



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D37925: Allow specifying sanitizers in blacklists

2017-09-15 Thread Vlad Tsyrklevich via Phabricator via cfe-commits
vlad.tsyrklevich created this revision.
Herald added a subscriber: mgorny.

This is the follow-up patch to https://reviews.llvm.org/D37924.

This change refactors clang to use the the newly added section headers
in SpecialCaseList to specify which sanitizers blacklists entries
should apply to, like so:

  [cfi-vcall]
  fun:*bad_vcall*
  [cfi-derived-cast|cfi-unrelated-cast]
  fun:*bad_cast*

The SanitizerSpecialCaseList class has been added to allow querying by
SanitizerMask, and SanitizerBlacklist and its downstream users have been
updated to provide that information. Old blacklists not using sections
will continue to function identically since the blacklist entries will
be placed into a '[*]' section by default matching against all
sanitizers.


https://reviews.llvm.org/D37925

Files:
  include/clang/Basic/SanitizerBlacklist.h
  include/clang/Basic/SanitizerSpecialCaseList.h
  lib/AST/Decl.cpp
  lib/Basic/CMakeLists.txt
  lib/Basic/SanitizerBlacklist.cpp
  lib/Basic/SanitizerSpecialCaseList.cpp
  lib/Basic/XRayLists.cpp
  lib/CodeGen/CGClass.cpp
  lib/CodeGen/CGDeclCXX.cpp
  lib/CodeGen/CGExpr.cpp
  lib/CodeGen/CodeGenFunction.cpp
  lib/CodeGen/CodeGenModule.cpp
  lib/CodeGen/CodeGenModule.h
  test/CodeGen/sanitizer-special-case-list.c
  test/CodeGenCXX/cfi-blacklist.cpp

Index: test/CodeGenCXX/cfi-blacklist.cpp
===
--- test/CodeGenCXX/cfi-blacklist.cpp
+++ test/CodeGenCXX/cfi-blacklist.cpp
@@ -1,6 +1,18 @@
 // RUN: %clang_cc1 -triple %itanium_abi_triple -fvisibility hidden -fms-extensions -fsanitize=cfi-vcall -emit-llvm -o - %s | FileCheck --check-prefix=CHECK --check-prefix=NOBL %s
-// RUN: echo "type:std::*" > %t.txt
-// RUN: %clang_cc1 -triple %itanium_abi_triple -fvisibility hidden -fms-extensions -fsanitize=cfi-vcall -fsanitize-blacklist=%t.txt -emit-llvm -o - %s | FileCheck --check-prefix=CHECK --check-prefix=NOSTD %s
+
+// Check that blacklisting cfi and cfi-vcall work correctly
+// RUN: echo "[cfi-vcall]" > %t.vcall.txt
+// RUN: echo "type:std::*" >> %t.vcall.txt
+// RUN: %clang_cc1 -triple %itanium_abi_triple -fvisibility hidden -fms-extensions -fsanitize=cfi-vcall -fsanitize-blacklist=%t.vcall.txt -emit-llvm -o - %s | FileCheck --check-prefix=CHECK --check-prefix=NOSTD %s
+//
+// RUN: echo "[cfi]" > %t.cfi.txt
+// RUN: echo "type:std::*" >> %t.cfi.txt
+// RUN: %clang_cc1 -triple %itanium_abi_triple -fvisibility hidden -fms-extensions -fsanitize=cfi-vcall -fsanitize-blacklist=%t.cfi.txt -emit-llvm -o - %s | FileCheck --check-prefix=CHECK --check-prefix=NOSTD %s
+
+// Check that blacklisting non-vcall modes does not affect vcalls
+// RUN: echo "[cfi-icall|cfi-nvcall|cfi-cast-strict|cfi-derived-cast|cfi-unrelated-cast]" > %t.other.txt
+// RUN: echo "type:std::*" >> %t.other.txt
+// RUN: %clang_cc1 -triple %itanium_abi_triple -fvisibility hidden -fms-extensions -fsanitize=cfi-vcall -fsanitize-blacklist=%t.other.txt -emit-llvm -o - %s | FileCheck --check-prefix=CHECK --check-prefix=NOBL %s
 
 struct S1 {
   virtual void f();
Index: test/CodeGen/sanitizer-special-case-list.c
===
--- /dev/null
+++ test/CodeGen/sanitizer-special-case-list.c
@@ -0,0 +1,47 @@
+// Verify that blacklist sections correctly select sanitizers to apply blacklist entries to.
+//
+// RUN: echo "fun:*cfi*" > %t.unsanitized1
+// RUN: echo "fun:*overflow*" >> %t.unsanitized1
+// RUN: %clang_cc1 -fsanitize=unsigned-integer-overflow,cfi-icall -fsanitize-blacklist=%t.unsanitized1 -emit-llvm %s -o - | FileCheck %s --check-prefix=UNSANITIZED
+//
+// RUN: echo "[cfi]" > %t.unsanitized2
+// RUN: echo "fun:*cfi*" >> %t.unsanitized2
+// RUN: echo "[unsigned-integer-overflow]" >> %t.unsanitized2
+// RUN: echo "fun:*overflow*" >> %t.unsanitized2
+// RUN: %clang_cc1 -fsanitize=unsigned-integer-overflow,cfi-icall -fsanitize-blacklist=%t.unsanitized2 -emit-llvm %s -o - | FileCheck %s --check-prefix=UNSANITIZED
+//
+// RUN: echo "[cfi-icall]" > %t.unsanitized3
+// RUN: echo "fun:*cfi*" >> %t.unsanitized3
+// RUN: echo "[unsigned-integer-overflow]" >> %t.unsanitized3
+// RUN: echo "fun:*overflow*" >> %t.unsanitized3
+// RUN: %clang_cc1 -fsanitize=unsigned-integer-overflow,cfi-icall -fsanitize-blacklist=%t.unsanitized3 -emit-llvm %s -o - | FileCheck %s --check-prefix=UNSANITIZED
+//
+// RUN: echo "[c*]" > %t.unsanitized4
+// RUN: echo "fun:*cfi*" >> %t.unsanitized4
+// RUN: echo "[u*]" >> %t.unsanitized4
+// RUN: echo "fun:*overflow*" >> %t.unsanitized4
+// RUN: %clang_cc1 -fsanitize=unsigned-integer-overflow,cfi-icall -fsanitize-blacklist=%t.unsanitized4 -emit-llvm %s -o - | FileCheck %s --check-prefix=UNSANITIZED
+//
+// RUN: echo "[unsigned-integer-overflow]" > %t.sanitized
+// RUN: echo "fun:*cfi*" >> %t.sanitized
+// RUN: echo "[cfi]" >> %t.sanitized
+// RUN: echo "fun:*overflow*" >> %t.sanitized
+// RUN: %clang_cc1 -fsanitize=unsigned-integer-overflow,cfi-icall -fsanitize-blacklist=%t.sanitized -emit-llvm %s -o - | 

[PATCH] D32842: Specify which sanitizers are covered by a sanitizer blacklist

2017-09-12 Thread Vlad Tsyrklevich via Phabricator via cfe-commits
vlad.tsyrklevich added a comment.

@vsk Why don't I take a look at implementing the blacklist selection methods 
@eugenis mentioned on top of this change now so that we can skip ahead and 
merge something everyone is satisfied with?


https://reviews.llvm.org/D32842



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D36294: CFI: blacklist STL allocate() from unrelated-casts

2017-08-04 Thread Vlad Tsyrklevich via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rL310097: CFI: blacklist STL allocate() from unrelated-casts 
(authored by vlad.tsyrklevich).

Repository:
  rL LLVM

https://reviews.llvm.org/D36294

Files:
  cfe/trunk/lib/CodeGen/CodeGenFunction.cpp
  cfe/trunk/test/CodeGen/cfi-unrelated-cast.cpp


Index: cfe/trunk/lib/CodeGen/CodeGenFunction.cpp
===
--- cfe/trunk/lib/CodeGen/CodeGenFunction.cpp
+++ cfe/trunk/lib/CodeGen/CodeGenFunction.cpp
@@ -723,6 +723,25 @@
   Fn->removeFnAttr(llvm::Attribute::SanitizeThread);
 }
 
+static bool matchesStlAllocatorFn(const Decl *D, const ASTContext ) {
+  auto *MD = dyn_cast_or_null(D);
+  if (!MD || !MD->getName().equals("allocate") ||
+  (MD->getNumParams() != 1 && MD->getNumParams() != 2))
+return false;
+
+  if (MD->parameters()[0]->getType().getCanonicalType() != Ctx.getSizeType())
+return false;
+
+  if (MD->getNumParams() == 2) {
+auto *PT = MD->parameters()[1]->getType()->getAs();
+if (!PT || !PT->isVoidPointerType() ||
+!PT->getPointeeType().isConstQualified())
+  return false;
+  }
+
+  return true;
+}
+
 void CodeGenFunction::StartFunction(GlobalDecl GD,
 QualType RetTy,
 llvm::Function *Fn,
@@ -782,6 +801,14 @@
 }
   }
 
+  // Ignore unrelated casts in STL allocate() since the allocator must cast
+  // from void* to T* before object initialization completes. Don't match on 
the
+  // namespace because not all allocators are in std::
+  if (D && SanOpts.has(SanitizerKind::CFIUnrelatedCast)) {
+if (matchesStlAllocatorFn(D, getContext()))
+  SanOpts.Mask &= ~SanitizerKind::CFIUnrelatedCast;
+  }
+
   // Apply xray attributes to the function (as a string, for now)
   if (D && ShouldXRayInstrumentFunction()) {
 if (const auto *XRayAttr = D->getAttr()) {
Index: cfe/trunk/test/CodeGen/cfi-unrelated-cast.cpp
===
--- cfe/trunk/test/CodeGen/cfi-unrelated-cast.cpp
+++ cfe/trunk/test/CodeGen/cfi-unrelated-cast.cpp
@@ -0,0 +1,37 @@
+// STL allocators should not have unrelated-cast tests applied
+// RUN: %clang_cc1 -flto -fvisibility hidden -fsanitize=cfi-unrelated-cast 
-emit-llvm -o - %s | FileCheck %s
+
+#include 
+
+template
+class myalloc {
+ public:
+  // CHECK: define{{.*}}allocateE{{.}}
+  // CHECK-NOT: llvm.type.test
+  T *allocate(size_t sz) {
+return (T*)::operator new(sz);
+  }
+
+  // CHECK: define{{.*}}allocateE{{.}}PKv
+  // CHECK-NOT: llvm.type.test
+  T *allocate(size_t sz, const void *ptr) {
+return (T*)::operator new(sz);
+  }
+
+  // CHECK: define{{.*}}differentName
+  // CHECK: llvm.type.test
+  T *differentName(size_t sz, const void *ptr) {
+return (T*)::operator new(sz);
+  }
+};
+
+class C1 {
+  virtual void f() {}
+};
+
+C1 *f1() {
+  myalloc allocator;
+  (void)allocator.allocate(16);
+  (void)allocator.allocate(16, 0);
+  (void)allocator.differentName(16, 0);
+}


Index: cfe/trunk/lib/CodeGen/CodeGenFunction.cpp
===
--- cfe/trunk/lib/CodeGen/CodeGenFunction.cpp
+++ cfe/trunk/lib/CodeGen/CodeGenFunction.cpp
@@ -723,6 +723,25 @@
   Fn->removeFnAttr(llvm::Attribute::SanitizeThread);
 }
 
+static bool matchesStlAllocatorFn(const Decl *D, const ASTContext ) {
+  auto *MD = dyn_cast_or_null(D);
+  if (!MD || !MD->getName().equals("allocate") ||
+  (MD->getNumParams() != 1 && MD->getNumParams() != 2))
+return false;
+
+  if (MD->parameters()[0]->getType().getCanonicalType() != Ctx.getSizeType())
+return false;
+
+  if (MD->getNumParams() == 2) {
+auto *PT = MD->parameters()[1]->getType()->getAs();
+if (!PT || !PT->isVoidPointerType() ||
+!PT->getPointeeType().isConstQualified())
+  return false;
+  }
+
+  return true;
+}
+
 void CodeGenFunction::StartFunction(GlobalDecl GD,
 QualType RetTy,
 llvm::Function *Fn,
@@ -782,6 +801,14 @@
 }
   }
 
+  // Ignore unrelated casts in STL allocate() since the allocator must cast
+  // from void* to T* before object initialization completes. Don't match on the
+  // namespace because not all allocators are in std::
+  if (D && SanOpts.has(SanitizerKind::CFIUnrelatedCast)) {
+if (matchesStlAllocatorFn(D, getContext()))
+  SanOpts.Mask &= ~SanitizerKind::CFIUnrelatedCast;
+  }
+
   // Apply xray attributes to the function (as a string, for now)
   if (D && ShouldXRayInstrumentFunction()) {
 if (const auto *XRayAttr = D->getAttr()) {
Index: cfe/trunk/test/CodeGen/cfi-unrelated-cast.cpp
===
--- cfe/trunk/test/CodeGen/cfi-unrelated-cast.cpp
+++ cfe/trunk/test/CodeGen/cfi-unrelated-cast.cpp
@@ -0,0 +1,37 @@
+// STL allocators should not have unrelated-cast tests applied
+// RUN: 

[PATCH] D36294: CFI: blacklist STL allocate() from unrelated-casts

2017-08-03 Thread Vlad Tsyrklevich via Phabricator via cfe-commits
vlad.tsyrklevich marked an inline comment as done.
vlad.tsyrklevich added inline comments.



Comment at: lib/CodeGen/CodeGenFunction.cpp:789
+auto *MD = dyn_cast_or_null(D);
+if (MD && MD->getName().equals("allocate") && MD->getNumParams() == 2) {
+  auto *BT = MD->parameters()[0]->getType()->getAs();

pcc wrote:
> Should this also match the C++17 allocate function which takes a single 
> argument?
absolutely, thanks for catching this!


https://reviews.llvm.org/D36294



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D36294: CFI: blacklist STL allocate() from unrelated-casts

2017-08-03 Thread Vlad Tsyrklevich via Phabricator via cfe-commits
vlad.tsyrklevich updated this revision to Diff 109668.
vlad.tsyrklevich marked 2 inline comments as done.
vlad.tsyrklevich added a comment.

Address pcc's comments


https://reviews.llvm.org/D36294

Files:
  lib/CodeGen/CodeGenFunction.cpp
  test/CodeGen/cfi-unrelated-cast.cpp


Index: test/CodeGen/cfi-unrelated-cast.cpp
===
--- /dev/null
+++ test/CodeGen/cfi-unrelated-cast.cpp
@@ -0,0 +1,37 @@
+// STL allocators should not have unrelated-cast tests applied
+// RUN: %clang_cc1 -flto -fvisibility hidden -fsanitize=cfi-unrelated-cast 
-emit-llvm -o - %s | FileCheck %s
+
+#include 
+
+template
+class myalloc {
+ public:
+  // CHECK: define{{.*}}allocateE{{.}}
+  // CHECK-NOT: llvm.type.test
+  T *allocate(size_t sz) {
+return (T*)::operator new(sz);
+  }
+
+  // CHECK: define{{.*}}allocateE{{.}}PKv
+  // CHECK-NOT: llvm.type.test
+  T *allocate(size_t sz, const void *ptr) {
+return (T*)::operator new(sz);
+  }
+
+  // CHECK: define{{.*}}differentName
+  // CHECK: llvm.type.test
+  T *differentName(size_t sz, const void *ptr) {
+return (T*)::operator new(sz);
+  }
+};
+
+class C1 {
+  virtual void f() {}
+};
+
+C1 *f1() {
+  myalloc allocator;
+  (void)allocator.allocate(16);
+  (void)allocator.allocate(16, 0);
+  (void)allocator.differentName(16, 0);
+}
Index: lib/CodeGen/CodeGenFunction.cpp
===
--- lib/CodeGen/CodeGenFunction.cpp
+++ lib/CodeGen/CodeGenFunction.cpp
@@ -723,6 +723,25 @@
   Fn->removeFnAttr(llvm::Attribute::SanitizeThread);
 }
 
+static bool matchesStlAllocatorFn(const Decl *D, const ASTContext ) {
+  auto *MD = dyn_cast_or_null(D);
+  if (!MD || !MD->getName().equals("allocate") ||
+  (MD->getNumParams() != 1 && MD->getNumParams() != 2))
+return false;
+
+  if (MD->parameters()[0]->getType().getCanonicalType() != Ctx.getSizeType())
+return false;
+
+  if (MD->getNumParams() == 2) {
+auto *PT = MD->parameters()[1]->getType()->getAs();
+if (!PT || !PT->isVoidPointerType() ||
+!PT->getPointeeType().isConstQualified())
+  return false;
+  }
+
+  return true;
+}
+
 void CodeGenFunction::StartFunction(GlobalDecl GD,
 QualType RetTy,
 llvm::Function *Fn,
@@ -782,6 +801,14 @@
 }
   }
 
+  // Ignore unrelated casts in STL allocate() since the allocator must cast
+  // from void* to T* before object initialization completes. Don't match on 
the
+  // namespace because not all allocators are in std::
+  if (D && SanOpts.has(SanitizerKind::CFIUnrelatedCast)) {
+if (matchesStlAllocatorFn(D, getContext()))
+  SanOpts.Mask &= ~SanitizerKind::CFIUnrelatedCast;
+  }
+
   // Apply xray attributes to the function (as a string, for now)
   if (D && ShouldXRayInstrumentFunction()) {
 if (const auto *XRayAttr = D->getAttr()) {


Index: test/CodeGen/cfi-unrelated-cast.cpp
===
--- /dev/null
+++ test/CodeGen/cfi-unrelated-cast.cpp
@@ -0,0 +1,37 @@
+// STL allocators should not have unrelated-cast tests applied
+// RUN: %clang_cc1 -flto -fvisibility hidden -fsanitize=cfi-unrelated-cast -emit-llvm -o - %s | FileCheck %s
+
+#include 
+
+template
+class myalloc {
+ public:
+  // CHECK: define{{.*}}allocateE{{.}}
+  // CHECK-NOT: llvm.type.test
+  T *allocate(size_t sz) {
+return (T*)::operator new(sz);
+  }
+
+  // CHECK: define{{.*}}allocateE{{.}}PKv
+  // CHECK-NOT: llvm.type.test
+  T *allocate(size_t sz, const void *ptr) {
+return (T*)::operator new(sz);
+  }
+
+  // CHECK: define{{.*}}differentName
+  // CHECK: llvm.type.test
+  T *differentName(size_t sz, const void *ptr) {
+return (T*)::operator new(sz);
+  }
+};
+
+class C1 {
+  virtual void f() {}
+};
+
+C1 *f1() {
+  myalloc allocator;
+  (void)allocator.allocate(16);
+  (void)allocator.allocate(16, 0);
+  (void)allocator.differentName(16, 0);
+}
Index: lib/CodeGen/CodeGenFunction.cpp
===
--- lib/CodeGen/CodeGenFunction.cpp
+++ lib/CodeGen/CodeGenFunction.cpp
@@ -723,6 +723,25 @@
   Fn->removeFnAttr(llvm::Attribute::SanitizeThread);
 }
 
+static bool matchesStlAllocatorFn(const Decl *D, const ASTContext ) {
+  auto *MD = dyn_cast_or_null(D);
+  if (!MD || !MD->getName().equals("allocate") ||
+  (MD->getNumParams() != 1 && MD->getNumParams() != 2))
+return false;
+
+  if (MD->parameters()[0]->getType().getCanonicalType() != Ctx.getSizeType())
+return false;
+
+  if (MD->getNumParams() == 2) {
+auto *PT = MD->parameters()[1]->getType()->getAs();
+if (!PT || !PT->isVoidPointerType() ||
+!PT->getPointeeType().isConstQualified())
+  return false;
+  }
+
+  return true;
+}
+
 void CodeGenFunction::StartFunction(GlobalDecl GD,
 QualType RetTy,
 llvm::Function *Fn,
@@ 

[PATCH] D36013: Fix logic for generating llvm.type.test()s

2017-07-28 Thread Vlad Tsyrklevich via Phabricator via cfe-commits
vlad.tsyrklevich updated this revision to Diff 108702.
vlad.tsyrklevich marked 2 inline comments as done.

https://reviews.llvm.org/D36013

Files:
  lib/CodeGen/CGClass.cpp
  test/CodeGenCXX/cfi-vcall-no-trap.cpp


Index: test/CodeGenCXX/cfi-vcall-no-trap.cpp
===
--- /dev/null
+++ test/CodeGenCXX/cfi-vcall-no-trap.cpp
@@ -0,0 +1,15 @@
+// Only output llvm.assume(llvm.type.test()) if cfi-vcall is disabled and 
whole-program-vtables is enabled
+// RUN: %clang_cc1 -fvisibility hidden -fsanitize=cfi-vcall 
-fwhole-program-vtables -emit-llvm -o - %s | FileCheck --check-prefix=CHECK 
--check-prefix=CFI %s
+// RUN: %clang_cc1 -fvisibility hidden -fwhole-program-vtables -emit-llvm -o - 
%s | FileCheck --check-prefix=CHECK --check-prefix=NOCFI %s
+
+struct S1 {
+  virtual void f();
+};
+
+// CHECK: define{{.*}}s1f
+// CHECK: llvm.type.test
+// CFI-NOT: llvm.assume
+// NOCFI: llvm.assume
+void s1f(S1 *s1) {
+  s1->f();
+}
Index: lib/CodeGen/CGClass.cpp
===
--- lib/CodeGen/CGClass.cpp
+++ lib/CodeGen/CGClass.cpp
@@ -2523,8 +2523,10 @@
 void CodeGenFunction::EmitTypeMetadataCodeForVCall(const CXXRecordDecl *RD,
llvm::Value *VTable,
SourceLocation Loc) {
-  if (CGM.getCodeGenOpts().WholeProgramVTables &&
-  CGM.HasHiddenLTOVisibility(RD)) {
+  if (SanOpts.has(SanitizerKind::CFIVCall))
+EmitVTablePtrCheckForCall(RD, VTable, CodeGenFunction::CFITCK_VCall, Loc);
+  else if (CGM.getCodeGenOpts().WholeProgramVTables &&
+   CGM.HasHiddenLTOVisibility(RD)) {
 llvm::Metadata *MD =
 CGM.CreateMetadataIdentifierForType(QualType(RD->getTypeForDecl(), 0));
 llvm::Value *TypeId =
@@ -2536,9 +2538,6 @@
{CastedVTable, TypeId});
 Builder.CreateCall(CGM.getIntrinsic(llvm::Intrinsic::assume), TypeTest);
   }
-
-  if (SanOpts.has(SanitizerKind::CFIVCall))
-EmitVTablePtrCheckForCall(RD, VTable, CodeGenFunction::CFITCK_VCall, Loc);
 }
 
 void CodeGenFunction::EmitVTablePtrCheckForCall(const CXXRecordDecl *RD,


Index: test/CodeGenCXX/cfi-vcall-no-trap.cpp
===
--- /dev/null
+++ test/CodeGenCXX/cfi-vcall-no-trap.cpp
@@ -0,0 +1,15 @@
+// Only output llvm.assume(llvm.type.test()) if cfi-vcall is disabled and whole-program-vtables is enabled
+// RUN: %clang_cc1 -fvisibility hidden -fsanitize=cfi-vcall -fwhole-program-vtables -emit-llvm -o - %s | FileCheck --check-prefix=CHECK --check-prefix=CFI %s
+// RUN: %clang_cc1 -fvisibility hidden -fwhole-program-vtables -emit-llvm -o - %s | FileCheck --check-prefix=CHECK --check-prefix=NOCFI %s
+
+struct S1 {
+  virtual void f();
+};
+
+// CHECK: define{{.*}}s1f
+// CHECK: llvm.type.test
+// CFI-NOT: llvm.assume
+// NOCFI: llvm.assume
+void s1f(S1 *s1) {
+  s1->f();
+}
Index: lib/CodeGen/CGClass.cpp
===
--- lib/CodeGen/CGClass.cpp
+++ lib/CodeGen/CGClass.cpp
@@ -2523,8 +2523,10 @@
 void CodeGenFunction::EmitTypeMetadataCodeForVCall(const CXXRecordDecl *RD,
llvm::Value *VTable,
SourceLocation Loc) {
-  if (CGM.getCodeGenOpts().WholeProgramVTables &&
-  CGM.HasHiddenLTOVisibility(RD)) {
+  if (SanOpts.has(SanitizerKind::CFIVCall))
+EmitVTablePtrCheckForCall(RD, VTable, CodeGenFunction::CFITCK_VCall, Loc);
+  else if (CGM.getCodeGenOpts().WholeProgramVTables &&
+   CGM.HasHiddenLTOVisibility(RD)) {
 llvm::Metadata *MD =
 CGM.CreateMetadataIdentifierForType(QualType(RD->getTypeForDecl(), 0));
 llvm::Value *TypeId =
@@ -2536,9 +2538,6 @@
{CastedVTable, TypeId});
 Builder.CreateCall(CGM.getIntrinsic(llvm::Intrinsic::assume), TypeTest);
   }
-
-  if (SanOpts.has(SanitizerKind::CFIVCall))
-EmitVTablePtrCheckForCall(RD, VTable, CodeGenFunction::CFITCK_VCall, Loc);
 }
 
 void CodeGenFunction::EmitVTablePtrCheckForCall(const CXXRecordDecl *RD,
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D36013: Fix logic for generating llvm.type.test()s

2017-07-28 Thread Vlad Tsyrklevich via Phabricator via cfe-commits
vlad.tsyrklevich created this revision.

`CodeGenFunction::EmitTypeMetadataCodeForVCall()` could output an 
`llvm.assume(llvm.type.test())`when CFI was enabled, optimizing out the vcall 
check. This case was only reached when: 1) CFI-vcall was enabled, 2) 
-fwhole-program-tables was specified, and 3) -fno-sanitize-trap=cfi-vcall was 
specified.

This change is blocked on https://reviews.llvm.org/D36012 as it uncovers that 
bug.


https://reviews.llvm.org/D36013

Files:
  lib/CodeGen/CGClass.cpp
  test/CodeGenCXX/cfi-vcall-no-trap.cpp


Index: test/CodeGenCXX/cfi-vcall-no-trap.cpp
===
--- /dev/null
+++ test/CodeGenCXX/cfi-vcall-no-trap.cpp
@@ -0,0 +1,14 @@
+// Only output llvm.assume(llvm.type.test()) if cfi-vcall is disabled and 
whole-program-vtables is enabled
+// RUN: %clang_cc1 -cc1 -fvisibility hidden -fsanitize=cfi-vcall 
-fwhole-program-vtables -emit-llvm -o - %s | FileCheck --check-prefix=CHECK 
--check-prefix=CFI %s
+// RUN: %clang_cc1 -cc1 -fvisibility hidden -fwhole-program-vtables -emit-llvm 
-o - %s | FileCheck --check-prefix=CHECK --check-prefix=NOCFI %s
+
+struct S1 {
+  virtual void f();
+};
+
+// CHECK: define{{.*}}s1f
+// CFI-NOT: llvm.assume
+// NOCFI: llvm.assume
+void s1f(S1 *s1) {
+  s1->f();
+}
Index: lib/CodeGen/CGClass.cpp
===
--- lib/CodeGen/CGClass.cpp
+++ lib/CodeGen/CGClass.cpp
@@ -2523,8 +2523,10 @@
 void CodeGenFunction::EmitTypeMetadataCodeForVCall(const CXXRecordDecl *RD,
llvm::Value *VTable,
SourceLocation Loc) {
-  if (CGM.getCodeGenOpts().WholeProgramVTables &&
-  CGM.HasHiddenLTOVisibility(RD)) {
+  if (SanOpts.has(SanitizerKind::CFIVCall))
+EmitVTablePtrCheckForCall(RD, VTable, CodeGenFunction::CFITCK_VCall, Loc);
+  else if (CGM.getCodeGenOpts().WholeProgramVTables &&
+   CGM.HasHiddenLTOVisibility(RD)) {
 llvm::Metadata *MD =
 CGM.CreateMetadataIdentifierForType(QualType(RD->getTypeForDecl(), 0));
 llvm::Value *TypeId =
@@ -2536,9 +2538,6 @@
{CastedVTable, TypeId});
 Builder.CreateCall(CGM.getIntrinsic(llvm::Intrinsic::assume), TypeTest);
   }
-
-  if (SanOpts.has(SanitizerKind::CFIVCall))
-EmitVTablePtrCheckForCall(RD, VTable, CodeGenFunction::CFITCK_VCall, Loc);
 }
 
 void CodeGenFunction::EmitVTablePtrCheckForCall(const CXXRecordDecl *RD,


Index: test/CodeGenCXX/cfi-vcall-no-trap.cpp
===
--- /dev/null
+++ test/CodeGenCXX/cfi-vcall-no-trap.cpp
@@ -0,0 +1,14 @@
+// Only output llvm.assume(llvm.type.test()) if cfi-vcall is disabled and whole-program-vtables is enabled
+// RUN: %clang_cc1 -cc1 -fvisibility hidden -fsanitize=cfi-vcall -fwhole-program-vtables -emit-llvm -o - %s | FileCheck --check-prefix=CHECK --check-prefix=CFI %s
+// RUN: %clang_cc1 -cc1 -fvisibility hidden -fwhole-program-vtables -emit-llvm -o - %s | FileCheck --check-prefix=CHECK --check-prefix=NOCFI %s
+
+struct S1 {
+  virtual void f();
+};
+
+// CHECK: define{{.*}}s1f
+// CFI-NOT: llvm.assume
+// NOCFI: llvm.assume
+void s1f(S1 *s1) {
+  s1->f();
+}
Index: lib/CodeGen/CGClass.cpp
===
--- lib/CodeGen/CGClass.cpp
+++ lib/CodeGen/CGClass.cpp
@@ -2523,8 +2523,10 @@
 void CodeGenFunction::EmitTypeMetadataCodeForVCall(const CXXRecordDecl *RD,
llvm::Value *VTable,
SourceLocation Loc) {
-  if (CGM.getCodeGenOpts().WholeProgramVTables &&
-  CGM.HasHiddenLTOVisibility(RD)) {
+  if (SanOpts.has(SanitizerKind::CFIVCall))
+EmitVTablePtrCheckForCall(RD, VTable, CodeGenFunction::CFITCK_VCall, Loc);
+  else if (CGM.getCodeGenOpts().WholeProgramVTables &&
+   CGM.HasHiddenLTOVisibility(RD)) {
 llvm::Metadata *MD =
 CGM.CreateMetadataIdentifierForType(QualType(RD->getTypeForDecl(), 0));
 llvm::Value *TypeId =
@@ -2536,9 +2538,6 @@
{CastedVTable, TypeId});
 Builder.CreateCall(CGM.getIntrinsic(llvm::Intrinsic::assume), TypeTest);
   }
-
-  if (SanOpts.has(SanitizerKind::CFIVCall))
-EmitVTablePtrCheckForCall(RD, VTable, CodeGenFunction::CFITCK_VCall, Loc);
 }
 
 void CodeGenFunction::EmitVTablePtrCheckForCall(const CXXRecordDecl *RD,
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D30406: [Analyzer] Add support for displaying cross-file diagnostic paths in HTML output

2017-06-16 Thread Vlad Tsyrklevich via Phabricator via cfe-commits
vlad.tsyrklevich added a comment.

Please commit on my behalf.


https://reviews.llvm.org/D30406



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D30406: [Analyzer] Add support for displaying cross-file diagnostic paths in HTML output

2017-06-16 Thread Vlad Tsyrklevich via Phabricator via cfe-commits
vlad.tsyrklevich updated this revision to Diff 102838.
vlad.tsyrklevich marked an inline comment as done.
vlad.tsyrklevich added a comment.

After reviewing this patch again last night I:

1. Updated some "%clang_cc1 -analyze" calls with  "%clang_analyze_cc1" due to 
2cfd901321423a96edd8513afc7c7c2bb0d18b2e
2. Isolated HTML generation into a separate function to simplify 
`HTMLDiagnostics::ReportDiag` even further


https://reviews.llvm.org/D30406

Files:
  include/clang/StaticAnalyzer/Core/Analyses.def
  lib/Rewrite/HTMLRewrite.cpp
  lib/StaticAnalyzer/Core/HTMLDiagnostics.cpp
  test/Analysis/diagnostics/diag-cross-file-boundaries.c
  test/Analysis/diagnostics/diag-cross-file-boundaries.h
  test/Analysis/html-diag-singlefile.c
  test/Analysis/html-diag-singlefile.h
  test/Analysis/html-diags-analyze-headers.c
  test/Analysis/html-diags-analyze-headers.h
  test/Analysis/html-diags-multifile.c
  test/Analysis/html-diags.c
  test/Coverage/html-diagnostics.c
  test/Coverage/html-multifile-diagnostics.c
  test/Coverage/html-multifile-diagnostics.h
  www/analyzer/open_projects.html

Index: www/analyzer/open_projects.html
===
--- www/analyzer/open_projects.html
+++ www/analyzer/open_projects.html
@@ -107,13 +107,6 @@
 
   Bug Reporting 
   
-Add support for displaying cross-file diagnostic paths in HTML output
-(used by scan-build).
-Currently scan-build output does not display reports that span 
-multiple files. The main problem is that we do not have a good format to
-display such paths in HTML output. (Difficulty: Medium) 
-
-
 Refactor path diagnostic generation in http://clang.llvm.org/doxygen/BugReporter_8cpp_source.html;>BugReporter.cpp.
 It would be great to have more code reuse between "Minimal" and 
 "Extensive" PathDiagnostic generation algorithms. One idea is to create an 
Index: test/Coverage/html-multifile-diagnostics.h
===
--- /dev/null
+++ test/Coverage/html-multifile-diagnostics.h
@@ -0,0 +1,3 @@
+void f1(int *ptr) {
+  *ptr = 0;
+}
Index: test/Coverage/html-multifile-diagnostics.c
===
--- /dev/null
+++ test/Coverage/html-multifile-diagnostics.c
@@ -0,0 +1,21 @@
+// RUN: rm -rf %t
+// RUN: %clang_cc1 -analyze -analyzer-output=html -analyzer-checker=core -o %t %s
+// RUN: find %t -name "*.html" -exec cat "{}" ";" | FileCheck %s
+
+// REQUIRES: staticanalyzer
+
+// CHECK: Annotated Source Code
+
+// Make sure it's generated as multi-file HTML output
+// CHECK: {{.*}}html-multifile-diagnostics.c
+// CHECK: {{.*}}html-multifile-diagnostics.h
+
+// Without tweaking expr, the expr would hit to the line below
+// emitted to the output as comment.
+// CHECK: {{[D]ereference of null pointer}}
+
+#include "html-multifile-diagnostics.h"
+
+void f0() {
+  f1((int*)0);
+}
Index: test/Coverage/html-diagnostics.c
===
--- test/Coverage/html-diagnostics.c
+++ test/Coverage/html-diagnostics.c
@@ -1,11 +1,18 @@
 // RUN: rm -rf %t
 // RUN: %clang_cc1 -analyze -analyzer-output=html -analyzer-checker=core -o %t %s
 // RUN: find %t -name "*.html" -exec cat "{}" ";" | FileCheck %s
+//
+// RUN: rm -rf %t
+// RUN: %clang_cc1 -analyze -analyzer-output=html-single-file -analyzer-checker=core -o %t %s
+// RUN: find %t -name "*.html" -exec cat "{}" ";" | FileCheck %s
 
 // REQUIRES: staticanalyzer
 
 // CHECK: Annotated Source Code
 
+// Make sure it's not generated as a multi-file HTML output
+// CHECK-NOT: {{.*}}
+
 // Without tweaking expr, the expr would hit to the line below
 // emitted to the output as comment.
 // CHECK: {{[D]ereference of null pointer}}
Index: test/Analysis/html-diags.c
===
--- test/Analysis/html-diags.c
+++ test/Analysis/html-diags.c
@@ -3,6 +3,12 @@
 // RUN: %clang_analyze_cc1 -analyzer-output=html -analyzer-checker=core -o %T/dir %s
 // RUN: ls %T/dir | grep report
 
+// D30406: Test new html-single-file output
+// RUN: rm -fR %T/dir
+// RUN: mkdir %T/dir
+// RUN: %clang_analyze_cc1 -analyzer-output=html-single-file -analyzer-checker=core -o %T/dir %s
+// RUN: ls %T/dir | grep report
+
 // PR16547: Test relative paths
 // RUN: cd %T/dir
 // RUN: %clang_analyze_cc1 -analyzer-output=html -analyzer-checker=core -o testrelative %s
Index: test/Analysis/html-diags-multifile.c
===
--- test/Analysis/html-diags-multifile.c
+++ test/Analysis/html-diags-multifile.c
@@ -1,10 +1,9 @@
 // RUN: mkdir -p %t.dir
 // RUN: %clang_analyze_cc1 -analyzer-output=html -analyzer-checker=core -o %t.dir %s
-// RUN: ls %t.dir | not grep report
+// RUN: ls %t.dir | grep report
 // RUN: rm -fR %t.dir
 
-// This tests that we do not currently emit HTML diagnostics for reports that
-// cross file boundaries.
+// 

[PATCH] D30406: [Analyzer] Add support for displaying cross-file diagnostic paths in HTML output

2017-06-15 Thread Vlad Tsyrklevich via Phabricator via cfe-commits
vlad.tsyrklevich updated this revision to Diff 102765.
vlad.tsyrklevich added a comment.
Herald added a subscriber: xazax.hun.

Updates to cleanly rebase on a recent clang master. Ran all tests with ASan to 
ensure I avoided a broken build post-merge as with  
https://reviews.llvm.org/D30909


https://reviews.llvm.org/D30406

Files:
  include/clang/StaticAnalyzer/Core/Analyses.def
  lib/Rewrite/HTMLRewrite.cpp
  lib/StaticAnalyzer/Core/HTMLDiagnostics.cpp
  test/Analysis/diagnostics/diag-cross-file-boundaries.c
  test/Analysis/diagnostics/diag-cross-file-boundaries.h
  test/Analysis/html-diag-singlefile.c
  test/Analysis/html-diag-singlefile.h
  test/Analysis/html-diags-analyze-headers.c
  test/Analysis/html-diags-analyze-headers.h
  test/Analysis/html-diags-multifile.c
  test/Analysis/html-diags.c
  test/Coverage/html-diagnostics.c
  test/Coverage/html-multifile-diagnostics.c
  test/Coverage/html-multifile-diagnostics.h
  www/analyzer/open_projects.html

Index: www/analyzer/open_projects.html
===
--- www/analyzer/open_projects.html
+++ www/analyzer/open_projects.html
@@ -107,13 +107,6 @@
 
   Bug Reporting 
   
-Add support for displaying cross-file diagnostic paths in HTML output
-(used by scan-build).
-Currently scan-build output does not display reports that span 
-multiple files. The main problem is that we do not have a good format to
-display such paths in HTML output. (Difficulty: Medium) 
-
-
 Refactor path diagnostic generation in http://clang.llvm.org/doxygen/BugReporter_8cpp_source.html;>BugReporter.cpp.
 It would be great to have more code reuse between "Minimal" and 
 "Extensive" PathDiagnostic generation algorithms. One idea is to create an 
Index: test/Coverage/html-multifile-diagnostics.h
===
--- /dev/null
+++ test/Coverage/html-multifile-diagnostics.h
@@ -0,0 +1,3 @@
+void f1(int *ptr) {
+  *ptr = 0;
+}
Index: test/Coverage/html-multifile-diagnostics.c
===
--- /dev/null
+++ test/Coverage/html-multifile-diagnostics.c
@@ -0,0 +1,21 @@
+// RUN: rm -rf %t
+// RUN: %clang_cc1 -analyze -analyzer-output=html -analyzer-checker=core -o %t %s
+// RUN: find %t -name "*.html" -exec cat "{}" ";" | FileCheck %s
+
+// REQUIRES: staticanalyzer
+
+// CHECK: Annotated Source Code
+
+// Make sure it's generated as multi-file HTML output
+// CHECK: {{.*}}html-multifile-diagnostics.c
+// CHECK: {{.*}}html-multifile-diagnostics.h
+
+// Without tweaking expr, the expr would hit to the line below
+// emitted to the output as comment.
+// CHECK: {{[D]ereference of null pointer}}
+
+#include "html-multifile-diagnostics.h"
+
+void f0() {
+  f1((int*)0);
+}
Index: test/Coverage/html-diagnostics.c
===
--- test/Coverage/html-diagnostics.c
+++ test/Coverage/html-diagnostics.c
@@ -1,11 +1,18 @@
 // RUN: rm -rf %t
 // RUN: %clang_cc1 -analyze -analyzer-output=html -analyzer-checker=core -o %t %s
 // RUN: find %t -name "*.html" -exec cat "{}" ";" | FileCheck %s
+//
+// RUN: rm -rf %t
+// RUN: %clang_cc1 -analyze -analyzer-output=html-single-file -analyzer-checker=core -o %t %s
+// RUN: find %t -name "*.html" -exec cat "{}" ";" | FileCheck %s
 
 // REQUIRES: staticanalyzer
 
 // CHECK: Annotated Source Code
 
+// Make sure it's not generated as a multi-file HTML output
+// CHECK-NOT: {{.*}}
+
 // Without tweaking expr, the expr would hit to the line below
 // emitted to the output as comment.
 // CHECK: {{[D]ereference of null pointer}}
Index: test/Analysis/html-diags.c
===
--- test/Analysis/html-diags.c
+++ test/Analysis/html-diags.c
@@ -3,6 +3,12 @@
 // RUN: %clang_analyze_cc1 -analyzer-output=html -analyzer-checker=core -o %T/dir %s
 // RUN: ls %T/dir | grep report
 
+// D30406: Test new html-single-file output
+// RUN: rm -fR %T/dir
+// RUN: mkdir %T/dir
+// RUN: %clang_cc1 -analyze -analyzer-output=html-single-file -analyzer-checker=core -o %T/dir %s
+// RUN: ls %T/dir | grep report
+
 // PR16547: Test relative paths
 // RUN: cd %T/dir
 // RUN: %clang_analyze_cc1 -analyzer-output=html -analyzer-checker=core -o testrelative %s
Index: test/Analysis/html-diags-multifile.c
===
--- test/Analysis/html-diags-multifile.c
+++ test/Analysis/html-diags-multifile.c
@@ -1,10 +1,9 @@
 // RUN: mkdir -p %t.dir
 // RUN: %clang_analyze_cc1 -analyzer-output=html -analyzer-checker=core -o %t.dir %s
-// RUN: ls %t.dir | not grep report
+// RUN: ls %t.dir | grep report
 // RUN: rm -fR %t.dir
 
-// This tests that we do not currently emit HTML diagnostics for reports that
-// cross file boundaries.
+// This tests that we emit HTML diagnostics for reports that cross file boundaries.
 
 #include "html-diags-multifile.h"
 

[PATCH] D30909: [Analyzer] Finish taint propagation to derived symbols of tainted regions

2017-05-13 Thread Vlad Tsyrklevich via Phabricator via cfe-commits
vlad.tsyrklevich updated this revision to Diff 98905.
vlad.tsyrklevich added a comment.

Some stylistic & comment updates.


https://reviews.llvm.org/D30909

Files:
  include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h
  include/clang/StaticAnalyzer/Core/PathSensitive/TaintManager.h
  lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp
  lib/StaticAnalyzer/Core/ProgramState.cpp
  lib/StaticAnalyzer/Core/RegionStore.cpp
  test/Analysis/taint-generic.c

Index: test/Analysis/taint-generic.c
===
--- test/Analysis/taint-generic.c
+++ test/Analysis/taint-generic.c
@@ -192,20 +192,41 @@
 
 void testStructArray() {
   struct {
-char buf[16];
-struct {
-  int length;
-} st[1];
-  } tainted;
+int length;
+  } tainted[4];
 
-  char buffer[16];
+  char dstbuf[16], srcbuf[16];
   int sock;
 
   sock = socket(AF_INET, SOCK_STREAM, 0);
-  read(sock, [0], sizeof(tainted.buf));
-  read(sock, [0], sizeof(tainted.st));
-  // FIXME: tainted.st[0].length should be marked tainted
-  __builtin_memcpy(buffer, tainted.buf, tainted.st[0].length); // no-warning
+  __builtin_memset(srcbuf, 0, sizeof(srcbuf));
+
+  read(sock, [0], sizeof(tainted));
+  __builtin_memcpy(dstbuf, srcbuf, tainted[0].length); // expected-warning {{Untrusted data is used to specify the buffer size}}
+
+  __builtin_memset(, 0, sizeof(tainted));
+  read(sock, , sizeof(tainted));
+  __builtin_memcpy(dstbuf, srcbuf, tainted[0].length); // expected-warning {{Untrusted data is used to specify the buffer size}}
+
+  __builtin_memset(, 0, sizeof(tainted));
+  // If we taint element 1, we should not raise an alert on taint for element 0 or element 2
+  read(sock, [1], sizeof(tainted));
+  __builtin_memcpy(dstbuf, srcbuf, tainted[0].length); // no-warning
+  __builtin_memcpy(dstbuf, srcbuf, tainted[2].length); // no-warning
+}
+
+void testUnion() {
+  union {
+int x;
+char y[4];
+  } tainted;
+
+  char buffer[4];
+
+  int sock = socket(AF_INET, SOCK_STREAM, 0);
+  read(sock, , sizeof(tainted.y));
+  // FIXME: overlapping regions aren't detected by isTainted yet
+  __builtin_memcpy(buffer, tainted.y, tainted.x);
 }
 
 int testDivByZero() {
Index: lib/StaticAnalyzer/Core/RegionStore.cpp
===
--- lib/StaticAnalyzer/Core/RegionStore.cpp
+++ lib/StaticAnalyzer/Core/RegionStore.cpp
@@ -496,7 +496,10 @@
 
   Optional getDefaultBinding(Store S, const MemRegion *R) override {
 RegionBindingsRef B = getRegionBindings(S);
-return B.getDefaultBinding(R);
+// Default bindings are always applied over a base region so look up the
+// base region's default binding, otherwise the lookup will fail when R
+// is at an offset from R->getBaseRegion().
+return B.getDefaultBinding(R->getBaseRegion());
   }
 
   SVal getBinding(RegionBindingsConstRef B, Loc L, QualType T = QualType());
Index: lib/StaticAnalyzer/Core/ProgramState.cpp
===
--- lib/StaticAnalyzer/Core/ProgramState.cpp
+++ lib/StaticAnalyzer/Core/ProgramState.cpp
@@ -644,15 +644,33 @@
   if (const Expr *E = dyn_cast_or_null(S))
 S = E->IgnoreParens();
 
-  SymbolRef Sym = getSVal(S, LCtx).getAsSymbol();
+  return addTaint(getSVal(S, LCtx), Kind);
+}
+
+ProgramStateRef ProgramState::addTaint(SVal V,
+   TaintTagType Kind) const {
+  SymbolRef Sym = V.getAsSymbol();
   if (Sym)
 return addTaint(Sym, Kind);
 
-  const MemRegion *R = getSVal(S, LCtx).getAsRegion();
-  addTaint(R, Kind);
+  // If the SVal represents a structure, try to mass-taint all values within the
+  // structure. For now it only works efficiently on lazy compound values that
+  // were conjured during a conservative evaluation of a function - either as
+  // return values of functions that return structures or arrays by value, or as
+  // values of structures or arrays passed into the function by reference,
+  // directly or through pointer aliasing. Such lazy compound values are
+  // characterized by having exactly one binding in their captured store within
+  // their parent region, which is a conjured symbol default-bound to the base
+  // region of the parent region.
+  if (auto LCV = V.getAs()) {
+if (Optional binding = getStateManager().StoreMgr->getDefaultBinding(*LCV)) {
+  if (SymbolRef Sym = binding->getAsSymbol())
+return addPartialTaint(Sym, LCV->getRegion(), Kind);
+}
+  }
 
-  // Cannot add taint, so just return the state.
-  return this;
+  const MemRegion *R = V.getAsRegion();
+  return addTaint(R, Kind);
 }
 
 ProgramStateRef ProgramState::addTaint(const MemRegion *R,
@@ -674,6 +692,28 @@
   return NewState;
 }
 
+ProgramStateRef ProgramState::addPartialTaint(SymbolRef ParentSym,
+  const SubRegion *SubRegion,
+  TaintTagType Kind) const {
+  // 

[PATCH] D30909: [Analyzer] Finish taint propagation to derived symbols of tainted regions

2017-05-13 Thread Vlad Tsyrklevich via Phabricator via cfe-commits
vlad.tsyrklevich added inline comments.



Comment at: lib/StaticAnalyzer/Core/ProgramState.cpp:656-659
+  // If the SVal is a LazyCompoundVal it might only cover sub-region of a given
+  // symbol. For example, the LCV might represent a field in an uninitialized
+  // struct. In this case, the LCV encapsulates a conjured symbol and reference
+  // to the sub-region representing the struct field.

NoQ wrote:
> vlad.tsyrklevich wrote:
> > NoQ wrote:
> > > I still feel bad about producing API with very tricky pre-conditions. The 
> > > LCV may have various forms - some may have empty store with no symbols at 
> > > all, and others may be full of direct bindings that make the symbol 
> > > essentially irrelevant. However, because the taint API is designed to be 
> > > defensive to cases when taint cannot be added, and it sounds like a good 
> > > thing, i guess we've taken the right approach here :)
> > > 
> > > I suggest commenting this more thoroughly though, something like:
> > > 
> > > > If the SVal represents a structure, try to mass-taint all values within 
> > > > the structure. For now it only works efficiently on lazy compound 
> > > > values that were conjured during a conservative evaluation of a 
> > > > function - either as return values of functions that return structures 
> > > > or arrays by value, or as values of structures or arrays passed into 
> > > > the function by reference, directly or through pointer aliasing. Such 
> > > > lazy compound values are characterized by having exactly one binding in 
> > > > their captured store within their parent region, which is a conjured 
> > > > symbol default-bound to the base region of the parent region.
> > > 
> > > Then inside `if (Sym)`:
> > > 
> > > > If the parent region is a base region, we add taint to the whole 
> > > > conjured symbol.
> > > 
> > > > Otherwise, when the value represents a record-typed field within the 
> > > > conjured structure, so we add partial taint for that symbol to that 
> > > > field.
> > The pre-conditions for using the API are actually a bit simpler than what's 
> > exposed here. I made it explicit to make the logic for tainting LCVs 
> > explicit, but the following simpler logic works:
> > ```
> >   if (auto LCV = V.getAs()) {
> > if (Optional binding = 
> > getStateManager().StoreMgr->getDefaultBinding(*LCV)) {
> >   if (SymbolRef Sym = binding->getAsSymbol()) {
> > return addPartialTaint(Sym, LCV->getRegion(), Kind);
> >   }
> > }
> >   }
> > ```
> > 
> > This works because `addPartialTaint()` actually already performs the 
> > 'getRegion() == getRegion()->getBaseRegion()` check already and taints the 
> > parent symbol if the region is over the base region already. I chose to 
> > replicate it here to make the logic more explicit, but now that I've 
> > written this down the overhead of duplicating the logic seems unnecessary. 
> > Do you agree?
> > The pre-conditions for using the API are actually a bit simpler than what's 
> > exposed here.
> 
> I'm talking about the situation when we add the partial taint to the 
> default-bound symbol but it has no effect because there's a direct binding in 
> the lazy compound value on top of it. The user should ideally understand why 
> it doesn't work that way.
> 
> > I chose to replicate it here to make the logic more explicit, but now that 
> > I've written this down the overhead of duplicating the logic seems 
> > unnecessary. Do you agree?
> 
> The variant without the check looks easier to read, and it is kind of obvious 
> that full taint is a special case of partial taint, so i'm for removing the 
> check.
> when we add the partial taint to the default-bound symbol but it has no 
> effect because there's a direct binding in the lazy compound value on top of 
> it

Ah, so you're talking about the case where the LCV encompasses a value with 
both direct & default bindings, e.g. `int foo[1024]; foo[123] = rand(); 
taint(foo);`? In that case we will miss tainting the `rand` SymbolConjured. I 
suppose we could scan the region store for matching entries? In practice I 
think we're really only interested in tainting default bindings anyway for some 
unknown network/user input anyway.

Anyways, your comment makes more sense now. I've added it.



Comment at: lib/StaticAnalyzer/Core/ProgramState.cpp:788
+  (R == I->first || R->isSubRegionOf(I->first)))
+return true;
+}

NoQ wrote:
> I actually have no idea why does this function accumulate things in the 
> `Tainted` variable, instead of returning :)
It made a little more stylistic sense before this change, but not so much now. 
I've updated them to return immediately.


https://reviews.llvm.org/D30909



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D30909: [Analyzer] Finish taint propagation to derived symbols of tainted regions

2017-05-12 Thread Vlad Tsyrklevich via Phabricator via cfe-commits
vlad.tsyrklevich added inline comments.



Comment at: lib/StaticAnalyzer/Core/ProgramState.cpp:656-659
+  // If the SVal is a LazyCompoundVal it might only cover sub-region of a given
+  // symbol. For example, the LCV might represent a field in an uninitialized
+  // struct. In this case, the LCV encapsulates a conjured symbol and reference
+  // to the sub-region representing the struct field.

NoQ wrote:
> I still feel bad about producing API with very tricky pre-conditions. The LCV 
> may have various forms - some may have empty store with no symbols at all, 
> and others may be full of direct bindings that make the symbol essentially 
> irrelevant. However, because the taint API is designed to be defensive to 
> cases when taint cannot be added, and it sounds like a good thing, i guess 
> we've taken the right approach here :)
> 
> I suggest commenting this more thoroughly though, something like:
> 
> > If the SVal represents a structure, try to mass-taint all values within the 
> > structure. For now it only works efficiently on lazy compound values that 
> > were conjured during a conservative evaluation of a function - either as 
> > return values of functions that return structures or arrays by value, or as 
> > values of structures or arrays passed into the function by reference, 
> > directly or through pointer aliasing. Such lazy compound values are 
> > characterized by having exactly one binding in their captured store within 
> > their parent region, which is a conjured symbol default-bound to the base 
> > region of the parent region.
> 
> Then inside `if (Sym)`:
> 
> > If the parent region is a base region, we add taint to the whole conjured 
> > symbol.
> 
> > Otherwise, when the value represents a record-typed field within the 
> > conjured structure, so we add partial taint for that symbol to that field.
The pre-conditions for using the API are actually a bit simpler than what's 
exposed here. I made it explicit to make the logic for tainting LCVs explicit, 
but the following simpler logic works:
```
  if (auto LCV = V.getAs()) {
if (Optional binding = 
getStateManager().StoreMgr->getDefaultBinding(*LCV)) {
  if (SymbolRef Sym = binding->getAsSymbol()) {
return addPartialTaint(Sym, LCV->getRegion(), Kind);
  }
}
  }
```

This works because `addPartialTaint()` actually already performs the 
'getRegion() == getRegion()->getBaseRegion()` check already and taints the 
parent symbol if the region is over the base region already. I chose to 
replicate it here to make the logic more explicit, but now that I've written 
this down the overhead of duplicating the logic seems unnecessary. Do you agree?



Comment at: lib/StaticAnalyzer/Core/ProgramState.cpp:701-703
+  // Ignore partial taint if the entire parent symbol is already tainted.
+  if (contains(ParentSym))
+return this;

NoQ wrote:
> Speaking of taint tags: right now we didn't add support for multiple taint 
> tags per symbol (because we have only one taint tag to choose from), but 
> `addTaint` overwrites the tag. I guess we should do the same for now.
I believe this is the current behavior. On line 714 I presume ImmutableMap::add 
overrides a key if it's already present in the map but I couldn't trace down 
the Tree ADT implementation to confirm this.


https://reviews.llvm.org/D30909



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D30909: [Analyzer] Finish taint propagation to derived symbols of tainted regions

2017-05-12 Thread Vlad Tsyrklevich via Phabricator via cfe-commits
vlad.tsyrklevich updated this revision to Diff 98726.
vlad.tsyrklevich marked 2 inline comments as done.
vlad.tsyrklevich added a comment.

Minor updates & some clarification on the feedback


https://reviews.llvm.org/D30909

Files:
  include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h
  include/clang/StaticAnalyzer/Core/PathSensitive/TaintManager.h
  lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp
  lib/StaticAnalyzer/Core/ProgramState.cpp
  lib/StaticAnalyzer/Core/RegionStore.cpp
  test/Analysis/taint-generic.c

Index: test/Analysis/taint-generic.c
===
--- test/Analysis/taint-generic.c
+++ test/Analysis/taint-generic.c
@@ -192,20 +192,41 @@
 
 void testStructArray() {
   struct {
-char buf[16];
-struct {
-  int length;
-} st[1];
-  } tainted;
+int length;
+  } tainted[4];
 
-  char buffer[16];
+  char dstbuf[16], srcbuf[16];
   int sock;
 
   sock = socket(AF_INET, SOCK_STREAM, 0);
-  read(sock, [0], sizeof(tainted.buf));
-  read(sock, [0], sizeof(tainted.st));
-  // FIXME: tainted.st[0].length should be marked tainted
-  __builtin_memcpy(buffer, tainted.buf, tainted.st[0].length); // no-warning
+  __builtin_memset(srcbuf, 0, sizeof(srcbuf));
+
+  read(sock, [0], sizeof(tainted));
+  __builtin_memcpy(dstbuf, srcbuf, tainted[0].length); // expected-warning {{Untrusted data is used to specify the buffer size}}
+
+  __builtin_memset(, 0, sizeof(tainted));
+  read(sock, , sizeof(tainted));
+  __builtin_memcpy(dstbuf, srcbuf, tainted[0].length); // expected-warning {{Untrusted data is used to specify the buffer size}}
+
+  __builtin_memset(, 0, sizeof(tainted));
+  // If we taint element 1, we should not raise an alert on taint for element 0 or element 2
+  read(sock, [1], sizeof(tainted));
+  __builtin_memcpy(dstbuf, srcbuf, tainted[0].length); // no-warning
+  __builtin_memcpy(dstbuf, srcbuf, tainted[2].length); // no-warning
+}
+
+void testUnion() {
+  union {
+int x;
+char y[4];
+  } tainted;
+
+  char buffer[4];
+
+  int sock = socket(AF_INET, SOCK_STREAM, 0);
+  read(sock, , sizeof(tainted.y));
+  // FIXME: overlapping regions aren't detected by isTainted yet
+  __builtin_memcpy(buffer, tainted.y, tainted.x);
 }
 
 int testDivByZero() {
Index: lib/StaticAnalyzer/Core/RegionStore.cpp
===
--- lib/StaticAnalyzer/Core/RegionStore.cpp
+++ lib/StaticAnalyzer/Core/RegionStore.cpp
@@ -496,7 +496,10 @@
 
   Optional getDefaultBinding(Store S, const MemRegion *R) override {
 RegionBindingsRef B = getRegionBindings(S);
-return B.getDefaultBinding(R);
+// Default bindings are always applied over a base region so look up the
+// base region's default binding, otherwise the lookup will fail when R
+// is at an offset from R->getBaseRegion().
+return B.getDefaultBinding(R->getBaseRegion());
   }
 
   SVal getBinding(RegionBindingsConstRef B, Loc L, QualType T = QualType());
Index: lib/StaticAnalyzer/Core/ProgramState.cpp
===
--- lib/StaticAnalyzer/Core/ProgramState.cpp
+++ lib/StaticAnalyzer/Core/ProgramState.cpp
@@ -644,15 +644,36 @@
   if (const Expr *E = dyn_cast_or_null(S))
 S = E->IgnoreParens();
 
-  SymbolRef Sym = getSVal(S, LCtx).getAsSymbol();
+  return addTaint(getSVal(S, LCtx), Kind);
+}
+
+ProgramStateRef ProgramState::addTaint(SVal V,
+   TaintTagType Kind) const {
+  SymbolRef Sym = V.getAsSymbol();
   if (Sym)
 return addTaint(Sym, Kind);
 
-  const MemRegion *R = getSVal(S, LCtx).getAsRegion();
-  addTaint(R, Kind);
+  // If the SVal is a LazyCompoundVal it might only cover sub-region of a given
+  // symbol. For example, the LCV might represent a field in an uninitialized
+  // struct. In this case, the LCV encapsulates a conjured symbol and reference
+  // to the sub-region representing the struct field.
+  if (auto LCV = V.getAs()) {
+Optional binding = getStateManager().StoreMgr->getDefaultBinding(*LCV);
+if (binding) {
+  SymbolRef Sym = binding->getAsSymbol();
+  if (Sym) {
+// If the LCV covers an entire base region, taint the symbol
+if (LCV->getRegion() == LCV->getRegion()->getBaseRegion())
+  return addTaint(Sym, Kind);
+
+// Otherwise, only taint the sub-region covered by the LCV
+return addPartialTaint(Sym, LCV->getRegion(), Kind);
+  }
+}
+  }
 
-  // Cannot add taint, so just return the state.
-  return this;
+  const MemRegion *R = V.getAsRegion();
+  return addTaint(R, Kind);
 }
 
 ProgramStateRef ProgramState::addTaint(const MemRegion *R,
@@ -674,6 +695,28 @@
   return NewState;
 }
 
+ProgramStateRef ProgramState::addPartialTaint(SymbolRef ParentSym,
+  const SubRegion *SubRegion,
+  TaintTagType Kind) const {
+  // Ignore partial taint 

[PATCH] D30909: [Analyzer] Finish taint propagation to derived symbols of tainted regions

2017-05-09 Thread Vlad Tsyrklevich via Phabricator via cfe-commits
vlad.tsyrklevich updated this revision to Diff 98390.
vlad.tsyrklevich marked 3 inline comments as done.
vlad.tsyrklevich added a comment.
Herald added a subscriber: xazax.hun.

- Update the logic to move the LCV symbol logic into 
ProgramState::addTaint(SVal) out of the GenericTaintChecker. This allows us to 
no longer have to synthesize a new SymbolDerived from a LazyCompoundVal. This 
also required adding a new addPartialTaint() function.
- Update TaintedSymRegions name to TaintedSubRegions per @NoQ's comment.
- I realized that the new partial taint logic did not respect the idea of 
TaintTagTypes, so I updated TaintSubRegion to include a TaintTagType and added 
appropriate logic to add/check them.


https://reviews.llvm.org/D30909

Files:
  include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h
  include/clang/StaticAnalyzer/Core/PathSensitive/TaintManager.h
  lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp
  lib/StaticAnalyzer/Core/ProgramState.cpp
  lib/StaticAnalyzer/Core/RegionStore.cpp
  test/Analysis/taint-generic.c

Index: test/Analysis/taint-generic.c
===
--- test/Analysis/taint-generic.c
+++ test/Analysis/taint-generic.c
@@ -192,20 +192,41 @@
 
 void testStructArray() {
   struct {
-char buf[16];
-struct {
-  int length;
-} st[1];
-  } tainted;
+int length;
+  } tainted[4];
 
-  char buffer[16];
+  char dstbuf[16], srcbuf[16];
   int sock;
 
   sock = socket(AF_INET, SOCK_STREAM, 0);
-  read(sock, [0], sizeof(tainted.buf));
-  read(sock, [0], sizeof(tainted.st));
-  // FIXME: tainted.st[0].length should be marked tainted
-  __builtin_memcpy(buffer, tainted.buf, tainted.st[0].length); // no-warning
+  __builtin_memset(srcbuf, 0, sizeof(srcbuf));
+
+  read(sock, [0], sizeof(tainted));
+  __builtin_memcpy(dstbuf, srcbuf, tainted[0].length); // expected-warning {{Untrusted data is used to specify the buffer size}}
+
+  __builtin_memset(, 0, sizeof(tainted));
+  read(sock, , sizeof(tainted));
+  __builtin_memcpy(dstbuf, srcbuf, tainted[0].length); // expected-warning {{Untrusted data is used to specify the buffer size}}
+
+  __builtin_memset(, 0, sizeof(tainted));
+  // If we taint element 1, we should not raise an alert on taint for element 0 or element 2
+  read(sock, [1], sizeof(tainted));
+  __builtin_memcpy(dstbuf, srcbuf, tainted[0].length); // no-warning
+  __builtin_memcpy(dstbuf, srcbuf, tainted[2].length); // no-warning
+}
+
+void testUnion() {
+  union {
+int x;
+char y[4];
+  } tainted;
+
+  char buffer[4];
+
+  int sock = socket(AF_INET, SOCK_STREAM, 0);
+  read(sock, , sizeof(tainted.y));
+  // FIXME: overlapping regions aren't detected by isTainted yet
+  __builtin_memcpy(buffer, tainted.y, tainted.x);
 }
 
 int testDivByZero() {
Index: lib/StaticAnalyzer/Core/RegionStore.cpp
===
--- lib/StaticAnalyzer/Core/RegionStore.cpp
+++ lib/StaticAnalyzer/Core/RegionStore.cpp
@@ -496,7 +496,10 @@
 
   Optional getDefaultBinding(Store S, const MemRegion *R) override {
 RegionBindingsRef B = getRegionBindings(S);
-return B.getDefaultBinding(R);
+// Default bindings are always applied over a base region so look up the
+// base region's default binding, otherwise the lookup will fail when R
+// is at an offset from R->getBaseRegion().
+return B.getDefaultBinding(R->getBaseRegion());
   }
 
   SVal getBinding(RegionBindingsConstRef B, Loc L, QualType T = QualType());
Index: lib/StaticAnalyzer/Core/ProgramState.cpp
===
--- lib/StaticAnalyzer/Core/ProgramState.cpp
+++ lib/StaticAnalyzer/Core/ProgramState.cpp
@@ -644,15 +644,36 @@
   if (const Expr *E = dyn_cast_or_null(S))
 S = E->IgnoreParens();
 
-  SymbolRef Sym = getSVal(S, LCtx).getAsSymbol();
+  return addTaint(getSVal(S, LCtx), Kind);
+}
+
+ProgramStateRef ProgramState::addTaint(SVal V,
+   TaintTagType Kind) const {
+  SymbolRef Sym = V.getAsSymbol();
   if (Sym)
 return addTaint(Sym, Kind);
 
-  const MemRegion *R = getSVal(S, LCtx).getAsRegion();
-  addTaint(R, Kind);
+  // If the SVal is a LazyCompoundVal it might only cover sub-region of a given
+  // symbol. For example, the LCV might represent a field in an uninitialized
+  // struct. In this case, the LCV encapsulates a conjured symbol and reference
+  // to the sub-region representing the struct field.
+  if (auto LCV = V.getAs()) {
+Optional binding = getStateManager().StoreMgr->getDefaultBinding(*LCV);
+if (binding) {
+  SymbolRef Sym = binding->getAsSymbol();
+  if (Sym) {
+// If the LCV covers an entire base region, taint the symbol
+if (LCV->getRegion() == LCV->getRegion()->getBaseRegion())
+  return addTaint(Sym, Kind);
+
+// Otherwise, only taint the sub-region covered by the LCV
+return addPartialTaint(Sym, 

[PATCH] D30909: [Analyzer] Finish taint propagation to derived symbols of tainted regions

2017-04-10 Thread Vlad Tsyrklevich via Phabricator via cfe-commits
vlad.tsyrklevich marked 2 inline comments as done.
vlad.tsyrklevich added inline comments.



Comment at: lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp:494
+  SymbolManager  = C.getSymbolManager();
+  return SM.getDerivedSymbol(Sym, LCV.getRegion());
 }

NoQ wrote:
> vlad.tsyrklevich wrote:
> > NoQ wrote:
> > > I'd think about this a bit more and come back.
> > > 
> > > I need to understand how come that constructing a symbol manually is the 
> > > right thing to do; that doesn't happen very often, but it seems correct 
> > > here.
> > Indeed it is odd. The best justification I could come up with: LCVs are 
> > meant to be optimizations, their 'purpose' is to expose an SVal that hides 
> > SymbolRef values so that we can have a split store. We don't have to copy 
> > all of a compound values SymbolRef mappings because LCVs are kept distinct. 
> > Hence to set/query/constrain region values you use SVals so that 
> > RegionStore can differentiate between LCVs and SymbolRef backed SVals for 
> > the two different stores it contains.
> > 
> > The taint interface however requires you taint a SymbolRef, not an SVal. If 
> > we wanted, instead of doing this logic here, we could change 
> > getPointedToSymbol() to return an SVal and update usages of it accordingly 
> > since that value is only passed on to 
> > ProgramState.isTainted()/ProgramState.addTaint() anyway. Then we could 
> > update addTaint/isTainted to perform this logic, hiding it from the checker.
> > 
> > This still requires manually constructing a symbol, now it's just performed 
> > in the analyzer instead of in a checker. Not sure if that addresses the 
> > issue you were considering, but the idea that we need to 'undo' the LCV 
> > optimization hiding the SymbolRef to have a value to taint seems somewhat 
> > convincing to me. What do you think?
> Hmm (!) I suggest adding a new function to the program state, that we'd call 
> `addPartialTaint()` or something like that, and this function would accept a 
> symbol and a region and would act identically to passing a derived symbol 
> (from this symbol and that region) to `addTaint()` (but we wouldn't need to 
> actually construct a derived symbol here).
> 
> Such API would be easier to understand and use than the current approach that 
> forces the user to construct a derived symbol manually in the checker code. 
> Unfortunately, this checker's `getLCVSymbol()` would become a bit more 
> complicated (having various return types depending on circumstances), but 
> this misfortune seems more random than systematic to me.
> 
> Since we're having this new kind of partial taint, why don't we expose it in 
> the API.
I'm happy to implement it this way, but figured I'd ask why you prefer this 
approach first in the interest of keeping the TaintChecker simple! The optimal 
approach to me seems to be changing `getPointedToSymbol()` to 
`getPointedToSVal()` and having `addTaint(SVal)` call `addPartialTaint()` when 
it's passed an LCV sub-region. That way users of the taint interface like the 
TaintChecker have a clean way to add & check regardless of whether it's a 
SymbolRef or an LCV but the partial taint functionality is still exposed and 
documented for those who might want to use it in new ways.

Just curious to understand your rationale. Thanks for the feedback!


https://reviews.llvm.org/D30909



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D30909: [Analyzer] Finish taint propagation to derived symbols of tainted regions

2017-03-26 Thread Vlad Tsyrklevich via Phabricator via cfe-commits
vlad.tsyrklevich added inline comments.



Comment at: lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp:494
+  SymbolManager  = C.getSymbolManager();
+  return SM.getDerivedSymbol(Sym, LCV.getRegion());
 }

NoQ wrote:
> I'd think about this a bit more and come back.
> 
> I need to understand how come that constructing a symbol manually is the 
> right thing to do; that doesn't happen very often, but it seems correct here.
Indeed it is odd. The best justification I could come up with: LCVs are meant 
to be optimizations, their 'purpose' is to expose an SVal that hides SymbolRef 
values so that we can have a split store. We don't have to copy all of a 
compound values SymbolRef mappings because LCVs are kept distinct. Hence to 
set/query/constrain region values you use SVals so that RegionStore can 
differentiate between LCVs and SymbolRef backed SVals for the two different 
stores it contains.

The taint interface however requires you taint a SymbolRef, not an SVal. If we 
wanted, instead of doing this logic here, we could change getPointedToSymbol() 
to return an SVal and update usages of it accordingly since that value is only 
passed on to ProgramState.isTainted()/ProgramState.addTaint() anyway. Then we 
could update addTaint/isTainted to perform this logic, hiding it from the 
checker.

This still requires manually constructing a symbol, now it's just performed in 
the analyzer instead of in a checker. Not sure if that addresses the issue you 
were considering, but the idea that we need to 'undo' the LCV optimization 
hiding the SymbolRef to have a value to taint seems somewhat convincing to me. 
What do you think?



Comment at: test/Analysis/taint-generic.c:210
+  read(sock, , sizeof(tainted.st));
+  __builtin_memcpy(buffer, tainted.buf, tainted.st[0].length); // 
expected-warning {{Untrusted data is used to specify the buffer size}}
 }

NoQ wrote:
> Are we already supporting the case when we're tainting some elements of an 
> array but not all of them, and this works as expected? Could we add such 
> tests (regardless of whether we already handle them)?
It does work in that case. If you taint element X of region Y the current logic 
will be conservative and only mark element X as tainted, not X-i or X+i. This 
is also true for element 0, so if a programmer passes [0] but reads 
sizeof(array) bytes it will not correctly mark that. This is also a short 
coming of the invalidation code so I don't think there's much to do until 
there's more general support for dealing with region extents.


https://reviews.llvm.org/D30909



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D30909: [Analyzer] Finish taint propagation to derived symbols of tainted regions

2017-03-26 Thread Vlad Tsyrklevich via Phabricator via cfe-commits
vlad.tsyrklevich updated this revision to Diff 93091.
vlad.tsyrklevich marked 2 inline comments as done.
vlad.tsyrklevich added a comment.

Respond to Artem's comments.


https://reviews.llvm.org/D30909

Files:
  include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h
  include/clang/StaticAnalyzer/Core/PathSensitive/TaintManager.h
  lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp
  lib/StaticAnalyzer/Core/ProgramState.cpp
  lib/StaticAnalyzer/Core/RegionStore.cpp
  test/Analysis/taint-generic.c

Index: test/Analysis/taint-generic.c
===
--- test/Analysis/taint-generic.c
+++ test/Analysis/taint-generic.c
@@ -192,20 +192,41 @@
 
 void testStructArray() {
   struct {
-char buf[16];
-struct {
-  int length;
-} st[1];
-  } tainted;
+int length;
+  } tainted[4];
 
-  char buffer[16];
+  char dstbuf[16], srcbuf[16];
   int sock;
 
   sock = socket(AF_INET, SOCK_STREAM, 0);
-  read(sock, [0], sizeof(tainted.buf));
-  read(sock, [0], sizeof(tainted.st));
-  // FIXME: tainted.st[0].length should be marked tainted
-  __builtin_memcpy(buffer, tainted.buf, tainted.st[0].length); // no-warning
+  __builtin_memset(srcbuf, 0, sizeof(srcbuf));
+
+  read(sock, [0], sizeof(tainted));
+  __builtin_memcpy(dstbuf, srcbuf, tainted[0].length); // expected-warning {{Untrusted data is used to specify the buffer size}}
+
+  __builtin_memset(, 0, sizeof(tainted));
+  read(sock, , sizeof(tainted));
+  __builtin_memcpy(dstbuf, srcbuf, tainted[0].length); // expected-warning {{Untrusted data is used to specify the buffer size}}
+
+  __builtin_memset(, 0, sizeof(tainted));
+  // If we taint element 1, we should not raise an alert on taint for element 0 or element 2
+  read(sock, [1], sizeof(tainted));
+  __builtin_memcpy(dstbuf, srcbuf, tainted[0].length); // no-warning
+  __builtin_memcpy(dstbuf, srcbuf, tainted[2].length); // no-warning
+}
+
+void testUnion() {
+  union {
+int x;
+char y[4];
+  } tainted;
+
+  char buffer[4];
+
+  int sock = socket(AF_INET, SOCK_STREAM, 0);
+  read(sock, , sizeof(tainted.y));
+  // FIXME: overlapping regions aren't detected by isTainted yet
+  __builtin_memcpy(buffer, tainted.y, tainted.x);
 }
 
 int testDivByZero() {
Index: lib/StaticAnalyzer/Core/RegionStore.cpp
===
--- lib/StaticAnalyzer/Core/RegionStore.cpp
+++ lib/StaticAnalyzer/Core/RegionStore.cpp
@@ -496,7 +496,10 @@
 
   Optional getDefaultBinding(Store S, const MemRegion *R) override {
 RegionBindingsRef B = getRegionBindings(S);
-return B.getDefaultBinding(R);
+// Default bindings are always applied over a base region so look up the
+// base region's default binding, otherwise the lookup will fail when R
+// is at an offset from R->getBaseRegion().
+return B.getDefaultBinding(R->getBaseRegion());
   }
 
   SVal getBinding(RegionBindingsConstRef B, Loc L, QualType T = QualType());
Index: lib/StaticAnalyzer/Core/ProgramState.cpp
===
--- lib/StaticAnalyzer/Core/ProgramState.cpp
+++ lib/StaticAnalyzer/Core/ProgramState.cpp
@@ -671,6 +671,19 @@
 
   ProgramStateRef NewState = set(Sym, Kind);
   assert(NewState);
+
+  if (const SymbolDerived *SD = dyn_cast(Sym)) {
+TaintedSymRegionsRef SymRegions(0, TSRFactory.getTreeFactory());
+
+if (const TaintedSymRegionsRef *SavedRegions =
+  get(SD->getParentSymbol()))
+  SymRegions = *SavedRegions;
+
+SymRegions = SymRegions.add(SD->getRegion());
+NewState = NewState->set(SD->getParentSymbol(), SymRegions);
+assert(NewState);
+  }
+
   return NewState;
 }
 
@@ -723,15 +736,34 @@
 const TaintTagType *Tag = get(*SI);
 Tainted = (Tag && *Tag == Kind);
 
-// If this is a SymbolDerived with a tainted parent, it's also tainted.
-if (const SymbolDerived *SD = dyn_cast(*SI))
+if (const SymbolDerived *SD = dyn_cast(*SI)) {
+  // If this is a SymbolDerived with a tainted parent, it's also tainted.
   Tainted = Tainted || isTainted(SD->getParentSymbol(), Kind);
 
+  // If this is a SymbolDerived with the same parent symbol as another
+  // tainted SymbolDerived and a region that's a sub-region of that tainted
+  // symbol, it's also tainted.
+  if (const TaintedSymRegionsRef *SymRegions =
+get(SD->getParentSymbol())) {
+const TypedValueRegion *R = SD->getRegion();
+for (TaintedSymRegionsRef::iterator I = SymRegions->begin(),
+E = SymRegions->end();
+ I != E; ++I) {
+  // FIXME: The logic to identify tainted regions could be more
+  // complete. For example, this would not currently identify
+  // overlapping fields in a union as tainted. To identify this we can
+  // check for overlapping/nested byte offsets.
+  if (R == *I || R->isSubRegionOf(*I))
+return 

[PATCH] D30909: [Analyzer] Finish taint propagation to derived symbols of tainted regions

2017-03-13 Thread Vlad Tsyrklevich via Phabricator via cfe-commits
vlad.tsyrklevich updated this revision to Diff 91615.
vlad.tsyrklevich added a comment.

Fix a stray assert(), correctly this time..


https://reviews.llvm.org/D30909

Files:
  include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h
  include/clang/StaticAnalyzer/Core/PathSensitive/TaintManager.h
  lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp
  lib/StaticAnalyzer/Core/ProgramState.cpp
  lib/StaticAnalyzer/Core/RegionStore.cpp
  test/Analysis/taint-generic.c

Index: test/Analysis/taint-generic.c
===
--- test/Analysis/taint-generic.c
+++ test/Analysis/taint-generic.c
@@ -204,8 +204,10 @@
   sock = socket(AF_INET, SOCK_STREAM, 0);
   read(sock, [0], sizeof(tainted.buf));
   read(sock, [0], sizeof(tainted.st));
-  // FIXME: tainted.st[0].length should be marked tainted
-  __builtin_memcpy(buffer, tainted.buf, tainted.st[0].length); // no-warning
+  __builtin_memcpy(buffer, tainted.buf, tainted.st[0].length); // expected-warning {{Untrusted data is used to specify the buffer size}}
+
+  read(sock, , sizeof(tainted.st));
+  __builtin_memcpy(buffer, tainted.buf, tainted.st[0].length); // expected-warning {{Untrusted data is used to specify the buffer size}}
 }
 
 int testDivByZero() {
Index: lib/StaticAnalyzer/Core/RegionStore.cpp
===
--- lib/StaticAnalyzer/Core/RegionStore.cpp
+++ lib/StaticAnalyzer/Core/RegionStore.cpp
@@ -496,7 +496,10 @@
 
   Optional getDefaultBinding(Store S, const MemRegion *R) override {
 RegionBindingsRef B = getRegionBindings(S);
-return B.getDefaultBinding(R);
+// Default bindings are always applied over a base region so look up the
+// base region's default binding, otherwise the lookup will fail when R
+// is at an offset from R->getBaseRegion().
+return B.getDefaultBinding(R->getBaseRegion());
   }
 
   SVal getBinding(RegionBindingsConstRef B, Loc L, QualType T = QualType());
Index: lib/StaticAnalyzer/Core/ProgramState.cpp
===
--- lib/StaticAnalyzer/Core/ProgramState.cpp
+++ lib/StaticAnalyzer/Core/ProgramState.cpp
@@ -671,6 +671,17 @@
 
   ProgramStateRef NewState = set(Sym, Kind);
   assert(NewState);
+
+  if (const SymbolDerived *SD = dyn_cast(Sym)) {
+TaintedSymRegionsRef SymRegions(0, TSRFactory.getTreeFactory());
+if (contains(SD->getParentSymbol()))
+  SymRegions = *get(SD->getParentSymbol());
+
+SymRegions = SymRegions.add(SD->getRegion());
+NewState = NewState->set(SD->getParentSymbol(), SymRegions);
+assert(NewState);
+  }
+
   return NewState;
 }
 
@@ -723,15 +734,31 @@
 const TaintTagType *Tag = get(*SI);
 Tainted = (Tag && *Tag == Kind);
 
-// If this is a SymbolDerived with a tainted parent, it's also tainted.
-if (const SymbolDerived *SD = dyn_cast(*SI))
+if (const SymbolDerived *SD = dyn_cast(*SI)) {
+  // If this is a SymbolDerived with a tainted parent, it's also tainted.
   Tainted = Tainted || isTainted(SD->getParentSymbol(), Kind);
 
+  // If this is a SymbolDerived with the same parent symbol as another
+  // tainted SymbolDerived and a region that's a sub-region of that tainted
+  // symbol, it's also tainted.
+  if (contains(SD->getParentSymbol())) {
+const TypedValueRegion *R = SD->getRegion();
+const TaintedSymRegionsRef *SymRegions =
+get(SD->getParentSymbol());
+for (TaintedSymRegionsRef::iterator I = SymRegions->begin(),
+E = SymRegions->end();
+ I != E; ++I) {
+  if (R == *I || R->isSubRegionOf(*I))
+return true;
+}
+  }
+}
+
 // If memory region is tainted, data is also tainted.
 if (const SymbolRegionValue *SRV = dyn_cast(*SI))
   Tainted = Tainted || isTainted(SRV->getRegion(), Kind);
 
-// If If this is a SymbolCast from a tainted value, it's also tainted.
+// If this is a SymbolCast from a tainted value, it's also tainted.
 if (const SymbolCast *SC = dyn_cast(*SI))
   Tainted = Tainted || isTainted(SC->getOperand(), Kind);
 
Index: lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp
===
--- lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp
+++ lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp
@@ -72,8 +72,6 @@
   /// covers the entire region, e.g. we avoid false positives by not returning
   /// a default bindingc for an entire struct if the symbol for only a single
   /// field or element within it is requested.
-  // TODO: Return an appropriate symbol for sub-fields/elements of an LCV so
-  // that they are also appropriately tainted.
   static SymbolRef getLCVSymbol(CheckerContext ,
 nonloc::LazyCompoundVal );
 
@@ -479,19 +477,21 @@
 
   // getLCVSymbol() is reached in a PostStmt so we can always 

[PATCH] D30909: [Analyzer] Finish taint propagation to derived symbols of tainted regions

2017-03-13 Thread Vlad Tsyrklevich via Phabricator via cfe-commits
vlad.tsyrklevich updated this revision to Diff 91614.
vlad.tsyrklevich added a comment.

Fix a stray assert()


https://reviews.llvm.org/D30909

Files:
  lib/StaticAnalyzer/Core/ProgramState.cpp


Index: lib/StaticAnalyzer/Core/ProgramState.cpp
===
--- lib/StaticAnalyzer/Core/ProgramState.cpp
+++ lib/StaticAnalyzer/Core/ProgramState.cpp
@@ -679,9 +679,9 @@
 
 SymRegions = SymRegions.add(SD->getRegion());
 NewState = NewState->set(SD->getParentSymbol(), 
SymRegions);
+assert(NewState);
   }
 
-  assert(NewState);
   return NewState;
 }
 


Index: lib/StaticAnalyzer/Core/ProgramState.cpp
===
--- lib/StaticAnalyzer/Core/ProgramState.cpp
+++ lib/StaticAnalyzer/Core/ProgramState.cpp
@@ -679,9 +679,9 @@
 
 SymRegions = SymRegions.add(SD->getRegion());
 NewState = NewState->set(SD->getParentSymbol(), SymRegions);
+assert(NewState);
   }
 
-  assert(NewState);
   return NewState;
 }
 
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D30909: [Analyzer] Finish taint propagation to derived symbols of tainted regions

2017-03-13 Thread Vlad Tsyrklevich via Phabricator via cfe-commits
vlad.tsyrklevich created this revision.

This is the second part of https://reviews.llvm.org/D28445, it extends taint 
propagation to cases where the tainted region is a sub-region and we can't 
taint a conjured symbol entirely. This required adding a new map in the GDM 
that maps tainted parent symbols to tainted sub-regions (in order to avoid a 
linear scan looking for appropriate symbols in the current TaintMap.) With this 
change, tainting of structs and unions should work as expected.


https://reviews.llvm.org/D30909

Files:
  include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h
  include/clang/StaticAnalyzer/Core/PathSensitive/TaintManager.h
  lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp
  lib/StaticAnalyzer/Core/ProgramState.cpp
  lib/StaticAnalyzer/Core/RegionStore.cpp
  test/Analysis/taint-generic.c

Index: test/Analysis/taint-generic.c
===
--- test/Analysis/taint-generic.c
+++ test/Analysis/taint-generic.c
@@ -204,8 +204,10 @@
   sock = socket(AF_INET, SOCK_STREAM, 0);
   read(sock, [0], sizeof(tainted.buf));
   read(sock, [0], sizeof(tainted.st));
-  // FIXME: tainted.st[0].length should be marked tainted
-  __builtin_memcpy(buffer, tainted.buf, tainted.st[0].length); // no-warning
+  __builtin_memcpy(buffer, tainted.buf, tainted.st[0].length); // expected-warning {{Untrusted data is used to specify the buffer size}}
+
+  read(sock, , sizeof(tainted.st));
+  __builtin_memcpy(buffer, tainted.buf, tainted.st[0].length); // expected-warning {{Untrusted data is used to specify the buffer size}}
 }
 
 int testDivByZero() {
Index: lib/StaticAnalyzer/Core/RegionStore.cpp
===
--- lib/StaticAnalyzer/Core/RegionStore.cpp
+++ lib/StaticAnalyzer/Core/RegionStore.cpp
@@ -496,7 +496,10 @@
 
   Optional getDefaultBinding(Store S, const MemRegion *R) override {
 RegionBindingsRef B = getRegionBindings(S);
-return B.getDefaultBinding(R);
+// Default bindings are always applied over a base region so look up the
+// base region's default binding, otherwise the lookup will fail when R
+// is at an offset from R->getBaseRegion().
+return B.getDefaultBinding(R->getBaseRegion());
   }
 
   SVal getBinding(RegionBindingsConstRef B, Loc L, QualType T = QualType());
Index: lib/StaticAnalyzer/Core/ProgramState.cpp
===
--- lib/StaticAnalyzer/Core/ProgramState.cpp
+++ lib/StaticAnalyzer/Core/ProgramState.cpp
@@ -671,6 +671,17 @@
 
   ProgramStateRef NewState = set(Sym, Kind);
   assert(NewState);
+
+  if (const SymbolDerived *SD = dyn_cast(Sym)) {
+TaintedSymRegionsRef SymRegions(0, TSRFactory.getTreeFactory());
+if (contains(SD->getParentSymbol()))
+  SymRegions = *get(SD->getParentSymbol());
+
+SymRegions = SymRegions.add(SD->getRegion());
+NewState = NewState->set(SD->getParentSymbol(), SymRegions);
+  }
+
+  assert(NewState);
   return NewState;
 }
 
@@ -723,15 +734,31 @@
 const TaintTagType *Tag = get(*SI);
 Tainted = (Tag && *Tag == Kind);
 
-// If this is a SymbolDerived with a tainted parent, it's also tainted.
-if (const SymbolDerived *SD = dyn_cast(*SI))
+if (const SymbolDerived *SD = dyn_cast(*SI)) {
+  // If this is a SymbolDerived with a tainted parent, it's also tainted.
   Tainted = Tainted || isTainted(SD->getParentSymbol(), Kind);
 
+  // If this is a SymbolDerived with the same parent symbol as another
+  // tainted SymbolDerived and a region that's a sub-region of that tainted
+  // symbol, it's also tainted.
+  if (contains(SD->getParentSymbol())) {
+const TypedValueRegion *R = SD->getRegion();
+const TaintedSymRegionsRef *SymRegions =
+get(SD->getParentSymbol());
+for (TaintedSymRegionsRef::iterator I = SymRegions->begin(),
+E = SymRegions->end();
+ I != E; ++I) {
+  if (R == *I || R->isSubRegionOf(*I))
+return true;
+}
+  }
+}
+
 // If memory region is tainted, data is also tainted.
 if (const SymbolRegionValue *SRV = dyn_cast(*SI))
   Tainted = Tainted || isTainted(SRV->getRegion(), Kind);
 
-// If If this is a SymbolCast from a tainted value, it's also tainted.
+// If this is a SymbolCast from a tainted value, it's also tainted.
 if (const SymbolCast *SC = dyn_cast(*SI))
   Tainted = Tainted || isTainted(SC->getOperand(), Kind);
 
Index: lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp
===
--- lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp
+++ lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp
@@ -72,8 +72,6 @@
   /// covers the entire region, e.g. we avoid false positives by not returning
   /// a default bindingc for an entire struct if the symbol for only a single
   /// field or 

[PATCH] D28445: [Analyzer] Extend taint propagation and checking

2017-03-07 Thread Vlad Tsyrklevich via Phabricator via cfe-commits
vlad.tsyrklevich added a comment.

In https://reviews.llvm.org/D28445#694906, @zaks.anna wrote:

> @vlad.tsyrklevich,
>
> Do you have commit access or should we commit on your behalf?


You should commit on my behalf.


https://reviews.llvm.org/D28445



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D30406: [Analyzer] Add support for displaying cross-file diagnostic paths in HTML output

2017-03-02 Thread Vlad Tsyrklevich via Phabricator via cfe-commits
vlad.tsyrklevich added inline comments.



Comment at: lib/StaticAnalyzer/Core/HTMLDiagnostics.cpp:211
+
+  if (I + 1 != E) {
+os << "getHashValue()

Is there a cleaner way to do these two comparisons?


https://reviews.llvm.org/D30406



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D30406: [Analyzer] Add support for displaying cross-file diagnostic paths in HTML output

2017-03-02 Thread Vlad Tsyrklevich via Phabricator via cfe-commits
vlad.tsyrklevich updated this revision to Diff 90417.
vlad.tsyrklevich edited the summary of this revision.
vlad.tsyrklevich added a comment.

Updated the formatting to make the file split more obvious (padding/line break 
height) and added simple navigation across files, example here: 
https://rawgit.com/vlad902/4aaa4e5e7a777b7098337370791352d7/raw/fc88cef667935e1eeae492b15590c18516e645dd/report.html

@NoQ: I had not thought about deduplication. I looked at scan-build and it 
looks like it currently de-dups based on MD5 matches of the HTML files. The 
simple case of multi-file reports with the same MD5 (e.g. because of repeated 
compilations of a single file during a build) being deduplicated still works 
correctly.

I also looked at what would happen if two separate C files include a common 
header file that only generates a report with -analyzer-opt-analyze-headers 
specified (e.g. if the path originates in the header file and doesn’t traverse 
the main C file at all.) This generated zero reports! My logic assumed the main 
file would always be included in the path and threw away 
-analyzer-opt-analyze-headers reports incorrectly. I was able to fix the logic 
such that these reports are correctly generated and also properly deduplicated 
by structuring the reports such that the main C file source is not included if 
it’s not traversed in the path.

@zaks.anna: I’ve added the single file output option but I would like to keep 
the multi-file option default—I suspect there are very few users parsing the 
HTML manually when plist is available and I’d like to ensure people don’t miss 
any results or have to dig into the source to understand they needed something 
other than the default output setting. What do you think?


https://reviews.llvm.org/D30406

Files:
  include/clang/StaticAnalyzer/Core/Analyses.def
  lib/Rewrite/HTMLRewrite.cpp
  lib/StaticAnalyzer/Core/HTMLDiagnostics.cpp
  test/Analysis/diagnostics/diag-cross-file-boundaries.c
  test/Analysis/diagnostics/diag-cross-file-boundaries.h
  test/Analysis/html-diag-singlefile.c
  test/Analysis/html-diag-singlefile.h
  test/Analysis/html-diags-analyze-headers.c
  test/Analysis/html-diags-analyze-headers.h
  test/Analysis/html-diags-multifile.c
  test/Analysis/html-diags.c
  test/Coverage/html-diagnostics.c
  test/Coverage/html-multifile-diagnostics.c
  test/Coverage/html-multifile-diagnostics.h
  www/analyzer/open_projects.html

Index: www/analyzer/open_projects.html
===
--- www/analyzer/open_projects.html
+++ www/analyzer/open_projects.html
@@ -107,13 +107,6 @@
 
   Bug Reporting 
   
-Add support for displaying cross-file diagnostic paths in HTML output
-(used by scan-build).
-Currently scan-build output does not display reports that span 
-multiple files. The main problem is that we do not have a good format to
-display such paths in HTML output. (Difficulty: Medium) 
-
-
 Refactor path diagnostic generation in http://clang.llvm.org/doxygen/BugReporter_8cpp_source.html;>BugReporter.cpp.
 It would be great to have more code reuse between "Minimal" and 
 "Extensive" PathDiagnostic generation algorithms. One idea is to create an 
Index: test/Coverage/html-multifile-diagnostics.h
===
--- /dev/null
+++ test/Coverage/html-multifile-diagnostics.h
@@ -0,0 +1,3 @@
+void f1(int *ptr) {
+  *ptr = 0;
+}
Index: test/Coverage/html-multifile-diagnostics.c
===
--- /dev/null
+++ test/Coverage/html-multifile-diagnostics.c
@@ -0,0 +1,21 @@
+// RUN: rm -rf %t
+// RUN: %clang_cc1 -analyze -analyzer-output=html -analyzer-checker=core -o %t %s
+// RUN: find %t -name "*.html" -exec cat "{}" ";" | FileCheck %s
+
+// REQUIRES: staticanalyzer
+
+// CHECK: Annotated Source Code
+
+// Make sure it's generated as multi-file HTML output
+// CHECK: {{.*}}html-multifile-diagnostics.c
+// CHECK: {{.*}}html-multifile-diagnostics.h
+
+// Without tweaking expr, the expr would hit to the line below
+// emitted to the output as comment.
+// CHECK: {{[D]ereference of null pointer}}
+
+#include "html-multifile-diagnostics.h"
+
+void f0() {
+  f1((int*)0);
+}
Index: test/Coverage/html-diagnostics.c
===
--- test/Coverage/html-diagnostics.c
+++ test/Coverage/html-diagnostics.c
@@ -1,11 +1,18 @@
 // RUN: rm -rf %t
 // RUN: %clang_cc1 -analyze -analyzer-output=html -analyzer-checker=core -o %t %s
 // RUN: find %t -name "*.html" -exec cat "{}" ";" | FileCheck %s
+//
+// RUN: rm -rf %t
+// RUN: %clang_cc1 -analyze -analyzer-output=html-single-file -analyzer-checker=core -o %t %s
+// RUN: find %t -name "*.html" -exec cat "{}" ";" | FileCheck %s
 
 // REQUIRES: staticanalyzer
 
 // CHECK: Annotated Source Code
 
+// Make sure it's not generated as a multi-file HTML output
+// CHECK-NOT: {{.*}}
+
 // Without 

[PATCH] D30406: [Analyzer] Add support for displaying cross-file diagnostic paths in HTML output

2017-02-27 Thread Vlad Tsyrklevich via Phabricator via cfe-commits
vlad.tsyrklevich added a comment.

Here's an example 3 file report from the Linux source: 
https://cdn.rawgit.com/vlad902/73bd32181151f2f0b07fa501a0f0b627/raw/0106f09cdb0d045b757de3d71ddc58072d33/report2.html

It's not as immediately clear this is a multi-file output. Ideas to improve 
this could include anchor tags in the header for every file included, or 
augmenting the line count to something like '$FILE:$LINE' instead. I'm open to 
suggestions on this front.


https://reviews.llvm.org/D30406



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D30406: [Analyzer] Add support for displaying cross-file diagnostic paths in HTML output

2017-02-27 Thread Vlad Tsyrklevich via Phabricator via cfe-commits
vlad.tsyrklevich created this revision.

While looking at checker output with https://reviews.llvm.org/D30289 applied I 
realized I was missing results. After some digging I found that it's because 
the Linux kernel makes heavy use of inlined functions included in header files, 
and the resulting diagnostic path now included cross-file diagnostics which are 
unsupported. This change adds support for cross-file diagnostic paths, 
resulting in output that looks like 
https://rawgit.com/vlad902/805a58327e12636fef119cdeb21ad639/raw/48f4183152a15e3e0f6fddfdc4edeb75c5a62295/report.html
 If the diagnostic path is not cross-file, there is no change in the output.


https://reviews.llvm.org/D30406

Files:
  lib/Rewrite/HTMLRewrite.cpp
  lib/StaticAnalyzer/Core/HTMLDiagnostics.cpp
  test/Analysis/diagnostics/diag-cross-file-boundaries.c
  test/Analysis/diagnostics/diag-cross-file-boundaries.h
  test/Analysis/html-diags-multifile.c
  test/Coverage/html-diagnostics.c
  test/Coverage/html-multifile-diagnostics.c
  test/Coverage/html-multifile-diagnostics.h
  www/analyzer/open_projects.html

Index: www/analyzer/open_projects.html
===
--- www/analyzer/open_projects.html
+++ www/analyzer/open_projects.html
@@ -107,13 +107,6 @@
 
   Bug Reporting 
   
-Add support for displaying cross-file diagnostic paths in HTML output
-(used by scan-build).
-Currently scan-build output does not display reports that span 
-multiple files. The main problem is that we do not have a good format to
-display such paths in HTML output. (Difficulty: Medium) 
-
-
 Refactor path diagnostic generation in http://clang.llvm.org/doxygen/BugReporter_8cpp_source.html;>BugReporter.cpp.
 It would be great to have more code reuse between "Minimal" and 
 "Extensive" PathDiagnostic generation algorithms. One idea is to create an 
Index: test/Coverage/html-multifile-diagnostics.h
===
--- /dev/null
+++ test/Coverage/html-multifile-diagnostics.h
@@ -0,0 +1,3 @@
+void f1(int *ptr) {
+  *ptr = 0;
+}
Index: test/Coverage/html-multifile-diagnostics.c
===
--- /dev/null
+++ test/Coverage/html-multifile-diagnostics.c
@@ -0,0 +1,21 @@
+// RUN: rm -rf %t
+// RUN: %clang_cc1 -analyze -analyzer-output=html -analyzer-checker=core -o %t %s
+// RUN: find %t -name "*.html" -exec cat "{}" ";" | FileCheck %s
+
+// REQUIRES: staticanalyzer
+
+// CHECK: Annotated Source Code
+
+// Make sure it's generated as multi-file HTML output
+// CHECK: {{.*}}html-multifile-diagnostics.c
+// CHECK: {{.*}}html-multifile-diagnostics.h
+
+// Without tweaking expr, the expr would hit to the line below
+// emitted to the output as comment.
+// CHECK: {{[D]ereference of null pointer}}
+
+#include "html-multifile-diagnostics.h"
+
+void f0() {
+  f1((int*)0);
+}
Index: test/Coverage/html-diagnostics.c
===
--- test/Coverage/html-diagnostics.c
+++ test/Coverage/html-diagnostics.c
@@ -6,6 +6,9 @@
 
 // CHECK: Annotated Source Code
 
+// Make sure it's not generated as a multi-file HTML output
+// CHECK-NOT: {{.*}}
+
 // Without tweaking expr, the expr would hit to the line below
 // emitted to the output as comment.
 // CHECK: {{[D]ereference of null pointer}}
Index: test/Analysis/html-diags-multifile.c
===
--- test/Analysis/html-diags-multifile.c
+++ test/Analysis/html-diags-multifile.c
@@ -1,10 +1,9 @@
 // RUN: mkdir -p %t.dir
 // RUN: %clang_cc1 -analyze -analyzer-output=html -analyzer-checker=core -o %t.dir %s
-// RUN: ls %t.dir | not grep report
+// RUN: ls %t.dir | grep report
 // RUN: rm -fR %t.dir
 
-// This tests that we do not currently emit HTML diagnostics for reports that
-// cross file boundaries.
+// This tests that we emit HTML diagnostics for reports that cross file boundaries.
 
 #include "html-diags-multifile.h"
 
Index: test/Analysis/diagnostics/diag-cross-file-boundaries.h
===
--- test/Analysis/diagnostics/diag-cross-file-boundaries.h
+++ /dev/null
@@ -1,4 +0,0 @@
-static void f() {
-  int *p = 0;
-  *p = 1;   // expected-warning{{Dereference of null pointer}}
-}
Index: test/Analysis/diagnostics/diag-cross-file-boundaries.c
===
--- test/Analysis/diagnostics/diag-cross-file-boundaries.c
+++ /dev/null
@@ -1,12 +0,0 @@
-// RUN: %clang_cc1 -analyze -analyzer-checker=core -verify %s
-// RUN: %clang_cc1 -analyze -analyzer-checker=core -analyzer-output=html -o PR12421.html %s 2>&1 | FileCheck %s
-
-// Test for PR12421
-#include "diag-cross-file-boundaries.h"
-
-int main(){
-  f();
-  return 0;
-}
-
-// CHECK: warning: Path diagnostic report is not generated.
Index: 

[PATCH] D30289: [Analyzer] Add bug visitor for taint checker

2017-02-23 Thread Vlad Tsyrklevich via Phabricator via cfe-commits
vlad.tsyrklevich updated this revision to Diff 89497.
vlad.tsyrklevich marked 2 inline comments as done.
vlad.tsyrklevich added a comment.

Fixes and a test for Artem's suggestions.


https://reviews.llvm.org/D30289

Files:
  lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp
  test/Analysis/taint-diagnostic-visitor.c


Index: test/Analysis/taint-diagnostic-visitor.c
===
--- /dev/null
+++ test/Analysis/taint-diagnostic-visitor.c
@@ -0,0 +1,13 @@
+// RUN: %clang_cc1 -analyze -analyzer-checker=alpha.security.taint,core 
-analyzer-output=text -verify %s
+
+// This file is for testing enhanced diagnostics produced by the 
GenericTaintChecker
+
+int scanf(const char *restrict format, ...);
+int system(const char *command);
+
+void taintDiagnostic()
+{
+  char buf[128];
+  scanf("%s", buf); // expected-note {{Taint originated here}}
+  system(buf); // expected-warning {{Untrusted data is passed to a system 
call}} // expected-note {{Untrusted data is passed to a system call 
(CERT/STR02-C. Sanitize data passed to complex subsystems)}}
+}
Index: lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp
===
--- lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp
+++ lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp
@@ -101,6 +101,22 @@
   bool generateReportIfTainted(const Expr *E, const char Msg[],
CheckerContext ) const;
 
+  /// The bug visitor prints a diagnostic message at the location where a given
+  /// variable was tainted.
+  class TaintBugVisitor
+  : public BugReporterVisitorImpl {
+  private:
+const SVal V;
+
+  public:
+TaintBugVisitor(const SVal V) : V(V) {}
+void Profile(llvm::FoldingSetNodeID ) const override { ID.Add(V); }
+
+std::shared_ptr VisitNode(const ExplodedNode *N,
+   const ExplodedNode *PrevN,
+   BugReporterContext ,
+   BugReport ) override;
+  };
 
   typedef SmallVector ArgVector;
 
@@ -194,6 +210,28 @@
 /// points to data, which should be tainted on return.
 REGISTER_SET_WITH_PROGRAMSTATE(TaintArgsOnPostVisit, unsigned)
 
+std::shared_ptr
+GenericTaintChecker::TaintBugVisitor::VisitNode(const ExplodedNode *N,
+const ExplodedNode *PrevN, BugReporterContext , BugReport ) {
+
+  // Find the ExplodedNode where the taint was first introduced
+  if (!N->getState()->isTainted(V) || PrevN->getState()->isTainted(V))
+return nullptr;
+
+  const Stmt *S = PathDiagnosticLocation::getStmt(N);
+  if (!S)
+return nullptr;
+
+  const LocationContext *NCtx = N->getLocationContext();
+  PathDiagnosticLocation L =
+  PathDiagnosticLocation::createBegin(S, BRC.getSourceManager(), NCtx);
+  if (!L.isValid() || !L.asLocation().isValid())
+return nullptr;
+
+  return std::make_shared(
+  L, "Taint originated here");
+}
+
 GenericTaintChecker::TaintPropagationRule
 GenericTaintChecker::TaintPropagationRule::getTaintPropagationRule(
  const FunctionDecl *FDecl,
@@ -635,15 +673,21 @@
 
   // Check for taint.
   ProgramStateRef State = C.getState();
-  if (!State->isTainted(getPointedToSymbol(C, E)) &&
-  !State->isTainted(E, C.getLocationContext()))
+  const SymbolRef PointedToSym = getPointedToSymbol(C, E);
+  SVal TaintedSVal;
+  if (State->isTainted(PointedToSym))
+TaintedSVal = nonloc::SymbolVal(PointedToSym);
+  else if (State->isTainted(E, C.getLocationContext()))
+TaintedSVal = C.getSVal(E);
+  else
 return false;
 
   // Generate diagnostic.
   if (ExplodedNode *N = C.generateNonFatalErrorNode()) {
 initBugType();
 auto report = llvm::make_unique(*BT, Msg, N);
 report->addRange(E->getSourceRange());
+report->addVisitor(llvm::make_unique(TaintedSVal));
 C.emitReport(std::move(report));
 return true;
   }


Index: test/Analysis/taint-diagnostic-visitor.c
===
--- /dev/null
+++ test/Analysis/taint-diagnostic-visitor.c
@@ -0,0 +1,13 @@
+// RUN: %clang_cc1 -analyze -analyzer-checker=alpha.security.taint,core -analyzer-output=text -verify %s
+
+// This file is for testing enhanced diagnostics produced by the GenericTaintChecker
+
+int scanf(const char *restrict format, ...);
+int system(const char *command);
+
+void taintDiagnostic()
+{
+  char buf[128];
+  scanf("%s", buf); // expected-note {{Taint originated here}}
+  system(buf); // expected-warning {{Untrusted data is passed to a system call}} // expected-note {{Untrusted data is passed to a system call (CERT/STR02-C. Sanitize data passed to complex subsystems)}}
+}
Index: lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp
===
--- lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp

[PATCH] D30289: [Analyzer] Add bug visitor for taint checker

2017-02-23 Thread Vlad Tsyrklevich via Phabricator via cfe-commits
vlad.tsyrklevich created this revision.

Add a bug visitor to the taint checker to make it easy to distinguish where the 
tainted value originated. This is especially useful when the original taint 
source is obscured by complex data flow.


https://reviews.llvm.org/D30289

Files:
  lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp


Index: lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp
===
--- lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp
+++ lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp
@@ -101,6 +101,22 @@
   bool generateReportIfTainted(const Expr *E, const char Msg[],
CheckerContext ) const;
 
+  /// The bug visitor prints a diagnostic message at the location where a given
+  /// variable was tainted.
+  class TaintBugVisitor
+  : public BugReporterVisitorImpl {
+  private:
+const SVal S;
+
+  public:
+TaintBugVisitor(const SVal S) : S(S) {}
+void Profile(llvm::FoldingSetNodeID ) const override { ID.Add(S); }
+
+std::shared_ptr VisitNode(const ExplodedNode *N,
+   const ExplodedNode *PrevN,
+   BugReporterContext ,
+   BugReport ) override;
+  };
 
   typedef SmallVector ArgVector;
 
@@ -194,6 +210,28 @@
 /// points to data, which should be tainted on return.
 REGISTER_SET_WITH_PROGRAMSTATE(TaintArgsOnPostVisit, unsigned)
 
+std::shared_ptr
+GenericTaintChecker::TaintBugVisitor::VisitNode(const ExplodedNode *N,
+const ExplodedNode *PrevN, BugReporterContext , BugReport ) {
+
+  // Find the ExplodedNode where the taint was first introduced
+  if (!N->getState()->isTainted(S) || PrevN->getState()->isTainted(S))
+return nullptr;
+
+  const Stmt *S = PathDiagnosticLocation::getStmt(N);
+  if (!S)
+return nullptr;
+
+  const LocationContext *NCtx = N->getLocationContext();
+  PathDiagnosticLocation L =
+  PathDiagnosticLocation::createBegin(S, BRC.getSourceManager(), NCtx);
+  if (!L.isValid() || !L.asLocation().isValid())
+return nullptr;
+
+  return std::make_shared(
+  L, "Taint originated here");
+}
+
 GenericTaintChecker::TaintPropagationRule
 GenericTaintChecker::TaintPropagationRule::getTaintPropagationRule(
  const FunctionDecl *FDecl,
@@ -635,15 +673,21 @@
 
   // Check for taint.
   ProgramStateRef State = C.getState();
-  if (!State->isTainted(getPointedToSymbol(C, E)) &&
-  !State->isTainted(E, C.getLocationContext()))
+  const SymbolRef PointedToSym = getPointedToSymbol(C, E);
+  SVal TaintedSVal;
+  if (State->isTainted(PointedToSym))
+TaintedSVal = nonloc::SymbolVal(PointedToSym);
+  else if (State->isTainted(E, C.getLocationContext()))
+TaintedSVal = State->getSVal(E, C.getLocationContext());
+  else
 return false;
 
   // Generate diagnostic.
   if (ExplodedNode *N = C.generateNonFatalErrorNode()) {
 initBugType();
 auto report = llvm::make_unique(*BT, Msg, N);
 report->addRange(E->getSourceRange());
+report->addVisitor(llvm::make_unique(TaintedSVal));
 C.emitReport(std::move(report));
 return true;
   }


Index: lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp
===
--- lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp
+++ lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp
@@ -101,6 +101,22 @@
   bool generateReportIfTainted(const Expr *E, const char Msg[],
CheckerContext ) const;
 
+  /// The bug visitor prints a diagnostic message at the location where a given
+  /// variable was tainted.
+  class TaintBugVisitor
+  : public BugReporterVisitorImpl {
+  private:
+const SVal S;
+
+  public:
+TaintBugVisitor(const SVal S) : S(S) {}
+void Profile(llvm::FoldingSetNodeID ) const override { ID.Add(S); }
+
+std::shared_ptr VisitNode(const ExplodedNode *N,
+   const ExplodedNode *PrevN,
+   BugReporterContext ,
+   BugReport ) override;
+  };
 
   typedef SmallVector ArgVector;
 
@@ -194,6 +210,28 @@
 /// points to data, which should be tainted on return.
 REGISTER_SET_WITH_PROGRAMSTATE(TaintArgsOnPostVisit, unsigned)
 
+std::shared_ptr
+GenericTaintChecker::TaintBugVisitor::VisitNode(const ExplodedNode *N,
+const ExplodedNode *PrevN, BugReporterContext , BugReport ) {
+
+  // Find the ExplodedNode where the taint was first introduced
+  if (!N->getState()->isTainted(S) || PrevN->getState()->isTainted(S))
+return nullptr;
+
+  const Stmt *S = PathDiagnosticLocation::getStmt(N);
+  if (!S)
+return nullptr;
+
+  const LocationContext *NCtx = N->getLocationContext();
+  PathDiagnosticLocation L =
+  

[PATCH] D28445: [Analyzer] Extend taint propagation and checking

2017-02-22 Thread Vlad Tsyrklevich via Phabricator via cfe-commits
vlad.tsyrklevich updated this revision to Diff 89467.
vlad.tsyrklevich added a comment.

@NoQ I've tried to address all the issues you mentioned in this change. Let me 
know if the expanded documentation doesn't address what you were looking for.


https://reviews.llvm.org/D28445

Files:
  include/clang/StaticAnalyzer/Core/PathSensitive/Store.h
  lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp
  lib/StaticAnalyzer/Core/RegionStore.cpp
  test/Analysis/taint-generic.c

Index: test/Analysis/taint-generic.c
===
--- test/Analysis/taint-generic.c
+++ test/Analysis/taint-generic.c
@@ -169,6 +169,43 @@
   sock = socket(AF_LOCAL, SOCK_STREAM, 0);
   read(sock, buffer, 100);
   execl(buffer, "filename", 0); // no-warning
+
+  sock = socket(AF_INET, SOCK_STREAM, 0);
+  // References to both buffer and  as an argument should taint the argument
+  read(sock, , 100);
+  execl(buffer, "filename", 0); // expected-warning {{Untrusted data is passed to a system call}}
+}
+
+void testStruct() {
+  struct {
+char buf[16];
+int length;
+  } tainted;
+
+  char buffer[16];
+  int sock;
+
+  sock = socket(AF_INET, SOCK_STREAM, 0);
+  read(sock, , sizeof(tainted));
+  __builtin_memcpy(buffer, tainted.buf, tainted.length); // expected-warning {{Untrusted data is used to specify the buffer size}}
+}
+
+void testStructArray() {
+  struct {
+char buf[16];
+struct {
+  int length;
+} st[1];
+  } tainted;
+
+  char buffer[16];
+  int sock;
+
+  sock = socket(AF_INET, SOCK_STREAM, 0);
+  read(sock, [0], sizeof(tainted.buf));
+  read(sock, [0], sizeof(tainted.st));
+  // FIXME: tainted.st[0].length should be marked tainted
+  __builtin_memcpy(buffer, tainted.buf, tainted.st[0].length); // no-warning
 }
 
 int testDivByZero() {
Index: lib/StaticAnalyzer/Core/RegionStore.cpp
===
--- lib/StaticAnalyzer/Core/RegionStore.cpp
+++ lib/StaticAnalyzer/Core/RegionStore.cpp
@@ -494,6 +494,11 @@
 return getBinding(getRegionBindings(S), L, T);
   }
 
+  Optional getDefaultBinding(Store S, const MemRegion *R) override {
+RegionBindingsRef B = getRegionBindings(S);
+return B.getDefaultBinding(R);
+  }
+
   SVal getBinding(RegionBindingsConstRef B, Loc L, QualType T = QualType());
 
   SVal getBindingForElement(RegionBindingsConstRef B, const ElementRegion *R);
Index: lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp
===
--- lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp
+++ lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp
@@ -65,6 +65,18 @@
   /// and thus, is tainted.
   static bool isStdin(const Expr *E, CheckerContext );
 
+  /// This is called from getPointedToSymbol() to resolve symbol references for
+  /// the region underlying a LazyCompoundVal. This is the default binding
+  /// for the LCV, which could be a conjured symbol from a function call that
+  /// initialized the region. It only returns the conjured symbol if the LCV
+  /// covers the entire region, e.g. we avoid false positives by not returning
+  /// a default bindingc for an entire struct if the symbol for only a single
+  /// field or element within it is requested.
+  // TODO: Return an appropriate symbol for sub-fields/elements of an LCV so
+  // that they are also appropriately tainted.
+  static SymbolRef getLCVSymbol(CheckerContext ,
+nonloc::LazyCompoundVal );
+
   /// \brief Given a pointer argument, get the symbol of the value it contains
   /// (points to).
   static SymbolRef getPointedToSymbol(CheckerContext , const Expr *Arg);
@@ -423,6 +435,27 @@
   return false;
 }
 
+SymbolRef GenericTaintChecker::getLCVSymbol(CheckerContext ,
+nonloc::LazyCompoundVal ) {
+  StoreManager  = C.getStoreManager();
+
+  // getLCVSymbol() is reached in a PostStmt so we can always expect a default
+  // binding to exist if one is present.
+  if (Optional binding = StoreMgr.getDefaultBinding(LCV)) {
+SymbolRef Sym = binding->getAsSymbol();
+if (!Sym)
+  return nullptr;
+
+// If the LCV covers an entire base region return the default conjured symbol.
+if (LCV.getRegion() == LCV.getRegion()->getBaseRegion())
+  return Sym;
+  }
+
+  // Otherwise, return a nullptr as there's not yet a functional way to taint
+  // sub-regions of LCVs.
+  return nullptr;
+}
+
 SymbolRef GenericTaintChecker::getPointedToSymbol(CheckerContext ,
   const Expr* Arg) {
   ProgramStateRef State = C.getState();
@@ -438,6 +471,10 @@
 dyn_cast(Arg->getType().getCanonicalType().getTypePtr());
   SVal Val = State->getSVal(*AddrLoc,
 ArgTy ? ArgTy->getPointeeType(): QualType());
+
+  if (auto LCV = Val.getAs())
+return getLCVSymbol(C, *LCV);
+
   return Val.getAsSymbol();
 }
 
Index: 

[PATCH] D28445: [Analyzer] Extend taint propagation and checking

2017-02-15 Thread Vlad Tsyrklevich via Phabricator via cfe-commits
vlad.tsyrklevich added inline comments.



Comment at: lib/StaticAnalyzer/Core/RegionStore.cpp:502
+RegionBindingsRef B = getRegionBindings(S);
+const MemRegion *MR  = L.getRegion()->getBaseRegion();
+if (Optional V = B.getDefaultBinding(MR))

vlad.tsyrklevich wrote:
> vlad.tsyrklevich wrote:
> > a.sidorin wrote:
> > > We get the LazyCompoundVal for some region but return the symbol for its 
> > > base. It means that at least method name is very confusing.
> > I believe that default bindings are only on base regions, so if you pass a 
> > reference to `outer_struct.inner_struct` the default binding for that LCV 
> > will be over `outer_struct`. I'm basing this on other references to LCVs in 
> > Core/RegionStore.cpp but I could be wrong. Either way, I'd be happy to 
> > change the interface to have the caller pass the correct MemRegion here.
> One change we could introduce to make getDefaultBinding() more explicit is to 
> have the caller pass LCV.getRegion()->getBaseRegion() instead of just passing 
> the LCV. However, this has the disadvantage of hardcoding an implementation 
> detail of RegionStoreManager into users of the StoreManager interface. I 
> think the correct way forward here might just be to add a comment that 
> mentions that currently RegionStoreManagers bindings are only over base 
> regions. What do you think?
I spoke too soon, after digging a little deeper I realized that lookups using 
`RegionBindingsRef ::getDefaultBinding` converts to a base region check anyway 
in `BindingKey::Make`. Therefore it'd be better to just completely hide that 
implementation detail to the RegionBindings than hard coding it here 
unnecessarily. The updated revision corrects this.


https://reviews.llvm.org/D28445



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D28445: [Analyzer] Extend taint propagation and checking

2017-02-15 Thread Vlad Tsyrklevich via Phabricator via cfe-commits
vlad.tsyrklevich updated this revision to Diff 88493.
vlad.tsyrklevich added a comment.

Remove an unnecessary call to `getBaseRegion()`, remove the logic to create a 
new SymbolDerived as it's currently unused, and add a comment to reflect that 
`getLCVSymbol()` is called in a PostStmt and a default binding should always be 
present.


https://reviews.llvm.org/D28445

Files:
  include/clang/StaticAnalyzer/Core/PathSensitive/Store.h
  lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp
  lib/StaticAnalyzer/Core/RegionStore.cpp
  test/Analysis/taint-generic.c

Index: test/Analysis/taint-generic.c
===
--- test/Analysis/taint-generic.c
+++ test/Analysis/taint-generic.c
@@ -169,6 +169,43 @@
   sock = socket(AF_LOCAL, SOCK_STREAM, 0);
   read(sock, buffer, 100);
   execl(buffer, "filename", 0); // no-warning
+
+  sock = socket(AF_INET, SOCK_STREAM, 0);
+  // References to both buffer and  as an argument should taint the argument
+  read(sock, , 100);
+  execl(buffer, "filename", 0); // expected-warning {{Untrusted data is passed to a system call}}
+}
+
+void testStruct() {
+  struct {
+char buf[16];
+int length;
+  } tainted;
+
+  char buffer[16];
+  int sock;
+
+  sock = socket(AF_INET, SOCK_STREAM, 0);
+  read(sock, , sizeof(tainted));
+  __builtin_memcpy(buffer, tainted.buf, tainted.length); // expected-warning {{Untrusted data is used to specify the buffer size}}
+}
+
+void testStructArray() {
+  struct {
+char buf[16];
+struct {
+  int length;
+} st[1];
+  } tainted;
+
+  char buffer[16];
+  int sock;
+
+  sock = socket(AF_INET, SOCK_STREAM, 0);
+  read(sock, [0], sizeof(tainted.buf));
+  read(sock, [0], sizeof(tainted.st));
+  // FIXME: tainted.st[0].length should be marked tainted
+  __builtin_memcpy(buffer, tainted.buf, tainted.st[0].length); // no-warning
 }
 
 int testDivByZero() {
Index: lib/StaticAnalyzer/Core/RegionStore.cpp
===
--- lib/StaticAnalyzer/Core/RegionStore.cpp
+++ lib/StaticAnalyzer/Core/RegionStore.cpp
@@ -494,6 +494,17 @@
 return getBinding(getRegionBindings(S), L, T);
   }
 
+  SVal getDefaultBinding(Store S, nonloc::LazyCompoundVal L) override {
+if (!L.getRegion())
+  return UnknownVal();
+
+RegionBindingsRef B = getRegionBindings(S);
+if (Optional V = B.getDefaultBinding(L.getRegion()))
+  return *V;
+
+return UnknownVal();
+  }
+
   SVal getBinding(RegionBindingsConstRef B, Loc L, QualType T = QualType());
 
   SVal getBindingForElement(RegionBindingsConstRef B, const ElementRegion *R);
Index: lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp
===
--- lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp
+++ lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp
@@ -65,6 +65,10 @@
   /// and thus, is tainted.
   static bool isStdin(const Expr *E, CheckerContext );
 
+  /// \brief Get the symbol for the region underlying a LazyCompoundVal.
+  static SymbolRef getLCVSymbol(CheckerContext ,
+nonloc::LazyCompoundVal );
+
   /// \brief Given a pointer argument, get the symbol of the value it contains
   /// (points to).
   static SymbolRef getPointedToSymbol(CheckerContext , const Expr *Arg);
@@ -423,6 +427,25 @@
   return false;
 }
 
+SymbolRef GenericTaintChecker::getLCVSymbol(CheckerContext ,
+nonloc::LazyCompoundVal ) {
+  StoreManager  = C.getStoreManager();
+
+  // getLCVSymbol() is reached in a PostStmt so we can always expect a default
+  // binding to exist if one is present.
+  SymbolRef Sym = StoreMgr.getDefaultBinding(LCV.getStore(), LCV).getAsSymbol();
+  if (!Sym)
+return nullptr;
+
+  // If the LCV covers an entire base region return the default conjured symbol.
+  if (LCV.getRegion() == LCV.getRegion()->getBaseRegion())
+return Sym;
+
+  // Otherwise, return a nullptr as there's not yet a functional way to taint
+  // sub-regions of LCVs.
+  return nullptr;
+}
+
 SymbolRef GenericTaintChecker::getPointedToSymbol(CheckerContext ,
   const Expr* Arg) {
   ProgramStateRef State = C.getState();
@@ -438,6 +461,10 @@
 dyn_cast(Arg->getType().getCanonicalType().getTypePtr());
   SVal Val = State->getSVal(*AddrLoc,
 ArgTy ? ArgTy->getPointeeType(): QualType());
+
+  if (auto LCV = Val.getAs())
+return getLCVSymbol(C, *LCV);
+
   return Val.getAsSymbol();
 }
 
Index: include/clang/StaticAnalyzer/Core/PathSensitive/Store.h
===
--- include/clang/StaticAnalyzer/Core/PathSensitive/Store.h
+++ include/clang/StaticAnalyzer/Core/PathSensitive/Store.h
@@ -59,6 +59,12 @@
   /// \return The value bound to the location \c loc.
   virtual SVal getBinding(Store store, Loc loc, QualType T = QualType()) = 0;
 
+  /// Return the 

[PATCH] D28445: [Analyzer] Extend taint propagation and checking

2017-02-15 Thread Vlad Tsyrklevich via Phabricator via cfe-commits
vlad.tsyrklevich added inline comments.



Comment at: lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp:442
+
+const RecordDecl *RD = RT->getDecl()->getDefinition();
+for (const auto *I : RD->fields()) {

a.sidorin wrote:
> vlad.tsyrklevich wrote:
> > a.sidorin wrote:
> > > NoQ wrote:
> > > > We need to be careful in the case when we don't have the definition in 
> > > > the current translation unit. In this case we may still have derived 
> > > > symbols by casting the pointer into some blindly guessed type, which 
> > > > may be primitive or having well-defined primitive fields.
> > > > 
> > > > By the way, in D26837 i'm suspecting that there are other errors of 
> > > > this kind in the checker, eg. when a function returns a void pointer, 
> > > > we put taint on symbols of type "void", which is weird.
> > > > 
> > > > Adding Alexey who may recall something on this topic.
> > > I will check the correctness of this code sample because I have some 
> > > doubts about it.
> > > The problem of casts is hard because of our approach to put taints on 0th 
> > > elements. We lose casts and may get some strange void symbols. However, I 
> > > guess this patch isn't related to this problem directly.
> > Not sure which form of correctness you're interested in here but I'll bring 
> > up one issue I'm aware of: currently this will create a new SymbolDerived 
> > for an LCV sub-region, but it won't be correctly matched against in 
> > `isTainted()` because subsequent references to the same region will have a 
> > different SymbolDerived. This is the FIXME I mentioned below in 
> > `taint-generic.c` I have some idea on how to fix this but I think it will 
> > probably require more back and forth, hence why I didn't include it in this 
> > change. As it stands now, the sub-region tainting could be removed without 
> > changing the functionality of the current patch.
> Checking a default binding symbol here works because we're in PostStmt of the 
> call that creates this default binding. I think this machinery deserves a 
> comment, it was not evident for me initially.
> However, I don't like to create a SymbolDerived manually. The first idea is 
> to just use getSVal(MemRegion*) which will return a SymbolDerived if it is. 
> The second is to create... SymbolMetadata that will carry a taint (if the 
> value is not a symbol, for example). Not sure if second idea is sane enough, 
> I need some comments on it. Artem, Anna?
> Also, instead of referring to the base region, we may need to walk parents 
> one-by-one.
I'd rather just get rid of the tainted SymbolDerived and re-introduce it for 
discussion in the follow-up change as it's currently not functional anyway and 
there is some room for debate on the correct way to make tainting of 
sub-regions of LCVs work correctly. 

As far as walking parents one-by-one, my current understanding of the 
RegionStoreManager led me to believe that that would be unnecessary. Currently, 
all bindings are made as offsets from a base region, reference the 
implementation of `RegionBindingsRef::addBinding`. Is there another reason to 
walk the parents that I'm missing?



Comment at: lib/StaticAnalyzer/Core/RegionStore.cpp:502
+RegionBindingsRef B = getRegionBindings(S);
+const MemRegion *MR  = L.getRegion()->getBaseRegion();
+if (Optional V = B.getDefaultBinding(MR))

vlad.tsyrklevich wrote:
> a.sidorin wrote:
> > We get the LazyCompoundVal for some region but return the symbol for its 
> > base. It means that at least method name is very confusing.
> I believe that default bindings are only on base regions, so if you pass a 
> reference to `outer_struct.inner_struct` the default binding for that LCV 
> will be over `outer_struct`. I'm basing this on other references to LCVs in 
> Core/RegionStore.cpp but I could be wrong. Either way, I'd be happy to change 
> the interface to have the caller pass the correct MemRegion here.
One change we could introduce to make getDefaultBinding() more explicit is to 
have the caller pass LCV.getRegion()->getBaseRegion() instead of just passing 
the LCV. However, this has the disadvantage of hardcoding an implementation 
detail of RegionStoreManager into users of the StoreManager interface. I think 
the correct way forward here might just be to add a comment that mentions that 
currently RegionStoreManagers bindings are only over base regions. What do you 
think?


https://reviews.llvm.org/D28445



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D28445: [Analyzer] Extend taint propagation and checking

2017-02-08 Thread Vlad Tsyrklevich via Phabricator via cfe-commits
vlad.tsyrklevich added inline comments.



Comment at: lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp:442
+
+const RecordDecl *RD = RT->getDecl()->getDefinition();
+for (const auto *I : RD->fields()) {

a.sidorin wrote:
> NoQ wrote:
> > We need to be careful in the case when we don't have the definition in the 
> > current translation unit. In this case we may still have derived symbols by 
> > casting the pointer into some blindly guessed type, which may be primitive 
> > or having well-defined primitive fields.
> > 
> > By the way, in D26837 i'm suspecting that there are other errors of this 
> > kind in the checker, eg. when a function returns a void pointer, we put 
> > taint on symbols of type "void", which is weird.
> > 
> > Adding Alexey who may recall something on this topic.
> I will check the correctness of this code sample because I have some doubts 
> about it.
> The problem of casts is hard because of our approach to put taints on 0th 
> elements. We lose casts and may get some strange void symbols. However, I 
> guess this patch isn't related to this problem directly.
Not sure which form of correctness you're interested in here but I'll bring up 
one issue I'm aware of: currently this will create a new SymbolDerived for an 
LCV sub-region, but it won't be correctly matched against in `isTainted()` 
because subsequent references to the same region will have a different 
SymbolDerived. This is the FIXME I mentioned below in `taint-generic.c` I have 
some idea on how to fix this but I think it will probably require more back and 
forth, hence why I didn't include it in this change. As it stands now, the 
sub-region tainting could be removed without changing the functionality of the 
current patch.



Comment at: lib/StaticAnalyzer/Core/RegionStore.cpp:502
+RegionBindingsRef B = getRegionBindings(S);
+const MemRegion *MR  = L.getRegion()->getBaseRegion();
+if (Optional V = B.getDefaultBinding(MR))

a.sidorin wrote:
> We get the LazyCompoundVal for some region but return the symbol for its 
> base. It means that at least method name is very confusing.
I believe that default bindings are only on base regions, so if you pass a 
reference to `outer_struct.inner_struct` the default binding for that LCV will 
be over `outer_struct`. I'm basing this on other references to LCVs in 
Core/RegionStore.cpp but I could be wrong. Either way, I'd be happy to change 
the interface to have the caller pass the correct MemRegion here.


https://reviews.llvm.org/D28445



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D28445: [Analyzer] Extend taint propagation and checking

2017-02-06 Thread Vlad Tsyrklevich via Phabricator via cfe-commits
vlad.tsyrklevich updated this revision to Diff 87237.
vlad.tsyrklevich marked 4 inline comments as done.
vlad.tsyrklevich added a comment.

As Artem mentioned, I reworked `getLCVSymbol()` to get the default bindings 
directly from the StoreManager which required adding a new method. I also 
reverted the tainting logic to add taint more conservatively. I have another 
change that will fix the new FIXME test that is added, but it might involved 
some refactoring and discussion so I've left it out to make this change as 
simple as possible.


https://reviews.llvm.org/D28445

Files:
  include/clang/StaticAnalyzer/Core/PathSensitive/Store.h
  lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp
  lib/StaticAnalyzer/Core/RegionStore.cpp
  test/Analysis/taint-generic.c

Index: test/Analysis/taint-generic.c
===
--- test/Analysis/taint-generic.c
+++ test/Analysis/taint-generic.c
@@ -169,6 +169,43 @@
   sock = socket(AF_LOCAL, SOCK_STREAM, 0);
   read(sock, buffer, 100);
   execl(buffer, "filename", 0); // no-warning
+
+  sock = socket(AF_INET, SOCK_STREAM, 0);
+  // References to both buffer and  as an argument should taint the argument
+  read(sock, , 100);
+  execl(buffer, "filename", 0); // expected-warning {{Untrusted data is passed to a system call}}
+}
+
+void testStruct() {
+  struct {
+char buf[16];
+int length;
+  } tainted;
+
+  char buffer[16];
+  int sock;
+
+  sock = socket(AF_INET, SOCK_STREAM, 0);
+  read(sock, , sizeof(tainted));
+  __builtin_memcpy(buffer, tainted.buf, tainted.length); // expected-warning {{Untrusted data is used to specify the buffer size}}
+}
+
+void testStructArray() {
+  struct {
+char buf[16];
+struct {
+  int length;
+} st[1];
+  } tainted;
+
+  char buffer[16];
+  int sock;
+
+  sock = socket(AF_INET, SOCK_STREAM, 0);
+  read(sock, [0], sizeof(tainted.buf));
+  read(sock, [0], sizeof(tainted.st));
+  // FIXME: tainted.st[0].length should be marked tainted
+  __builtin_memcpy(buffer, tainted.buf, tainted.st[0].length); // no-warning
 }
 
 int testDivByZero() {
Index: lib/StaticAnalyzer/Core/RegionStore.cpp
===
--- lib/StaticAnalyzer/Core/RegionStore.cpp
+++ lib/StaticAnalyzer/Core/RegionStore.cpp
@@ -494,6 +494,18 @@
 return getBinding(getRegionBindings(S), L, T);
   }
 
+  SVal getDefaultBinding(Store S, nonloc::LazyCompoundVal L) override {
+if (!L.getRegion())
+  return UnknownVal();
+
+RegionBindingsRef B = getRegionBindings(S);
+const MemRegion *MR  = L.getRegion()->getBaseRegion();
+if (Optional V = B.getDefaultBinding(MR))
+  return *V;
+
+return UnknownVal();
+  }
+
   SVal getBinding(RegionBindingsConstRef B, Loc L, QualType T = QualType());
 
   SVal getBindingForElement(RegionBindingsConstRef B, const ElementRegion *R);
Index: lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp
===
--- lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp
+++ lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp
@@ -65,6 +65,10 @@
   /// and thus, is tainted.
   static bool isStdin(const Expr *E, CheckerContext );
 
+  /// \brief Get the symbol for the region underlying a LazyCompoundVal.
+  static SymbolRef getLCVSymbol(CheckerContext ,
+nonloc::LazyCompoundVal );
+
   /// \brief Given a pointer argument, get the symbol of the value it contains
   /// (points to).
   static SymbolRef getPointedToSymbol(CheckerContext , const Expr *Arg);
@@ -423,6 +427,22 @@
   return false;
 }
 
+SymbolRef GenericTaintChecker::getLCVSymbol(CheckerContext ,
+nonloc::LazyCompoundVal ) {
+  StoreManager  = C.getStoreManager();
+  SymbolRef Sym = StoreMgr.getDefaultBinding(LCV.getStore(), LCV).getAsSymbol();
+  if (!Sym)
+return nullptr;
+
+  // If the LCV covers an entire base region, return the default conjured symbol
+  if (LCV.getRegion() == LCV.getRegion()->getBaseRegion())
+return Sym;
+
+  // Otherwise, return a derived symbol indicating only a sub-region is tainted
+  SymbolManager  = C.getSymbolManager();
+  return SM.getDerivedSymbol(Sym, LCV.getRegion());
+}
+
 SymbolRef GenericTaintChecker::getPointedToSymbol(CheckerContext ,
   const Expr* Arg) {
   ProgramStateRef State = C.getState();
@@ -438,6 +458,10 @@
 dyn_cast(Arg->getType().getCanonicalType().getTypePtr());
   SVal Val = State->getSVal(*AddrLoc,
 ArgTy ? ArgTy->getPointeeType(): QualType());
+
+  if (auto LCV = Val.getAs())
+return getLCVSymbol(C, *LCV);
+
   return Val.getAsSymbol();
 }
 
Index: include/clang/StaticAnalyzer/Core/PathSensitive/Store.h
===
--- include/clang/StaticAnalyzer/Core/PathSensitive/Store.h
+++ 

[PATCH] D28445: [Analyzer] Extend taint propagation and checking

2017-01-26 Thread Vlad Tsyrklevich via Phabricator via cfe-commits
vlad.tsyrklevich added a comment.

Hello @NoQ, I just wanted to ping you on the updated change since I'm not sure 
if you saw it.


https://reviews.llvm.org/D28445



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D28765: CStringChecker can crash when uninitialized checks are disabled

2017-01-19 Thread Vlad Tsyrklevich via Phabricator via cfe-commits
vlad.tsyrklevich abandoned this revision.
vlad.tsyrklevich added a comment.

The motivation was to make resulting output easier to navigate and to cut the 
result size by ~90%, one default run against the FreeBSD kernel takes 3 gigs of 
storage and I'm running several builds a day as I iterate on checks. I did not 
realize that running without core was unsupported. A silencing flag would have 
done the trick.


https://reviews.llvm.org/D28765



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D28765: CStringChecker can crash when uninitialized checks are disabled

2017-01-16 Thread Vlad Tsyrklevich via Phabricator via cfe-commits
vlad.tsyrklevich created this revision.
vlad.tsyrklevich added reviewers: cfe-commits, zaks.anna, dcoughlin, NoQ.

CStringChecker assumes that SVals are not undefined at two points with comments 
stating that other checkers will check for that condition first; however, it 
can crash if a user chooses a particular configuration. I hit such an unlucky 
configuration while eliminating false positive heavy checks analyzing the Linux 
kernel and tracked down the crashes to this assumption.

Add UndefinedVal checks where appropriate.


https://reviews.llvm.org/D28765

Files:
  lib/StaticAnalyzer/Checkers/CStringChecker.cpp
  test/Analysis/cstring-regressions.c


Index: test/Analysis/cstring-regressions.c
===
--- /dev/null
+++ test/Analysis/cstring-regressions.c
@@ -0,0 +1,18 @@
+// RUN: %clang_cc1 -analyze 
-analyzer-checker=core,unix.cstring,debug.ExprInspection 
-analyzer-disable-checker=core.UndefinedBinaryOperatorResult,core.CallAndMessage,core.NullDereference,core.uninitialized
 -analyzer-store=region -verify %s
+//
+// CStringChecker crashes found running analyzer over the Linux kernel source
+// with a very particular set of enabled/disabled checks.
+
+int strcmp(const char * s1, const char * s2);
+int memcmp(const void *s1, const void *s2, unsigned long n);
+void clang_analyzer_eval(int);
+
+void test1(void *ptr) {
+ int uninit;
+ clang_analyzer_eval(strcmp(ptr + uninit, "mcp_trace_meta") == 0); // 
expected-warning{{UNKNOWN}}
+}
+
+void test2(char *foo, void *ptr) {
+ int uninit;
+ clang_analyzer_eval(memcmp(foo, ptr + uninit, 48) == 0); // 
expected-warning{{UNKNOWN}}
+}
Index: lib/StaticAnalyzer/Checkers/CStringChecker.cpp
===
--- lib/StaticAnalyzer/Checkers/CStringChecker.cpp
+++ lib/StaticAnalyzer/Checkers/CStringChecker.cpp
@@ -1179,15 +1179,17 @@
   if (stateNonZeroSize) {
 state = stateNonZeroSize;
 // If we know the two buffers are the same, we know the result is 0.
-// First, get the two buffers' addresses. Another checker will have already
-// made sure they're not undefined.
-DefinedOrUnknownSVal LV =
-state->getSVal(Left, LCtx).castAs();
-DefinedOrUnknownSVal RV =
-state->getSVal(Right, LCtx).castAs();
+// First, get the two buffers' addresses.
+Optional LV =
+state->getSVal(Left, LCtx).getAs();
+Optional RV =
+state->getSVal(Right, LCtx).getAs();
+
+if (!LV || !RV)
+  return;
 
 // See if they are the same.
-DefinedOrUnknownSVal SameBuf = svalBuilder.evalEQ(state, LV, RV);
+DefinedOrUnknownSVal SameBuf = svalBuilder.evalEQ(state, *LV, *RV);
 ProgramStateRef StSameBuf, StNotSameBuf;
 std::tie(StSameBuf, StNotSameBuf) = state->assume(SameBuf);
 
@@ -1781,13 +1783,19 @@
   // Check that the first string is non-null
   const Expr *s1 = CE->getArg(0);
   SVal s1Val = state->getSVal(s1, LCtx);
+  if (s1Val.isUndef())
+return;
+
   state = checkNonNull(C, state, s1, s1Val);
   if (!state)
 return;
 
   // Check that the second string is non-null.
   const Expr *s2 = CE->getArg(1);
   SVal s2Val = state->getSVal(s2, LCtx);
+  if (s2Val.isUndef())
+return;
+
   state = checkNonNull(C, state, s2, s2Val);
   if (!state)
 return;
@@ -1803,8 +1811,7 @@
 return;
 
   // If we know the two buffers are the same, we know the result is 0.
-  // First, get the two buffers' addresses. Another checker will have already
-  // made sure they're not undefined.
+  // First, get the two buffers' addresses.
   DefinedOrUnknownSVal LV = s1Val.castAs();
   DefinedOrUnknownSVal RV = s2Val.castAs();
 


Index: test/Analysis/cstring-regressions.c
===
--- /dev/null
+++ test/Analysis/cstring-regressions.c
@@ -0,0 +1,18 @@
+// RUN: %clang_cc1 -analyze -analyzer-checker=core,unix.cstring,debug.ExprInspection -analyzer-disable-checker=core.UndefinedBinaryOperatorResult,core.CallAndMessage,core.NullDereference,core.uninitialized -analyzer-store=region -verify %s
+//
+// CStringChecker crashes found running analyzer over the Linux kernel source
+// with a very particular set of enabled/disabled checks.
+
+int strcmp(const char * s1, const char * s2);
+int memcmp(const void *s1, const void *s2, unsigned long n);
+void clang_analyzer_eval(int);
+
+void test1(void *ptr) {
+ int uninit;
+ clang_analyzer_eval(strcmp(ptr + uninit, "mcp_trace_meta") == 0); // expected-warning{{UNKNOWN}}
+}
+
+void test2(char *foo, void *ptr) {
+ int uninit;
+ clang_analyzer_eval(memcmp(foo, ptr + uninit, 48) == 0); // expected-warning{{UNKNOWN}}
+}
Index: lib/StaticAnalyzer/Checkers/CStringChecker.cpp
===
--- lib/StaticAnalyzer/Checkers/CStringChecker.cpp
+++ lib/StaticAnalyzer/Checkers/CStringChecker.cpp
@@ -1179,15 +1179,17 @@
   if (stateNonZeroSize) {
 state = stateNonZeroSize;
 

[PATCH] D28445: [Analyzer] Extend taint propagation and checking

2017-01-15 Thread Vlad Tsyrklevich via Phabricator via cfe-commits
vlad.tsyrklevich updated this revision to Diff 84517.
vlad.tsyrklevich added a comment.

Artem, thank you for the very detailed reply! Between this, and hitting the 
right search terms to find your clang analyzer guide my understanding of the 
symbol abstractions the analyzer exposes has improved significantly.

You state that it's not easy to derive the conjured symbols from the Store; 
however, it didn't seem to be too difficult to do by recursively finding the 
bindings for the constituent FieldRegions (if the LCV is backing a 
struct/union) or the first ElementRegion (if the LCV is backing an array) until 
you reach an element/field initialized with the conjured symbol. Does the new 
patch look correct to you? Your comment about the difficulty has me unsure 
whether I've fully grasped the scope of the problem.

One wrinkle you'll notice is in the patch to `taint-tester.c`, one FIXME for 
missing taint has been fixed, but now one variable that should not be tainted 
is! This seems to be because of overeager invalidation, not strictly the fault 
of the patch but it is exposed by it.


https://reviews.llvm.org/D28445

Files:
  lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp
  lib/StaticAnalyzer/Core/ProgramState.cpp
  test/Analysis/taint-generic.c
  test/Analysis/taint-tester.c

Index: test/Analysis/taint-tester.c
===
--- test/Analysis/taint-tester.c
+++ test/Analysis/taint-tester.c
@@ -51,8 +51,9 @@
   scanf("%d", );
   scanf("%d", );
   int tx = xy.x; // expected-warning + {{tainted}}
-  int ty = xy.y; // FIXME: This should be tainted as well.
-  char ntz = xy.z;// no warning
+  int ty = xy.y; // expected-warning + {{tainted}}
+  // FIXME: xy.z should not be tainted
+  char ntz = xy.z; // expected-warning + {{tainted}}
   // Now, scanf scans both.
   scanf("%d %d", , );
   int ttx = xy.x; // expected-warning + {{tainted}}
Index: test/Analysis/taint-generic.c
===
--- test/Analysis/taint-generic.c
+++ test/Analysis/taint-generic.c
@@ -169,6 +169,26 @@
   sock = socket(AF_LOCAL, SOCK_STREAM, 0);
   read(sock, buffer, 100);
   execl(buffer, "filename", 0); // no-warning
+
+  sock = socket(AF_INET, SOCK_STREAM, 0);
+  // References to both buffer and  as an argument should taint the argument
+  read(sock, , 100);
+  execl(buffer, "filename", 0); // expected-warning {{Untrusted data is passed to a system call}}
+}
+
+void testStruct() {
+  struct {
+struct {} st;
+char buf[16];
+int length;
+  } tainted;
+
+  char buffer[16];
+  int sock;
+
+  sock = socket(AF_INET, SOCK_STREAM, 0);
+  read(sock, , sizeof(tainted));
+  __builtin_memcpy(buffer, tainted.buf, tainted.length); // expected-warning {{Untrusted data is used to specify the buffer size}}
 }
 
 int testDivByZero() {
Index: lib/StaticAnalyzer/Core/ProgramState.cpp
===
--- lib/StaticAnalyzer/Core/ProgramState.cpp
+++ lib/StaticAnalyzer/Core/ProgramState.cpp
@@ -664,6 +664,10 @@
   while (const SymbolCast *SC = dyn_cast(Sym))
 Sym = SC->getOperand();
 
+  // If this a derived symbol, taint the parent symbol.
+  if (const SymbolDerived *SD = dyn_cast(Sym))
+Sym = SD->getParentSymbol();
+
   ProgramStateRef NewState = set(Sym, Kind);
   assert(NewState);
   return NewState;
Index: lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp
===
--- lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp
+++ lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp
@@ -65,6 +65,11 @@
   /// and thus, is tainted.
   static bool isStdin(const Expr *E, CheckerContext );
 
+  /// \brief Given a LazyCompoundValue, get the symbol of the first FieldRegion/
+  /// ElementRegion we can find a binding for.
+  static SymbolRef getLCVSymbol(CheckerContext ,
+nonloc::LazyCompoundVal );
+
   /// \brief Given a pointer argument, get the symbol of the value it contains
   /// (points to).
   static SymbolRef getPointedToSymbol(CheckerContext , const Expr *Arg);
@@ -423,6 +428,43 @@
   return false;
 }
 
+SymbolRef GenericTaintChecker::getLCVSymbol(CheckerContext ,
+nonloc::LazyCompoundVal ) {
+  StoreManager  = C.getStoreManager();
+  MemRegionManager  = C.getSValBuilder().getRegionManager();
+
+  QualType T = LCV.getRegion()->getValueType();
+  if (T->isStructureType() || T->isUnionType()) {
+const RecordType *RT = T->getAsStructureType();
+if (!RT)
+  RT = T->getAsUnionType();
+
+const RecordDecl *RD = RT->getDecl()->getDefinition();
+for (const auto *I : RD->fields()) {
+  const FieldRegion *FR = MrMgr.getFieldRegion(I, LCV.getRegion());
+  const SVal  =
+  StoreMgr.getBinding(LCV.getStore(), loc::MemRegionVal(FR));
+  if (auto Sym = V.getAsSymbol())
+return Sym;
+  else if (auto _LCV = 

[PATCH] D28445: [Analyzer] Extend taint propagation and checking

2017-01-10 Thread Vlad Tsyrklevich via Phabricator via cfe-commits
vlad.tsyrklevich added inline comments.



Comment at: lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp:443
+  if (auto LCV = Val.getAs())
+return C.getSymbolManager().getRegionValueSymbol(LCV->getRegion());
+

zaks.anna wrote:
> This might create a new symbol. Is this what we want?
I'm not sure how to turn an LCV into a proper symbol, so without creating new 
symbols the best approach I can see is changing `getPointedToSymbol()` to 
`getPointedToSval()` and also update `addTaint()` and `isTainted()` to accept 
SVals. Then you could have separate TaintMaps that include both symbols and 
regions and check both for taintedness. Does that sound like the correct 
approach to you?


https://reviews.llvm.org/D28445



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D28445: [Analyzer] Extend taint propagation and checking

2017-01-07 Thread Vlad Tsyrklevich via Phabricator via cfe-commits
vlad.tsyrklevich created this revision.
vlad.tsyrklevich added reviewers: zaks.anna, cfe-commits.

While extending the GenericTaintChecker for my purposes I'm hitting a case 
where taint is not propagated where I believe it should be. Currently, the 
following example will propagate taint correctly:

  char buf[16];
  taint_source(buf);
  taint_sink(buf);

However, the following fails:

  char buf[16];
  taint_source();
  taint_sink(buf);

In the first example, buf has it's symbol correctly extracted (via 
`GenericTaintChecker::getPointedToSymbol()`) as a  
`SymbolDerived{conj_$N{char}, element{buf,0 S64b,char}}`, it's marked as 
tainted and then the taint check correctly finds it using 
`ProgramState::isTainted()`.

In the second example, the SVal obtained in 
`GenericTaintChecker::getPointedToSymbol()` is a LazyCompoundVal so 
`SVal::getAsSymbol()` returns a NULL SymbolRef, meaning the symbol is not 
tainted.

This change extends GenericTaintChecker to obtain a SymbolRegionValue from the 
LCV MemRegion in `getPointedToSymbol()`, and then extends 
`ProgramState::isTainted()` to correctly match a `SymbolRegionValue{buf}` 
against a `SymbolDerived{conj_$N{char}, element{buf,0 S64b,char}}`.

I'm not familiar enough with analyzer internals to be confident in whether this 
is the right approach to fix this bug, so feedback is welcome.


https://reviews.llvm.org/D28445

Files:
  lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp
  lib/StaticAnalyzer/Core/ProgramState.cpp
  test/Analysis/taint-generic.c


Index: test/Analysis/taint-generic.c
===
--- test/Analysis/taint-generic.c
+++ test/Analysis/taint-generic.c
@@ -169,6 +169,11 @@
   sock = socket(AF_LOCAL, SOCK_STREAM, 0);
   read(sock, buffer, 100);
   execl(buffer, "filename", 0); // no-warning
+
+  sock = socket(AF_INET, SOCK_STREAM, 0);
+  // References to both buffer and  as an argument should taint the 
argument
+  read(sock, , 100);
+  execl(buffer, "filename", 0); // expected-warning {{Untrusted data is passed 
to a system call}}
 }
 
 int testDivByZero() {
Index: lib/StaticAnalyzer/Core/ProgramState.cpp
===
--- lib/StaticAnalyzer/Core/ProgramState.cpp
+++ lib/StaticAnalyzer/Core/ProgramState.cpp
@@ -690,6 +690,15 @@
   if (!Reg)
 return false;
 
+  if (const TypedValueRegion *TVR = dyn_cast(Reg)) {
+SymbolRef Sym = getSymbolManager().getRegionValueSymbol(TVR);
+
+// We don't call isTainted(Sym, K) here because it could lead to infinite 
recursion.
+const TaintTagType *Tag = get(Sym);
+if (Tag && *Tag == K)
+  return true;
+  }
+
   // Element region (array element) is tainted if either the base or the offset
   // are tainted.
   if (const ElementRegion *ER = dyn_cast(Reg))
@@ -720,7 +729,8 @@
 
 // If this is a SymbolDerived with a tainted parent, it's also tainted.
 if (const SymbolDerived *SD = dyn_cast(*SI))
-  Tainted = Tainted || isTainted(SD->getParentSymbol(), Kind);
+  Tainted = Tainted || isTainted(SD->getParentSymbol(), Kind)
+|| isTainted(SD->getOriginRegion(), Kind);
 
 // If memory region is tainted, data is also tainted.
 if (const SymbolRegionValue *SRV = dyn_cast(*SI))
Index: lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp
===
--- lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp
+++ lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp
@@ -438,6 +438,10 @@
 dyn_cast(Arg->getType().getCanonicalType().getTypePtr());
   SVal Val = State->getSVal(*AddrLoc,
 ArgTy ? ArgTy->getPointeeType(): QualType());
+
+  if (auto LCV = Val.getAs())
+return C.getSymbolManager().getRegionValueSymbol(LCV->getRegion());
+
   return Val.getAsSymbol();
 }
 


Index: test/Analysis/taint-generic.c
===
--- test/Analysis/taint-generic.c
+++ test/Analysis/taint-generic.c
@@ -169,6 +169,11 @@
   sock = socket(AF_LOCAL, SOCK_STREAM, 0);
   read(sock, buffer, 100);
   execl(buffer, "filename", 0); // no-warning
+
+  sock = socket(AF_INET, SOCK_STREAM, 0);
+  // References to both buffer and  as an argument should taint the argument
+  read(sock, , 100);
+  execl(buffer, "filename", 0); // expected-warning {{Untrusted data is passed to a system call}}
 }
 
 int testDivByZero() {
Index: lib/StaticAnalyzer/Core/ProgramState.cpp
===
--- lib/StaticAnalyzer/Core/ProgramState.cpp
+++ lib/StaticAnalyzer/Core/ProgramState.cpp
@@ -690,6 +690,15 @@
   if (!Reg)
 return false;
 
+  if (const TypedValueRegion *TVR = dyn_cast(Reg)) {
+SymbolRef Sym = getSymbolManager().getRegionValueSymbol(TVR);
+
+// We don't call isTainted(Sym, K) here because it could lead to infinite recursion.
+const TaintTagType *Tag = get(Sym);
+if (Tag &&