首页 > 解决方案 > 在预处理中计算其评估可能导致副作用的 2 个操作数的最大值

问题描述

我发现自己需要计算 2 个操作数的最大值。

到目前为止,我提出的最佳解决方案是将bit-or它们放在一起,这比算术加法的开销更小。即使这没有得到 2 个操作数的最大值,它也给出了一个足够大的值来容纳任一大小的工作上下文。

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))
...

我认为这是可以接受的原因是因为我实际上是为数据结构联合(因此是整数)分配内存工作上下文,它可能在不同时间由 2 组不同的函数使用而不会发生冲突,我希望可以发现一些 XY 问题并且可以设计出更好的解决方案。

我希望在和是常量PKCS1_PADDING_ORACLES_CTX_SIZE_X(hmsg,hmgf)表达式时扩展为常量表达式,但它们可以是任何东西并且可能会导致副作用。hmsghmgf

语言是标准C,任何版本。编译器特定的功能不是首选。

标签: cmaxc-preprocessorside-effects

解决方案


2个操作数有副作用

这意味着它们不是常量表达式。所以只需编写一个函数来计算最大值。使用适当的类型。

// hash_ret_type - the return type of hash function.
// Or it's just unsigned long long or uintmax_t, if super lazy.

hash_ret_type hash_max(hash_ret_type a, hash_ret_type b) {
     return a > b ? a : b;
}

#define PKCS1_PADDING_ORACLES_CTX_SIZE_X(hmsg, hmgf) (  \
        sizeof(pkcs1_padding_oracles_base_t) +          \
        hash_max(CTX_BYTES(hmsg), CTX_BYTES(hmgf)) )

如果您对使用 GNU 扩展感兴趣,您可能想对max() linux 内核宏感兴趣。


推荐阅读