(root)/
gcc-13.2.0/
gcc/
testsuite/
gcc.dg/
analyzer/
feasibility-3.c
       1  /* Reduced and adapted from Linux: fs/proc/inode.c: proc_reg_open
       2     (GPL v2.0).  */
       3  
       4  /* Types.  */
       5  
       6  typedef unsigned char u8;
       7  typedef _Bool bool;
       8  typedef unsigned int gfp_t;
       9  
      10  struct file;
      11  struct kmem_cache;
      12  struct proc_dir_entry;
      13  
      14  struct inode { /* [...snip...] */ };
      15  
      16  enum {
      17   PROC_ENTRY_PERMANENT = 1U << 0,
      18  };
      19  
      20  struct proc_ops {
      21   /* [...snip...] */
      22   int (*proc_open)(struct inode *, struct file *);
      23   /* [...snip...] */
      24   int (*proc_release)(struct inode *, struct file *);
      25   /* [...snip...] */
      26  };
      27  
      28  struct proc_dir_entry {
      29   /* [...snip...] */
      30   struct completion *pde_unload_completion;
      31   /* [...snip...] */
      32   union {
      33    const struct proc_ops *proc_ops;
      34    const struct file_operations *proc_dir_ops;
      35   };
      36   /* [...snip...] */
      37   u8 flags;
      38   /* [...snip...] */
      39  };
      40  
      41  struct pde_opener {
      42   /* [...snip...] */
      43   struct file *file;
      44   /* [...snip...] */
      45  };
      46  
      47  struct proc_inode {
      48   /* [...snip...] */
      49   struct proc_dir_entry *pde;
      50   /* [...snip...] */
      51   struct inode vfs_inode;
      52  };
      53  
      54  /* Data.  */
      55  
      56  static struct kmem_cache *pde_opener_cache __attribute__((__section__(".data..ro_after_init")));
      57  
      58  /* Functions. */
      59  
      60  void *kmem_cache_alloc(struct kmem_cache *, gfp_t flags) __attribute__((__malloc__));
      61  void kmem_cache_free(struct kmem_cache *, void *);
      62  
      63  static inline bool pde_is_permanent(const struct proc_dir_entry *pde)
      64  {
      65   return pde->flags & PROC_ENTRY_PERMANENT;
      66  }
      67  
      68  static inline struct proc_inode *PROC_I(const struct inode *inode)
      69  {
      70    void *__mptr = (void *)(inode);
      71    return ((struct proc_inode *)(__mptr - __builtin_offsetof(struct proc_inode, vfs_inode)));
      72  }
      73  
      74  static inline struct proc_dir_entry *PDE(const struct inode *inode)
      75  {
      76   return PROC_I(inode)->pde;
      77  }
      78  
      79  /* We don't want to emit bogus use of uninitialized value 'pdeo'
      80     warnings from -Wanalyzer-use-of-uninitialized-value in this function;
      81     these would require following infeasible paths in which "release" is
      82     first NULL (to avoid the initialization of "pdeo") and then is non-NULL
      83     (to access "pdeo").
      84  
      85     "release" is sufficiently complicated in this function to hit the
      86     complexity limit for symbolic values during enode exploration.  */
      87  
      88  static int proc_reg_open(struct inode *inode, struct file *file)
      89  {
      90   struct proc_dir_entry *pde = PDE(inode);
      91   int rv = 0;
      92   typeof(((struct proc_ops*)0)->proc_open) open;
      93   typeof(((struct proc_ops*)0)->proc_release) release;
      94   struct pde_opener *pdeo;
      95  
      96   if (pde_is_permanent(pde)) {
      97    open = pde->proc_ops->proc_open;
      98    if (open)
      99     rv = open(inode, file);
     100    return rv;
     101   }
     102  
     103   /* [...snip...] */
     104  
     105   release = pde->proc_ops->proc_release;
     106   if (release) {
     107    pdeo = kmem_cache_alloc(pde_opener_cache,
     108  			  ((( gfp_t)(0x400u|0x800u))
     109  			   | (( gfp_t)0x40u)
     110  			   | (( gfp_t)0x80u)));
     111    if (!pdeo) {
     112     rv = -12;
     113     goto out_unuse;
     114    }
     115   }
     116  
     117   open = pde->proc_ops->proc_open;
     118   if (open)
     119    rv = open(inode, file);
     120  
     121   if (release) {
     122    if (rv == 0) {
     123  
     124     pdeo->file = file; /* { dg-bogus "uninit" } */
     125     /* [...snip...] */
     126    } else
     127     kmem_cache_free(pde_opener_cache, pdeo); /* { dg-bogus "uninit" } */
     128   }
     129  
     130  out_unuse:
     131   /* [...snip...] */
     132   return rv;
     133  }