(root)/
gcc-13.2.0/
gcc/
testsuite/
gcc.dg/
analyzer/
deref-before-check-pr108455-git-pack-revindex.c
       1  /* Reduced from git-2.39.0's pack-revindex.c  */
       2  
       3  typedef unsigned int __uint32_t;
       4  typedef unsigned long int __uintmax_t;
       5  typedef long int __off_t;
       6  typedef long int __off64_t;
       7  typedef __SIZE_TYPE__ size_t;
       8  typedef __off64_t off_t;
       9  typedef __uint32_t uint32_t;
      10  typedef __uintmax_t uintmax_t;
      11  
      12  struct stat {
      13    /* [...snip...] */
      14    __off_t st_size;
      15    /* [...snip...] */
      16  };
      17  
      18  extern int close(int __fd);
      19  extern int fstat(int __fd, struct stat *__buf)
      20    __attribute__((__nothrow__, __leaf__)) __attribute__((__nonnull__(2)));
      21  extern uint32_t default_swab32(uint32_t val);
      22  extern uint32_t git_bswap32(uint32_t x);
      23  __attribute__((__noreturn__)) void die(const char *err, ...)
      24      __attribute__((format(printf, 1, 2)));
      25  int error(const char *err, ...) __attribute__((format(printf, 1, 2)));
      26  int error_errno(const char *err, ...) __attribute__((format(printf, 1, 2)));
      27  static inline int const_error(void) { return -1; }
      28  extern int munmap(void *__addr, size_t __len)
      29      __attribute__((__nothrow__, __leaf__));
      30  extern size_t st_mult(size_t a, size_t b);
      31  extern void *xmmap(void *start, size_t length, int prot, int flags, int fd,
      32  		   off_t offset);
      33  extern size_t xsize_t(off_t len);
      34  
      35  extern char *gettext(const char *__msgid) __attribute__((__nothrow__, __leaf__))
      36  __attribute__((__format_arg__(1)));
      37  static inline __attribute__((format_arg(1))) const char *_(const char *msgid) {
      38    if (!*msgid)
      39      return "";
      40    return gettext(msgid);
      41  }
      42  
      43  struct repository {
      44    /* [...snip...] */
      45    const struct git_hash_algo *hash_algo;
      46    /* [...snip...] */
      47  };
      48  extern struct repository *the_repository;
      49  struct git_hash_algo {
      50    /* [...snip...] */
      51    size_t rawsz;
      52    /* [...snip...] */
      53  };
      54  
      55  int git_open_cloexec(const char *name, int flags);
      56  
      57  struct revindex_header {
      58    uint32_t signature;
      59    uint32_t version;
      60    uint32_t hash_id;
      61  };
      62  
      63  int load_revindex_from_disk(char *revindex_name, uint32_t num_objects,
      64                              const uint32_t **data_p, size_t *len_p) {
      65    int fd, ret = 0;
      66    struct stat st;
      67    void *data = ((void *)0);
      68    size_t revindex_size;
      69    struct revindex_header *hdr;
      70  
      71    fd = git_open_cloexec(revindex_name, 00);
      72  
      73    if (fd < 0) {
      74      ret = -1;
      75      goto cleanup;
      76    }
      77    if (fstat(fd, &st)) {
      78      ret = (error_errno(_("failed to read %s"), revindex_name), const_error());
      79      goto cleanup;
      80    }
      81  
      82    revindex_size = xsize_t(st.st_size);
      83  
      84    if (revindex_size < ((12) + (2 * the_repository->hash_algo->rawsz))) {
      85      ret = (error(_("reverse-index file %s is too small"), revindex_name),
      86             const_error());
      87      goto cleanup;
      88    }
      89  
      90    if (revindex_size - ((12) + (2 * the_repository->hash_algo->rawsz)) !=
      91        st_mult(sizeof(uint32_t), num_objects)) {
      92      ret = (error(_("reverse-index file %s is corrupt"), revindex_name),
      93             const_error());
      94      goto cleanup;
      95    }
      96  
      97    data = xmmap(((void *)0), revindex_size, 0x1, 0x02, fd, 0);
      98    hdr = data;
      99  
     100    if (git_bswap32(hdr->signature) != 0x52494458) {
     101      ret =
     102          (error(_("reverse-index file %s has unknown signature"), revindex_name),
     103           const_error());
     104      goto cleanup;
     105    }
     106    if (git_bswap32(hdr->version) != 1) {
     107      ret = (error(_("reverse-index file %s has unsupported version %"
     108                     "u"),
     109                   revindex_name, git_bswap32(hdr->version)),
     110             const_error());
     111      goto cleanup;
     112    }
     113    if (!(git_bswap32(hdr->hash_id) == 1 || git_bswap32(hdr->hash_id) == 2)) {
     114      ret = (error(_("reverse-index file %s has unsupported hash id %"
     115                     "u"),
     116                   revindex_name, git_bswap32(hdr->hash_id)),
     117             const_error());
     118      goto cleanup;
     119    }
     120  
     121  cleanup:
     122    if (ret) {
     123      if (data) /* { dg-bogus "check of 'data' for NULL after already dereferencing it" } */
     124        munmap(data, revindex_size);
     125    } else {
     126      *len_p = revindex_size;
     127      *data_p = (const uint32_t *)data;
     128    }
     129  
     130    if (fd >= 0)
     131      close(fd);
     132    return ret;
     133  }