Passing ``++NULL++`` to a C library function that requires non-null pointer arguments results in undefined behavior.

== Why is this an issue?

The standard C library includes a variety of functions for string and general memory manipulations.
Many of these functions require valid parameters and when given values outside a function's domain, the behavior is undefined.
Functions like ``++strlen++``, ``++memset++``, ``++memcpy++``, ``++qsort++``, ``++fread++``, etc., for instance, require non-``++NULL++`` parameters, and passing a ``++NULL++`` value introduces undefined behavior. 
In that case, the application may crash or, even worse, silently lose data or produce incorrect results.

Consider the following code.
If the pointer-typed variable `buf` is `NULL` due to a failed memory allocation, for instance, the call to `memset()` will cause undefined behavior.

[source,c]
----
#include <string.h>

void process_buffer(char *buf, size_t size) {
  // Call to `memset()` may lead to undefined behavior, if `buf` is NULL.
  memset(buf, 0, size);
}
----

Similarly, if for some reason a ``++NULL++`` pointer slips through and reaches the string manipulation code shown in the following, the application's behavior is undefined.

[source,c]
----
#include <string.h>

int compare_strings(const char *str_a, const char *str_b) {
  // Both functions `strlen()` and `strncmp()` may not receive a `NULL` pointer.
  size_t len_a = strlen(str_a);
  size_t len_b = strlen(str_b);
  size_t min = (len_a <= len_b) ? len_a : len_b;
  return strncmp(str_a, str_b, min);
}
----

Hence, users have to ensure that the C standard library functions' preconditions are met and valid parameters are passed.

The C library functions that are considered by this rule and that require non-``++NULL++`` pointer parameters are listed in this rule's Resources section.


== What is the potential impact?

If an argument to one of the C library functions mentioned by this rule is a ``++NULL++`` pointer, the behavior of the application is undefined.

When a program comprises undefined behavior, the compiler no longer needs to adhere to the language standard, and the program has no meaning assigned to it.

Due to the resulting ``++NULL++`` pointer dereferences in the C library functions, the application might just crash, but in the worst case, the application may appear to execute correctly, while losing data or producing incorrect results.

Besides affecting the application's availability, ``++NULL++`` pointer dereferences may lead to code execution, in rare circumstances.
If ``++NULL++`` is equivalent to the ``++0x0++`` memory address that can be accessed by privileged code, writing and reading memory is possible, which compromises the integrity and confidentiality of the application.


== How to fix it

Ensure that any pointer passed to any of the C library functions mentioned by this rule _is not_ ``++NULL++``.


=== Code examples

==== Noncompliant code example

[source,c,diff-id=1,diff-type=noncompliant]
----
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int process_string() {
  char buffer[] = "Hello, World!";
  char *str = (char *)malloc(sizeof(buffer));
  if (!str) {
    printf("Memory allocation failed!\n");
  }
  // Noncompliant: 1st parameter in the subsequent call to `memcpy()` might be
  // NULL due to insufficient handling of a potentially failed memory
  // allocation.
  memcpy(str, buffer, sizeof(buffer));
  // Process dynamically alloacted `str` variable.
  // ...
  // Free memory, if it is no longer in use.
  free(str);
  return 0;
}
----

==== Compliant solution

[source,c,diff-id=1,diff-type=compliant]
----
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int process_string() {
  char buffer[] = "Hello, World!";
  char *str = (char *)malloc(sizeof(buffer));
  if (!str) {
    printf("Memory allocation failed!\n");
    return 1;
  }
  // Compliant: 1st parameter will always denote a non-null pointer.
  memcpy(str, buffer, sizeof(buffer));
  // Process dynamically alloacted `str` variable.
  // ...
  // Free memory, if it is no longer in use.
  free(str);
  return 0;
}
----


== Resources

=== Documentation


The list of functions considered by this rule is shown in the following:

[source,text]
----
aio_suspend, bcmp, bcopy, bsearch, bzero, confstr, encrypt, erand48,
explicit_bzero, explicit_memset, fgetpwent_r, fgets, fgetws, fread, fwrite,
getdelim, getgrgid_r, getgrnam_r, gethostbyaddr_r, gethostbyname2_r,
gethostbyname_r, gethostent_r, gethostname, getline, getlogin_r,
getnetbyaddr_r, getnetbyname_r, getnetent_r, getnetgrent_r, getopt,
getopt_long, getopt_long_only, getprotobyname_r, getprotobynumber_r,
getprotoent_r, getpwent_r, getpwnam_r, getpwuid_r, getservbyname_r,
getservbyport_r, getservent_r, iconv, initstate, jrand48, lcong48, lfind,
lio_listio, lsearch, mblen, mbrlen, mbrtowc, mbsnrtowcs, mbsrtowcs,
mbstowcs, mbtowc, memccpy, memchr, memcmp, memcpy, memmove, mempcpy,
memset, mq_receive, mq_send, mq_timedreceive, mq_timedsend, nrand48,
posix_trace_event, posix_trace_trygetnext_event, pread, preadv, preadv2,
pthread_attr_setstack, pwrite, pwritev, pwritev2, qsort, qsort_r, read,
readlink, readlinkat, readv, realpath, recv, recvfrom, regerror, regexec,
seed48, semop, semtimedop, send, sendto, setbuf, setbuffer, setvbuf,
snprintf, socketpair, std::copy (for C++), std::copy_backward (for C++),
stpcpy, strcasecmp, strcat, strcmp, strcpy, strfmon, strfmon_l, strftime,
strftime_l, strlcat, strlcpy, strlen, strncasecmp, strncat, strncmp, strncpy,
strnlen, strsep, swab, swprintf, ttyname_r, utimes, vsnprintf, vswprintf,
wcpncpy, wcsftime, wcslen, wcsncasecmp, wcsncasecmp_l, wcsncmp, wcsncpy,
wcsnlen, wcsnrtombs, wcsrtombs, wcstombs, wcswidth, wcsxfrm, wcsxfrm_l,
wmemchr, wmemcmp, wmemcpy, wmemmove, wmemcpy, wmemset, write, writev
----

=== Standards

* CWE - https://cwe.mitre.org/data/definitions/476[CWE-476 NULL Pointer Dereference]
CERT - https://wiki.sei.cmu.edu/confluence/x/QdcxBQ[EXP34-C.Do not dereference null pointers]

=== Related rules

* S2259 detects dereferences of null pointers
* S2637 detects uses of null pointers as arguments for parameters that are annotated with `nonnull`


ifdef::env-github,rspecator-view[]

'''
== Implementation Specification
(visible only on this page)

=== Message

Change this parameter to not be {null/zero}.


=== Highlighting

parameter


endif::env-github,rspecator-view[]
