From f18837f1955372b9fa0cb59fcd2cedb0e9d84f8f Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 25 Mar 2023 16:46:46 +0900 Subject: [PATCH] [gamecode] Fix a pile of UB in the test cases I always suspected the overflow conversions were UB, but with gcc doing different things on arm, I thought it was about time to abandon those particular tests. What I was not expecting was for the return value of strcmp to be "UB" (in that there's no guarantee of the exact value, just < = > 0). Fortunately, nothing actually relies on the value of the op other than the tests, so modify the test to make the behavior well defined. --- libs/gamecode/test/main.c | 4 ++-- libs/gamecode/test/test-conv0.c | 12 +++++------ libs/gamecode/test/test-conv2.c | 20 +++++++++--------- libs/gamecode/test/test-conv4.c | 28 ++++++++----------------- libs/gamecode/test/test-conv6.c | 35 +++++++++++++------------------- libs/gamecode/test/test-string.c | 8 ++++++-- 6 files changed, 46 insertions(+), 61 deletions(-) diff --git a/libs/gamecode/test/main.c b/libs/gamecode/test/main.c index 6186c4ac9..4d4c31d1e 100644 --- a/libs/gamecode/test/main.c +++ b/libs/gamecode/test/main.c @@ -161,8 +161,8 @@ check_result (test_t *test) pr_ivec4_t *a = (pr_ivec4_t *) &test->expect_globals[i]; pr_ivec4_t *b = (pr_ivec4_t *) &test_pr.pr_globals[i]; if (memcmp (a, b, sizeof (pr_ivec4_t))) { - printf ("-%4x { %8x, %8x %8x %8x }\n", i, VEC4_EXP (*a)); - printf ("+%4x { %8x, %8x %8x %8x }\n", i, VEC4_EXP (*b)); + printf ("-%4x { %8x, %8x, %8x, %8x }\n", i, VEC4_EXP (*a)); + printf ("+%4x { %8x, %8x, %8x, %8x }\n", i, VEC4_EXP (*b)); } } } diff --git a/libs/gamecode/test/test-conv0.c b/libs/gamecode/test/test-conv0.c index 3b6e06359..d5153b5a4 100644 --- a/libs/gamecode/test/test-conv0.c +++ b/libs/gamecode/test/test-conv0.c @@ -4,11 +4,11 @@ static pr_ivec4_t int_conv_init[] = { { 5, -5, 0x80000000, 0x7fffffff}, //int - { 0x3fc00000, 0xbfc00000, 0x7149f2ca, 0xf149f2ca}, //float 1e30, -1e30 + { 0x3fc00000, 0xbfc00000, 0x40100000, 0xc0100000}, //float 1.5, -1.5, 2.25, -2.25 { 99, 0x80000000, 0x80000000, 99}, //long { 256, 0, 0x7fffffff, 0}, //long - { 0x39a08cea, 0x46293e59, 0x39a08cea, 0xc6293e59}, //double 1e30, -1e30 { 0, 0x3ff80000, 0, 0xbff80000}, //double 1.5, -1.5 + { 0, 0x40020000, 0, 0xc0020000}, //double 2.25, -2.25 { 5, -5, 0x80000000, 0x7fffffff}, //uint { ~0, 1, 0x80000000, 0}, //bool32 { 99, 0x80000000, 0x80000000, 99}, //ulong @@ -27,11 +27,11 @@ static pr_ivec4_t int_conv_init[] = { static pr_ivec4_t int_conv_expect[] = { { 5, -5, 0x80000000, 0x7fffffff}, //int - { 0x3fc00000, 0xbfc00000, 0x7149f2ca, 0xf149f2ca}, //float + { 0x3fc00000, 0xbfc00000, 0x40100000, 0xc0100000}, //float 1.5, -1.5, 2.25, -2.25 { 99, 0x80000000, 0x80000000, 99}, //long { 256, 0, 0x7fffffff, 0}, //long - { 0x39a08cea, 0x46293e59, 0x39a08cea, 0xc6293e59}, //double 1e30, -1e30 { 0, 0x3ff80000, 0, 0xbff80000}, //double 1.5, -1.5 + { 0, 0x40020000, 0, 0xc0020000}, //double 2.25, -2.25 { 5, -5, 0x80000000, 0x7fffffff}, //uint { ~0, 1, 0x80000000, 0}, //bool32 { 99, 0x80000000, 0x80000000, 99}, //ulong @@ -39,9 +39,9 @@ static pr_ivec4_t int_conv_expect[] = { { ~0, ~0, ~0, 0}, //bool64 { 0, ~0, 0, 0}, //bool64 { 5, -5, 0x80000000, 0x7fffffff}, // int - { 1, -1, 0x80000000, 0x80000000}, // float undef? + { 1, -1, 2, -2}, // float { 99, 0x80000000, 256, 0x7fffffff}, // long - { 0x80000000, 0x80000000, 1, -1}, // double undef? + { 1, -1, 2, -2}, // double { 5, -5, 0x80000000, 0x7fffffff}, // uint { 1, 1, 1, 0}, // bool32 { 99, 0x80000000, 256, 0x7fffffff}, // ulong diff --git a/libs/gamecode/test/test-conv2.c b/libs/gamecode/test/test-conv2.c index 0dd4f5d41..647ea2ed4 100644 --- a/libs/gamecode/test/test-conv2.c +++ b/libs/gamecode/test/test-conv2.c @@ -4,11 +4,11 @@ static pr_ivec4_t long_conv_init[] = { { 5, -5, 0x80000000, 0x7fffffff}, //int - { 0x3fc00000, 0xbfc00000, 0x7149f2ca, 0xf149f2ca}, //float 1e30, -1e30 + { 0x3fc00000, 0x40100000, 0x40700000, 0x40a00000}, //float 1.5, 2.25, 3.75, 5 { 99, 0x80000000, 0x80000000, 99}, //long { 256, 0, 0x7fffffff, 0}, //long - { 0x39a08cea, 0x46293e59, 0x39a08cea, 0xc6293e59}, //double 1e30, -1e30 - { 0, 0x3ff80000, 0, 0xbff80000}, //double 1.5, -1.5 + { 0, 0x3ff80000, 0, 0x40020000}, //double 1.5, 2.25, 3.75, 5 + { 0, 0x400e0000, 0, 0x40140000}, { 5, -5, 0x80000000, 0x7fffffff}, //uint { ~0, 1, 0x80000000, 0}, //bool32 { 99, 0x80000000, 0x80000000, 99}, //ulong @@ -35,11 +35,11 @@ static pr_ivec4_t long_conv_init[] = { static pr_ivec4_t long_conv_expect[] = { { 5, -5, 0x80000000, 0x7fffffff}, //int - { 0x3fc00000, 0xbfc00000, 0x7149f2ca, 0xf149f2ca}, //float + { 0x3fc00000, 0x40100000, 0x40700000, 0x40a00000}, //float 1.5, 2.25, 3.75, 5 { 99, 0x80000000, 0x80000000, 99}, //long { 256, 0, 0x7fffffff, 0}, //long - { 0x39a08cea, 0x46293e59, 0x39a08cea, 0xc6293e59}, //double 1e30, -1e30 - { 0, 0x3ff80000, 0, 0xbff80000}, //double 1.5, -1.5 + { 0, 0x3ff80000, 0, 0x40020000}, //double 1.5, 2.25, 3.75, 5 + { 0, 0x400e0000, 0, 0x40140000}, { 5, -5, 0x80000000, 0x7fffffff}, //uint { ~0, 1, 0x80000000, 0}, //bool32 { 99, 0x80000000, 0x80000000, 99}, //ulong @@ -48,12 +48,12 @@ static pr_ivec4_t long_conv_expect[] = { { 0, ~0, 0, 0}, //bool64 { 5, 0, -5, 0xffffffff}, // int { 0x80000000, 0xffffffff, 0x7fffffff, 0}, - { 1, 0, -1, -1}, // float - { 0, 0x80000000, 0, 0x80000000}, // undef? + { 1, 0, 2, 0}, // float + { 3, 0, 5, 0}, { 99, 0x80000000, 0x80000000, 99}, // long { 256, 0, 0x7fffffff, 0}, - { 0, 0x80000000, 0, 0x80000000}, // double undef? - { 1, 0, -1, -1}, + { 1, 0, 2, 0}, // double + { 3, 0, 5, 0}, { 5, 0, -5, 0}, // uint { 0x80000000, 0, 0x7fffffff, 0}, { 1, 0, 1, 0}, // bool32 diff --git a/libs/gamecode/test/test-conv4.c b/libs/gamecode/test/test-conv4.c index 35cc00979..ed455b02f 100644 --- a/libs/gamecode/test/test-conv4.c +++ b/libs/gamecode/test/test-conv4.c @@ -4,13 +4,11 @@ static pr_ivec4_t uint_conv_init[] = { { 5, -5, 0x80000000, 0x7fffffff}, //int - //XXX{ 0x3fc00000, 0xbfc00000, 0x7149f2ca, 0xf149f2ca}, //float 1e30, -1e30 - { 0x3fc00000, 0xbfc00000, 0, 0}, //float + { 0x3fc00000, 0x40100000, 0x40700000, 0x40a00000}, //float 1.5, 2.25, 3.75, 5 { 99, 0x80000000, 0x80000000, 99}, //long { 256, 0, 0x7fffffff, 0}, //long - //XXX{ 0x39a08cea, 0x46293e59, 0x39a08cea, 0xc6293e59}, //double 1e30, -1e30 - { 0, 0, 0, 0}, //double 1e30, -1e30 - { 0, 0x3ff80000, 0, 0xbff80000}, //double 1.5, -1.5 + { 0, 0x3ff80000, 0, 0x40020000}, //double 1.5, 2.25, 3.75, 5 + { 0, 0x400e0000, 0, 0x40140000}, { 5, -5, 0x80000000, 0x7fffffff}, //uint { ~0, 1, 0x80000000, 0}, //bool32 { 99, 0x80000000, 0x80000000, 99}, //ulong @@ -27,23 +25,13 @@ static pr_ivec4_t uint_conv_init[] = { { 0, 0, 0, 0}, }; -/* Note that these tests (specifically 1, 3a and 3b) fail when compiled with - * clang and optimzing due to difference between clang and gcc, and more - * interestingly, within clang itself: with optimization enabled, the entries - * marked with "undef?" produce 0x80000000 instead of 0, but with optimization - * disabled, the expected 0 is produced. - * Inspecting the results, it seems that clang sets negative floats and doubles - * to 0 when casting to unsigned long, but not consistently. - */ static pr_ivec4_t uint_conv_expect[] = { { 5, -5, 0x80000000, 0x7fffffff}, //int - //XXX{ 0x3fc00000, 0xbfc00000, 0x7149f2ca, 0xf149f2ca}, //float - { 0x3fc00000, 0xbfc00000, 0, 0}, //float + { 0x3fc00000, 0x40100000, 0x40700000, 0x40a00000}, //float 1.5, 2.25, 3.75, 5 { 99, 0x80000000, 0x80000000, 99}, //long { 256, 0, 0x7fffffff, 0}, //long - //XXX{ 0x39a08cea, 0x46293e59, 0x39a08cea, 0xc6293e59}, //double 1e30, -1e30 - { 0, 0, 0, 0}, //double 1e30, -1e30 - { 0, 0x3ff80000, 0, 0xbff80000}, //double 1.5, -1.5 + { 0, 0x3ff80000, 0, 0x40020000}, //double 1.5, 2.25, 3.75, 5 + { 0, 0x400e0000, 0, 0x40140000}, { 5, -5, 0x80000000, 0x7fffffff}, //uint { ~0, 1, 0x80000000, 0}, //bool32 { 99, 0x80000000, 0x80000000, 99}, //ulong @@ -51,9 +39,9 @@ static pr_ivec4_t uint_conv_expect[] = { { ~0, ~0, ~0, 0}, //bool64 { 0, ~0, 0, 0}, //bool64 { 5, -5, 0x80000000, 0x7fffffff}, // int - { 1, 0xffffffff, 0, 0}, // float undef? + { 1, 2, 3, 5}, // float { 99, 0x80000000, 256, 0x7fffffff}, // long - { 0, 0, 1, 0xffffffff}, // double undef? + { 1, 2, 3, 5}, // double { 5, -5, 0x80000000, 0x7fffffff}, // uint { 1, 1, 1, 0}, // bool32 { 99, 0x80000000, 256, 0x7fffffff}, // ulong diff --git a/libs/gamecode/test/test-conv6.c b/libs/gamecode/test/test-conv6.c index 72f1c6b9f..5cfaab926 100644 --- a/libs/gamecode/test/test-conv6.c +++ b/libs/gamecode/test/test-conv6.c @@ -4,13 +4,11 @@ static pr_ivec4_t ulong_conv_init[] = { { 5, -5, 0x80000000, 0x7fffffff}, //int - //XXX{ 0x3fc00000, 0xbfc00000, 0x7149f2ca, 0xf149f2ca}, //float 1e30, -1e30 - { 0x3fc00000, 0xbfc00000, 0, 0}, //float 1e30, -1e30 + { 0x3fc00000, 0x40100000, 0x40700000, 0x40a00000}, //float 1.5, 2.25, 3.75, 5 { 99, 0x80000000, 0x80000000, 99}, //long { 256, 0, 0x7fffffff, 0}, //long - //XXX{ 0x39a08cea, 0x46293e59, 0x39a08cea, 0xc6293e59}, //double 1e30, -1e30 - { 0, 0, 0, 0}, //double 1e30, -1e30 - { 0, 0x3ff80000, 0, 0xbff80000}, //double 1.5, -1.5 + { 0, 0x3ff80000, 0, 0x40020000}, //double 1.5, 2.25, 3.75, 5 + { 0, 0x400e0000, 0, 0x40140000}, { 5, -5, 0x80000000, 0x7fffffff}, //uint { ~0, 1, 0x80000000, 0}, //bool32 { 99, 0x80000000, 0x80000000, 99}, //ulong @@ -35,37 +33,32 @@ static pr_ivec4_t ulong_conv_init[] = { { 0, 0, 0, 0}, }; -/* Note that these tests fail when compiled with clang due to difference - * between clang and gcc. However, unlike test-conv4, the failure is - * consistent between optimized and unoptimized: all tests fail either way. - * Inspecting the results, it seems that clang sets negative floats and doubles - * to 0 when casting to unsigned long. - */ static pr_ivec4_t ulong_conv_expect[] = { { 5, -5, 0x80000000, 0x7fffffff}, //int //XXX{ 0x3fc00000, 0xbfc00000, 0x7149f2ca, 0xf149f2ca}, //float 1e30, -1e30 - { 0x3fc00000, 0xbfc00000, 0, 0}, //float 1e30, -1e30 + { 0x3fc00000, 0x40100000, 0x40700000, 0x40a00000}, //float 1.5, 2.25, 3.75, 5 { 99, 0x80000000, 0x80000000, 99}, //long { 256, 0, 0x7fffffff, 0}, //long - //XXX{ 0x39a08cea, 0x46293e59, 0x39a08cea, 0xc6293e59}, //double 1e30, -1e30 - { 0, 0, 0, 0}, //double 1e30, -1e30 - { 0, 0x3ff80000, 0, 0xbff80000}, //double 1.5, -1.5 + + { 0, 0x3ff80000, 0, 0x40020000}, //double 1.5, 2.25, 3.75, 5 + { 0, 0x400e0000, 0, 0x40140000}, { 5, -5, 0x80000000, 0x7fffffff}, //uint { ~0, 1, 0x80000000, 0}, //bool32 + { 99, 0x80000000, 0x80000000, 99}, //ulong { 256, 0, 0x7fffffff, 0}, //ulong { ~0, ~0, ~0, 0}, //bool64 { 0, ~0, 0, 0}, //bool64 + { 5, 0, -5, 0xffffffff}, // int { 0x80000000, 0xffffffff, 0x7fffffff, 0}, - { 1, 0, -1, -1}, // float - //XXX{ 0, 0, 0, 0x80000000}, // undef? - { 0, 0, 0, 0}, // undef? + { 1, 0, 2, 0}, // float + { 3, 0, 5, 0}, + { 99, 0x80000000, 0x80000000, 99}, // long { 256, 0, 0x7fffffff, 0}, - //XXX{ 0, 0, 0, 0x80000000}, // double undef? - { 0, 0, 0, 0}, // double undef? - { 1, 0, -1, -1}, + { 1, 0, 2, 0}, // double + { 3, 0, 5, 0}, { 5, 0, -5, 0}, // uint { 0x80000000, 0, 0x7fffffff, 0}, { 1, 0, 1, 0}, // bool32 diff --git a/libs/gamecode/test/test-string.c b/libs/gamecode/test/test-string.c index ceb716570..955431d19 100644 --- a/libs/gamecode/test/test-string.c +++ b/libs/gamecode/test/test-string.c @@ -26,7 +26,7 @@ static pr_int_t string_globals_expect[] = { -1, 0, 0, 0, 0, -1, 0, -1, 0, 0, -1, 0, 0, -1, 0, -1, // eq 0, -1, -1, -1, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, -1, 0, // lt 0, 0, 0, 0, -1, 0, 0, 0, -1, -1, 0, -1, -1, 0, 0, 0, // gt - 0,-97,-100,-97, 97, 0, -3, 0, 100, 3, 0, 3, 97, 0, -3, 0, // cmp + 0, -1, -1, -1, 1, 0, -1, 0, 1, 1, 0, 1, 1, 0, -1, 0, // cmp -1, 0, 0, 0, -1, -1, 0, -1, -1, -1, -1, -1, -1, -1, 0, -1, // ge -1, -1, -1, -1, 0, -1, -1, -1, 0, 0, -1, 0, 0, -1, -1, -1, // le -1, -1, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // not @@ -59,18 +59,22 @@ static dstatement_t string_statements[] = { { OP(1, 2, 3, OP_LT_S), 0, 0, 16 }, { OP(1, 2, 3, OP_GT_S), 0, 0, 32 }, { OP(1, 2, 3, OP_CMP_S), 0, 0, 48 }, + { OP(3, 0, 0, OP_LT_I_1), 48, 0, 7 }, // convert < 0, 0, > 0 to -1, 0, 1 + { OP(3, 0, 3, OP_GT_I_1), 48, 0, 48 }, // ... + { OP(0, 3, 3, OP_SUB_I_1), 7, 48, 48 }, // ... { OP(1, 2, 3, OP_GE_S), 0, 0, 64 }, { OP(1, 2, 3, OP_LE_S), 0, 0, 80 }, { OP(1, 2, 3, OP_NOT_S), 0, 0, 96 }, // } - { OP(0, 0, 0, OP_JUMP_A), -13, 0, 0 }, + { OP(0, 0, 0, OP_JUMP_A), -16, 0, 0 }, // } }; test_t tests[] = { { .desc = "string", + .extra_globals = 4 * 1, .num_globals = num_globals (string_globals_init, string_globals_expect), .num_statements = num_statements (string_statements), .statements = string_statements,