1 /*
2  * Copyright (C) by Argonne National Laboratory
3  *     See COPYRIGHT in top-level directory
4  */
5 
6 #ifndef MPIR_POINTERS_H_INCLUDED
7 #define MPIR_POINTERS_H_INCLUDED
8 
9 #include "mpi.h"
10 #include "mpichconf.h"
11 #include "mpichconfconst.h"
12 #include "mpir_assert.h"
13 #include "mpl.h"
14 
15 
16 /* This test is lame.  Should eventually include cookie test
17    and in-range addresses */
18 #define MPIR_Valid_ptr_class(kind,ptr,errclass,err) \
19     do {                                                                \
20         if (!(ptr)) {                                                   \
21             err = MPIR_Err_create_code(MPI_SUCCESS, MPIR_ERR_RECOVERABLE, __func__, __LINE__, errclass, \
22                                        "**nullptrtype", "**nullptrtype %s", #kind); \
23             /* Explicitly tell Coverity that errclass != MPI_SUCCESS => err != MPI_SUCCESS */ \
24             MPIR_Assert((errclass) == MPI_SUCCESS || ((err) != MPI_SUCCESS)); \
25         }                                                               \
26     } while (0)
27 
28 #define MPIR_Info_valid_ptr(ptr,err) MPIR_Valid_ptr_class(Info,ptr,MPI_ERR_INFO,err)
29 /* Check not only for a null pointer but for an invalid communicator,
30    such as one that has been freed.  Let's try the ref_count as the test
31    for now */
32 /* ticket #1441: check (refcount<=0) to cover the case of 0, an "over-free" of
33  * -1 or similar, and the 0xecec... case when --enable-g=mem is used */
34 #define MPIR_Comm_valid_ptr(ptr,err,ignore_rev) {     \
35      MPIR_Valid_ptr_class(Comm,ptr,MPI_ERR_COMM,err); \
36      if ((ptr) && MPIR_Object_get_ref(ptr) <= 0) {    \
37          MPIR_ERR_SET(err,MPI_ERR_COMM,"**comm");     \
38          ptr = 0;                                     \
39      } else if ((ptr) && (ptr)->revoked && !(ignore_rev)) {        \
40          MPIR_ERR_SET(err,MPIX_ERR_REVOKED,"**comm"); \
41      }                                                \
42 }
43 #define MPIR_Win_valid_ptr(ptr,err) MPIR_Valid_ptr_class(Win,ptr,MPI_ERR_WIN,err)
44 #define MPIR_Group_valid_ptr(ptr,err) MPIR_Valid_ptr_class(Group,ptr,MPI_ERR_GROUP,err)
45 #define MPIR_Op_valid_ptr(ptr,err) MPIR_Valid_ptr_class(Op,ptr,MPI_ERR_OP,err)
46 #define MPIR_Errhandler_valid_ptr(ptr,err) MPIR_Valid_ptr_class(Errhandler,ptr,MPI_ERR_ARG,err)
47 #define MPIR_Request_valid_ptr(ptr,err) MPIR_Valid_ptr_class(Request,ptr,MPI_ERR_REQUEST,err)
48 #define MPII_Keyval_valid_ptr(ptr,err) MPIR_Valid_ptr_class(Keyval,ptr,MPI_ERR_KEYVAL,err)
49 
50 
51 /* Assigns (src_) to (dst_), checking that (src_) fits in (dst_) without
52  * truncation.
53  *
54  * When fiddling with this macro, please keep C's overly complicated integer
55  * promotion/truncation/conversion rules in mind.  A discussion of these issues
56  * can be found in Chapter 5 of "Secure Coding in C and C++" by Robert Seacord.
57  */
58 #define MPIR_Assign_trunc(dst_,src_,dst_type_)                                         \
59     do {                                                                               \
60         /* will catch some of the cases if the expr_inttype macros aren't available */ \
61         MPIR_Assert((src_) == (dst_type_)(src_));                                      \
62         dst_ = (dst_type_)(src_);                                                      \
63     } while (0)
64 
65 /*
66  * Ensure an MPI_Aint value fits into a signed int.
67  * Useful for detecting overflow when MPI_Aint is larger than an int.
68  *
69  * \param[in]  aint  Variable of type MPI_Aint
70  */
71 #define MPIR_Ensure_Aint_fits_in_int(aint) \
72   MPIR_Assert((aint) == (MPI_Aint)(int)(aint));
73 
74 #endif /* MPIR_POINTERS_H_INCLUDED */
75