cb424d7448
verify-patch-sanity.py validates every active recipe .patch has internally- consistent hunk line counts — catching the 'malformed patch at line N' failure at commit/CI/preflight time instead of hours into a cook. This cycle hit that class three times (qtwaylandscanner, sddm, xwayland), each only discovered when cookbook tried to apply the patch. Running it across the repo found 29 latent malformed patches (validated against GNU patch: e.g. relibc/P3-sysv-ipc reproduces 'malformed patch at line 22'). They were harmless only because they sit in vendored recipes (baked, not re- applied) — but would fail on any version-bump re-derivation. --fix recounts the hunk headers (body untouched) and repaired all 29. Wired into build-preflight.sh (Phase 1.0D) and redbear-ci.yml, with a unit test (test-patch-sanity.sh). Skips archived/legacy trees and unvalidatable formats (empty placeholders, bare-@@ git hunks).
169 lines
7.3 KiB
C
169 lines
7.3 KiB
C
// RUN: %clang_analyze_cc1 -analyzer-checker=core.BitwiseShift \
|
|
// RUN: -analyzer-checker=debug.ExprInspection \
|
|
// RUN: -analyzer-output=text -verify \
|
|
// RUN: -triple x86_64-pc-linux-gnu -x c %s \
|
|
// RUN: -Wno-shift-count-negative -Wno-shift-negative-value \
|
|
// RUN: -Wno-shift-count-overflow -Wno-shift-overflow \
|
|
// RUN: -Wno-shift-sign-overflow
|
|
//
|
|
// RUN: %clang_analyze_cc1 -analyzer-checker=core.BitwiseShift \
|
|
// RUN: -analyzer-checker=debug.ExprInspection \
|
|
// RUN: -analyzer-config core.BitwiseShift:Pedantic=true \
|
|
// RUN: -analyzer-output=text -verify \
|
|
// RUN: -triple x86_64-pc-linux-gnu -x c++ -std=c++20 %s \
|
|
// RUN: -Wno-shift-count-negative -Wno-shift-negative-value \
|
|
// RUN: -Wno-shift-count-overflow -Wno-shift-overflow \
|
|
// RUN: -Wno-shift-sign-overflow
|
|
//
|
|
// This test file verifies the default behavior of the BitwiseShift checker,
|
|
// which reports the serious logical defects, but doesn't warn on code that's
|
|
// legal under C++20 (or later) and widely accepted (but theoretically
|
|
// undefined) in other compilation modes.
|
|
|
|
// TEST NEGATIVE RIGHT OPERAND
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
int negative_right_operand_literal(void) {
|
|
return 2 << -2;
|
|
// expected-warning@-1 {{Right operand is negative in left shift}}
|
|
// expected-note@-2 {{The result of left shift is undefined because the right operand is negative}}
|
|
}
|
|
|
|
int negative_right_operand_symbolic(int left, int right) {
|
|
// expected-note@+2 {{Assuming 'right' is < 0}}
|
|
// expected-note@+1 {{Taking false branch}}
|
|
if (right >= 0)
|
|
return 0;
|
|
return left >> right;
|
|
// expected-warning@-1 {{Right operand is negative in right shift}}
|
|
// expected-note@-2 {{The result of right shift is undefined because the right operand is negative}}
|
|
}
|
|
|
|
int negative_right_operand_compound(short arg) {
|
|
// expected-note@+2 {{Assuming 'arg' is < 2}}
|
|
// expected-note@+1 {{Taking false branch}}
|
|
if (arg >= 2 )
|
|
return 0;
|
|
return 2 << (arg - 1 - 1 - 1);
|
|
// expected-warning@-1 {{Right operand is negative in left shift}}
|
|
// expected-note@-2 {{The result of left shift is undefined because the right operand is negative}}
|
|
}
|
|
|
|
// TEST TOO LARGE RIGHT OPERAND
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
int too_large_right_operand_literal(void) {
|
|
return 2 << 32;
|
|
// expected-warning@-1 {{Left shift by '32' overflows the capacity of 'int'}}
|
|
// expected-note@-2 {{The result of left shift is undefined because the right operand '32' is not smaller than 32, the capacity of 'int'}}
|
|
}
|
|
|
|
int too_large_right_operand_exact_symbolic(int arg) {
|
|
// expected-note@+4 {{Assuming 'arg' is > 33}}
|
|
// expected-note@+3 {{Left side of '||' is false}}
|
|
// expected-note@+2 {{Assuming 'arg' is < 35}}
|
|
// expected-note@+1 {{Taking false branch}}
|
|
if (arg <= 33 || arg >= 35)
|
|
return 0;
|
|
return 3 << arg;
|
|
// expected-warning@-1 {{Left shift by '34' overflows the capacity of 'int'}}
|
|
// expected-note@-2 {{The result of left shift is undefined because the right operand '34' is not smaller than 32, the capacity of 'int'}}
|
|
}
|
|
|
|
int too_large_right_operand_exact_symbolic_2(char arg) {
|
|
// expected-note@+2 {{Assuming the condition is false}}
|
|
// expected-note@+1 {{Taking false branch}}
|
|
if (arg != ' ')
|
|
return 0;
|
|
return 3 << arg;
|
|
// expected-warning@-1 {{Left shift by '32' overflows the capacity of 'int'}}
|
|
// expected-note@-2 {{The result of left shift is undefined because the right operand '32' is not smaller than 32, the capacity of 'int'}}
|
|
}
|
|
|
|
int too_large_right_operand_symbolic(int left, int right) {
|
|
// expected-note@+2 {{Assuming 'right' is > 31}}
|
|
// expected-note@+1 {{Taking false branch}}
|
|
if (right <= 31)
|
|
return 0;
|
|
return left >> right;
|
|
// expected-warning@-1 {{Right shift overflows the capacity of 'int'}}
|
|
// expected-note@-2 {{The result of right shift is undefined because the right operand is >= 32, not smaller than 32, the capacity of 'int'}}
|
|
}
|
|
|
|
void clang_analyzer_value(int);
|
|
int too_large_right_operand_compound(unsigned short arg) {
|
|
// Note: this would be valid code with an 'unsigned int' because
|
|
// unsigned addition is allowed to overflow.
|
|
clang_analyzer_value(32+arg);
|
|
// expected-warning@-1 {{32s:{ [-2147483648, 2147483647] }}
|
|
// expected-note@-2 {{32s:{ [-2147483648, 2147483647] }}
|
|
return 1 << (32 + arg);
|
|
// expected-warning@-1 {{Left shift overflows the capacity of 'int'}}
|
|
// expected-note@-2 {{The result of left shift is undefined because the right operand is not smaller than 32, the capacity of 'int'}}
|
|
// FIXME: this message should be
|
|
// {{The result of left shift is undefined because the right operand is >= 32, not smaller than 32, the capacity of 'int'}}
|
|
// but for some reason neither the new logic, nor debug.ExprInspection and
|
|
// clang_analyzer_value reports this range information.
|
|
}
|
|
|
|
// TEST STATE UPDATES
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
void state_update(char a, int *p) {
|
|
// NOTE: with 'int a' this would not produce a bug report because the engine
|
|
// would not rule out an overflow.
|
|
*p += 1 << a;
|
|
// expected-note@-1 {{Assuming right operand of bit shift is non-negative but less than 32}}
|
|
*p += 1 << (a + 32);
|
|
// expected-warning@-1 {{Left shift overflows the capacity of 'int'}}
|
|
// expected-note@-2 {{The result of left shift is undefined because the right operand is not smaller than 32, the capacity of 'int'}}
|
|
}
|
|
|
|
void state_update_2(char a, int *p) {
|
|
*p += 1234 >> (a + 32);
|
|
// expected-note@-1 {{Assuming right operand of bit shift is non-negative but less than 32}}
|
|
*p += 1234 >> a;
|
|
// expected-warning@-1 {{Right operand is negative in right shift}}
|
|
// expected-note@-2 {{The result of right shift is undefined because the right operand is negative}}
|
|
}
|
|
|
|
// TEST EXPRESSION TRACKING
|
|
//===----------------------------------------------------------------------===//
|
|
// Expression tracking a "generic" tool that's used by many other checkers,
|
|
// so this is just a minimal test to see that it's activated.
|
|
|
|
void setValue(unsigned *p, unsigned newval) {
|
|
*p = newval;
|
|
// expected-note@-1 {{The value 33 is assigned to 'right'}}
|
|
}
|
|
|
|
int expression_tracked_back(void) {
|
|
unsigned left = 115; // expected-note {{'left' initialized to 115}}
|
|
unsigned right;
|
|
setValue(&right, 33);
|
|
// expected-note@-1 {{Calling 'setValue'}}
|
|
// expected-note@-2 {{Passing the value 33 via 2nd parameter 'newval'}}
|
|
// expected-note@-3 {{Returning from 'setValue'}}
|
|
|
|
return left << right;
|
|
// expected-warning@-1 {{Left shift by '33' overflows the capacity of 'unsigned int'}}
|
|
// expected-note@-2 {{The result of left shift is undefined because the right operand '33' is not smaller than 32, the capacity of 'unsigned int'}}
|
|
}
|
|
|
|
// TEST PERMISSIVENESS
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
int allow_overflows_and_negative_operands(void) {
|
|
// These are all legal under C++20 and many compilers accept them under
|
|
// earlier standards as well.
|
|
int int_min = 1 << 31; // no-warning
|
|
int this_overflows = 1027 << 30; // no-warning
|
|
return (-2 << 5) + (-3 >> 4); // no-warning
|
|
}
|
|
|
|
int double_negative(void) {
|
|
return -2 >> -2;
|
|
// expected-warning@-1 {{Right operand is negative in right shift}}
|
|
// expected-note@-2 {{The result of right shift is undefined because the right operand is negative}}
|
|
}
|