On Mon, May 13, 2024 at 02:46:32PM -0600, Jeff Law wrote: > > > On 5/13/24 1:48 PM, Qing Zhao wrote: > > -Warray-bounds is an important option to enable linux kernal to keep > > the array out-of-bound errors out of the source tree. > > > > However, due to the false positive warnings reported in PR109071 > > (-Warray-bounds false positive warnings due to code duplication from > > jump threading), -Warray-bounds=1 cannot be added on by default. > > > > Although it's impossible to elinimate all the false positive warnings > > from -Warray-bounds=1 (See PR104355 Misleading -Warray-bounds > > documentation says "always out of bounds"), we should minimize the > > false positive warnings in -Warray-bounds=1. > > > > The root reason for the false positive warnings reported in PR109071 is: > > > > When the thread jump optimization tries to reduce the # of branches > > inside the routine, sometimes it needs to duplicate the code and > > split into two conditional pathes. for example: > > > > The original code: > > > > void sparx5_set (int * ptr, struct nums * sg, int index) > > { > > if (index >= 4) > > warn (); > > *ptr = 0; > > *val = sg->vals[index]; > > if (index >= 4) > > warn (); > > *ptr = *val; > > > > return; > > } > > > > With the thread jump, the above becomes: > > > > void sparx5_set (int * ptr, struct nums * sg, int index) > > { > > if (index >= 4) > > { > > warn (); > > *ptr = 0; // Code duplications since "warn" does return; > > *val = sg->vals[index]; // same this line. > > // In this path, since it's under the condition > > // "index >= 4", the compiler knows the value > > // of "index" is larger then 4, therefore the > > // out-of-bound warning. > > warn (); > > } > > else > > { > > *ptr = 0; > > *val = sg->vals[index]; > > } > > *ptr = *val; > > return; > > } > > > > We can see, after the thread jump optimization, the # of branches inside > > the routine "sparx5_set" is reduced from 2 to 1, however, due to the > > code duplication (which is needed for the correctness of the code), we > > got a false positive out-of-bound warning. > > > > In order to eliminate such false positive out-of-bound warning, > > > > A. Add one more flag for GIMPLE: is_splitted. > > B. During the thread jump optimization, when the basic blocks are > > duplicated, mark all the STMTs inside the original and duplicated > > basic blocks as "is_splitted"; > > C. Inside the array bound checker, add the following new heuristic: > > > > If > > 1. the stmt is duplicated and splitted into two conditional paths; > > + 2. the warning level < 2; > > + 3. the current block is not dominating the exit block > > Then not report the warning. > > > > The false positive warnings are moved from -Warray-bounds=1 to > > -Warray-bounds=2 now. > > > > Bootstrapped and regression tested on both x86 and aarch64. adjusted > > -Warray-bounds-61.c due to the false positive warnings. > > > > Let me know if you have any comments and suggestions. > This sounds horribly wrong. In the code above, the warning is correct.
It's not sensible from a user's perspective. If this doesn't warn: void sparx5_set (int * ptr, struct nums * sg, int index) { *ptr = 0; *val = sg->vals[index]; *ptr = *val; } ... because the value range tracking of "index" spans [INT_MIN,INT_MAX], and warnings based on the value range are silenced if they haven't been clamped at all. (Otherwise warnings would be produced everywhere: only when a limited set of values is known is it useful to produce a warning.) But it makes no sense to warn about: void sparx5_set (int * ptr, struct nums * sg, int index) { if (index >= 4) warn (); *ptr = 0; *val = sg->vals[index]; if (index >= 4) warn (); *ptr = *val; } Because at "*val = sg->vals[index];" the actual value range tracking for index is _still_ [INT_MIN,INT_MAX]. (Only within the "then" side of the "if" statements is the range tracking [4,INT_MAX].) However, in the case where jump threading has split the execution flow and produced a copy of "*val = sg->vals[index];" where the value range tracking for "index" is now [4,INT_MAX], is the warning valid. But it is only for that instance. Reporting it for effectively both (there is only 1 source line for the array indexing) is misleading because there is nothing the user can do about it -- the compiler created the copy and then noticed it had a range it could apply to that array index. This situation makes -Warray-bounds unusable for the Linux kernel (we cannot have false positives says BDFL), but we'd *really* like to have it enabled since it usually finds real bugs. But these false positives can't be fixed on our end. :( So, moving them to -Warray-bounds=2 makes sense as that's the level documented to have potential false positives. -Kees -- Kees Cook