On Mon, Jun 04, 2012 at 10:34:21AM +0200, Florian Weimer wrote:
> >>+This protection mechanism is only a last resort.  As a programmer, you
> >>+must not rely on its presence, but use explicit buffer length checks
> >>+to avoid buffer overflows.  GCC may not be able to determine buffer
> >>+sizes accurately, and the accuracy depends on compiler version and
> >>+optimization level (currently, at least @option{-O2} is required).
> >
> >That isn't true, at -O1 or -Os it should work just fine too, and
> >to some extent on the compiler side even at -O0.
> 
> Fold needs to run.  Without it, __builtin_object_size constantly

Folding is performed at all optimization levels.
The objsz pass is only performed at -O1 and above (as it is among
optimization passes).  So say on:
char buf[64];
int f1 (void) { return __builtin_object_size (buf, 0); }
int f2 (void) { return __builtin_object_size (&buf[4], 0); }
static inline int __attribute__((always_inline)) f3 (char *p) { return 
__builtin_object_size (p, 0); }
int f4 (void) { return f3 (buf); }
int f5 (void) { return f3 (&buf[4]); }
int f6 (void) { char *q = buf; return f3 (q); }
int f7 (void) { struct S { char *q; } s; s.q = buf; return f3 (s.q); }
at -O0 f1 returns 64 and f2 returns 60, but due to not performing
objsz f[4567] already return -1.  By running the objsz pass
even at -O0 (as done in the attached pass) even f[456] could return
64 resp. 60, though of course as it isn't optimizing, many other
cases wouldn't be determined accurately, e.g f7 due to SRA not being
performed.  Still, it is purely glibc decision not to do fortification
at -O0.

--- gcc/passes.c.jj     2012-06-01 14:41:05.000000000 +0200
+++ gcc/passes.c        2012-06-04 10:49:50.581693645 +0200
@@ -1501,6 +1501,7 @@ init_optimization_passes (void)
       NEXT_PASS (pass_tm_edges);
     }
   NEXT_PASS (pass_lower_complex_O0);
+  NEXT_PASS (pass_object_sizes_O0);
   NEXT_PASS (pass_cleanup_eh);
   NEXT_PASS (pass_lower_resx);
   NEXT_PASS (pass_nrv);
--- gcc/tree-pass.h.jj  2012-05-12 10:21:06.000000000 +0200
+++ gcc/tree-pass.h     2012-05-12 10:21:06.000000000 +0200
@@ -411,6 +411,7 @@ extern struct gimple_opt_pass pass_diagn
 extern struct gimple_opt_pass pass_expand_omp;
 extern struct gimple_opt_pass pass_expand_omp_ssa;
 extern struct gimple_opt_pass pass_object_sizes;
+extern struct gimple_opt_pass pass_object_sizes_O0;
 extern struct gimple_opt_pass pass_strlen;
 extern struct gimple_opt_pass pass_fold_builtins;
 extern struct gimple_opt_pass pass_stdarg;
--- gcc/tree-object-size.c.jj   2011-12-16 08:37:45.000000000 +0100
+++ gcc/tree-object-size.c      2012-06-04 10:52:35.033699016 +0200
@@ -1285,3 +1285,28 @@ struct gimple_opt_pass pass_object_sizes
   TODO_verify_ssa                      /* todo_flags_finish */
  }
 };
+
+static bool
+gate_object_sizes_O0 (void)
+{
+  return !optimize;
+}
+
+struct gimple_opt_pass pass_object_sizes_O0 =
+{
+ {
+  GIMPLE_PASS,
+  "objsz0",                            /* name */
+  gate_object_sizes_O0,                        /* gate */
+  compute_object_sizes,                        /* execute */
+  NULL,                                        /* sub */
+  NULL,                                        /* next */
+  0,                                   /* static_pass_number */
+  TV_NONE,                             /* tv_id */
+  PROP_cfg | PROP_ssa,                 /* properties_required */
+  0,                                   /* properties_provided */
+  0,                                   /* properties_destroyed */
+  0,                                   /* todo_flags_start */
+  TODO_verify_ssa                      /* todo_flags_finish */
+ }
+};


        Jakub

Reply via email to