Viewing file: feasibility-3.c (2.96 KB) -rw-r--r-- Select action/file-type: (+) | (+) | (+) | Code (+) | Session (+) | (+) | SDB (+) | (+) | (+) | (+) | (+) | (+) |
/* Reduced and adapted from Linux: fs/proc/inode.c: proc_reg_open (GPL v2.0). */
/* Types. */
typedef unsigned char u8; typedef _Bool bool; typedef unsigned int gfp_t;
struct file; struct kmem_cache; struct proc_dir_entry;
struct inode { /* [...snip...] */ };
enum { PROC_ENTRY_PERMANENT = 1U << 0, };
struct proc_ops { /* [...snip...] */ int (*proc_open)(struct inode *, struct file *); /* [...snip...] */ int (*proc_release)(struct inode *, struct file *); /* [...snip...] */ };
struct proc_dir_entry { /* [...snip...] */ struct completion *pde_unload_completion; /* [...snip...] */ union { const struct proc_ops *proc_ops; const struct file_operations *proc_dir_ops; }; /* [...snip...] */ u8 flags; /* [...snip...] */ };
struct pde_opener { /* [...snip...] */ struct file *file; /* [...snip...] */ };
struct proc_inode { /* [...snip...] */ struct proc_dir_entry *pde; /* [...snip...] */ struct inode vfs_inode; };
/* Data. */
static struct kmem_cache *pde_opener_cache __attribute__((__section__(".data..ro_after_init")));
/* Functions. */
void *kmem_cache_alloc(struct kmem_cache *, gfp_t flags) __attribute__((__malloc__)); void kmem_cache_free(struct kmem_cache *, void *);
static inline bool pde_is_permanent(const struct proc_dir_entry *pde) { return pde->flags & PROC_ENTRY_PERMANENT; }
static inline struct proc_inode *PROC_I(const struct inode *inode) { void *__mptr = (void *)(inode); return ((struct proc_inode *)(__mptr - __builtin_offsetof(struct proc_inode, vfs_inode))); }
static inline struct proc_dir_entry *PDE(const struct inode *inode) { return PROC_I(inode)->pde; }
/* We don't want to emit bogus use of uninitialized value 'pdeo' warnings from -Wanalyzer-use-of-uninitialized-value in this function; these would require following infeasible paths in which "release" is first NULL (to avoid the initialization of "pdeo") and then is non-NULL (to access "pdeo").
"release" is sufficiently complicated in this function to hit the complexity limit for symbolic values during enode exploration. */
static int proc_reg_open(struct inode *inode, struct file *file) { struct proc_dir_entry *pde = PDE(inode); int rv = 0; typeof(((struct proc_ops*)0)->proc_open) open; typeof(((struct proc_ops*)0)->proc_release) release; struct pde_opener *pdeo;
if (pde_is_permanent(pde)) { open = pde->proc_ops->proc_open; if (open) rv = open(inode, file); return rv; }
/* [...snip...] */
release = pde->proc_ops->proc_release; if (release) { pdeo = kmem_cache_alloc(pde_opener_cache, ((( gfp_t)(0x400u|0x800u)) | (( gfp_t)0x40u) | (( gfp_t)0x80u))); if (!pdeo) { rv = -12; goto out_unuse; } }
open = pde->proc_ops->proc_open; if (open) rv = open(inode, file);
if (release) { if (rv == 0) {
pdeo->file = file; /* { dg-bogus "uninit" } */ /* [...snip...] */ } else kmem_cache_free(pde_opener_cache, pdeo); /* { dg-bogus "uninit" } */ }
out_unuse: /* [...snip...] */ return rv; }
|