public inbox for gcc-cvs@sourceware.org
help / color / mirror / Atom feed
* [gcc r13-6749] analyzer: fix ICE on certain longjmp calls [PR109094]
@ 2023-03-18 16:49 David Malcolm
  0 siblings, 0 replies; only message in thread
From: David Malcolm @ 2023-03-18 16:49 UTC (permalink / raw)
  To: gcc-cvs

https://gcc.gnu.org/g:430d7d88c1a123d787f529dbc29e6632c6e556fb

commit r13-6749-g430d7d88c1a123d787f529dbc29e6632c6e556fb
Author: David Malcolm <dmalcolm@redhat.com>
Date:   Sat Mar 18 12:48:01 2023 -0400

    analyzer: fix ICE on certain longjmp calls [PR109094]
    
    PR analyzer/109094 reports an ICE in the analyzer seen on qemu's
    target/i386/tcg/translate.c
    
    The issue turned out to be that when handling a longjmp, the code
    to pop the frames was generating an svalue for the result_decl of any
    popped frame that had a non-void return type (and discarding it) leading
    to "uninit" poisoned_svalue_diagnostic instances being saved since the
    result_decl is only set by the greturn stmt.  Later, when checking the
    feasibility of the path to these diagnostics, m_check_expr was evaluated
    in the context of the frame of the longjmp, leading to an attempt to
    evaluate the result_decl of each intervening frames whilst in the
    context of the topmost frame, leading to an assertion failure in
    frame_region::get_region_for_local here:
    
    919             case RESULT_DECL:
    920               gcc_assert (DECL_CONTEXT (expr) == m_fun->decl);
    921               break;
    
    This patch updates the analyzer's longjmp implementation so that it
    doesn't attempt to generate svalues for the result_decls when popping
    frames, fixing the assertion failure (and presumably fixing "uninit"
    false positives in a release build).
    
    gcc/analyzer/ChangeLog:
            PR analyzer/109094
            * region-model.cc (region_model::on_longjmp): Pass false for
            new "eval_return_svalue" param of pop_frame.
            (region_model::pop_frame): Add new "eval_return_svalue" param and
            use it to suppress the call to get_rvalue on the result when
            needed by on_longjmp.
            * region-model.h (region_model::pop_frame): Add new
            "eval_return_svalue" param.
    
    gcc/testsuite/ChangeLog:
            PR analyzer/109094
            * gcc.dg/analyzer/setjmp-pr109094.c: New test.
    
    Signed-off-by: David Malcolm <dmalcolm@redhat.com>

Diff:
---
 gcc/analyzer/region-model.cc                    | 15 ++++++++--
 gcc/analyzer/region-model.h                     |  3 +-
 gcc/testsuite/gcc.dg/analyzer/setjmp-pr109094.c | 38 +++++++++++++++++++++++++
 3 files changed, 52 insertions(+), 4 deletions(-)

diff --git a/gcc/analyzer/region-model.cc b/gcc/analyzer/region-model.cc
index 56beaa82f95..fb81d43f91b 100644
--- a/gcc/analyzer/region-model.cc
+++ b/gcc/analyzer/region-model.cc
@@ -1952,7 +1952,7 @@ region_model::on_longjmp (const gcall *longjmp_call, const gcall *setjmp_call,
      setjmp was called.  */
   gcc_assert (get_stack_depth () >= setjmp_stack_depth);
   while (get_stack_depth () > setjmp_stack_depth)
-    pop_frame (NULL, NULL, ctxt);
+    pop_frame (NULL, NULL, ctxt, false);
 
   gcc_assert (get_stack_depth () == setjmp_stack_depth);
 
@@ -4679,6 +4679,10 @@ region_model::get_current_function () const
    If OUT_RESULT is non-null, copy any return value from the frame
    into *OUT_RESULT.
 
+   If EVAL_RETURN_SVALUE is false, then don't evaluate the return value.
+   This is for use when unwinding frames e.g. due to longjmp, to suppress
+   erroneously reporting uninitialized return values.
+
    Purge the frame region and all its descendent regions.
    Convert any pointers that point into such regions into
    POISON_KIND_POPPED_STACK svalues.  */
@@ -4686,7 +4690,8 @@ region_model::get_current_function () const
 void
 region_model::pop_frame (tree result_lvalue,
 			 const svalue **out_result,
-			 region_model_context *ctxt)
+			 region_model_context *ctxt,
+			 bool eval_return_svalue)
 {
   gcc_assert (m_current_frame);
 
@@ -4700,7 +4705,9 @@ region_model::pop_frame (tree result_lvalue,
   tree fndecl = m_current_frame->get_function ()->decl;
   tree result = DECL_RESULT (fndecl);
   const svalue *retval = NULL;
-  if (result && TREE_TYPE (result) != void_type_node)
+  if (result
+      && TREE_TYPE (result) != void_type_node
+      && eval_return_svalue)
     {
       retval = get_rvalue (result, ctxt);
       if (out_result)
@@ -4712,6 +4719,8 @@ region_model::pop_frame (tree result_lvalue,
 
   if (result_lvalue && retval)
     {
+      gcc_assert (eval_return_svalue);
+
       /* Compute result_dst_reg using RESULT_LVALUE *after* popping
 	 the frame, but before poisoning pointers into the old frame.  */
       const region *result_dst_reg = get_lvalue (result_lvalue, ctxt);
diff --git a/gcc/analyzer/region-model.h b/gcc/analyzer/region-model.h
index 197b5358678..fe3db0b0c98 100644
--- a/gcc/analyzer/region-model.h
+++ b/gcc/analyzer/region-model.h
@@ -341,7 +341,8 @@ class region_model
   function * get_current_function () const;
   void pop_frame (tree result_lvalue,
 		  const svalue **out_result,
-		  region_model_context *ctxt);
+		  region_model_context *ctxt,
+		  bool eval_return_svalue = true);
   int get_stack_depth () const;
   const frame_region *get_frame_at_index (int index) const;
 
diff --git a/gcc/testsuite/gcc.dg/analyzer/setjmp-pr109094.c b/gcc/testsuite/gcc.dg/analyzer/setjmp-pr109094.c
new file mode 100644
index 00000000000..10591ce60a7
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/analyzer/setjmp-pr109094.c
@@ -0,0 +1,38 @@
+/* Reduced from an ICE seen in qemu's target/i386/tcg/translate.c  */
+
+typedef long int __jmp_buf[8];
+struct __jmp_buf_tag {
+  __jmp_buf __jmpbuf;
+};
+typedef struct __jmp_buf_tag sigjmp_buf[1];
+
+extern int __sigsetjmp(sigjmp_buf env, int savesigs);
+extern void siglongjmp(sigjmp_buf env, int val);
+
+typedef struct DisasContextBase {
+  int num_insns;
+} DisasContextBase;
+
+typedef struct DisasContext {
+  DisasContextBase base;
+  sigjmp_buf jmpbuf;
+} DisasContext;
+
+extern int translator_ldub(DisasContextBase *base, int);
+
+int advance_pc(DisasContext *s, int num_bytes) {
+  if (s->base.num_insns > 1) {
+    siglongjmp(s->jmpbuf, 2);
+  }
+  return 0;
+}
+
+static inline int x86_ldub_code(DisasContext *s) {
+  return translator_ldub(&s->base, advance_pc(s, 1));
+}
+
+static void disas_insn(DisasContext *s) {
+  int b;
+  __sigsetjmp(s->jmpbuf, 0);
+  b = x86_ldub_code(s);
+}

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2023-03-18 16:49 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-03-18 16:49 [gcc r13-6749] analyzer: fix ICE on certain longjmp calls [PR109094] David Malcolm

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).