The following patches change quite a bit of things regarding shifts with bad count. Add testcases to ensure everything is covered and catch possible future regressions. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@xxxxxxxxx> --- validation/shift-undef-long.c | 22 +++++++++++ validation/shift-undef.c | 73 +++++++++++++++++++++++++++++++++++ 2 files changed, 95 insertions(+) create mode 100644 validation/shift-undef-long.c create mode 100644 validation/shift-undef.c diff --git a/validation/shift-undef-long.c b/validation/shift-undef-long.c new file mode 100644 index 000000000..50fcd98eb --- /dev/null +++ b/validation/shift-undef-long.c @@ -0,0 +1,22 @@ +static unsigned very_big_shift(unsigned int a) +{ + unsigned r = 0; + r |= a << (0ULL ^ ~0U); + r |= a << ((( signed long long) ~0U) + 1); + r |= a << (((unsigned long long) ~0U) + 1); + r |= a << (~((unsigned long long) ~0U)); + return r; +} + +/* + * check-name: shift-undef-long + * check-command: sparse -m64 $file + * check-known-to-fail + * + * check-error-start +shift-undef-long.c:4:16: warning: shift too big (4294967295) for type unsigned int +shift-undef-long.c:5:16: warning: shift too big (4294967296) for type unsigned int +shift-undef-long.c:6:16: warning: shift too big (4294967296) for type unsigned int +shift-undef-long.c:7:16: warning: shift count is negative (-4294967296) + * check-error-end + */ diff --git a/validation/shift-undef.c b/validation/shift-undef.c new file mode 100644 index 000000000..5aead8d79 --- /dev/null +++ b/validation/shift-undef.c @@ -0,0 +1,73 @@ +int simple(int s, unsigned int u, int p) +{ + s = s >> 100; + u = u >> 101; + u = u << 102; + s = s >> -1; + u = u >> -2; + u = u << -3; + if (0) return s >> 103; + if (0) return u >> 104; + if (0) return u << 105; + if (0) return s >> -4; + if (0) return u >> -5; + if (0) return u << -6; + if (p && 0) return s >> 106; + if (p && 0) return u >> 107; + if (p && 0) return u << 108; + if (p && 0) return s >> -7; + if (p && 0) return u >> -8; + if (p && 0) return u << -9; + s = s >> ((p & 0) + 109); + u = u >> ((p & 0) + 110); + u = u << ((p & 0) + 111); + s = s >> ((p & 0) + -10); + u = u >> ((p & 0) + -11); + u = u << ((p & 0) + -12); + return s + u; +} + +int ok(int s, unsigned int u, int p) +{ + // GCC doesn't warn on these + if (0 && (s >> 100)) return 0; + if (0 && (u >> 101)) return 0; + if (0 && (u << 102)) return 0; + if (0 && (s >> -1)) return 0; + if (0 && (u >> -2)) return 0; + if (0 && (u << -3)) return 0; + if (0 && (s >>= 103)) return 0; + if (0 && (u >>= 104)) return 0; + if (0 && (u <<= 105)) return 0; + if (0 && (s >>= -4)) return 0; + if (0 && (u >>= -5)) return 0; + if (0 && (u <<= -6)) return 0; + return 1; +} + +/* + * check-name: shift too big or negative + * check-command: sparse -Wno-decl $file + * + * check-error-start +shift-undef.c:3:15: warning: shift too big (100) for type int +shift-undef.c:4:15: warning: shift too big (101) for type unsigned int +shift-undef.c:5:15: warning: shift too big (102) for type unsigned int +shift-undef.c:6:15: warning: shift too big (4294967295) for type int +shift-undef.c:7:15: warning: shift too big (4294967294) for type unsigned int +shift-undef.c:8:15: warning: shift too big (4294967293) for type unsigned int +shift-undef.c:9:25: warning: shift too big (103) for type int +shift-undef.c:10:25: warning: shift too big (104) for type unsigned int +shift-undef.c:11:25: warning: shift too big (105) for type unsigned int +shift-undef.c:12:25: warning: shift too big (4294967292) for type int +shift-undef.c:13:25: warning: shift too big (4294967291) for type unsigned int +shift-undef.c:14:25: warning: shift too big (4294967290) for type unsigned int +shift-undef.c:15:30: warning: shift too big (106) for type int +shift-undef.c:16:30: warning: shift too big (107) for type unsigned int +shift-undef.c:17:30: warning: shift too big (108) for type unsigned int +shift-undef.c:18:30: warning: shift too big (4294967289) for type int +shift-undef.c:19:30: warning: shift too big (4294967288) for type unsigned int +shift-undef.c:20:30: warning: shift too big (4294967287) for type unsigned int +shift-undef.c:21:29: warning: right shift by bigger than source value + * check-error-end + */ -- 2.18.0 -- To unsubscribe from this list: send the line "unsubscribe linux-sparse" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html