I found myself in need of computing the maximal value of 2 operands.
- The 2 operands may have side effects and must be evaluated only once, and
- The evaluation take place in preprocessing macro, and allocation of additional variable is not preferred (although if viable, it's allowed).
The best solution I've come up so far is to bit-or
them together, which has smaller overhead than arithmetic addition. Even though this doesn't get the maximal value of the 2 operands, it tells a value that's big enough to hold working context of either size.
typedef struct {
void (*initfunc)(void *restrict x);
void (*updatefunc)(void *restrict x, const void *restrict in, size_t len);
void (*finalfunc)(void *restrict x, void *restrict out);
} hash_funcs_set;
typedef struct {
unsigned hlen_msg;
unsigned hlen_mgf;
hash_funcs_set_t hfuncs_msg, hfuncs_mgf;
} pkcs1_padding_oracles_base_t;
#define PKCS1_PADDING_ORACLES_T(...) \
struct { \
pkcs1_padding_oracles_base_t base; \
uint8_t hashctx[__VA_ARGS__]; \
}
typedef PKCS1_PADDING_ORACLES_T() pkcs1_padding_oracles_t;
#define PKCS1_PADDING_ORACLES_CTX_SIZE_X(hmsg, hmgf) ( \
sizeof(pkcs1_padding_oracles_base_t) + \
(CTX_BYTES(hmsg) | CTX_BYTES(hmgf)) )
// CTX_BYTES is a function-like macro that invokes hmsg (which
// can be either another function-like expression macro, or a
// function pointer), to obtain the size of hash function working
// context size.
// Possible definitions of a hmsg/hmgf:
#define macro_SHA256(q) (\
q==1 ? 32 /* output bytes */ : \
q==2 ? 256 /* size of working variable set */ : \
q==3 ? (intptr_t)SHA256_Init : \
q==4 ? (intptr_t)SHA256_Update : \
q==5 ? (intptr_t)SHA256_Final : \
0)
intptr_t info_SHA256(int q) { return macro_SHA256(q); }
...
#define OUT_BYTES(obj) (obj(1))
#define CTX_BYTES(obj) (obj(2))
...
The reason I deem this acceptable is because I'm actually allocating memory working contexts for a data structure union (therefore integers) which may be used by 2 different set of functions at different times without conflict, and I hope some XY problem can be spotted and better solution can be devised.
I expect PKCS1_PADDING_ORACLES_CTX_SIZE_X(hmsg,hmgf)
expands to constant expression when hmsg
and hmgf
are constant expressions, but they can be anything and may cause side effects.
The language is standard C, any version. Compiler-specific features are not preferred.