# endif
# endif
+# include <limits.h>
# include <errno.h>
# define ERR_TXT_MALLOCED 0x01
# define X509err(f, r) ERR_raise_data(ERR_LIB_X509, (r), NULL)
# endif
-/*
- * The error code currently packs as follows (viewed as hex nibbles):
+/*-
+ * The error code packs differently depending on if it records a system
+ * error or an OpenSSL error.
*
- * LL rRRRRR
+ * A system error packs like this (we follow POSIX and only allow positive
+ * numbers that fit in an |int|):
*
- * Where LL is the library code, r is the reason flags, and rRRRRR is the
- * reason code.
- * Do note that the reason flags is part of the reason code, and could as
- * well be seen as a section of all possible reason codes. We do this for
- * backward compatibility reasons, i.e. how ERR_R_FATAL was implemented.
+ * +-+-------------------------------------------------------------+
+ * |1| system error number |
+ * +-+-------------------------------------------------------------+
+ *
+ * An OpenSSL error packs like this:
*
- * System errors (ERR_LIB_SYS) are structured the same way, except they
- * don't have any reason flag.
+ * <---------------------------- 32 bits -------------------------->
+ * <--- 8 bits ---><------------------ 23 bits ----------------->
+ * +-+---------------+---------------------------------------------+
+ * |0| library | reason |
+ * +-+---------------+---------------------------------------------+
*
- * LL RRRRRR
+ * A few of the reason bits are reserved as flags with special meaning:
+ *
+ * <4 bits><-------------- 19 bits ------------->
+ * +-------+-------------------------------------+
+ * | rflags| reason |
+ * +-------+-------------------------------------+
+ *
+ * We have the reason flags being part of the overall reason code for
+ * backward compatibility reasons, i.e. how ERR_R_FATAL was implemented.
*/
-# define ERR_LIB_OFFSET 24L
-# define ERR_LIB_MASK 0xFF
-# define ERR_RFLAGS_OFFSET 20L
-# define ERR_RFLAGS_MASK 0xF
-# define ERR_REASON_MASK 0XFFFFFF
+
+/* Macros to help decode recorded system errors */
+# define ERR_SYSTEM_FLAG ((unsigned int)INT_MAX + 1)
+# define ERR_SYSTEM_MASK ((unsigned int)INT_MAX)
+
+/* Macros to help decode recorded OpenSSL errors */
+# define ERR_LIB_OFFSET 23L
+# define ERR_LIB_MASK 0xFF
+# define ERR_RFLAGS_OFFSET 19L
+# define ERR_RFLAGS_MASK 0xF
+# define ERR_REASON_MASK 0X7FFFFF
/*
* Reason flags are defined pre-shifted to easily combine with the reason
* number.
*/
-# define ERR_RFLAG_FATAL (0x1 << ERR_RFLAGS_OFFSET)
-
-/* ERR_PACK takes reason flags and reason code combined in |r| */
-# define ERR_PACK(l,f,r) \
- ( (((unsigned int)(l) & ERR_LIB_MASK) << ERR_LIB_OFFSET) | \
- (((unsigned int)(r) & ERR_REASON_MASK)) )
-# define ERR_GET_LIB(l) (int)(((l) >> ERR_LIB_OFFSET) & ERR_LIB_MASK)
-# define ERR_GET_FUNC(l) 0
-# define ERR_GET_RFLAGS(l) (int)((l) & (ERR_RFLAGS_MASK << ERR_RFLAGS_OFFSET))
-# define ERR_GET_REASON(l) (int)((l) & ERR_REASON_MASK)
-# define ERR_FATAL_ERROR(l) (int)((l) & ERR_RFLAG_FATAL)
+# define ERR_RFLAG_FATAL (0x1 << ERR_RFLAGS_OFFSET)
+
+# define ERR_SYSTEM_ERROR(errcode) (((errcode) & ERR_SYSTEM_FLAG) != 0)
+
+static ossl_inline int ERR_GET_LIB(unsigned long errcode)
+{
+ if (ERR_SYSTEM_ERROR(errcode))
+ return ERR_LIB_SYS;
+ return (errcode >> ERR_LIB_OFFSET) & ERR_LIB_MASK;
+}
+
+static ossl_inline int ERR_GET_FUNC(unsigned long errcode)
+{
+ return 0;
+}
+
+static ossl_inline int ERR_GET_RFLAGS(unsigned long errcode)
+{
+ if (ERR_SYSTEM_ERROR(errcode))
+ return 0;
+ return errcode & (ERR_RFLAGS_MASK << ERR_RFLAGS_OFFSET);
+}
+
+static ossl_inline int ERR_GET_REASON(unsigned long errcode)
+{
+ if (ERR_SYSTEM_ERROR(errcode))
+ return errcode & ERR_SYSTEM_MASK;
+ return errcode & ERR_REASON_MASK;
+}
+
+static ossl_inline int ERR_FATAL_ERROR(unsigned long errcode)
+{
+ return (ERR_GET_RFLAGS(errcode) & ERR_RFLAG_FATAL) != 0;
+}
+
+/*
+ * ERR_PACK is a helper macro to properly pack OpenSSL error codes and may
+ * only be used for that purpose. System errors are packed internally.
+ * ERR_PACK takes reason flags and reason code combined in |reason|.
+ * ERR_PACK ignores |func|, that parameter is just legacy from pre-3.0 OpenSSL.
+ */
+# define ERR_PACK(lib,func,reason) \
+ ( (((unsigned long)(lib) & ERR_LIB_MASK ) << ERR_LIB_OFFSET) | \
+ (((unsigned long)(reason) & ERR_REASON_MASK)) )
# ifndef OPENSSL_NO_DEPRECATED_3_0
# define SYS_F_FOPEN 0