/ external / libecc / include / libecc / utils / utils.h
utils.h
  1  /*
  2   *  Copyright (C) 2017 - This file is part of libecc project
  3   *
  4   *  Authors:
  5   *      Ryad BENADJILA <ryadbenadjila@gmail.com>
  6   *      Arnaud EBALARD <arnaud.ebalard@ssi.gouv.fr>
  7   *      Jean-Pierre FLORI <jean-pierre.flori@ssi.gouv.fr>
  8   *
  9   *  Contributors:
 10   *      Nicolas VIVET <nicolas.vivet@ssi.gouv.fr>
 11   *      Karim KHALFALLAH <karim.khalfallah@ssi.gouv.fr>
 12   *
 13   *  This software is licensed under a dual BSD and GPL v2 license.
 14   *  See LICENSE file at the root folder of the project.
 15   */
 16  #ifndef __UTILS_H__
 17  #define __UTILS_H__
 18  
 19  #include <libecc/words/words.h>
 20  
 21  /*
 22   * At various locations in the code, we expect expect some specific
 23   * conditions to be true for correct operation of the code after
 24   * those locations. This is commonly the case on input parameters
 25   * at the beginning of functions. Other conditions may be expected
 26   * but are not necessarily impacting for correct operation of the
 27   * code.
 28   *
 29   * We use the three following macros for that purpose:
 30   *
 31   * MUST_HAVE(): The condition is always tested, i.e. both in debug
 32   * and non debug build. This macros is used when it's better not to
 33   * continue if the condition does not hold. In production code,
 34   * if the condition does not hold, a while (1) loop is currently
 35   * executed (but this may be changed for some specific code the
 36   * system provide (e.g. abort())). In debug mode, an assert() is
 37   * used when the condition is false.
 38   *
 39   * SHOULD_HAVE(): the condition is only executed in debug mode and
 40   * the whole macros is a nop in production code. This can be used
 41   * to add more checks in the code to detect specific conditions
 42   * or changes. Those checks may have performance impact which are
 43   * acceptable in debug mode but are not in production mode.
 44   *
 45   * KNOWN_FACT(): the condition is only executed in debug mode and
 46   * the whole macro is a nop in production code. This macro is used
 47   * to add conditions that are known to be true which may help analysis
 48   * tools to work on the code. The macro can be used in order to make
 49   * those conditions explicit.
 50   */
 51  
 52  /* Some helper for printing where we have an issue */
 53  #if defined(USE_ASSERT_PRINT)
 54  #include <libecc/external_deps/print.h>
 55  #define MUST_HAVE_EXT_PRINT do {					\
 56  	ext_printf("MUST_HAVE error: %s at %d\n", __FILE__,__LINE__);	\
 57  } while (0)
 58  #define SHOULD_HAVE_EXT_PRINT do {					\
 59  	ext_printf("SHOULD_HAVE error: %s at %d\n", __FILE__,__LINE__);	\
 60  } while (0)
 61  #define KNOWN_FACT_EXT_PRINT do {					\
 62  	ext_printf("KNOWN_FACT error: %s at %d\n", __FILE__,__LINE__);	\
 63  } while (0)
 64  #else
 65  #define MUST_HAVE_EXT_PRINT
 66  #define SHOULD_HAVE_EXT_PRINT
 67  #define KNOWN_FACT_EXT_PRINT
 68  #endif
 69  
 70  /*
 71   * We known it is BAD BAD BAD to define macro with goto inside them
 72   * but this is the best way we found to avoid making the code
 73   * unreadable with tests of error conditions when implementing
 74   * error handling in the project.
 75   *
 76   * EG stands for Error Goto, which represents the purpose of the
 77   * macro, i.e. test a condition cond, and if false goto label
 78   * lbl.
 79   */
 80  #define EG(cond,lbl) do { if (cond) { goto lbl ; } } while (0)
 81  
 82  /****** Regular DEBUG and production modes cases  ****************/
 83  
 84  /****** DEBUG mode ***********************************************/
 85  #if defined(DEBUG)
 86  #include <assert.h>
 87  /*
 88   * In DEBUG mode, we enforce a regular assert() in MUST_HAVE,
 89   * SHOULD_HAVE and KNOWN_FACT, i.e. they are all the same.
 90   */
 91  
 92  #define MUST_HAVE(cond, ret, lbl) do {	\
 93  	if(!(cond)){			\
 94  		MUST_HAVE_EXT_PRINT;	\
 95  	}				\
 96  	assert((cond));			\
 97  	if (0) { /* silence unused	\
 98  		    label warning  */	\
 99  		ret = -1;		\
100  		goto lbl;		\
101  	}				\
102  }  while (0)
103  
104  #define SHOULD_HAVE(cond, ret, lbl) do {\
105  	if(!(cond)){			\
106  		SHOULD_HAVE_EXT_PRINT;	\
107  	}				\
108  	assert((cond));			\
109  	if (0) { /* silence unused	\
110  		    label warning  */	\
111  		ret = -1;		\
112  		goto lbl;		\
113  	}				\
114  }  while (0)
115  
116  #define KNOWN_FACT(cond, ret, lbl) do {	\
117  	if(!(cond)){			\
118  		KNOWN_FACT_EXT_PRINT;	\
119  	}				\
120  	assert((cond));			\
121  	if (0) { /* silence unused	\
122  		    label warning  */	\
123  		ret = -1;		\
124  		goto lbl;		\
125  	}				\
126  }  while (0)
127  
128  /****** Production mode ******************************************/
129  #else /* !defined(DEBUG) */
130  
131  /*
132   * In regular production mode, SHOULD_HAVE and KNOWN_FACT are void for
133   * performance reasons. MUST_HAVE includes an ext_printf call for
134   * tracing the origin of the error when necessary (if USE_ASSERT_PRINT
135   * is specified by the user).
136   */
137  #define MUST_HAVE(cond, ret, lbl) do {		\
138  	if (!(cond)) {				\
139  		MUST_HAVE_EXT_PRINT;		\
140  		ret = -1;			\
141  		goto lbl;			\
142  	}					\
143  }  while (0)
144  
145  #define SHOULD_HAVE(cond, ret, lbl) do { \
146  	if (0) { /* silence unused	 \
147  		    label warning  */	 \
148  		ret = -1;		 \
149  		goto lbl;		 \
150  	}				 \
151  }  while (0)
152  
153  #define KNOWN_FACT(cond, ret, lbl)  do { \
154  	if (0) { /* silence unused	 \
155  		    label warning  */	 \
156  		ret = -1;		 \
157  		goto lbl;		 \
158  	}				 \
159  }  while (0)
160  
161  /******************************************************************/
162  #endif  /* defined(DEBUG) */
163  
164  #define LOCAL_MAX(x, y) (((x) > (y)) ? (x) : (y))
165  #define LOCAL_MIN(x, y) (((x) < (y)) ? (x) : (y))
166  
167  #define BYTECEIL(numbits) (((numbits) + 7) / 8)
168  
169  ATTRIBUTE_WARN_UNUSED_RET int are_equal(const void *a, const void *b, u32 len, int *check);
170  ATTRIBUTE_WARN_UNUSED_RET int local_memcpy(void *dst, const void *src, u32 n);
171  ATTRIBUTE_WARN_UNUSED_RET int local_memset(void *v, u8 c, u32 n);
172  ATTRIBUTE_WARN_UNUSED_RET int are_str_equal(const char *s1, const char *s2, int *check);
173  ATTRIBUTE_WARN_UNUSED_RET int are_str_equal_nlen(const char *s1, const char *s2, u32 maxlen, int *check);
174  ATTRIBUTE_WARN_UNUSED_RET int local_strlen(const char *s, u32 *len);
175  ATTRIBUTE_WARN_UNUSED_RET int local_strnlen(const char *s, u32 maxlen, u32 *len);
176  ATTRIBUTE_WARN_UNUSED_RET int local_strncpy(char *dst, const char *src, u32 n);
177  ATTRIBUTE_WARN_UNUSED_RET int local_strncat(char *dest, const char *src, u32 n);
178  
179  /* Return 1 if architecture is big endian, 0 otherwise. */
180  static inline int arch_is_big_endian(void)
181  {
182  	const u16 val = 0x0102;
183  	const u8 *buf = (const u8 *)(&val);
184  
185  	return buf[0] == 0x01;
186  }
187  
188  #define VAR_ZEROIFY(x) do { \
189  		x = 0;      \
190  	} while (0)
191  
192  #define PTR_NULLIFY(x) do { \
193  		x = NULL;   \
194  	} while (0)
195  
196  #endif /* __UTILS_H__ */