[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.
This commit is contained in:
Bill Currie 2023-03-25 16:46:46 +09:00
parent a058cff59f
commit f18837f195
6 changed files with 46 additions and 61 deletions

View file

@ -161,8 +161,8 @@ check_result (test_t *test)
pr_ivec4_t *a = (pr_ivec4_t *) &test->expect_globals[i]; pr_ivec4_t *a = (pr_ivec4_t *) &test->expect_globals[i];
pr_ivec4_t *b = (pr_ivec4_t *) &test_pr.pr_globals[i]; pr_ivec4_t *b = (pr_ivec4_t *) &test_pr.pr_globals[i];
if (memcmp (a, b, sizeof (pr_ivec4_t))) { 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 (*a));
printf ("+%4x { %8x, %8x %8x %8x }\n", i, VEC4_EXP (*b)); printf ("+%4x { %8x, %8x, %8x, %8x }\n", i, VEC4_EXP (*b));
} }
} }
} }

View file

@ -4,11 +4,11 @@
static pr_ivec4_t int_conv_init[] = { static pr_ivec4_t int_conv_init[] = {
{ 5, -5, 0x80000000, 0x7fffffff}, //int { 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 { 99, 0x80000000, 0x80000000, 99}, //long
{ 256, 0, 0x7fffffff, 0}, //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, 0xbff80000}, //double 1.5, -1.5
{ 0, 0x40020000, 0, 0xc0020000}, //double 2.25, -2.25
{ 5, -5, 0x80000000, 0x7fffffff}, //uint { 5, -5, 0x80000000, 0x7fffffff}, //uint
{ ~0, 1, 0x80000000, 0}, //bool32 { ~0, 1, 0x80000000, 0}, //bool32
{ 99, 0x80000000, 0x80000000, 99}, //ulong { 99, 0x80000000, 0x80000000, 99}, //ulong
@ -27,11 +27,11 @@ static pr_ivec4_t int_conv_init[] = {
static pr_ivec4_t int_conv_expect[] = { static pr_ivec4_t int_conv_expect[] = {
{ 5, -5, 0x80000000, 0x7fffffff}, //int { 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 { 99, 0x80000000, 0x80000000, 99}, //long
{ 256, 0, 0x7fffffff, 0}, //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, 0xbff80000}, //double 1.5, -1.5
{ 0, 0x40020000, 0, 0xc0020000}, //double 2.25, -2.25
{ 5, -5, 0x80000000, 0x7fffffff}, //uint { 5, -5, 0x80000000, 0x7fffffff}, //uint
{ ~0, 1, 0x80000000, 0}, //bool32 { ~0, 1, 0x80000000, 0}, //bool32
{ 99, 0x80000000, 0x80000000, 99}, //ulong { 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
{ 0, ~0, 0, 0}, //bool64 { 0, ~0, 0, 0}, //bool64
{ 5, -5, 0x80000000, 0x7fffffff}, // int { 5, -5, 0x80000000, 0x7fffffff}, // int
{ 1, -1, 0x80000000, 0x80000000}, // float undef? { 1, -1, 2, -2}, // float
{ 99, 0x80000000, 256, 0x7fffffff}, // long { 99, 0x80000000, 256, 0x7fffffff}, // long
{ 0x80000000, 0x80000000, 1, -1}, // double undef? { 1, -1, 2, -2}, // double
{ 5, -5, 0x80000000, 0x7fffffff}, // uint { 5, -5, 0x80000000, 0x7fffffff}, // uint
{ 1, 1, 1, 0}, // bool32 { 1, 1, 1, 0}, // bool32
{ 99, 0x80000000, 256, 0x7fffffff}, // ulong { 99, 0x80000000, 256, 0x7fffffff}, // ulong

View file

@ -4,11 +4,11 @@
static pr_ivec4_t long_conv_init[] = { static pr_ivec4_t long_conv_init[] = {
{ 5, -5, 0x80000000, 0x7fffffff}, //int { 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 { 99, 0x80000000, 0x80000000, 99}, //long
{ 256, 0, 0x7fffffff, 0}, //long { 256, 0, 0x7fffffff, 0}, //long
{ 0x39a08cea, 0x46293e59, 0x39a08cea, 0xc6293e59}, //double 1e30, -1e30 { 0, 0x3ff80000, 0, 0x40020000}, //double 1.5, 2.25, 3.75, 5
{ 0, 0x3ff80000, 0, 0xbff80000}, //double 1.5, -1.5 { 0, 0x400e0000, 0, 0x40140000},
{ 5, -5, 0x80000000, 0x7fffffff}, //uint { 5, -5, 0x80000000, 0x7fffffff}, //uint
{ ~0, 1, 0x80000000, 0}, //bool32 { ~0, 1, 0x80000000, 0}, //bool32
{ 99, 0x80000000, 0x80000000, 99}, //ulong { 99, 0x80000000, 0x80000000, 99}, //ulong
@ -35,11 +35,11 @@ static pr_ivec4_t long_conv_init[] = {
static pr_ivec4_t long_conv_expect[] = { static pr_ivec4_t long_conv_expect[] = {
{ 5, -5, 0x80000000, 0x7fffffff}, //int { 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 { 99, 0x80000000, 0x80000000, 99}, //long
{ 256, 0, 0x7fffffff, 0}, //long { 256, 0, 0x7fffffff, 0}, //long
{ 0x39a08cea, 0x46293e59, 0x39a08cea, 0xc6293e59}, //double 1e30, -1e30 { 0, 0x3ff80000, 0, 0x40020000}, //double 1.5, 2.25, 3.75, 5
{ 0, 0x3ff80000, 0, 0xbff80000}, //double 1.5, -1.5 { 0, 0x400e0000, 0, 0x40140000},
{ 5, -5, 0x80000000, 0x7fffffff}, //uint { 5, -5, 0x80000000, 0x7fffffff}, //uint
{ ~0, 1, 0x80000000, 0}, //bool32 { ~0, 1, 0x80000000, 0}, //bool32
{ 99, 0x80000000, 0x80000000, 99}, //ulong { 99, 0x80000000, 0x80000000, 99}, //ulong
@ -48,12 +48,12 @@ static pr_ivec4_t long_conv_expect[] = {
{ 0, ~0, 0, 0}, //bool64 { 0, ~0, 0, 0}, //bool64
{ 5, 0, -5, 0xffffffff}, // int { 5, 0, -5, 0xffffffff}, // int
{ 0x80000000, 0xffffffff, 0x7fffffff, 0}, { 0x80000000, 0xffffffff, 0x7fffffff, 0},
{ 1, 0, -1, -1}, // float { 1, 0, 2, 0}, // float
{ 0, 0x80000000, 0, 0x80000000}, // undef? { 3, 0, 5, 0},
{ 99, 0x80000000, 0x80000000, 99}, // long { 99, 0x80000000, 0x80000000, 99}, // long
{ 256, 0, 0x7fffffff, 0}, { 256, 0, 0x7fffffff, 0},
{ 0, 0x80000000, 0, 0x80000000}, // double undef? { 1, 0, 2, 0}, // double
{ 1, 0, -1, -1}, { 3, 0, 5, 0},
{ 5, 0, -5, 0}, // uint { 5, 0, -5, 0}, // uint
{ 0x80000000, 0, 0x7fffffff, 0}, { 0x80000000, 0, 0x7fffffff, 0},
{ 1, 0, 1, 0}, // bool32 { 1, 0, 1, 0}, // bool32

View file

@ -4,13 +4,11 @@
static pr_ivec4_t uint_conv_init[] = { static pr_ivec4_t uint_conv_init[] = {
{ 5, -5, 0x80000000, 0x7fffffff}, //int { 5, -5, 0x80000000, 0x7fffffff}, //int
//XXX{ 0x3fc00000, 0xbfc00000, 0x7149f2ca, 0xf149f2ca}, //float 1e30, -1e30 { 0x3fc00000, 0x40100000, 0x40700000, 0x40a00000}, //float 1.5, 2.25, 3.75, 5
{ 0x3fc00000, 0xbfc00000, 0, 0}, //float
{ 99, 0x80000000, 0x80000000, 99}, //long { 99, 0x80000000, 0x80000000, 99}, //long
{ 256, 0, 0x7fffffff, 0}, //long { 256, 0, 0x7fffffff, 0}, //long
//XXX{ 0x39a08cea, 0x46293e59, 0x39a08cea, 0xc6293e59}, //double 1e30, -1e30 { 0, 0x3ff80000, 0, 0x40020000}, //double 1.5, 2.25, 3.75, 5
{ 0, 0, 0, 0}, //double 1e30, -1e30 { 0, 0x400e0000, 0, 0x40140000},
{ 0, 0x3ff80000, 0, 0xbff80000}, //double 1.5, -1.5
{ 5, -5, 0x80000000, 0x7fffffff}, //uint { 5, -5, 0x80000000, 0x7fffffff}, //uint
{ ~0, 1, 0x80000000, 0}, //bool32 { ~0, 1, 0x80000000, 0}, //bool32
{ 99, 0x80000000, 0x80000000, 99}, //ulong { 99, 0x80000000, 0x80000000, 99}, //ulong
@ -27,23 +25,13 @@ static pr_ivec4_t uint_conv_init[] = {
{ 0, 0, 0, 0}, { 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[] = { static pr_ivec4_t uint_conv_expect[] = {
{ 5, -5, 0x80000000, 0x7fffffff}, //int { 5, -5, 0x80000000, 0x7fffffff}, //int
//XXX{ 0x3fc00000, 0xbfc00000, 0x7149f2ca, 0xf149f2ca}, //float { 0x3fc00000, 0x40100000, 0x40700000, 0x40a00000}, //float 1.5, 2.25, 3.75, 5
{ 0x3fc00000, 0xbfc00000, 0, 0}, //float
{ 99, 0x80000000, 0x80000000, 99}, //long { 99, 0x80000000, 0x80000000, 99}, //long
{ 256, 0, 0x7fffffff, 0}, //long { 256, 0, 0x7fffffff, 0}, //long
//XXX{ 0x39a08cea, 0x46293e59, 0x39a08cea, 0xc6293e59}, //double 1e30, -1e30 { 0, 0x3ff80000, 0, 0x40020000}, //double 1.5, 2.25, 3.75, 5
{ 0, 0, 0, 0}, //double 1e30, -1e30 { 0, 0x400e0000, 0, 0x40140000},
{ 0, 0x3ff80000, 0, 0xbff80000}, //double 1.5, -1.5
{ 5, -5, 0x80000000, 0x7fffffff}, //uint { 5, -5, 0x80000000, 0x7fffffff}, //uint
{ ~0, 1, 0x80000000, 0}, //bool32 { ~0, 1, 0x80000000, 0}, //bool32
{ 99, 0x80000000, 0x80000000, 99}, //ulong { 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
{ 0, ~0, 0, 0}, //bool64 { 0, ~0, 0, 0}, //bool64
{ 5, -5, 0x80000000, 0x7fffffff}, // int { 5, -5, 0x80000000, 0x7fffffff}, // int
{ 1, 0xffffffff, 0, 0}, // float undef? { 1, 2, 3, 5}, // float
{ 99, 0x80000000, 256, 0x7fffffff}, // long { 99, 0x80000000, 256, 0x7fffffff}, // long
{ 0, 0, 1, 0xffffffff}, // double undef? { 1, 2, 3, 5}, // double
{ 5, -5, 0x80000000, 0x7fffffff}, // uint { 5, -5, 0x80000000, 0x7fffffff}, // uint
{ 1, 1, 1, 0}, // bool32 { 1, 1, 1, 0}, // bool32
{ 99, 0x80000000, 256, 0x7fffffff}, // ulong { 99, 0x80000000, 256, 0x7fffffff}, // ulong

View file

@ -4,13 +4,11 @@
static pr_ivec4_t ulong_conv_init[] = { static pr_ivec4_t ulong_conv_init[] = {
{ 5, -5, 0x80000000, 0x7fffffff}, //int { 5, -5, 0x80000000, 0x7fffffff}, //int
//XXX{ 0x3fc00000, 0xbfc00000, 0x7149f2ca, 0xf149f2ca}, //float 1e30, -1e30 { 0x3fc00000, 0x40100000, 0x40700000, 0x40a00000}, //float 1.5, 2.25, 3.75, 5
{ 0x3fc00000, 0xbfc00000, 0, 0}, //float 1e30, -1e30
{ 99, 0x80000000, 0x80000000, 99}, //long { 99, 0x80000000, 0x80000000, 99}, //long
{ 256, 0, 0x7fffffff, 0}, //long { 256, 0, 0x7fffffff, 0}, //long
//XXX{ 0x39a08cea, 0x46293e59, 0x39a08cea, 0xc6293e59}, //double 1e30, -1e30 { 0, 0x3ff80000, 0, 0x40020000}, //double 1.5, 2.25, 3.75, 5
{ 0, 0, 0, 0}, //double 1e30, -1e30 { 0, 0x400e0000, 0, 0x40140000},
{ 0, 0x3ff80000, 0, 0xbff80000}, //double 1.5, -1.5
{ 5, -5, 0x80000000, 0x7fffffff}, //uint { 5, -5, 0x80000000, 0x7fffffff}, //uint
{ ~0, 1, 0x80000000, 0}, //bool32 { ~0, 1, 0x80000000, 0}, //bool32
{ 99, 0x80000000, 0x80000000, 99}, //ulong { 99, 0x80000000, 0x80000000, 99}, //ulong
@ -35,37 +33,32 @@ static pr_ivec4_t ulong_conv_init[] = {
{ 0, 0, 0, 0}, { 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[] = { static pr_ivec4_t ulong_conv_expect[] = {
{ 5, -5, 0x80000000, 0x7fffffff}, //int { 5, -5, 0x80000000, 0x7fffffff}, //int
//XXX{ 0x3fc00000, 0xbfc00000, 0x7149f2ca, 0xf149f2ca}, //float 1e30, -1e30 //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 { 99, 0x80000000, 0x80000000, 99}, //long
{ 256, 0, 0x7fffffff, 0}, //long { 256, 0, 0x7fffffff, 0}, //long
//XXX{ 0x39a08cea, 0x46293e59, 0x39a08cea, 0xc6293e59}, //double 1e30, -1e30
{ 0, 0, 0, 0}, //double 1e30, -1e30 { 0, 0x3ff80000, 0, 0x40020000}, //double 1.5, 2.25, 3.75, 5
{ 0, 0x3ff80000, 0, 0xbff80000}, //double 1.5, -1.5 { 0, 0x400e0000, 0, 0x40140000},
{ 5, -5, 0x80000000, 0x7fffffff}, //uint { 5, -5, 0x80000000, 0x7fffffff}, //uint
{ ~0, 1, 0x80000000, 0}, //bool32 { ~0, 1, 0x80000000, 0}, //bool32
{ 99, 0x80000000, 0x80000000, 99}, //ulong { 99, 0x80000000, 0x80000000, 99}, //ulong
{ 256, 0, 0x7fffffff, 0}, //ulong { 256, 0, 0x7fffffff, 0}, //ulong
{ ~0, ~0, ~0, 0}, //bool64 { ~0, ~0, ~0, 0}, //bool64
{ 0, ~0, 0, 0}, //bool64 { 0, ~0, 0, 0}, //bool64
{ 5, 0, -5, 0xffffffff}, // int { 5, 0, -5, 0xffffffff}, // int
{ 0x80000000, 0xffffffff, 0x7fffffff, 0}, { 0x80000000, 0xffffffff, 0x7fffffff, 0},
{ 1, 0, -1, -1}, // float { 1, 0, 2, 0}, // float
//XXX{ 0, 0, 0, 0x80000000}, // undef? { 3, 0, 5, 0},
{ 0, 0, 0, 0}, // undef?
{ 99, 0x80000000, 0x80000000, 99}, // long { 99, 0x80000000, 0x80000000, 99}, // long
{ 256, 0, 0x7fffffff, 0}, { 256, 0, 0x7fffffff, 0},
//XXX{ 0, 0, 0, 0x80000000}, // double undef? { 1, 0, 2, 0}, // double
{ 0, 0, 0, 0}, // double undef? { 3, 0, 5, 0},
{ 1, 0, -1, -1},
{ 5, 0, -5, 0}, // uint { 5, 0, -5, 0}, // uint
{ 0x80000000, 0, 0x7fffffff, 0}, { 0x80000000, 0, 0x7fffffff, 0},
{ 1, 0, 1, 0}, // bool32 { 1, 0, 1, 0}, // bool32

View file

@ -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 -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, -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, 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, 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, -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 -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_LT_S), 0, 0, 16 },
{ OP(1, 2, 3, OP_GT_S), 0, 0, 32 }, { OP(1, 2, 3, OP_GT_S), 0, 0, 32 },
{ OP(1, 2, 3, OP_CMP_S), 0, 0, 48 }, { 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_GE_S), 0, 0, 64 },
{ OP(1, 2, 3, OP_LE_S), 0, 0, 80 }, { OP(1, 2, 3, OP_LE_S), 0, 0, 80 },
{ OP(1, 2, 3, OP_NOT_S), 0, 0, 96 }, { 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[] = { test_t tests[] = {
{ {
.desc = "string", .desc = "string",
.extra_globals = 4 * 1,
.num_globals = num_globals (string_globals_init, string_globals_expect), .num_globals = num_globals (string_globals_init, string_globals_expect),
.num_statements = num_statements (string_statements), .num_statements = num_statements (string_statements),
.statements = string_statements, .statements = string_statements,