https://gcc.gnu.org/bugzilla/show_bug.cgi?id=117023
--- Comment #6 from GCC Commits <cvs-commit at gcc dot gnu.org> --- The master branch has been updated by Jakub Jelinek <ja...@gcc.gnu.org>: https://gcc.gnu.org/g:19fe55c4801de50deee03b333e94d007aae222e3 commit r15-5750-g19fe55c4801de50deee03b333e94d007aae222e3 Author: Jakub Jelinek <ja...@redhat.com> Date: Thu Nov 28 11:48:33 2024 +0100 Add support for nonnull_if_nonzero attribute [PR117023] As mentioned in an earlier thread, C2Y voted in a change which made various library APIs callable with NULL arguments in certain cases, e.g. memcpy (NULL, NULL, 0); is now valid, although memcpy (NULL, NULL, 1); remains invalid. This affects various APIs, including several of GCC builtins; plus on the C library side those APIs are often declared with nonnull attribute(s) as well. Florian suggested using the access attribute for this, but our docs explicitly say that access attribute doesn't imply nonnull and it doesn't cover e.g. the qsort case where the comparison function pointer may be also NULL if nmemb is 0, but must be non-zero otherwise. As this case affects 21 APIs in C standard and I think is going to affect various wrappers around those in various packages as well, I think it is a common thing that should have its own attribute, because we should still warn when people use qsort (NULL, 1, 1, NULL); etc., and similarly want to have -fsanitize=null instrumentation for those. So, the following patch introduces nonnull_if_nonzero attribute (or would you prefer cond_nonnull or some other name?), which has always 2 arguments, argument index of a pointer argument (like one argument nonnull) and argument index of an associated integral argument. If that argument is non-zero, it is UB to pass NULL to the pointer argument, if that argument is zero, it is valid. And changes various spots which already handled the nonnull attribute to handle this one as well, with sometimes using the ranger (or for -fsanitize=nonnull explicitly checking the associated argument value, so instead of if (!ptr) __ubsan_... (...); it will now do if (!ptr && sz) __ubsan_... (...);). I've so far omitted changing gimple_infer_range (am not 100% sure how I can use the ranger inside of the ranger) and changing the analyzer to handle it. And I haven't changed builtins.def etc. to make use of that attribute instead of nonnull where appropriate. I'd then follow with the builtins.def changes (and eventually glibc etc. would need to be adjusted too). 2024-11-28 Jakub Jelinek <ja...@redhat.com> PR c/117023 gcc/ * gimple.h (infer_nonnull_range_by_attribute): Add a tree * argument defaulted to NULL. * gimple.cc (infer_nonnull_range_by_attribute): Add op2 argument. Handle also nonnull_if_nonzero attributes. * tree.cc (get_nonnull_args): Fix comment typo. * builtins.cc (validate_arglist): Handle nonnull_if_nonzero attribute. * tree-ssa-ccp.cc (pass_post_ipa_warn::execute): Handle nonnull_if_nonzero attributes. * ubsan.cc (instrument_nonnull_arg): Adjust infer_nonnull_range_by_attribute caller. If it returned true and filed in non-NULL arg2, check that arg2 is non-zero as another condition next to checking that arg is zero. * doc/extend.texi (nonnull_if_nonzero): Document new attribute. gcc/c-family/ * c-attribs.cc (handle_nonnull_if_nonzero_attribute): New function. (c_common_gnu_attributes): Add nonnull_if_nonzero attribute. (handle_nonnull_attribute): Fix comment typo. * c-common.cc (struct nonnull_arg_ctx): Add other member. (check_function_nonnull): Also check nonnull_if_nonzero attributes. (check_nonnull_arg): Use different warning wording if pctx->other is non-zero. (check_function_arguments): Initialize ctx.other. gcc/testsuite/ * gcc.dg/nonnull-8.c: New test. * gcc.dg/nonnull-9.c: New test. * gcc.dg/nonnull-10.c: New test. * c-c++-common/ubsan/nonnull-6.c: New test. * c-c++-common/ubsan/nonnull-7.c: New test.