Another great UBSan feature is -fsanitize=integer which detects truncation and sign changes in implicit casts. But if you start using it, you'll realize that explicit casts enforced by -Wconversion only hide errors. You really have to remove as many explicit casts as possible to detect unwanted truncation.
After testing and fuzzing with -fsanitize=integer for a while, I came to the conclusion that implicit casts are a feature and C even has an advantage there compared to other languages which require explicit casts. To test for unwanted truncation, you really need two different casting operations. One which silently truncates in the rare cases where you really need it and another one which warns about truncation in test builds.
So my recommendation is: Remove all explicit casts and warnings like -Wconversion. Test with -fsanitize=integer. If UBSan detects truncation, you can often adjust some types so that no truncation happens. Only use explicit casts if you must convert between signed and unsigned chars for example.
After testing and fuzzing with -fsanitize=integer for a while, I came to the conclusion that implicit casts are a feature and C even has an advantage there compared to other languages which require explicit casts. To test for unwanted truncation, you really need two different casting operations. One which silently truncates in the rare cases where you really need it and another one which warns about truncation in test builds.
So my recommendation is: Remove all explicit casts and warnings like -Wconversion. Test with -fsanitize=integer. If UBSan detects truncation, you can often adjust some types so that no truncation happens. Only use explicit casts if you must convert between signed and unsigned chars for example.