Try in colab: https://colab.research.google.com/github/philzook58/philzook58.github.io/blob/master/pynb/2024-02-05-undefined_behavior.ipynb

I posted a little tutorial on CBMC, the C Bounded model checker last week.

It made it to the front page of Hacker news, which is neat. What I didn’t expect is how people latched onto the uninitialized read in this example

%%file /tmp/ex1.c
#include <assert.h>
int main(){
    int x;
    if (x <= 42){
            assert(x != 12345);
    }
}

Writing /tmp/ex1.c

This is a serious issue that CBMC does not check for. It is a tool that can fairly easily and effectively answer certain kinds of questions, but not all. It is in the process of getting better

CBMC on it’s own is insufficient to guarantee that a program does what you want and what you expect or that it obeys best practices. Defense in depth is important. We’re awhiles off from something that reads your mind and makes your thoughts precise and cogent.

%%bash
# download and install CBMC
wget https://github.com/diffblue/cbmc/releases/download/cbmc-5.95.1/ubuntu-20.04-cbmc-5.95.1-Linux.deb
apt-get install bash-completion
dpkg -i ubuntu-20.04-cbmc-5.95.1-Linux.deb
! cbmc /tmp/ex1.c
CBMC version 5.95.1 (cbmc-5.95.1) 64-bit x86_64 linux
Parsing /tmp/ex1.c
Converting
Type-checking ex1
Generating GOTO Program
Adding CPROVER library (x86_64)
Removal of function pointers and virtual functions
Generic Property Instrumentation
Running with 8 object bits, 56 offset bits (default)
Starting Bounded Model Checking
Runtime Symex: 0.00265417s
size of program expression: 23 steps
simple slicing removed 5 assignments
Generated 1 VCC(s), 1 remaining after simplification
Runtime Postprocess Equation: 1.2691e-05s
Passing problem to propositional reduction
converting SSA
Runtime Convert SSA: 0.0010266s
Running propositional reduction
Post-processing
Runtime Post-process: 4.841e-06s
Solving with MiniSAT 2.2.1 with simplifier
67 variables, 100 clauses
SAT checker inconsistent: instance is UNSATISFIABLE
Runtime Solver: 1.542e-05s
Runtime decision procedure: 0.0014064s

** Results:
/tmp/ex1.c function main
[2m[main.assertion.1] [0mline 5 assertion x != 12345: [32mSUCCESS[0m

** 0 of 1 failed (1 iterations)
VERIFICATION SUCCESSFUL

It was commented that your compiler’s -Wall -Wextra -Wpedantic can check this issue. It is good to enable and deal with all warnings somehow. Indeed, this program is obviously suspicious. These checks will not catch all problems and cannot catch some things CBMC can.

! gcc -Wall -Wextra -Wpedantic /tmp/ex1.c -o /tmp/ex1 -fdiagnostics-plain-output
/tmp/ex1.c: In function ‘main’:
/tmp/ex1.c:4:8: warning: ‘x’ is used uninitialized [-Wuninitialized]

Another interesting tool to sort of spread spectrum apply static analyses to projects is CodeChecker. This applies some lighter weight larger scale analyses like cppcheck, infer, and the compiler built in analyzers. It also makes nice little html pages and has some kind of CI story.

These are good things to run. Coming back clean is no guarantee of software quality, but it is a good sign.

%%bash
#install codechecker and other tools
apt-get install cppcheck clang-tidy
python3 -m pip install codechecker 
! CodeChecker check --build "clang /tmp/ex1.c"
[INFO 2024-02-05 15:26] - Starting build...
[INFO 2024-02-05 15:26] - Using CodeChecker ld-logger.
[INFO 2024-02-05 15:26] - Build finished successfully.
[INFO 2024-02-05 15:26] - Previous analysis results in '/tmp/tmpc7xy9pwi' have been removed, overwriting with current result
[INFO 2024-02-05 15:27] - Enabled checkers:
clangsa: alpha.security.cert.pos.34c, core.BitwiseShift, core.CallAndMessage, core.DivideZero, core.NonNullParamChecker, core.NullDereference, core.StackAddressEscape, core.UndefinedBinaryOperatorResult, core.VLASize, core.uninitialized.ArraySubscript, core.uninitialized.Assign, core.uninitialized.Branch, core.uninitialized.CapturedBlockVariable, core.uninitialized.NewArraySize, core.uninitialized.UndefReturn, cplusplus.InnerPointer, cplusplus.Move, cplusplus.NewDelete, cplusplus.NewDeleteLeaks, cplusplus.PlacementNew, cplusplus.PureVirtualCall, cplusplus.StringChecker, deadcode.DeadStores, nullability.NullPassedToNonnull, nullability.NullReturnedFromNonnull, optin.cplusplus.UninitializedObject, optin.cplusplus.VirtualCall, optin.portability.UnixAPI, security.cert.env.InvalidPtr, security.FloatLoopCounter, security.insecureAPI.UncheckedReturn, security.insecureAPI.getpw, security.insecureAPI.gets, security.insecureAPI.mkstemp, security.insecureAPI.mktemp, security.insecureAPI.rand, security.insecureAPI.vfork, unix.API, unix.Malloc, unix.MallocSizeof, unix.MismatchedDeallocator, unix.StdCLibraryFunctions, unix.Vfork, unix.cstring.BadSizeArg, unix.cstring.NullArg, valist.CopyToSelf, valist.Uninitialized, valist.Unterminated
cppcheck: cppcheck-IOWithoutPositioning, cppcheck-StlMissingComparison, cppcheck-accessForwarded, cppcheck-accessMoved, cppcheck-argumentSize, cppcheck-arrayIndexOutOfBounds, cppcheck-arrayIndexOutOfBoundsCond, cppcheck-assertWithSideEffect, cppcheck-assignBoolToPointer, cppcheck-assignmentInAssert, cppcheck-autoVariables, cppcheck-autovarInvalidDeallocation, cppcheck-badBitmaskCheck, cppcheck-boostForeachError, cppcheck-bufferAccessOutOfBounds, cppcheck-charBitOp, cppcheck-charLiteralWithCharPtrCompare, cppcheck-checkCastIntToCharAndBack, cppcheck-clarifyStatement, cppcheck-compareBoolExpressionWithInt, cppcheck-comparePointers, cppcheck-comparisonFunctionIsAlwaysTrueOrFalse, cppcheck-comparisonOfBoolWithInvalidComparator, cppcheck-constStatement, cppcheck-containerOutOfBounds, cppcheck-copyCtorAndEqOperator, cppcheck-copyCtorPointerCopying, cppcheck-coutCerrMisusage, cppcheck-danglingLifetime, cppcheck-danglingReference, cppcheck-danglingTemporaryLifetime, cppcheck-deallocDealloc, cppcheck-deallocret, cppcheck-deallocuse, cppcheck-derefInvalidIterator, cppcheck-divideSizeof, cppcheck-doubleFree, cppcheck-duplInheritedMember, cppcheck-eraseDereference, cppcheck-exceptDeallocThrow, cppcheck-exceptThrowInDestructor, cppcheck-floatConversionOverflow, cppcheck-funcArgOrderDifferent, cppcheck-identicalConditionAfterEarlyExit, cppcheck-identicalInnerCondition, cppcheck-ignoredReturnValue, cppcheck-incompatibleFileOpen, cppcheck-incompleteArrayFill, cppcheck-incorrectCharBooleanError, cppcheck-incorrectLogicOperator, cppcheck-incorrectStringBooleanError, cppcheck-incorrectStringCompare, cppcheck-integerOverflow, cppcheck-invalidContainerLoop, cppcheck-invalidContainer, cppcheck-invalidFree, cppcheck-invalidFunctionArg, cppcheck-invalidFunctionArgBool, cppcheck-invalidFunctionArgStr, cppcheck-invalidIterator1, cppcheck-invalidLengthModifierError, cppcheck-invalidLifetime, cppcheck-invalidPrintfArgType_float, cppcheck-invalidPrintfArgType_n, cppcheck-invalidPrintfArgType_p, cppcheck-invalidPrintfArgType_s, cppcheck-invalidPrintfArgType_sint, cppcheck-invalidPrintfArgType_uint, cppcheck-invalidScanfArgType_float, cppcheck-invalidScanfArgType_int, cppcheck-invalidScanfArgType_s, cppcheck-invalidScanfFormatWidth, cppcheck-invalidScanfFormatWidth_smaller, cppcheck-invalidTestForOverflow, cppcheck-invalidscanf, cppcheck-iterators1, cppcheck-iterators2, cppcheck-iterators3, cppcheck-iteratorsCmp1, cppcheck-iteratorsCmp2, cppcheck-leakNoVarFunctionCall, cppcheck-leakReturnValNotUsed, cppcheck-leakUnsafeArgAlloc, cppcheck-literalWithCharPtrCompare, cppcheck-mallocOnClassError, cppcheck-mallocOnClassWarning, cppcheck-memleak, cppcheck-memleakOnRealloc, cppcheck-memsetClass, cppcheck-memsetClassFloat, cppcheck-memsetClassReference, cppcheck-memsetValueOutOfRange, cppcheck-memsetZeroBytes, cppcheck-mismatchAllocDealloc, cppcheck-mismatchSize, cppcheck-mismatchingContainerExpression, cppcheck-mismatchingContainers, cppcheck-missingMemberCopy, cppcheck-missingReturn, cppcheck-moduloAlwaysTrueFalse, cppcheck-multiplySizeof, cppcheck-negativeArraySize, cppcheck-negativeContainerIndex, cppcheck-negativeIndex, cppcheck-negativeMemoryAllocationSize, cppcheck-noCopyConstructor, cppcheck-noDestructor, cppcheck-noOperatorEq, cppcheck-nullPointer, cppcheck-nullPointerArithmetic, cppcheck-nullPointerArithmeticRedundantCheck, cppcheck-nullPointerDefaultArg, cppcheck-nullPointerRedundantCheck, cppcheck-objectIndex, cppcheck-operatorEqMissingReturnStatement, cppcheck-operatorEqToSelf, cppcheck-operatorEqVarError, cppcheck-oppositeInnerCondition, cppcheck-overlappingStrcmp, cppcheck-overlappingWriteFunction, cppcheck-overlappingWriteUnion, cppcheck-pointerAdditionResultNotNull, cppcheck-pointerArithBool, cppcheck-pointerSize, cppcheck-publicAllocationError, cppcheck-pureVirtualCall, cppcheck-raceAfterInterlockedDecrement, cppcheck-readWriteOnlyFile, cppcheck-redundantAssignInSwitch, cppcheck-redundantBitwiseOperationInSwitch, cppcheck-redundantCopyInSwitch, cppcheck-resourceLeak, cppcheck-rethrowNoCurrentException, cppcheck-returnAddressOfAutoVariable, cppcheck-returnAddressOfFunctionParameter, cppcheck-returnDanglingLifetime, cppcheck-returnLocalVariable, cppcheck-returnReference, cppcheck-returnTempReference, cppcheck-seekOnAppendedFile, cppcheck-selfAssignment, cppcheck-selfInitialization, cppcheck-shiftNegativeLHS, cppcheck-shiftNegative, cppcheck-shiftTooManyBits, cppcheck-shiftTooManyBitsSigned, cppcheck-signConversion, cppcheck-signedCharArrayIndex, cppcheck-sizeofCalculation, cppcheck-sizeofDivisionMemfunc, cppcheck-sizeofFunctionCall, cppcheck-sizeofsizeof, cppcheck-sizeofwithnumericparameter, cppcheck-sizeofwithsilentarraypointer, cppcheck-sprintfOverlappingData, cppcheck-staticStringCompare, cppcheck-stlBoundaries, cppcheck-stlIfFind, cppcheck-stlOutOfBounds, cppcheck-stlcstr, cppcheck-stlcstrReturn, cppcheck-stlcstrParam, cppcheck-stlcstrthrow, cppcheck-strPlusChar, cppcheck-stringCompare, cppcheck-stringLiteralWrite, cppcheck-suspiciousCase, cppcheck-suspiciousSemicolon, cppcheck-thisSubtraction, cppcheck-throwInNoexceptFunction, cppcheck-uninitDerivedMemberVar, cppcheck-uninitDerivedMemberVarPrivate, cppcheck-uninitMemberVar, cppcheck-uninitMemberVarPrivate, cppcheck-uninitStructMember, cppcheck-uninitdata, cppcheck-uninitstring, cppcheck-uninitvar, cppcheck-unknownEvaluationOrder, cppcheck-unsafeClassRefMember, cppcheck-unusedLabelSwitch, cppcheck-unusedLabelSwitchConfiguration, cppcheck-useClosedFile, cppcheck-uselessAssignmentPtrArg, cppcheck-uselessCallsCompare, cppcheck-uselessCallsEmpty, cppcheck-uselessCallsRemove, cppcheck-va_end_missing, cppcheck-va_list_usedBeforeStarted, cppcheck-va_start_referencePassed, cppcheck-va_start_subsequentCalls, cppcheck-va_start_wrongParameter, cppcheck-virtualCallInConstructor, cppcheck-virtualDestructor, cppcheck-writeReadOnlyFile, cppcheck-wrongPipeParameterSize, cppcheck-wrongPrintfScanfArgNum, cppcheck-wrongPrintfScanfParameterPositionError, cppcheck-wrongmathcall, cppcheck-zerodiv, cppcheck-zerodivcond
clang-tidy: bugprone-assert-side-effect, bugprone-bool-pointer-implicit-conversion, bugprone-compare-pointer-to-member-virtual-function, bugprone-copy-constructor-init, bugprone-dangling-handle, bugprone-dynamic-static-initializers, bugprone-fold-init-type, bugprone-forward-declaration-namespace, bugprone-forwarding-reference-overload, bugprone-inaccurate-erase, bugprone-inc-dec-in-conditions, bugprone-incorrect-enable-if, bugprone-incorrect-roundings, bugprone-infinite-loop, bugprone-integer-division, bugprone-lambda-function-name, bugprone-macro-repeated-side-effects, bugprone-misplaced-operator-in-strlen-in-alloc, bugprone-misplaced-pointer-arithmetic-in-alloc, bugprone-misplaced-widening-cast, bugprone-move-forwarding-reference, bugprone-multiple-new-in-one-expression, bugprone-not-null-terminated-result, bugprone-optional-value-conversion, bugprone-shared-ptr-array-mismatch, bugprone-signal-handler, bugprone-signed-char-misuse, bugprone-sizeof-container, bugprone-sizeof-expression, bugprone-standalone-empty, bugprone-string-constructor, bugprone-stringview-nullptr, bugprone-string-literal-with-embedded-nul, bugprone-suspicious-enum-usage, bugprone-suspicious-memory-comparison, bugprone-suspicious-memset-usage, bugprone-suspicious-missing-comma, bugprone-suspicious-realloc-usage, bugprone-suspicious-semicolon, bugprone-swapped-arguments, bugprone-switch-missing-default-case, bugprone-terminating-continue, bugprone-throw-keyword-missing, bugprone-too-small-loop-variable, bugprone-undefined-memory-manipulation, bugprone-undelegated-constructor, bugprone-unhandled-exception-at-new, bugprone-unique-ptr-array-mismatch, bugprone-unused-raii, bugprone-unused-return-value, bugprone-use-after-move, bugprone-virtual-near-miss, cert-dcl54-cpp, cert-dcl58-cpp, cert-dcl59-cpp, cert-err09-cpp, cert-fio38-c, cert-mem57-cpp, cert-oop11-cpp, cert-oop58-cpp, cert-pos44-c, cert-pos47-c, clang-diagnostic-array-bounds-pointer-arithmetic, clang-diagnostic-bitwise-conditional-parentheses, clang-diagnostic-bitwise-instead-of-logical, clang-diagnostic-bitwise-op-parentheses, clang-diagnostic-bool-operation, clang-diagnostic-cast-of-sel-type, clang-diagnostic-char-subscripts, clang-diagnostic-comment, clang-diagnostic-comments, clang-diagnostic-dangling-else, clang-diagnostic-delete-abstract-non-virtual-dtor, clang-diagnostic-delete-non-abstract-non-virtual-dtor, clang-diagnostic-delete-non-virtual-dtor, clang-diagnostic-deprecated-copy, clang-diagnostic-deprecated-copy-with-dtor, clang-diagnostic-deprecated-copy-with-user-provided-dtor, clang-diagnostic-deprecated-copy-dtor, clang-diagnostic-deprecated-copy-with-user-provided-copy, clang-diagnostic-division-by-zero, clang-diagnostic-double-promotion, clang-diagnostic-embedded-directive, clang-diagnostic-empty-init-stmt, clang-diagnostic-extern-c-compat, clang-diagnostic-float-conversion, clang-diagnostic-for-loop-analysis, clang-diagnostic-format, clang-diagnostic-format-overflow, clang-diagnostic-format-overflow-non-kprintf, clang-diagnostic-format-truncation, clang-diagnostic-format-truncation-non-kprintf, clang-diagnostic-format-non-iso, clang-diagnostic-format-pedantic, clang-diagnostic-format-type-confusion, clang-diagnostic-format=2, clang-diagnostic-format-extra-args, clang-diagnostic-format-insufficient-args, clang-diagnostic-format-invalid-specifier, clang-diagnostic-format-nonliteral, clang-diagnostic-format-security, clang-diagnostic-format-y2k, clang-diagnostic-format-zero-length, clang-diagnostic-frame-address, clang-diagnostic-fuse-ld-path, clang-diagnostic-ignored-qualifiers, clang-diagnostic-ignored-reference-qualifiers, clang-diagnostic-implicit, clang-diagnostic-implicit-atomic-properties, clang-diagnostic-implicit-conversion-floating-point-to-bool, clang-diagnostic-implicit-exception-spec-mismatch, clang-diagnostic-implicit-fallthrough, clang-diagnostic-implicit-fallthrough-per-function, clang-diagnostic-implicit-fixed-point-conversion, clang-diagnostic-implicit-retain-self, clang-diagnostic-implicitly-unsigned-literal, clang-diagnostic-implicit-float-conversion, clang-diagnostic-implicit-const-int-float-conversion, clang-diagnostic-implicit-function-declaration, clang-diagnostic-implicit-int, clang-diagnostic-implicit-int-conversion, clang-diagnostic-implicit-int-float-conversion, clang-diagnostic-infinite-recursion, clang-diagnostic-initializer-overrides, clang-diagnostic-int-in-bool-context, clang-diagnostic-logical-not-parentheses, clang-diagnostic-logical-op-parentheses, clang-diagnostic-misleading-indentation, clang-diagnostic-mismatched-tags, clang-diagnostic-missing-braces, clang-diagnostic-missing-field-initializers, clang-diagnostic-missing-method-return-type, clang-diagnostic-most, clang-diagnostic-move, clang-diagnostic-multichar, clang-diagnostic-non-virtual-dtor, clang-diagnostic-nonnull, clang-diagnostic-null-pointer-arithmetic, clang-diagnostic-null-pointer-subtraction, clang-diagnostic-objc-designated-initializers, clang-diagnostic-objc-flexible-array, clang-diagnostic-objc-missing-super-calls, clang-diagnostic-overloaded-shift-op-parentheses, clang-diagnostic-overloaded-virtual, clang-diagnostic-parentheses, clang-diagnostic-parentheses-equality, clang-diagnostic-pessimizing-move, clang-diagnostic-potentially-evaluated-expression, clang-diagnostic-private-extern, clang-diagnostic-range-loop-construct, clang-diagnostic-redundant-move, clang-diagnostic-reorder, clang-diagnostic-reorder-ctor, clang-diagnostic-reorder-init-list, clang-diagnostic-return-std-move, clang-diagnostic-return-type, clang-diagnostic-return-type-c-linkage, clang-diagnostic-self-assign, clang-diagnostic-self-assign-field, clang-diagnostic-self-assign-overloaded, clang-diagnostic-self-move, clang-diagnostic-semicolon-before-method-body, clang-diagnostic-shift-op-parentheses, clang-diagnostic-sign-compare, clang-diagnostic-sizeof-array-argument, clang-diagnostic-sizeof-array-decay, clang-diagnostic-sometimes-uninitialized, clang-diagnostic-static-in-inline, clang-diagnostic-static-self-init, clang-diagnostic-string-concatenation, clang-diagnostic-string-plus-int, clang-diagnostic-switch, clang-diagnostic-switch-default, clang-diagnostic-switch-enum, clang-diagnostic-switch-bool, clang-diagnostic-tautological-bitwise-compare, clang-diagnostic-tautological-compare, clang-diagnostic-tautological-constant-compare, clang-diagnostic-tautological-constant-out-of-range-compare, clang-diagnostic-tautological-objc-bool-compare, clang-diagnostic-tautological-overlap-compare, clang-diagnostic-tautological-pointer-compare, clang-diagnostic-tautological-undefined-compare, clang-diagnostic-trigraphs, clang-diagnostic-unevaluated-expression, clang-diagnostic-uninitialized, clang-diagnostic-uninitialized-const-reference, clang-diagnostic-unknown-pragmas, clang-diagnostic-unneeded-internal-declaration, clang-diagnostic-unused-argument, clang-diagnostic-unused-but-set-parameter, clang-diagnostic-unused-but-set-variable, clang-diagnostic-unused-comparison, clang-diagnostic-unused-const-variable, clang-diagnostic-unused-function, clang-diagnostic-unused-label, clang-diagnostic-unused-lambda-capture, clang-diagnostic-unused-local-typedef, clang-diagnostic-unused-local-typedefs, clang-diagnostic-unused-parameter, clang-diagnostic-unused-private-field, clang-diagnostic-unused-property-ivar, clang-diagnostic-unused-result, clang-diagnostic-unused-value, clang-diagnostic-unused-variable, clang-diagnostic-user-defined-warnings, clang-diagnostic-volatile-register-var, concurrency-thread-canceltype-asynchronous, cppcoreguidelines-avoid-capturing-lambda-coroutines, cppcoreguidelines-avoid-reference-coroutine-parameters, cppcoreguidelines-virtual-class-destructor, google-build-namespaces, misc-confusable-identifiers, misc-definitions-in-headers, misc-header-include-cycle, misc-misleading-bidirectional, misc-misleading-identifier, misc-misplaced-const, misc-redundant-expression, misc-unconventional-assign-operator, misc-uniqueptr-reset-release, performance-inefficient-algorithm, performance-move-const-arg, performance-move-constructor-init, performance-no-automatic-move, performance-noexcept-destructor, performance-noexcept-move-constructor, performance-noexcept-swap, performance-trivially-destructible, readability-container-contains, readability-container-data-pointer, readability-reference-to-constructed-temporary, readability-suspicious-call-argument
[INFO 2024-02-05 15:27] - Starting static analysis ...
[INFO 2024-02-05 15:27] - [1/3] cppcheck analyzed ex1.c successfully.
[INFO 2024-02-05 15:27] - [2/3] clangsa analyzed ex1.c successfully.
[INFO 2024-02-05 15:27] - [3/3] clang-tidy analyzed ex1.c successfully.
[INFO 2024-02-05 15:27] - ----==== Summary ====----
[INFO 2024-02-05 15:27] - Successfully analyzed
[INFO 2024-02-05 15:27] -   clangsa: 1
[INFO 2024-02-05 15:27] -   cppcheck: 1
[INFO 2024-02-05 15:27] -   clang-tidy: 1
[INFO 2024-02-05 15:27] - Total analyzed compilation commands: 1
[INFO 2024-02-05 15:27] - ----=================----
[INFO 2024-02-05 15:27] - Analysis finished.
[INFO 2024-02-05 15:27] - To view results in the terminal use the "CodeChecker parse" command.
[INFO 2024-02-05 15:27] - To store results use the "CodeChecker store" command.
[INFO 2024-02-05 15:27] - See --help and the user guide for further options about parsing and storing the reports.
[INFO 2024-02-05 15:27] - ----=================----
[INFO 2024-02-05 15:27] - Analysis length: 0.45849108695983887 sec.
[WARNING 2024-02-05 15:27] - Analyzer 'gcc' is enabled but CodeChecker is failed to execute analysis with it: 'Incompatible version: GCC binary found is too old at v11.4.0; minimum version is 13.0.0. Maybe try setting an absolute path to a different analyzer binary via the env variable CC_ANALYZER_BIN?'. Please check your 'PATH' environment variable and the 'config/package_layout.json' file!
[HIGH] /tmp/ex1.c:4:11: The left operand of '<=' is a garbage value [core.UndefinedBinaryOperatorResult]
    if (x <= 42){
          ^

Found 1 defect(s) in ex1.c

[HIGH] /tmp/ex1.c:4:9: Uninitialized variable: x [cppcheck-uninitvar]
    if (x <= 42){
        ^

Found 1 defect(s) in ex1.c

[MEDIUM] /tmp/ex1.c:4:9: variable 'x' is uninitialized when used here [clang-diagnostic-uninitialized]
    if (x <= 42){
        ^

Found 1 defect(s) in ex1.c


----==== Severity Statistics ====----
----------------------------
Severity | Number of reports
----------------------------
HIGH     |                 2
MEDIUM   |                 1
----------------------------
----=================----

----==== Checker Statistics ====----
-----------------------------------------------------------------
Checker name                       | Severity | Number of reports
-----------------------------------------------------------------
core.UndefinedBinaryOperatorResult | HIGH     |                 1
cppcheck-uninitvar                 | HIGH     |                 1
clang-diagnostic-uninitialized     | MEDIUM   |                 1
-----------------------------------------------------------------
----=================----

----==== File Statistics ====----
-----------------------------
File name | Number of reports
-----------------------------
ex1.c     |                 3
-----------------------------
----=================----

----======== Summary ========----
---------------------------------------------
Number of processed analyzer result files | 3
Number of analyzer reports                | 3
---------------------------------------------
----=================----

I am still suspicious of the exact truth on whether the example given is actually undefined behavior. I mentioned a couple tools for checking on undefined behavior. Here I’ll try the undefined behavior sanitizer which comes with your compiler and the Cerberus interpreter. The UBSanitizer injects runtime checks for undefined behavior happening. I am unsure how complete these checks are or whther they can be optimized away. They probably try to make sure they are as reliable as is possible.

The UB sanitizer does not take issue with this example, nor does cerberus. Curious.

! clang -fsanitize=undefined /tmp/ex1.c -o /tmp/ex1 && /tmp/ex1
%%bash
# install cerberus. This needs to get ocaml first. Might take a bit
apt install opam
opam init -y
eval $(opam env)
git clone https://github.com/rems-project/cerberus.git
cd cerberus
apt-get install libgmp-dev
opam install -y --deps-only ./cerberus-lib.opam ./cerberus.opam
make
! cerberus --exec /tmp/ex1.c

Just to check that it isn’t compiling away.

! objdump /tmp/ex1 -d | grep -A 20 main.:
000000000002ea38 <main>:
   2ea38: 55                    push   %rbp
   2ea39: 48 89 e5              mov    %rsp,%rbp
   2ea3c: 48 83 ec 10           sub    $0x10,%rsp
   2ea40: c7 45 fc 00 00 00 00  movl   $0x0,-0x4(%rbp)
   2ea47: 83 7d f8 2a           cmpl   $0x2a,-0x8(%rbp)
   2ea4b: 0f 8f 4c 00 00 00     jg     2ea9d <main+0x65>
   2ea51: 81 7d f8 39 30 00 00  cmpl   $0x3039,-0x8(%rbp)
   2ea58: 0f 84 05 00 00 00     je     2ea63 <main+0x2b>
   2ea5e: e9 35 00 00 00        jmp    2ea98 <main+0x60>
   2ea63: 48 8d 3d c1 92 00 00  lea    0x92c1(%rip),%rdi        # 37d2b <_ZL10kVptrCheck+0xf25>
   2ea6a: 48 8d 35 c5 92 00 00  lea    0x92c5(%rip),%rsi        # 37d36 <_ZL10kVptrCheck+0xf30>
   2ea71: ba 05 00 00 00        mov    $0x5,%edx
   2ea76: 48 8d 0d c4 92 00 00  lea    0x92c4(%rip),%rcx        # 37d41 <_ZL10kVptrCheck+0xf3b>
   2ea7d: e8 4e 66 fd ff        call   50d0 <__assert_fail@plt>
   2ea82: 31 c0                 xor    %eax,%eax
   2ea84: a8 01                 test   $0x1,%al
   2ea86: 0f 85 0c 00 00 00     jne    2ea98 <main+0x60>
   2ea8c: 48 8d 3d d5 80 01 00  lea    0x180d5(%rip),%rdi        # 46b68 <_ZL17kSuppressionTypes+0x128>
   2ea93: e8 08 d1 ff ff        call   2bba0 <__ubsan_handle_builtin_unreachable>
   2ea98: e9 00 00 00 00        jmp    2ea9d <main+0x65>

Asserts that aren’t triggering may be an odd case, so let’s do something more straightforward: printing uninitialized values.

%%file /tmp/ex2.c
#include <stdio.h>
int main(){
    int x;
    printf("Value of x: %d\n", x);
}
Overwriting /tmp/ex2.c

The UB sanitizer still does not take issue. Cerberus thinks this is unspecified behavior (which prints differently from undefined behavior)

! clang -fsanitize=undefined /tmp/ex2.c -o /tmp/ex2 && /tmp/ex2
Value of x: 0
! cerberus --exec /tmp/ex2.c
Value of x: UNSPEC

This slightly different program is however, quite bad. An uninitialized pointer is dereferenced and both methods complain accordingly.

%%file /tmp/ex3.c
#include <stdio.h>
int main(){
    int* x;
    printf("Value of x: %d\n", *x);
}
Overwriting /tmp/ex3.c
! clang -fsanitize=undefined /tmp/ex3.c -o /tmp/ex3 && /tmp/ex3
[1m/tmp/ex3.c:4:32:[1m[31m runtime error: [1m[0m[1mload of null pointer of type 'int'[1m[0m
SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior /tmp/ex3.c:4:32 
UndefinedBehaviorSanitizer:DEADLYSIGNAL
[1m[31m==33249==ERROR: UndefinedBehaviorSanitizer: SEGV on unknown address 0x000000000000 (pc 0x563890a65a7f bp 0x7ffde3c0d8b0 sp 0x7ffde3c0d890 T33249)
[1m[0m==33249==The signal is caused by a READ memory access.
==33249==Hint: address points to the zero page.
    #0 0x563890a65a7f in main (/tmp/ex3+0x2ea7f) (BuildId: c9aba5b3a42c58e96d9e5e92c81c7a22b892dcf2)
    #1 0x7f73eb0abd8f in __libc_start_call_main csu/../sysdeps/nptl/libc_start_call_main.h:58:16
    #2 0x7f73eb0abe3f in __libc_start_main csu/../csu/libc-start.c:392:3
    #3 0x563890a3c3e4 in _start (/tmp/ex3+0x53e4) (BuildId: c9aba5b3a42c58e96d9e5e92c81c7a22b892dcf2)

UndefinedBehaviorSanitizer can not provide additional info.
SUMMARY: UndefinedBehaviorSanitizer: SEGV (/tmp/ex3+0x2ea7f) (BuildId: c9aba5b3a42c58e96d9e5e92c81c7a22b892dcf2) in main
==33249==ABORTING
! cerberus --exec /tmp/ex3.c
/tmp/ex3.c:4:32: error: undefined behaviour: the operand of the unary '*' operator has an invalid value
    printf("Value of x: %d\n", *x);
                               ^~ 
§6.5.3.2#4, sentence 4: 
4   The unary * operator denotes indirection. If the operand points to a function, the result is
    a function designator; if it points to an object, the result is an lvalue designating the
    object. If the operand has type ``pointer to type'', the result has type ``type''. If an
    invalid value has been assigned to the pointer, the behavior of the unary * operator is
    undefined.102)
    Forward references: storage-class specifiers (6.7.1), structure and union specifiers
    (6.7.2.1).

Bits and Bobbles

I am not an expert in undefined behavior. Take anything you read here with a grain of salt. (Honestly, take anything you read anywhere on this topic with a grain of salt. People say of a lot of confident wrong stuff.) This represents my best guess at the topic, using the best tools i know of.

First off, you don’t have to be that scared. A mistake about undefined behavior is an unlikely cause of death. We are more likely to get cancer from some kind of slovenly corporate oversight about deodorant ingredients or basking in the wrong sunbeam.

We all die some day anyway. It is hopefully a whiles off and hopefully won’t be that horrifying or painful.

On the other hand, I would nearly guarantee C and C++ are in the bioweapon, medical radiation, and nuclear stack. So it only takes one real nasty bug or even misconception to kill us all.

Turn on s lot of warnings (-Wall -Wextra -Wpedantic is a start) when you are working in an unsafe language and deal with them. In principle, it is quite possible for the compiler to detect situations that humans are likely to be confused. It isn’t perfect, but even precise language lawyering isn’t perfect if it doesn’t comply with this particular user’s intuitions and intent.

A true Achilles heal of all modelling and verification tools is the connection of the model back to physical reality or the mushy concept of human intent. A model or verification or optimization is only as good as it’s weakest link.

I do not have (and suspect there cannot be) a final satisfying answer to this problem.

I also do not consider it to be a a complete demonstration of the futility or uselessness of checking of verification attempts.

https://en.wikipedia.org/wiki/Undefined_behavior

Here’s my basic understanding of the distinction between undefine, unspecified, and implementation defined behavior.

An imperative program is kind of like a state -> state function. If you were to write an interpreter of your target imperative language in a purely functional style, this comes very naturally. The interpreter has a type program -> state -> state and if you partially apply it, you get it’s state transformer semantics. x := x + 1; gets parsed as something like Assign("x", Plus(Var("x"), Lit(1)). It takes in an initial state, which is the value of variables and memory, and outputs a final state of new values of variables and memory. blahblahblahblah

undefined behavior: If the program is allowed to fail, then the final state is not defined. Then we can model programs as state -> option state.

unspecified behavior: A different thing programs can do is do something, but it can be kind of random. This is unspecified behavior. Programs can be different choices of order of operations. We can think of programs as state -> list state with a list of possible final states. A slightly different notion is that programs can be implementation-defined.

implementation defined They still do something that isn’t quite clear, but the implementation picks a consistent thing to do. We can model this purely functionally. impl_record -> state -> state

We can combine these things into impl_record -> state -> option (list state)

It is not always obvious in unsafe languages where the boundary between totally well-defined, undefined, unspecified, and implementation defined.

I am also suspicious that many of the HN comments are not right. People will talk at great length about undefined behavior. It was claimed that this example is an instance of “undefined behavior”. I believe that this may be (or perhaps should be) an instance of “unspecified behavior’, a distinct and slightly less insidious cousin. If so, CBMC is treating it’s emulation of unspecified behavior in fairly reasonably manner I believe.

See for example 2.6.1 https://robbertkrebbers.nl/research/thesis.pdf Defect Report #260 https://www.open-std.org/jtc1/sc22/wg14/www/docs/dr_260.htm Defect Report is numbered #451 https://www.open-std.org/jtc1/sc22/wg14/www/docs/dr_451.htm

I may be just confusing the issue because I hate being shown to be wrong and ignorant on the internet by strangers. Could be. Could be.

John Regehr has many great blog posts around this an other topics https://blog.regehr.org/archives/1234

This is not the whole story, maybe not even a majority of the story. What is the difference between a “do nothing” program and one that prints "Hello World? In our current conception of state, it is not clear that printing is evident in final state. There are a couple of ways out of this. We could attempt to say that no no no, state is the entire universe including our eyeballs and the screen. This is slightly actionable. but also a bit silly. We could also abandon our entire conception of imperative programs as mathematical functions. This is a weird way to think about it for most of the population, and smacks of sophistry and great faith and love of traditional mathematics. Traditional mathematics is the prime example of being complex and yet (varying degrees of) precise. The other thing we can do is say that there is

The C and C++ standards. I have not mastered the art of reading these (yea, yea go ahead and rip into me, you jackals.). C11 https://port70.net/~nsz/c/c11/n1570.html#J

Also take a look at the Compcert Formal verification of a realistic compiler A formally verified compiler back-end,

C semantics

https://www.cis.upenn.edu/~stevez/papers/XZHH+20.pdf interaction trees. Algerbaic effect style modeling

memory model semantics.

%%bash
# various installations
#pip install codechecker
#apt install cppcheck
# face book infer
#VERSION=1.1.0; \
#curl -sSL "https://github.com/facebook/infer/releases/download/v$VERSION/infer-linux64-v$VERSION.tar.xz" \
#| sudo tar -C /opt -xJ && \
#sudo ln -s "/opt/infer-linux64-v$VERSION/bin/infer" /usr/local/bin/infer
# cerberus


https://news.ycombinator.com/item?id=39191507

-Wall -Wpedantic -Wextra -Werror

For undefined behavior detection, I have heard of these:

https://wordsandbuttons.online/so_you_think_you_know_c.html

https://clang-analyzer.llvm.org/ https://codechecker.readthedocs.io/en/latest/ https://clang-analyzer.llvm.org/scan-build.html

https://stackoverflow.com/questions/7237963/is-there-a-c-implementation-that-detects-all-undefined-behavior

https://twitter.com/kees_cook/status/1588007082288353281?s=20&t=udFq9u7zLY-5-Ae6VrdqeQ

-Wall
-D_FORTIFY_SOURCE=2
-fsanitize=bounds fsanitize-undefined-trap-on-error
-fstrict-flex-arrays (GCC 13+, Clang 16+)

semgrep codeql

frama-c

astree

Clang-tidy

https://clang.llvm.org/extra/clang-tidy/

! clang-tidy /tmp/ex1.c
%%file /tmp/ub.c
#include <assert.h>
#include <stdio.h>
int main(){
    int x;
    x++;
    printf("Value of x: %d\n", x);
    //int y = *(int *)NULL;
    //assert(x != 12345);
    //assert(1 == 0);
}
Overwriting /tmp/ub.c
! gcc -O3 -Wall -Wpedantic -Wextra  /tmp/ub.c -o /tmp/ub && /tmp/ub
[01m[K/tmp/ub.c:[m[K In function ‘[01m[Kmain[m[K’:
[01m[K/tmp/ub.c:5:6:[m[K [01;35m[Kwarning: [m[K‘[01m[Kx[m[K’ is used uninitialized [[01;35m[K]8;;https://gcc.gnu.org/onlinedocs/gcc/Warning-Options.html#index-Wuninitialized-Wuninitialized]8;;[m[K]
    5 |     [01;35m[Kx++[m[K;
      |     [01;35m[K~^~[m[K
Value of x: 1
! objdump -d /tmp/ub | grep -A 20 main.:
0000000000001060 <main>:
    1060: f3 0f 1e fa           endbr64 
    1064: 48 83 ec 08           sub    $0x8,%rsp
    1068: ba 01 00 00 00        mov    $0x1,%edx
    106d: bf 01 00 00 00        mov    $0x1,%edi
    1072: 31 c0                 xor    %eax,%eax
    1074: 48 8d 35 89 0f 00 00  lea    0xf89(%rip),%rsi        # 2004 <_IO_stdin_used+0x4>
    107b: e8 d0 ff ff ff        call   1050 <__printf_chk@plt>
    1080: 31 c0                 xor    %eax,%eax
    1082: 48 83 c4 08           add    $0x8,%rsp
    1086: c3                    ret    
    1087: 66 0f 1f 84 00 00 00  nopw   0x0(%rax,%rax,1)
    108e: 00 00 

0000000000001090 <_start>:
    1090: f3 0f 1e fa           endbr64 
    1094: 31 ed                 xor    %ebp,%ebp
    1096: 49 89 d1              mov    %rdx,%r9
    1099: 5e                    pop    %rsi
    109a: 48 89 e2              mov    %rsp,%rdx
    109d: 48 83 e4 f0           and    $0xfffffffffffffff0,%rsp
%%bash
cerberus --exec /tmp/ub.c
#cerberus --batch 
/tmp/ub.c:7:13: error: undefined behaviour: the operand of the unary '*' operator has an invalid value
    int y = *(int *)NULL;
            ^~~~~~~~~~~~~~~~~~~~~~ 
§6.5.3.2#4, sentence 4: 
4   The unary * operator denotes indirection. If the operand points to a function, the result is
    a function designator; if it points to an object, the result is an lvalue designating the
    object. If the operand has type ``pointer to type'', the result has type ``type''. If an
    invalid value has been assigned to the pointer, the behavior of the unary * operator is
    undefined.102)
    Forward references: storage-class specifiers (6.7.1), structure and union specifiers
    (6.7.2.1).

Codechecker

https://github.com/Ericsson/codechecker That compile_commands.json might be kind of interesting

%%bash
# instrument a build first
CodeChecker log -o /tmp/compile_commands.json --build "clang -o /tmp/ub /tmp/ub.c"
# Then run the analyzer
CodeChecker analyze /tmp/compile_commands.json -o /tmp/reports
CodeChecker parse /tmp/reports -e html -o /tmp/reports.html

# all in one
#CodeChecker check --build "make" --output ./reports --clean \
#    --enable sensitive
[INFO 2024-02-01 11:11] - Starting build...
[INFO 2024-02-01 11:11] - Using CodeChecker ld-logger.
[INFO 2024-02-01 11:11] - Build finished successfully.
[INFO 2024-02-01 11:11] - Enabled checkers:
clang-tidy: bugprone-assert-side-effect, bugprone-bool-pointer-implicit-conversion, bugprone-compare-pointer-to-member-virtual-function, bugprone-copy-constructor-init, bugprone-dangling-handle, bugprone-dynamic-static-initializers, bugprone-fold-init-type, bugprone-forward-declaration-namespace, bugprone-forwarding-reference-overload, bugprone-inaccurate-erase, bugprone-inc-dec-in-conditions, bugprone-incorrect-enable-if, bugprone-incorrect-roundings, bugprone-infinite-loop, bugprone-integer-division, bugprone-lambda-function-name, bugprone-macro-repeated-side-effects, bugprone-misplaced-operator-in-strlen-in-alloc, bugprone-misplaced-pointer-arithmetic-in-alloc, bugprone-misplaced-widening-cast, bugprone-move-forwarding-reference, bugprone-multiple-new-in-one-expression, bugprone-not-null-terminated-result, bugprone-optional-value-conversion, bugprone-shared-ptr-array-mismatch, bugprone-signal-handler, bugprone-signed-char-misuse, bugprone-sizeof-container, bugprone-sizeof-expression, bugprone-standalone-empty, bugprone-string-constructor, bugprone-stringview-nullptr, bugprone-string-literal-with-embedded-nul, bugprone-suspicious-enum-usage, bugprone-suspicious-memory-comparison, bugprone-suspicious-memset-usage, bugprone-suspicious-missing-comma, bugprone-suspicious-realloc-usage, bugprone-suspicious-semicolon, bugprone-swapped-arguments, bugprone-switch-missing-default-case, bugprone-terminating-continue, bugprone-throw-keyword-missing, bugprone-too-small-loop-variable, bugprone-undefined-memory-manipulation, bugprone-undelegated-constructor, bugprone-unhandled-exception-at-new, bugprone-unique-ptr-array-mismatch, bugprone-unused-raii, bugprone-unused-return-value, bugprone-use-after-move, bugprone-virtual-near-miss, cert-dcl54-cpp, cert-dcl58-cpp, cert-dcl59-cpp, cert-err09-cpp, cert-fio38-c, cert-mem57-cpp, cert-oop11-cpp, cert-oop58-cpp, cert-pos44-c, cert-pos47-c, clang-diagnostic-array-bounds-pointer-arithmetic, clang-diagnostic-bitwise-conditional-parentheses, clang-diagnostic-bitwise-instead-of-logical, clang-diagnostic-bitwise-op-parentheses, clang-diagnostic-bool-operation, clang-diagnostic-cast-of-sel-type, clang-diagnostic-char-subscripts, clang-diagnostic-comment, clang-diagnostic-comments, clang-diagnostic-dangling-else, clang-diagnostic-delete-abstract-non-virtual-dtor, clang-diagnostic-delete-non-abstract-non-virtual-dtor, clang-diagnostic-delete-non-virtual-dtor, clang-diagnostic-deprecated-copy, clang-diagnostic-deprecated-copy-with-dtor, clang-diagnostic-deprecated-copy-with-user-provided-dtor, clang-diagnostic-deprecated-copy-dtor, clang-diagnostic-deprecated-copy-with-user-provided-copy, clang-diagnostic-division-by-zero, clang-diagnostic-double-promotion, clang-diagnostic-embedded-directive, clang-diagnostic-empty-init-stmt, clang-diagnostic-extern-c-compat, clang-diagnostic-float-conversion, clang-diagnostic-for-loop-analysis, clang-diagnostic-format, clang-diagnostic-format-overflow, clang-diagnostic-format-overflow-non-kprintf, clang-diagnostic-format-truncation, clang-diagnostic-format-truncation-non-kprintf, clang-diagnostic-format-non-iso, clang-diagnostic-format-pedantic, clang-diagnostic-format-type-confusion, clang-diagnostic-format=2, clang-diagnostic-format-extra-args, clang-diagnostic-format-insufficient-args, clang-diagnostic-format-invalid-specifier, clang-diagnostic-format-nonliteral, clang-diagnostic-format-security, clang-diagnostic-format-y2k, clang-diagnostic-format-zero-length, clang-diagnostic-frame-address, clang-diagnostic-fuse-ld-path, clang-diagnostic-ignored-qualifiers, clang-diagnostic-ignored-reference-qualifiers, clang-diagnostic-implicit, clang-diagnostic-implicit-atomic-properties, clang-diagnostic-implicit-conversion-floating-point-to-bool, clang-diagnostic-implicit-exception-spec-mismatch, clang-diagnostic-implicit-fallthrough, clang-diagnostic-implicit-fallthrough-per-function, clang-diagnostic-implicit-fixed-point-conversion, clang-diagnostic-implicit-retain-self, clang-diagnostic-implicitly-unsigned-literal, clang-diagnostic-implicit-float-conversion, clang-diagnostic-implicit-const-int-float-conversion, clang-diagnostic-implicit-function-declaration, clang-diagnostic-implicit-int, clang-diagnostic-implicit-int-conversion, clang-diagnostic-implicit-int-float-conversion, clang-diagnostic-infinite-recursion, clang-diagnostic-initializer-overrides, clang-diagnostic-int-in-bool-context, clang-diagnostic-logical-not-parentheses, clang-diagnostic-logical-op-parentheses, clang-diagnostic-misleading-indentation, clang-diagnostic-mismatched-tags, clang-diagnostic-missing-braces, clang-diagnostic-missing-field-initializers, clang-diagnostic-missing-method-return-type, clang-diagnostic-most, clang-diagnostic-move, clang-diagnostic-multichar, clang-diagnostic-non-virtual-dtor, clang-diagnostic-nonnull, clang-diagnostic-null-pointer-arithmetic, clang-diagnostic-null-pointer-subtraction, clang-diagnostic-objc-designated-initializers, clang-diagnostic-objc-flexible-array, clang-diagnostic-objc-missing-super-calls, clang-diagnostic-overloaded-shift-op-parentheses, clang-diagnostic-overloaded-virtual, clang-diagnostic-parentheses, clang-diagnostic-parentheses-equality, clang-diagnostic-pessimizing-move, clang-diagnostic-potentially-evaluated-expression, clang-diagnostic-private-extern, clang-diagnostic-range-loop-construct, clang-diagnostic-redundant-move, clang-diagnostic-reorder, clang-diagnostic-reorder-ctor, clang-diagnostic-reorder-init-list, clang-diagnostic-return-std-move, clang-diagnostic-return-type, clang-diagnostic-return-type-c-linkage, clang-diagnostic-self-assign, clang-diagnostic-self-assign-field, clang-diagnostic-self-assign-overloaded, clang-diagnostic-self-move, clang-diagnostic-semicolon-before-method-body, clang-diagnostic-shift-op-parentheses, clang-diagnostic-sign-compare, clang-diagnostic-sizeof-array-argument, clang-diagnostic-sizeof-array-decay, clang-diagnostic-sometimes-uninitialized, clang-diagnostic-static-in-inline, clang-diagnostic-static-self-init, clang-diagnostic-string-concatenation, clang-diagnostic-string-plus-int, clang-diagnostic-switch, clang-diagnostic-switch-default, clang-diagnostic-switch-enum, clang-diagnostic-switch-bool, clang-diagnostic-tautological-bitwise-compare, clang-diagnostic-tautological-compare, clang-diagnostic-tautological-constant-compare, clang-diagnostic-tautological-constant-out-of-range-compare, clang-diagnostic-tautological-objc-bool-compare, clang-diagnostic-tautological-overlap-compare, clang-diagnostic-tautological-pointer-compare, clang-diagnostic-tautological-undefined-compare, clang-diagnostic-trigraphs, clang-diagnostic-unevaluated-expression, clang-diagnostic-uninitialized, clang-diagnostic-uninitialized-const-reference, clang-diagnostic-unknown-pragmas, clang-diagnostic-unneeded-internal-declaration, clang-diagnostic-unused-argument, clang-diagnostic-unused-but-set-parameter, clang-diagnostic-unused-but-set-variable, clang-diagnostic-unused-comparison, clang-diagnostic-unused-const-variable, clang-diagnostic-unused-function, clang-diagnostic-unused-label, clang-diagnostic-unused-lambda-capture, clang-diagnostic-unused-local-typedef, clang-diagnostic-unused-local-typedefs, clang-diagnostic-unused-parameter, clang-diagnostic-unused-private-field, clang-diagnostic-unused-property-ivar, clang-diagnostic-unused-result, clang-diagnostic-unused-value, clang-diagnostic-unused-variable, clang-diagnostic-user-defined-warnings, clang-diagnostic-volatile-register-var, concurrency-thread-canceltype-asynchronous, cppcoreguidelines-avoid-capturing-lambda-coroutines, cppcoreguidelines-avoid-reference-coroutine-parameters, cppcoreguidelines-virtual-class-destructor, google-build-namespaces, misc-confusable-identifiers, misc-definitions-in-headers, misc-header-include-cycle, misc-misleading-bidirectional, misc-misleading-identifier, misc-misplaced-const, misc-redundant-expression, misc-unconventional-assign-operator, misc-uniqueptr-reset-release, performance-inefficient-algorithm, performance-move-const-arg, performance-move-constructor-init, performance-no-automatic-move, performance-noexcept-destructor, performance-noexcept-move-constructor, performance-noexcept-swap, performance-trivially-destructible, readability-container-contains, readability-container-data-pointer, readability-reference-to-constructed-temporary, readability-suspicious-call-argument
clangsa: alpha.security.cert.pos.34c, core.BitwiseShift, core.CallAndMessage, core.DivideZero, core.NonNullParamChecker, core.NullDereference, core.StackAddressEscape, core.UndefinedBinaryOperatorResult, core.VLASize, core.uninitialized.ArraySubscript, core.uninitialized.Assign, core.uninitialized.Branch, core.uninitialized.CapturedBlockVariable, core.uninitialized.NewArraySize, core.uninitialized.UndefReturn, cplusplus.InnerPointer, cplusplus.Move, cplusplus.NewDelete, cplusplus.NewDeleteLeaks, cplusplus.PlacementNew, cplusplus.PureVirtualCall, cplusplus.StringChecker, deadcode.DeadStores, nullability.NullPassedToNonnull, nullability.NullReturnedFromNonnull, optin.cplusplus.UninitializedObject, optin.cplusplus.VirtualCall, optin.portability.UnixAPI, security.cert.env.InvalidPtr, security.FloatLoopCounter, security.insecureAPI.UncheckedReturn, security.insecureAPI.getpw, security.insecureAPI.gets, security.insecureAPI.mkstemp, security.insecureAPI.mktemp, security.insecureAPI.rand, security.insecureAPI.vfork, unix.API, unix.Malloc, unix.MallocSizeof, unix.MismatchedDeallocator, unix.StdCLibraryFunctions, unix.Vfork, unix.cstring.BadSizeArg, unix.cstring.NullArg, valist.CopyToSelf, valist.Uninitialized, valist.Unterminated
cppcheck: cppcheck-IOWithoutPositioning, cppcheck-StlMissingComparison, cppcheck-accessForwarded, cppcheck-accessMoved, cppcheck-argumentSize, cppcheck-arrayIndexOutOfBounds, cppcheck-arrayIndexOutOfBoundsCond, cppcheck-assertWithSideEffect, cppcheck-assignBoolToPointer, cppcheck-assignmentInAssert, cppcheck-autoVariables, cppcheck-autovarInvalidDeallocation, cppcheck-badBitmaskCheck, cppcheck-boostForeachError, cppcheck-bufferAccessOutOfBounds, cppcheck-charBitOp, cppcheck-charLiteralWithCharPtrCompare, cppcheck-checkCastIntToCharAndBack, cppcheck-clarifyStatement, cppcheck-compareBoolExpressionWithInt, cppcheck-comparePointers, cppcheck-comparisonFunctionIsAlwaysTrueOrFalse, cppcheck-comparisonOfBoolWithInvalidComparator, cppcheck-constStatement, cppcheck-containerOutOfBounds, cppcheck-copyCtorAndEqOperator, cppcheck-copyCtorPointerCopying, cppcheck-coutCerrMisusage, cppcheck-danglingLifetime, cppcheck-danglingReference, cppcheck-danglingTemporaryLifetime, cppcheck-deallocDealloc, cppcheck-deallocret, cppcheck-deallocuse, cppcheck-derefInvalidIterator, cppcheck-divideSizeof, cppcheck-doubleFree, cppcheck-duplInheritedMember, cppcheck-eraseDereference, cppcheck-exceptDeallocThrow, cppcheck-exceptThrowInDestructor, cppcheck-floatConversionOverflow, cppcheck-funcArgOrderDifferent, cppcheck-identicalConditionAfterEarlyExit, cppcheck-identicalInnerCondition, cppcheck-ignoredReturnValue, cppcheck-incompatibleFileOpen, cppcheck-incompleteArrayFill, cppcheck-incorrectCharBooleanError, cppcheck-incorrectLogicOperator, cppcheck-incorrectStringBooleanError, cppcheck-incorrectStringCompare, cppcheck-integerOverflow, cppcheck-invalidContainerLoop, cppcheck-invalidContainer, cppcheck-invalidFree, cppcheck-invalidFunctionArg, cppcheck-invalidFunctionArgBool, cppcheck-invalidFunctionArgStr, cppcheck-invalidIterator1, cppcheck-invalidLengthModifierError, cppcheck-invalidLifetime, cppcheck-invalidPrintfArgType_float, cppcheck-invalidPrintfArgType_n, cppcheck-invalidPrintfArgType_p, cppcheck-invalidPrintfArgType_s, cppcheck-invalidPrintfArgType_sint, cppcheck-invalidPrintfArgType_uint, cppcheck-invalidScanfArgType_float, cppcheck-invalidScanfArgType_int, cppcheck-invalidScanfArgType_s, cppcheck-invalidScanfFormatWidth, cppcheck-invalidScanfFormatWidth_smaller, cppcheck-invalidTestForOverflow, cppcheck-invalidscanf, cppcheck-iterators1, cppcheck-iterators2, cppcheck-iterators3, cppcheck-iteratorsCmp1, cppcheck-iteratorsCmp2, cppcheck-leakNoVarFunctionCall, cppcheck-leakReturnValNotUsed, cppcheck-leakUnsafeArgAlloc, cppcheck-literalWithCharPtrCompare, cppcheck-mallocOnClassError, cppcheck-mallocOnClassWarning, cppcheck-memleak, cppcheck-memleakOnRealloc, cppcheck-memsetClass, cppcheck-memsetClassFloat, cppcheck-memsetClassReference, cppcheck-memsetValueOutOfRange, cppcheck-memsetZeroBytes, cppcheck-mismatchAllocDealloc, cppcheck-mismatchSize, cppcheck-mismatchingContainerExpression, cppcheck-mismatchingContainers, cppcheck-missingMemberCopy, cppcheck-missingReturn, cppcheck-moduloAlwaysTrueFalse, cppcheck-multiplySizeof, cppcheck-negativeArraySize, cppcheck-negativeContainerIndex, cppcheck-negativeIndex, cppcheck-negativeMemoryAllocationSize, cppcheck-noCopyConstructor, cppcheck-noDestructor, cppcheck-noOperatorEq, cppcheck-nullPointer, cppcheck-nullPointerArithmetic, cppcheck-nullPointerArithmeticRedundantCheck, cppcheck-nullPointerDefaultArg, cppcheck-nullPointerRedundantCheck, cppcheck-objectIndex, cppcheck-operatorEqMissingReturnStatement, cppcheck-operatorEqToSelf, cppcheck-operatorEqVarError, cppcheck-oppositeInnerCondition, cppcheck-overlappingStrcmp, cppcheck-overlappingWriteFunction, cppcheck-overlappingWriteUnion, cppcheck-pointerAdditionResultNotNull, cppcheck-pointerArithBool, cppcheck-pointerSize, cppcheck-publicAllocationError, cppcheck-pureVirtualCall, cppcheck-raceAfterInterlockedDecrement, cppcheck-readWriteOnlyFile, cppcheck-redundantAssignInSwitch, cppcheck-redundantBitwiseOperationInSwitch, cppcheck-redundantCopyInSwitch, cppcheck-resourceLeak, cppcheck-rethrowNoCurrentException, cppcheck-returnAddressOfAutoVariable, cppcheck-returnAddressOfFunctionParameter, cppcheck-returnDanglingLifetime, cppcheck-returnLocalVariable, cppcheck-returnReference, cppcheck-returnTempReference, cppcheck-seekOnAppendedFile, cppcheck-selfAssignment, cppcheck-selfInitialization, cppcheck-shiftNegativeLHS, cppcheck-shiftNegative, cppcheck-shiftTooManyBits, cppcheck-shiftTooManyBitsSigned, cppcheck-signConversion, cppcheck-signedCharArrayIndex, cppcheck-sizeofCalculation, cppcheck-sizeofDivisionMemfunc, cppcheck-sizeofFunctionCall, cppcheck-sizeofsizeof, cppcheck-sizeofwithnumericparameter, cppcheck-sizeofwithsilentarraypointer, cppcheck-sprintfOverlappingData, cppcheck-staticStringCompare, cppcheck-stlBoundaries, cppcheck-stlIfFind, cppcheck-stlOutOfBounds, cppcheck-stlcstr, cppcheck-stlcstrReturn, cppcheck-stlcstrParam, cppcheck-stlcstrthrow, cppcheck-strPlusChar, cppcheck-stringCompare, cppcheck-stringLiteralWrite, cppcheck-suspiciousCase, cppcheck-suspiciousSemicolon, cppcheck-thisSubtraction, cppcheck-throwInNoexceptFunction, cppcheck-uninitDerivedMemberVar, cppcheck-uninitDerivedMemberVarPrivate, cppcheck-uninitMemberVar, cppcheck-uninitMemberVarPrivate, cppcheck-uninitStructMember, cppcheck-uninitdata, cppcheck-uninitstring, cppcheck-uninitvar, cppcheck-unknownEvaluationOrder, cppcheck-unsafeClassRefMember, cppcheck-unusedLabelSwitch, cppcheck-unusedLabelSwitchConfiguration, cppcheck-useClosedFile, cppcheck-uselessAssignmentPtrArg, cppcheck-uselessCallsCompare, cppcheck-uselessCallsEmpty, cppcheck-uselessCallsRemove, cppcheck-va_end_missing, cppcheck-va_list_usedBeforeStarted, cppcheck-va_start_referencePassed, cppcheck-va_start_subsequentCalls, cppcheck-va_start_wrongParameter, cppcheck-virtualCallInConstructor, cppcheck-virtualDestructor, cppcheck-writeReadOnlyFile, cppcheck-wrongPipeParameterSize, cppcheck-wrongPrintfScanfArgNum, cppcheck-wrongPrintfScanfParameterPositionError, cppcheck-wrongmathcall, cppcheck-zerodiv, cppcheck-zerodivcond
[INFO 2024-02-01 11:11] - Starting static analysis ...
[INFO 2024-02-01 11:11] - [1/3] cppcheck analyzed ub.c successfully.
[INFO 2024-02-01 11:11] - [2/3] clangsa analyzed ub.c successfully.
[INFO 2024-02-01 11:11] - [3/3] clang-tidy analyzed ub.c successfully.
[INFO 2024-02-01 11:11] - ----==== Summary ====----
[INFO 2024-02-01 11:11] - Successfully analyzed
[INFO 2024-02-01 11:11] -   clang-tidy: 1
[INFO 2024-02-01 11:11] -   clangsa: 1
[INFO 2024-02-01 11:11] -   cppcheck: 1
[INFO 2024-02-01 11:11] - Total analyzed compilation commands: 1
[INFO 2024-02-01 11:11] - ----=================----
[INFO 2024-02-01 11:11] - Analysis finished.
[INFO 2024-02-01 11:11] - To view results in the terminal use the "CodeChecker parse" command.
[INFO 2024-02-01 11:11] - To store results use the "CodeChecker store" command.
[INFO 2024-02-01 11:11] - See --help and the user guide for further options about parsing and storing the reports.
[INFO 2024-02-01 11:11] - ----=================----
[INFO 2024-02-01 11:11] - Analysis length: 0.3319387435913086 sec.
[WARNING 2024-02-01 11:11] - Analyzer 'gcc' is enabled but CodeChecker is failed to execute analysis with it: 'Incompatible version: GCC binary found is too old at v11.4.0; minimum version is 13.0.0. Maybe try setting an absolute path to a different analyzer binary via the env variable CC_ANALYZER_BIN?'. Please check your 'PATH' environment variable and the 'config/package_layout.json' file!
Parsing input file '/tmp/reports/ub.c_clangsa_fb9868167746a12b0aa35cb54a22e877.plist'.
[INFO 2024-02-01 11:11] - Html file was generated: /tmp/reports.html/ub.c_clangsa_fb9868167746a12b0aa35cb54a22e877.plist.html
Parsing input file '/tmp/reports/ub.c_clang-tidy_fb9868167746a12b0aa35cb54a22e877.plist'.
[INFO 2024-02-01 11:11] - Html file was generated: /tmp/reports.html/ub.c_clang-tidy_fb9868167746a12b0aa35cb54a22e877.plist.html
Parsing input file '/tmp/reports/ub.c_cppcheck_0795e4a55ea44198516e5ae416d02dbb.plist'.
[INFO 2024-02-01 11:11] - Html file was generated: /tmp/reports.html/ub.c_cppcheck_0795e4a55ea44198516e5ae416d02dbb.plist.html
Parsing input file '/tmp/reports/ub.c_clangsa_0795e4a55ea44198516e5ae416d02dbb.plist'.
[INFO 2024-02-01 11:11] - No report data in /tmp/reports/ub.c_clangsa_0795e4a55ea44198516e5ae416d02dbb.plist file.
Parsing input file '/tmp/reports/ub.c_cppcheck_fb9868167746a12b0aa35cb54a22e877.plist'.
[INFO 2024-02-01 11:11] - No report data in /tmp/reports/ub.c_cppcheck_fb9868167746a12b0aa35cb54a22e877.plist file.

----==== Severity Statistics ====----
----------------------------
Severity | Number of reports
----------------------------
HIGH     |                 2
MEDIUM   |                 1
----------------------------
----=================----

----==== Checker Statistics ====----
-------------------------------------------------------------
Checker name                   | Severity | Number of reports
-------------------------------------------------------------
core.uninitialized.Assign      | HIGH     |                 1
clang-diagnostic-uninitialized | MEDIUM   |                 1
cppcheck-uninitvar             | HIGH     |                 1
-------------------------------------------------------------
----=================----

----==== File Statistics ====----
-----------------------------
File name | Number of reports
-----------------------------
ub.c      |                 3
-----------------------------
----=================----

----======== Summary ========----
---------------------------------------------
Number of processed analyzer result files | 5
Number of analyzer reports                | 3
---------------------------------------------
----=================----

To view statistics in a browser run:
> firefox /tmp/reports.html/statistics.html

To view the results in a browser run:
> firefox /tmp/reports.html/index.html



---------------------------------------------------------------------------

CalledProcessError                        Traceback (most recent call last)

Cell In [15], line 1
----> 1 get_ipython().run_cell_magic('bash', '', '# instrument a build first\nCodeChecker log -o /tmp/compile_commands.json --build "clang -o /tmp/ub /tmp/ub.c"\n# Then run the analyzer\nCodeChecker analyze /tmp/compile_commands.json -o /tmp/reports\nCodeChecker parse /tmp/reports -e html -o /tmp/reports.html\n\n# all in one\n#CodeChecker check --build "make" --output ./reports --clean \\\n#    --enable sensitive\n')


File ~/.local/lib/python3.10/site-packages/IPython/core/interactiveshell.py:2362, in InteractiveShell.run_cell_magic(self, magic_name, line, cell)
   2360 with self.builtin_trap:
   2361     args = (magic_arg_s, cell)
-> 2362     result = fn(*args, **kwargs)
   2363 return result


File ~/.local/lib/python3.10/site-packages/IPython/core/magics/script.py:153, in ScriptMagics._make_script_magic.<locals>.named_script_magic(line, cell)
    151 else:
    152     line = script
--> 153 return self.shebang(line, cell)


File ~/.local/lib/python3.10/site-packages/IPython/core/magics/script.py:305, in ScriptMagics.shebang(self, line, cell)
    300 if args.raise_error and p.returncode != 0:
    301     # If we get here and p.returncode is still None, we must have
    302     # killed it but not yet seen its return code. We don't wait for it,
    303     # in case it's stuck in uninterruptible sleep. -9 = SIGKILL
    304     rc = p.returncode or -9
--> 305     raise CalledProcessError(rc, cell)


CalledProcessError: Command 'b'# instrument a build first\nCodeChecker log -o /tmp/compile_commands.json --build "clang -o /tmp/ub /tmp/ub.c"\n# Then run the analyzer\nCodeChecker analyze /tmp/compile_commands.json -o /tmp/reports\nCodeChecker parse /tmp/reports -e html -o /tmp/reports.html\n\n# all in one\n#CodeChecker check --build "make" --output ./reports --clean \\\n#    --enable sensitive\n'' returned non-zero exit status 2.

Cppcheck

https://cppcheck.sourceforge.io/ https://github.com/danmar/cppcheck

! cppcheck /tmp/ub.c
[32mChecking /tmp/ub.c ...[0m
[1m/tmp/ub.c:4:5: [31merror:[39m Uninitialized variable: x [uninitvar][0m
    x++;
    ^

%%file /tmp/blast.sh
CCOPTIONS = -Wall -Wpedantic -fanalzye -fsanitize=address,bounds,undefined
clang $CCOPTIONS $1 -o  /tmp.a.out && ./a.out 
gcc $CCOPTIONS $1 &&
#cppcheck --enable=all $1
valgrind --leak-check=full --show-leak-kinds=all ./a.out
# codechecker
# infer


https://github.com/verateam/vera Probably old clang-tidy also runs analyzer? clang-tidy-diff.py

%%bash
apt install opam
opam init -y
eval $(opam env)
git clone https://github.com/rems-project/cerberus.git
cd cerberus
opam install --deps-only ./cerberus-lib.opam ./cerberus.opam
make
%%bash
cd ~/Downloads/cerberus
opam install angstrom
make cerberus-bmc
# make all

[NOTE] Package angstrom is already installed (current version is 0.15.0).


[DUNE] cerberus-bmc


File "backend/bmc/bmc_utils.ml", lines 326-356, characters 2-3:
326 | ..(match pe_ with
327 |   | PEsym s -> PEsym s
328 |   | PEimpl impl1 -> PEimpl impl1
329 |   | PEval v -> PEval v
330 |   | PEconstrained cs ->
...
353 |   | PEis_unsigned pe -> PEis_unsigned (self( 1) pe)
354 |   | PEbmc_assume pe -> PEbmc_assume (self( 1) pe)
355 |   | PEare_compatible( pe1, pe2) -> PEare_compatible( (self( 1) pe1), (self( 2) pe2))
356 |   )..
Error (warning 8 [partial-match]): this pattern-matching is not exhaustive.
Here is an example of a case that is not matched:
(PEconv_int (_, _)|PEwrapI (_, _, _, _)|
PEcatch_exceptional_condition (_, _, _, _))
make: *** [Makefile:69: cerberus-bmc] Error 1



---------------------------------------------------------------------------

CalledProcessError                        Traceback (most recent call last)

Cell In [3], line 1
----> 1 get_ipython().run_cell_magic('bash', '', 'cd ~/Downloads/cerberus\nopam install angstrom\nmake cerberus-bmc\n')


File ~/.local/lib/python3.10/site-packages/IPython/core/interactiveshell.py:2362, in InteractiveShell.run_cell_magic(self, magic_name, line, cell)
   2360 with self.builtin_trap:
   2361     args = (magic_arg_s, cell)
-> 2362     result = fn(*args, **kwargs)
   2363 return result


File ~/.local/lib/python3.10/site-packages/IPython/core/magics/script.py:153, in ScriptMagics._make_script_magic.<locals>.named_script_magic(line, cell)
    151 else:
    152     line = script
--> 153 return self.shebang(line, cell)


File ~/.local/lib/python3.10/site-packages/IPython/core/magics/script.py:305, in ScriptMagics.shebang(self, line, cell)
    300 if args.raise_error and p.returncode != 0:
    301     # If we get here and p.returncode is still None, we must have
    302     # killed it but not yet seen its return code. We don't wait for it,
    303     # in case it's stuck in uninterruptible sleep. -9 = SIGKILL
    304     rc = p.returncode or -9
--> 305     raise CalledProcessError(rc, cell)


CalledProcessError: Command 'b'cd ~/Downloads/cerberus\nopam install angstrom\nmake cerberus-bmc\n'' returned non-zero exit status 2.
%%bash
cd ~/Downloads/cerberus
dune exec cerberus -- --help

CERBERUS(1)                     Cerberus Manual                    CERBERUS(1)



NAME
       cerberus - Cerberus C semantics

SYNOPSIS
       cerberus [OPTION]… [FILE]…

ARGUMENTS
       FILE
           source C or Core file

OPTIONS
       --agnostic
           Asks Cerberus to delay looking at implementation settings until as
           late as possible. This makes the pipeline somewhat implementation
           agnostic.

       --args="ARG1 ARG2 ..."
           List of arguments for the C program

       --ast=LANG1,...
           Pretty print the intermediate syntax tree for the listed languages
           (ranging over {cabs, ail, core}).

       --batch
           makes the execution driver produce batch friendly output

       -c  Run frontend generating a target '.co' core object file.

       --charon-batch
           makes the execution driver produce batch friendly output (for
           Charon)

       --concurrency
           Activate the C11 concurrency

       --cpp=CMD (absent=cc -std=c11 -E -CC -Werror
       -Wno-builtin-macro-redefined -nostdinc -undef -D__cerb__)
           Command to call for the C preprocessing.

       -D NAME[=VALUE], --define-macro=NAME[=VALUE]
           Adds an implicit #define into the predefines buffer which is read
           before the source file is preprocessed.

       -d N, --debug=N (absent=0)
           Set the debug message level to N (should range over [0-9]).

       --defacto
           relax some of the ISO constraints (outside of the memory)

       --dignore-bitfields
           (DEBUG) accept and ignore bit-field width specifiers. CAUTION: the
           constraints relating to bit-fields are NOT checked, and the
           desugaring produces Ail struct/union types with normal members.
           This flag will be removed when support for bit-fields is added.

       -E  Run only the preprocessor stage.

       --exec
           Execute the Core program after the elaboration.

       --fs=DIR
           Initialise the internal file system with the contents of the
           directory DIR

       --fs-dump
           dump the file system at the end of the execution

       -I DIR, --include-directory=DIR
           Add the specified directory to the search path for theC
           preprocessor.

       --impl=NAME (absent=gcc_4.9.0_x86_64-apple-darwin10.8.0)
           Set the C implementation file (to be found in
           CERB_COREPATH/implsand excluding the .impl suffix).

       --include=VAL
           Adds an implicit #include into the predefines buffer which is read
           before the source file is preprocessed.

       --iso
           sets the switches corresponding to the ISO semantics (this
           overrides --switches if it is also present)

       --json-batch
           outputs the executions in json

       -l X
           This option tells the core linker to search for libX.co in the
           library search path.

       -L X
           Adds a new library search path.

       --mode=MODE (absent=random)
           Set the Core evaluation mode (interactive | exhaustive | random).

       --nolibc
           Do not search the standard system directories for include files.

       --nostdinc
           Do not search includes in the standard lib C directories.

       -o VAL
           Write output to file.

       --permissive
           allow extensions to ISO (by default Cerberus behaves like compilers
           with -pedantic)

       --pp=LANG1,...
           Pretty print the intermediate programs for the listed languages
           (ranging over {ail, core}).

       --pp_ail_out=VAL
           Write Ail pprint to a file.

       --pp_core_out=VAL
           Write Core pprint to a file.

       --pp_flags=VAL
           Pretty print flags [annot: include location and ISO annotations,
           loc: include C source locations].

       --progress
           Progress mode: the return code indicate how far the source program
           went through the pipeline [1 = total failure, 10 = parsed, 11 =
           desugared, 12 = typed, 13 = elaborated, 14 = executed]

       -r DIR, --runtime=DIR
           custom Cerberus runtime directory

       --rewrite
           Activate the Core to Core transformations

       --sequentialise
           Replace all unseq() with left to right wseq(s)

       --switches=SWITCH1,...
           list of semantics switches to turn on (see documentation for the
           list)

       --syntax-only
           Stop the pipeline after the Ail typechecking (only supported when
           called on .c files)

       --trace
           trace memory actions

       --typecheck-core
           typecheck the elaborated Core program

       -U VAL
           Adds an implicit #undef into the predefines buffer which is read
           before the source file is preprocessed.

COMMON OPTIONS
       --help[=FMT] (default=auto)
           Show this help in format FMT. The value FMT must be one of auto,
           pager, groff or plain. With auto, the format is pager or plain
           whenever the TERM env var is dumb or undefined.

       --version
           Show version information.

EXIT STATUS
       cerberus exits with:

       0   on success.

       123 on indiscriminate errors reported on standard error.

       124 on command line parsing errors.

       125 on unexpected internal errors (bugs).



Cerberus git-4806a4479                                             CERBERUS(1)
%%file 
struct S {
  int i;
  char c;
} s;

int main(void) {
  return sizeof(*(&s));
}
%%file
int main(void) {
  char a = 0;
  short int b = 0;
  return sizeof(b) == sizeof(a+b);
}
int main(void) {
  char a = ' ' * 13;
  return a;
}
 
int main(void) {
  int i = 16;
  return (((((i >= i) << i) >> i) <= i));
}
int main(void) {
  int i = 0;
  return i++ + ++i;
}