Skip to content

Commit cb7dd62

Browse files
committed
Fix UB from casting
1 parent 059b8aa commit cb7dd62

File tree

1 file changed

+84
-67
lines changed
  • examples/standalone_examples/math_test/src

1 file changed

+84
-67
lines changed

examples/standalone_examples/math_test/src/main.c

Lines changed: 84 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -236,9 +236,24 @@ static void finishOutput()
236236
DEFINE_BINOP_DIV_LIKE_FUNC_LL(u, name, func, post)
237237

238238

239+
typedef struct Op_
240+
{
241+
bool isBinary;
242+
bool isUnsigned;
243+
const char *name;
244+
void (*b)();
245+
void (*s)();
246+
void (*i)();
247+
void (*l)();
248+
void (*i48)();
249+
void (*ll)();
250+
} Op;
251+
239252
#define DEFINE_UNOP_TYPE(u) \
240253
typedef struct u##UnOp_ \
241254
{ \
255+
bool isBinary; \
256+
bool isUnsigned; \
242257
const char *name; \
243258
u##int8_t (*b)(u##int8_t); \
244259
u##int16_t (*s)(u##int16_t); \
@@ -251,6 +266,8 @@ static void finishOutput()
251266
#define DEFINE_BINOP_TYPE(u) \
252267
typedef struct u##BinOp_ \
253268
{ \
269+
bool isBinary; \
270+
bool isUnsigned; \
254271
const char *name; \
255272
u##int8_t (*b)(u##int8_t, u##int8_t); \
256273
u##int16_t (*s)(u##int16_t, u##int16_t); \
@@ -266,44 +283,47 @@ DEFINE_UNOP_TYPE(u)
266283
DEFINE_BINOP_TYPE()
267284
DEFINE_BINOP_TYPE(u)
268285

286+
static const bool _0IsUnsigned = 0;
287+
static const bool _0IsUnsignedu = 1;
288+
269289
#define DEFINE_UNOP_STRUCT_B(u, name) \
270-
static const u##UnOp unop_##name = {#name, b##name##_};
290+
static const u##UnOp u##unop_##name = {0, _0IsUnsigned##u, #name, b##name##_};
271291
#define DEFINE_UNOP_STRUCT_B_TO_S(u, name) \
272-
static const u##UnOp unop_##name = {#name, b##name##_, s##name##_};
292+
static const u##UnOp u##unop_##name = {0, _0IsUnsigned##u, #name, b##name##_, s##name##_};
273293
#define DEFINE_UNOP_STRUCT_B_TO_I(u, name) \
274-
static const u##UnOp unop_##name = {#name, b##name##_, s##name##_, i##name##_};
294+
static const u##UnOp u##unop_##name = {0, _0IsUnsigned##u, #name, b##name##_, s##name##_, i##name##_};
275295
#define DEFINE_UNOP_STRUCT_B_TO_L(u, name) \
276-
static const u##UnOp unop_##name = {#name, b##name##_, s##name##_, i##name##_, l##name##_};
296+
static const u##UnOp u##unop_##name = {0, _0IsUnsigned##u, #name, b##name##_, s##name##_, i##name##_, l##name##_};
277297
#define DEFINE_UNOP_STRUCT_B_TO_I48(u, name) \
278-
static const u##UnOp unop_##name = {#name, b##name##_, s##name##_, i##name##_, l##name##_, i48##name##_};
298+
static const u##UnOp u##unop_##name = {0, _0IsUnsigned##u, #name, b##name##_, s##name##_, i##name##_, l##name##_, i48##name##_};
279299
#define DEFINE_UNOP_STRUCT_B_TO_LL(u, name) \
280-
static const u##UnOp unop_##name = {#name, b##name##_, s##name##_, i##name##_, l##name##_, i48##name##_, ll##name##_};
300+
static const u##UnOp u##unop_##name = {0, _0IsUnsigned##u, #name, b##name##_, s##name##_, i##name##_, l##name##_, i48##name##_, ll##name##_};
281301
#define DEFINE_UNOP_STRUCT_B_TO_LL_EXCEPT_I48(u, name) \
282-
static const u##UnOp unop_##name = {#name, b##name##_, s##name##_, i##name##_, l##name##_, NULL, ll##name##_};
302+
static const u##UnOp u##unop_##name = {0, _0IsUnsigned##u, #name, b##name##_, s##name##_, i##name##_, l##name##_, NULL, ll##name##_};
283303
// clang version 15.0.0 (https://github.com/CE-Programming/llvm-project
284304
// 23b78267b5d376b232475d0805a937e54b61e0d0): unable to legalize instruction:
285305
// %5:_(s48) = G_BSWAP %0:_ (in function: i48bswap_)
286306
#define DEFINE_UNOP_STRUCT_BSWAP(u, name) \
287-
static const u##UnOp unop_##name = {#name, NULL, s##name##_, i##name##_, l##name##_, NULL, ll##name##_};
307+
static const u##UnOp u##unop_##name = {0, _0IsUnsigned##u, #name, NULL, s##name##_, i##name##_, l##name##_, NULL, ll##name##_};
288308

289309
#define DEFINE_BINOP_STRUCT_B(u, name) \
290-
static const u##BinOp binop_##name = {#name, b##name##_};
310+
static const u##BinOp u##binop_##name = {1, _0IsUnsigned##u, #name, b##name##_};
291311
#define DEFINE_BINOP_STRUCT_B_TO_S(u, name) \
292-
static const u##BinOp binop_##name = {#name, b##name##_, s##name##_};
312+
static const u##BinOp u##binop_##name = {1, _0IsUnsigned##u, #name, b##name##_, s##name##_};
293313
#define DEFINE_BINOP_STRUCT_B_TO_I(u, name) \
294-
static const u##BinOp binop_##name = {#name, b##name##_, s##name##_, i##name##_};
314+
static const u##BinOp u##binop_##name = {1, _0IsUnsigned##u, #name, b##name##_, s##name##_, i##name##_};
295315
#define DEFINE_BINOP_STRUCT_B_TO_L(u, name) \
296-
static const u##BinOp binop_##name = {#name, b##name##_, s##name##_, i##name##_, l##name##_};
316+
static const u##BinOp u##binop_##name = {1, _0IsUnsigned##u, #name, b##name##_, s##name##_, i##name##_, l##name##_};
297317
#define DEFINE_BINOP_STRUCT_B_TO_I48(u, name) \
298-
static const u##BinOp binop_##name = {#name, b##name##_, s##name##_, i##name##_, l##name##_, i48##name##_};
318+
static const u##BinOp u##binop_##name = {1, _0IsUnsigned##u, #name, b##name##_, s##name##_, i##name##_, l##name##_, i48##name##_};
299319
#define DEFINE_BINOP_STRUCT_B_TO_LL(u, name) \
300-
static const u##BinOp binop_##name = {#name, b##name##_, s##name##_, i##name##_, l##name##_, i48##name##_, ll##name##_};
320+
static const u##BinOp u##binop_##name = {1, _0IsUnsigned##u, #name, b##name##_, s##name##_, i##name##_, l##name##_, i48##name##_, ll##name##_};
301321
#define DEFINE_BINOP_STRUCT_I_TO_L(u, name) \
302-
static const u##BinOp binop_##name = {#name, NULL, NULL, i##name##_, l##name##_};
322+
static const u##BinOp u##binop_##name = {1, _0IsUnsigned##u, #name, NULL, NULL, i##name##_, l##name##_};
303323
// #define DEFINE_BINOP_STRUCT_I_TO_I48(u, name) \
304-
// static const u##BinOp binop_##name = {#name, NULL, NULL, i##name##_, l##name##_, i48##name##_};
324+
// static const u##BinOp u##binop_##name = {1, _0IsUnsigned##u, #name, NULL, NULL, i##name##_, l##name##_, i48##name##_};
305325
#define DEFINE_BINOP_STRUCT_I_TO_LL(u, name) \
306-
static const u##BinOp binop_##name = {#name, NULL, NULL, i##name##_, l##name##_, NULL, ll##name##_};
326+
static const u##BinOp u##binop_##name = {1, _0IsUnsigned##u, #name, NULL, NULL, i##name##_, l##name##_, NULL, ll##name##_};
307327

308328

309329
#define DEFINE_UNOP_PREFIX_B(u, name, op) \
@@ -345,14 +365,14 @@ DEFINE_BINOP_TYPE(u)
345365
DEFINE_BINOP_STRUCT_B_TO_LL(u, name)
346366

347367

348-
static void testOp(bool isBinOp, const BinOp *op, int64_t x, int64_t y)
368+
static void testOp(const Op *op, int64_t x, int64_t y)
349369
{
350370
unsigned lhsLength = 9;
351371
unsigned nameLength = strlen(op->name);
352372
unsigned prefixLength = lhsLength - nameLength;
353373

354374
x_printffull("%*s=%016llX", lhsLength, "x", (long long)x);
355-
if (!isBinOp)
375+
if (!op->isBinary)
356376
{
357377
x_printf("\n");
358378
}
@@ -362,12 +382,27 @@ static void testOp(bool isBinOp, const BinOp *op, int64_t x, int64_t y)
362382
}
363383
x_printf("\n");
364384

365-
#define TEST_OP(prefix, bits) \
366-
if (op->prefix) \
367-
{ \
368-
unsigned digits = (bits + 3) / 4; \
369-
unsigned long long result = (op->prefix)(x, y) & ((1ULL << (bits - 1) << 1) - 1); \
370-
x_printffull("%*s%s=%*s%0*llX", prefixLength, #prefix, op->name, 16 - digits, "", digits, result); \
385+
#define TEST_OP(prefix, bits) \
386+
if (op->prefix) \
387+
{ \
388+
unsigned digits = (bits + 3) / 4; \
389+
unsigned long long result = \
390+
!op->isBinary \
391+
? !op->isUnsigned \
392+
? ((const UnOp *)(op))->prefix(x) \
393+
: ((const uUnOp *)(op))->prefix(x) \
394+
: !op->isUnsigned \
395+
? ((const BinOp *)(op))->prefix(x, y) \
396+
: ((const uBinOp *)(op))->prefix(x, y); \
397+
result &= ((1ULL << (bits - 1) << 1) - 1); \
398+
x_printffull("%*s%s=%*s%0*llX", \
399+
prefixLength, \
400+
#prefix, \
401+
op->name, \
402+
16 - digits, \
403+
"", \
404+
digits, \
405+
result); \
371406
} \
372407
else \
373408
{ \
@@ -384,16 +419,6 @@ static void testOp(bool isBinOp, const BinOp *op, int64_t x, int64_t y)
384419
finishOutput();
385420
}
386421

387-
static void testUnOp(const UnOp *op, int64_t x)
388-
{
389-
testOp(false, (const BinOp*)op, x, 0);
390-
}
391-
392-
static void testBinOp(const BinOp *op, int64_t x, int64_t y)
393-
{
394-
testOp(true, op, x, y);
395-
}
396-
397422

398423
DEFINE_UNOP_PREFIX_B_TO_LL( , not, ~)
399424
DEFINE_UNOP_PREFIX_B_TO_LL( , neg, -)
@@ -449,31 +474,28 @@ DEFINE_BINOP_DIV_LIKE_FUNC_I_TO_LL( , div_r, div, .rem)
449474
DEFINE_BINOP_STRUCT_I_TO_LL( , div_r)
450475

451476

452-
static const UnOp *unops[] = {
453-
&unop_not,
454-
&unop_neg,
455-
&unop_abs,
456-
&unop_bitrev,
457-
(const UnOp *)&unop_bswap,
458-
(const UnOp *)&unop_popcnt,
459-
};
460-
461-
static const BinOp *binops[] = {
462-
&binop_and,
463-
&binop_or,
464-
&binop_xor,
465-
&binop_add,
466-
&binop_sub,
467-
&binop_shl,
468-
(const BinOp *)&binop_shru,
469-
&binop_shrs,
470-
(const BinOp *)&binop_mulu,
471-
(const BinOp *)&binop_divu,
472-
(const BinOp *)&binop_remu,
473-
&binop_divs,
474-
&binop_rems,
475-
&binop_div_q,
476-
&binop_div_r,
477+
static const Op *ops[] = {
478+
(const Op *)&unop_not,
479+
(const Op *)&unop_neg,
480+
(const Op *)&unop_abs,
481+
(const Op *)&unop_bitrev,
482+
(const Op *)&uunop_bswap,
483+
(const Op *)&uunop_popcnt,
484+
(const Op *)&binop_and,
485+
(const Op *)&binop_or,
486+
(const Op *)&binop_xor,
487+
(const Op *)&binop_add,
488+
(const Op *)&binop_sub,
489+
(const Op *)&binop_shl,
490+
(const Op *)&ubinop_shru,
491+
(const Op *)&binop_shrs,
492+
(const Op *)&ubinop_mulu,
493+
(const Op *)&ubinop_divu,
494+
(const Op *)&ubinop_remu,
495+
(const Op *)&binop_divs,
496+
(const Op *)&binop_rems,
497+
(const Op *)&binop_div_q,
498+
(const Op *)&binop_div_r,
477499
};
478500

479501

@@ -484,14 +506,9 @@ int main(int argc, char *argv[])
484506

485507
separateOutput();
486508

487-
for (size_t i = 0; i < sizeof(unops) / sizeof(*unops); i++)
488-
{
489-
testUnOp(unops[i], x);
490-
}
491-
492-
for (size_t i = 0; i < sizeof(binops) / sizeof(*binops); i++)
509+
for (size_t i = 0; i < sizeof(ops) / sizeof(*ops); i++)
493510
{
494-
testBinOp(binops[i], x, y);
511+
testOp(ops[i], x, y);
495512
}
496513

497514
return 0;

0 commit comments

Comments
 (0)