aboutsummaryrefslogtreecommitdiffstats
path: root/lang
diff options
context:
space:
mode:
Diffstat (limited to 'lang')
-rw-r--r--lang/gcc/files/patch-stackprotector-gcc157
-rw-r--r--lang/gcc/files/patch-stackprotector-gcc_c-family11
-rw-r--r--lang/gcc/files/patch-stackprotector-gcc_doc39
-rw-r--r--lang/gcc/files/patch-stackprotector-gcc_testsuite176
4 files changed, 383 insertions, 0 deletions
diff --git a/lang/gcc/files/patch-stackprotector-gcc b/lang/gcc/files/patch-stackprotector-gcc
new file mode 100644
index 000000000000..115df78141a7
--- /dev/null
+++ b/lang/gcc/files/patch-stackprotector-gcc
@@ -0,0 +1,157 @@
+--- gcc/cfgexpand.c.orig
++++ gcc/cfgexpand.c
+@@ -1291,6 +1291,12 @@
+ clear_tree_used (t);
+ }
+
++ enum {
++ SPCT_FLAG_DEFAULT = 1,
++ SPCT_FLAG_ALL = 2,
++ SPCT_FLAG_STRONG = 3
++ };
++
+ /* Examine TYPE and determine a bit mask of the following features. */
+
+ #define SPCT_HAS_LARGE_CHAR_ARRAY 1
+@@ -1360,7 +1366,8 @@
+ if (bits & SPCT_HAS_SMALL_CHAR_ARRAY)
+ has_short_buffer = true;
+
+- if (flag_stack_protect == 2)
++ if (flag_stack_protect == SPCT_FLAG_ALL
++ || flag_stack_protect == SPCT_FLAG_STRONG)
+ {
+ if ((bits & (SPCT_HAS_SMALL_CHAR_ARRAY | SPCT_HAS_LARGE_CHAR_ARRAY))
+ && !(bits & SPCT_HAS_AGGREGATE))
+@@ -1514,6 +1521,27 @@
+ return size;
+ }
+
++/* Helper routine to check if a record or union contains an array field. */
++
++static int
++record_or_union_type_has_array_p (const_tree tree_type)
++{
++ tree fields = TYPE_FIELDS (tree_type);
++ tree f;
++
++ for (f = fields; f; f = DECL_CHAIN (f))
++ if (TREE_CODE (f) == FIELD_DECL)
++ {
++ tree field_type = TREE_TYPE (f);
++ if (RECORD_OR_UNION_TYPE_P (field_type)
++ && record_or_union_type_has_array_p (field_type))
++ return 1;
++ if (TREE_CODE (field_type) == ARRAY_TYPE)
++ return 1;
++ }
++ return 0;
++}
++
+ /* Expand all variables used in the function. */
+
+ static rtx
+@@ -1525,6 +1553,7 @@
+ struct pointer_map_t *ssa_name_decls;
+ unsigned i;
+ unsigned len;
++ bool gen_stack_protect_signal = false;
+
+ /* Compute the phase of the stack frame for this function. */
+ {
+@@ -1575,6 +1604,24 @@
+ }
+ }
+ pointer_map_destroy (ssa_name_decls);
++
++ if (flag_stack_protect == SPCT_FLAG_STRONG)
++ FOR_EACH_LOCAL_DECL (cfun, i, var)
++ if (!is_global_var (var))
++ {
++ tree var_type = TREE_TYPE (var);
++ /* Examine local referenced variables that have their addresses taken,
++ contain an array, or are arrays. */
++ if (TREE_CODE (var) == VAR_DECL
++ && (TREE_CODE (var_type) == ARRAY_TYPE
++ || TREE_ADDRESSABLE (var)
++ || (RECORD_OR_UNION_TYPE_P (var_type)
++ && record_or_union_type_has_array_p (var_type))))
++ {
++ gen_stack_protect_signal = true;
++ break;
++ }
++ }
+
+ /* At this point all variables on the local_decls with TREE_USED
+ set are not associated with any block scope. Lay them out. */
+@@ -1662,12 +1709,32 @@
+ dump_stack_var_partition ();
+ }
+
+- /* There are several conditions under which we should create a
+- stack guard: protect-all, alloca used, protected decls present. */
+- if (flag_stack_protect == 2
+- || (flag_stack_protect
+- && (cfun->calls_alloca || has_protected_decls)))
+- create_stack_guard ();
++ /* Create stack guard, if
++ a) "-fstack-protector-all" - always;
++ b) "-fstack-protector-strong" - if there are arrays, memory
++ references to local variables, alloca used, or protected decls present;
++ c) "-fstack-protector" - if alloca used, or protected decls present */
++
++ switch (flag_stack_protect)
++ {
++ case SPCT_FLAG_ALL:
++ create_stack_guard ();
++ break;
++
++ case SPCT_FLAG_STRONG:
++ if (gen_stack_protect_signal
++ || cfun->calls_alloca || has_protected_decls)
++ create_stack_guard ();
++ break;
++
++ case SPCT_FLAG_DEFAULT:
++ if (cfun->calls_alloca || has_protected_decls)
++ create_stack_guard ();
++ break;
++
++ default:
++ ;
++ }
+
+ /* Assign rtl to each variable based on these partitions. */
+ if (stack_vars_num > 0)
+@@ -1688,7 +1755,7 @@
+ expand_stack_vars (stack_protect_decl_phase_1, &data);
+
+ /* Phase 2 contains other kinds of arrays. */
+- if (flag_stack_protect == 2)
++ if (flag_stack_protect == SPCT_FLAG_ALL)
+ expand_stack_vars (stack_protect_decl_phase_2, &data);
+ }
+
+--- gcc/common.opt.orig
++++ gcc/common.opt
+@@ -1942,6 +1942,10 @@ fstack-protector-all
+ Common Report RejectNegative Var(flag_stack_protect, 2)
+ Use a stack protection method for every function
+
++fstack-protector-strong
++Common Report RejectNegative Var(flag_stack_protect, 3)
++Use a smart stack protection method for certain functions
++
+ fstack-usage
+ Common RejectNegative Var(flag_stack_usage)
+ Output stack usage information on a per-function basis
+--- gcc/gcc.c.orig
++++ gcc/gcc.c
+@@ -655,7 +655,7 @@ proper position among the other output files. */
+ #ifdef TARGET_LIBC_PROVIDES_SSP
+ #define LINK_SSP_SPEC "%{fstack-protector:}"
+ #else
+-#define LINK_SSP_SPEC "%{fstack-protector|fstack-protector-all:-lssp_nonshared -lssp}"
++#define LINK_SSP_SPEC "%{fstack-protector|fstack-protector-strong|fstack-protector-all:-lssp_nonshared -lssp}"
+ #endif
+ #endif
diff --git a/lang/gcc/files/patch-stackprotector-gcc_c-family b/lang/gcc/files/patch-stackprotector-gcc_c-family
new file mode 100644
index 000000000000..2dabcb8abcb4
--- /dev/null
+++ b/lang/gcc/files/patch-stackprotector-gcc_c-family
@@ -0,0 +1,11 @@
+--- gcc/c-family/c-cppbuiltin.c.orig
++++ gcc/c-family/c-cppbuiltin.c
+@@ -888,6 +888,8 @@ c_cpp_builtins (cpp_reader *pfile)
+ /* Make the choice of the stack protector runtime visible to source code.
+ The macro names and values here were chosen for compatibility with an
+ earlier implementation, i.e. ProPolice. */
++ if (flag_stack_protect == 3)
++ cpp_define (pfile, "__SSP_STRONG__=3");
+ if (flag_stack_protect == 2)
+ cpp_define (pfile, "__SSP_ALL__=2");
+ else if (flag_stack_protect == 1)
diff --git a/lang/gcc/files/patch-stackprotector-gcc_doc b/lang/gcc/files/patch-stackprotector-gcc_doc
new file mode 100644
index 000000000000..cc95c871d849
--- /dev/null
+++ b/lang/gcc/files/patch-stackprotector-gcc_doc
@@ -0,0 +1,39 @@
+--- gcc/doc/cpp.texi.orig
++++ gcc/doc/cpp.texi
+@@ -2349,6 +2349,10 @@ use.
+ This macro is defined, with value 2, when @option{-fstack-protector-all} is
+ in use.
+
++@item __SSP_STRONG__
++This macro is defined, with value 3, when @option{-fstack-protector-strong} is
++in use.
++
+ @item __SANITIZE_ADDRESS__
+ This macro is defined, with value 1, when @option{-fsanitize=address} is
+ in use.
+--- gcc/doc/invoke.texi.orig
++++ gcc/doc/invoke.texi
+@@ -407,8 +407,8 @@ Objective-C and Objective-C++ Dialects}.
+ -fsel-sched-pipelining -fsel-sched-pipelining-outer-loops @gol
+ -fshrink-wrap -fsignaling-nans -fsingle-precision-constant @gol
+ -fsplit-ivs-in-unroller -fsplit-wide-types -fstack-protector @gol
+--fstack-protector-all -fstrict-aliasing -fstrict-overflow @gol
+--fthread-jumps -ftracer -ftree-bit-ccp @gol
++-fstack-protector-all -fstack-protector-strong -fstrict-aliasing @gol
++-fstrict-overflow -fthread-jumps -ftracer -ftree-bit-ccp @gol
+ -ftree-builtin-call-dce -ftree-ccp -ftree-ch @gol
+ -ftree-coalesce-inline-vars -ftree-coalesce-vars -ftree-copy-prop @gol
+ -ftree-copyrename -ftree-dce -ftree-dominator-opts -ftree-dse @gol
+@@ -8957,6 +8957,12 @@ If a guard check fails, an error message is printed and the program exits.
+ @opindex fstack-protector-all
+ Like @option{-fstack-protector} except that all functions are protected.
+
++@item -fstack-protector-strong
++@opindex fstack-protector-strong
++Like @option{-fstack-protector} but includes additional functions to
++be protected --- those that have local array definitions, or have
++references to local frame addresses.
++
+ @item -fsection-anchors
+ @opindex fsection-anchors
+ Try to reduce the number of symbolic address calculations by using
diff --git a/lang/gcc/files/patch-stackprotector-gcc_testsuite b/lang/gcc/files/patch-stackprotector-gcc_testsuite
new file mode 100644
index 000000000000..443a7b4ef893
--- /dev/null
+++ b/lang/gcc/files/patch-stackprotector-gcc_testsuite
@@ -0,0 +1,176 @@
+--- /dev/null
++++ gcc/testsuite/g++.dg/fstack-protector-strong.C
+@@ -0,0 +1,35 @@
++/* Test that stack protection is done on chosen functions. */
++
++/* { dg-do compile { target i?86-*-* x86_64-*-* } } */
++/* { dg-options "-O2 -fstack-protector-strong" } */
++
++class A
++{
++public:
++ A() {}
++ ~A() {}
++ void method();
++ int state;
++};
++
++/* Frame address exposed to A::method via "this". */
++int
++foo1 ()
++{
++ A a;
++ a.method ();
++ return a.state;
++}
++
++/* Possible destroying foo2's stack via &a. */
++int
++global_func (A& a);
++
++/* Frame address exposed to global_func. */
++int foo2 ()
++{
++ A a;
++ return global_func (a);
++}
++
++/* { dg-final { scan-assembler-times "stack_chk_fail" 2 } } */
+--- /dev/null
++++ gcc/testsuite/gcc.dg/fstack-protector-strong.c
+@@ -0,0 +1,135 @@
++/* Test that stack protection is done on chosen functions. */
++
++/* { dg-do compile { target i?86-*-* x86_64-*-* } } */
++/* { dg-options "-O2 -fstack-protector-strong" } */
++
++#include<string.h>
++#include<stdlib.h>
++
++extern int g0;
++extern int* pg0;
++int
++goo (int *);
++int
++hoo (int);
++
++/* Function frame address escaped function call. */
++int
++foo1 ()
++{
++ int i;
++ return goo (&i);
++}
++
++struct ArrayStruct
++{
++ int a;
++ int array[10];
++};
++
++struct AA
++{
++ int b;
++ struct ArrayStruct as;
++};
++
++/* Function frame contains array. */
++int
++foo2 ()
++{
++ struct AA aa;
++ int i;
++ for (i = 0; i < 10; ++i)
++ {
++ aa.as.array[i] = i * (i-1) + i / 2;
++ }
++ return aa.as.array[5];
++}
++
++/* Address computation based on a function frame address. */
++int
++foo3 ()
++{
++ int a;
++ int *p;
++ p = &a + 5;
++ return goo (p);
++}
++
++/* Address cast based on a function frame address. */
++int
++foo4 ()
++{
++ int a;
++ return goo (g0 << 2 ? (int *)(3 * (long)(void *)(&a)) : 0);
++}
++
++/* Address cast based on a local array. */
++int
++foo5 ()
++{
++ short array[10];
++ return goo ((int *)(array + 5));
++}
++
++struct BB
++{
++ int one;
++ int two;
++ int three;
++};
++
++/* Address computaton based on a function frame address.*/
++int
++foo6 ()
++{
++ struct BB bb;
++ return goo (&bb.one + sizeof(int));
++}
++
++/* Function frame address escaped via global variable. */
++int
++foo7 ()
++{
++ int a;
++ pg0 = &a;
++ goo (pg0);
++ return *pg0;
++}
++
++/* Check that this covers -fstack-protector. */
++int
++foo8 ()
++{
++ char base[100];
++ memcpy ((void *)base, (const void *)pg0, 105);
++ return (int)(base[32]);
++}
++
++/* Check that this covers -fstack-protector. */
++int
++foo9 ()
++{
++ char* p = alloca (100);
++ return goo ((int *)(p + 50));
++}
++
++int
++global2 (struct BB* pbb);
++
++/* Address taken on struct. */
++int
++foo10 ()
++{
++ struct BB bb;
++ int i;
++ bb.one = global2 (&bb);
++ for (i = 0; i < 10; ++i)
++ {
++ bb.two = bb.one + bb.two;
++ bb.three = bb.one + bb.two + bb.three;
++ }
++ return bb.three;
++}
++
++/* { dg-final { scan-assembler-times "stack_chk_fail" 10 } } */