diff --git a/lib/checkother.cpp b/lib/checkother.cpp index b428cecc3..ecbab5725 100644 --- a/lib/checkother.cpp +++ b/lib/checkother.cpp @@ -3793,11 +3793,12 @@ void CheckOther::varFuncNullUBError(const Token *tok) reportError(tok, Severity::portability, "varFuncNullUB", - "Passing NULL to a function with variable number of arguments leads to undefined behaviour on some platforms.\n" - "Passing NULL to a function with variable number of arguments leads to undefined behaviour on some platforms.\n" - "The behaviour is undefined when NULL is #defined as 0, sizeof(int)!=sizeof(void*) and the function expects a pointer. Otherwise the behaviour is defined.\n" - "See section section 7.1.4 and section 7.15.1.1 in the C standard. Section 7.1.4 explains that the function call is UB. Section 7.15.1.1 explains that the va_arg macro has UB.\n" - "To reproduce you might be able to use this little code example. Try it on a platform where sizeof(int)!=sizeof(void*), for instance on a x86_64 machine. If ERROR is written by the program on the screen it means that 0 is not converted to a NULL pointer. Changing the 0 to (void*)0 will fix the program.\n" + "Passing NULL after the last typed argument to a variadic function leads to undefined behaviour.\n" + "Passing NULL after the last typed argument to a variadic function leads to undefined behaviour.\n" + "The C99 standard, in section 7.15.1.1, states that if the type used by va_arg() is not compatible with the type of the actual next argument (as promoted according to the default argument promotions), the behavior is undefined.\n" + "The value of the NULL macro is an implementation-defined null pointer constant (7.17), which can be any integer constant expression with the value 0, or such an expression casted to (void*) (6.3.2.3). This includes values like 0, 0L, or even 0LL.\n" + "In practice on common architectures, this will cause real crashes if sizeof(int) != sizeof(void*), and NULL is defined to 0 or any other null pointer constant that promotes to int.\n" + "To reproduce you might be able to use this little code example on 64bit platforms. If the output includes \"ERROR\", the sentinel had only 4 out of 8 bytes initialized to zero and was not detected as the final argument to stop argument processing via va_arg(). Changing the 0 to (void*)0 or 0L will make the \"ERROR\" output go away.\n" "#include \n" "#include \n" "\n" @@ -3814,9 +3815,9 @@ void CheckOther::varFuncNullUBError(const Token *tok) "\n" "void g() {\n" " char *s2 = \"x\";\n" - " char *s3 = \"ERROR\";\n" + " char *s3 = \"ERROR\";\n" "\n" - " // changing 0 to 0L makes the error go away on x86_64\n" + " // changing 0 to 0L for the 7th argument (which is intended to act as sentinel) makes the error go away on x86_64\n" " f(\"first\", s2, s2, s2, s2, s2, 0, s3, (char*)0);\n" "}\n" "\n"