linux Debugging code may derefence a NULL pointer

Pointer `dst' may be NULL and, if SCTP_DEBUG_PRINTK is enabled, is dereferenced by a call to printk.
Bug fixed by commit ee3f34e8572
Type NullDereference
Config "IP_SCTP && IPV6 && SCTP_DBG_MSG" (3rd degree)
C-features PointerAliasing
Fix-in code
Location net/sctp/
#include <stdbool.h>
#include <stdlib.h>

#ifndef SCTP_DEBUG
#ifdef CONFIG_SCTP_DBG_MSG
#define SCTP_DEBUG      1
#else
#define SCTP_DEBUG      0
#endif /* CONFIG_SCTP_DBG */
#endif /* SCTP_DEBUG */

bool IS_ERR(const void *ptr)
{
  return (ptr == (void *)-1);
}

bool IS_ERR_OR_NULL(const void *ptr)
{
  return !ptr || IS_ERR(ptr);
}

#if SCTP_DEBUG
#define SCTP_DEBUG_PRINTK(ptr) ((*ptr)++)
#else
#define SCTP_DEBUG_PRINTK(ptr)
#endif

#if defined(CONFIG_IP_SCTP) && defined(CONFIG_IPV6)
static int some_int = 1;

int *ip6_dst_lookup_flow()
{
  return &some_int;
}

void sctp_v6_get_dst()
{
  int *dst = NULL;
  dst = ip6_dst_lookup_flow();
  if (!IS_ERR(dst)) {
    dst = NULL; // (2)
  }
  if (!IS_ERR(dst)) {
    char *rt =(char *) dst; // (3)
    SCTP_DEBUG_PRINTK(rt); // (4) ERROR
  }
}
#endif

int main()
{
#if defined(CONFIG_IP_SCTP) && defined(CONFIG_IPV6)
  sctp_v6_get_dst(); // (1)
#endif
  return 0;
}

diff --git a/simple/ee3f34e.c b/simple/ee3f34e.c
--- a/simple/ee3f34e.c
+++ b/simple/ee3f34e.c
@@ -41,7 +41,7 @@
   if (!IS_ERR(dst)) {
     dst = NULL;
   }
-  if (!IS_ERR(dst)) {
+  if (!IS_ERR_OR_NULL(dst)) {
     char *rt =(char *) dst;
     SCTP_DEBUG_PRINTK(rt); // ERROR
   }
#include <stdbool.h>
#include <stdlib.h>

#ifndef SCTP_DEBUG
#ifdef CONFIG_SCTP_DBG_MSG
#define SCTP_DEBUG      1
#else
#define SCTP_DEBUG      0
#endif /* CONFIG_SCTP_DBG */
#endif /* SCTP_DEBUG */

#if defined(CONFIG_IP_SCTP) && defined(CONFIG_IPV6)
static int some_int = 1;
#endif

int main()
{
#if defined(CONFIG_IP_SCTP) && defined(CONFIG_IPV6)
//  sctp_v6_get_dst();
  int *dst = NULL;
  dst = &some_int;
  if (!(dst == (void *)-1)) {
    dst = NULL;
  }
  if (!(dst == (void *)-1)) {
    char *rt =(char *) dst;
//    SCTP_DEBUG_PRINTK(rt); // ERROR
    #if SCTP_DEBUG
    ((*rt)++);
    #else
    #endif
  }
#endif
  return 0;
}

. call net/sctp/ipv6.c:257:sctp_v6_get_dst()
. 265: union sctp_addr *baddr = NULL;
. 290: dst = ip6_dst_lookup_flow(sk, fl6, NULL, false);
. 299: if (!IS_ERR(dst))
. 321:     dst = NULL;
// somehow `baddr' is still pointing to NULL
// or maybe `dst' becomes NULL at 344
. 348: if (!IS_ERR(dst))
. 350: rt = (struct rt6_info *)dst;
// `rt' is an alias for `dst'
. [SCTP_DBG_MSG] 352: SCTP_DEBUG_PRINTK("rt6_dst:%pI6 rt6_src:%pI6\n",
. ERROR 353:                   &rt->rt6i_dst.addr, &fl6->saddr);