From 9123fce6418ae4140ef384c9d3912453b980be93 Mon Sep 17 00:00:00 2001
From: David Cermak <cermak@espressif.com>
Date: Fri, 18 Feb 2022 17:55:37 +0100
Subject: [PATCH] PPP: Add test exhibiting empty packet null-deref

Also updates lcp.c to compile with PPP_AUTH_SUPPORT=0 in clang
---
 src/netif/ppp/lcp.c        |  8 +++--
 test/unit/Filelists.cmake  |  1 +
 test/unit/Filelists.mk     |  3 +-
 test/unit/lwip_unittests.c |  4 +++
 test/unit/lwipopts.h       |  4 +++
 test/unit/ppp/test_pppos.c | 64 ++++++++++++++++++++++++++++++++++++++
 test/unit/ppp/test_pppos.h | 13 ++++++++
 7 files changed, 94 insertions(+), 3 deletions(-)
 create mode 100644 test/unit/ppp/test_pppos.c
 create mode 100644 test/unit/ppp/test_pppos.h

diff --git a/src/netif/ppp/lcp.c b/src/netif/ppp/lcp.c
index 9c550520..8b51a8f6 100644
--- a/src/netif/ppp/lcp.c
+++ b/src/netif/ppp/lcp.c
@@ -1498,7 +1498,11 @@ static int lcp_nakci(fsm *f, u_char *p, int len, int treat_as_reject) {
 		goto bad;
 	    break;
 	case CI_AUTHTYPE:
-	    if (0
+		/* This is potentially dead code (#if !PPP_AUTH_SUPPORT)
+		 * Thus the double parantheses to mark the code explicitely
+		 * disabled when building with clang
+		 */
+	    if ((0
 #if CHAP_SUPPORT
                 || go->neg_chap || no.neg_chap
 #endif /* CHAP_SUPPORT */
@@ -1508,7 +1512,7 @@ static int lcp_nakci(fsm *f, u_char *p, int len, int treat_as_reject) {
 #if EAP_SUPPORT
 		|| go->neg_eap || no.neg_eap
 #endif /* EAP_SUPPORT */
-		)
+		))
 		goto bad;
 	    break;
 	case CI_MAGICNUMBER:
diff --git a/test/unit/Filelists.cmake b/test/unit/Filelists.cmake
index 7f5041bd..ea0bbe74 100644
--- a/test/unit/Filelists.cmake
+++ b/test/unit/Filelists.cmake
@@ -33,4 +33,5 @@ set(LWIP_TESTFILES
 	${LWIP_TESTDIR}/tcp/test_tcp_oos.c
 	${LWIP_TESTDIR}/tcp/test_tcp.c
 	${LWIP_TESTDIR}/udp/test_udp.c
+	${LWIP_TESTDIR}/ppp/test_pppos.c
 )
diff --git a/test/unit/Filelists.mk b/test/unit/Filelists.mk
index bb8160a1..3ba64b36 100644
--- a/test/unit/Filelists.mk
+++ b/test/unit/Filelists.mk
@@ -48,5 +48,6 @@ TESTFILES=$(TESTDIR)/lwip_unittests.c \
 	$(TESTDIR)/tcp/tcp_helper.c \
 	$(TESTDIR)/tcp/test_tcp_oos.c \
 	$(TESTDIR)/tcp/test_tcp.c \
-	$(TESTDIR)/udp/test_udp.c
+	$(TESTDIR)/udp/test_udp.c \
+	$(TESTDIR)/ppp/test_pppos.c
 
diff --git a/test/unit/lwip_unittests.c b/test/unit/lwip_unittests.c
index 9fde40e6..b223e701 100644
--- a/test/unit/lwip_unittests.c
+++ b/test/unit/lwip_unittests.c
@@ -16,6 +16,7 @@
 #include "mdns/test_mdns.h"
 #include "mqtt/test_mqtt.h"
 #include "api/test_sockets.h"
+#include "ppp/test_pppos.h"
 
 #include "lwip/init.h"
 #if !NO_SYS
@@ -89,6 +90,9 @@ int main(void)
     mdns_suite,
     mqtt_suite,
     sockets_suite
+#if PPP_SUPPORT && PPPOS_SUPPORT
+    , pppos_suite
+#endif /* PPP_SUPPORT && PPPOS_SUPPORT */
   };
   size_t num = sizeof(suites)/sizeof(void*);
   LWIP_ASSERT("No suites defined", num > 0);
diff --git a/test/unit/lwipopts.h b/test/unit/lwipopts.h
index 09175c48..0ee09dff 100644
--- a/test/unit/lwipopts.h
+++ b/test/unit/lwipopts.h
@@ -73,6 +73,10 @@
 #define LWIP_MDNS_RESPONDER             1
 #define LWIP_NUM_NETIF_CLIENT_DATA      (LWIP_MDNS_RESPONDER)
 
+/* Enable PPP and PPPOS support for PPPOS test suites */
+#define PPP_SUPPORT                     1
+#define PPPOS_SUPPORT                   1
+
 /* Minimal changes to opt.h required for etharp unit tests: */
 #define ETHARP_SUPPORT_STATIC_ENTRIES   1
 
diff --git a/test/unit/ppp/test_pppos.c b/test/unit/ppp/test_pppos.c
new file mode 100644
index 00000000..a6fbb934
--- /dev/null
+++ b/test/unit/ppp/test_pppos.c
@@ -0,0 +1,64 @@
+#include "test_pppos.h"
+
+#include "lwip/netif.h"
+#include "netif/ppp/pppos.h"
+#include "netif/ppp/ppp.h"
+
+#if PPP_SUPPORT && PPPOS_SUPPORT
+static struct netif pppos_netif;
+static ppp_pcb *ppp;
+
+static u32_t ppp_output_cb(struct ppp_pcb_s *pcb, u8_t *data, u32_t len, void *ctx)
+{
+  LWIP_UNUSED_ARG(pcb);
+  LWIP_UNUSED_ARG(data);
+  LWIP_UNUSED_ARG(len);
+  LWIP_UNUSED_ARG(ctx);
+
+  return  0;
+}
+
+static void ppp_link_status_cb(ppp_pcb *pcb, int err_code, void *ctx)
+{
+  LWIP_UNUSED_ARG(pcb);
+  LWIP_UNUSED_ARG(err_code);
+  LWIP_UNUSED_ARG(ctx);
+}
+
+static void pppos_setup(void)
+{
+  ppp = pppos_create(&pppos_netif, ppp_output_cb, ppp_link_status_cb, NULL);
+  fail_if(ppp == NULL);
+  ppp_connect(ppp, 0);
+}
+
+static void pppos_teardown(void)
+{
+}
+
+START_TEST(test_pppos_empty_packet_with_valid_fcs)
+{
+  u8_t two_breaks[] = { 0x7e, 0, 0, 0x7e };
+  u8_t other_packet[] = { 0x7e, 0x7d, 0x20, 0x00, 0x7e };
+  /* Set internal states of the underlying pcb */
+  pppos_pcb *pppos = (pppos_pcb *)ppp->link_ctx_cb;
+  pppos->open = 1;  /* Pretend the connection is open already */
+  pppos->in_accm[0] = 0xf0;  /* Make sure 0x0's are not escaped chars */
+
+  pppos_input(ppp, two_breaks, sizeof(two_breaks));
+  pppos_input(ppp, other_packet, sizeof(other_packet));
+
+}
+END_TEST
+
+/** Create the suite including all tests for this module */
+Suite *
+pppos_suite(void)
+{
+  testfunc tests[] = {
+    TESTFUNC(test_pppos_empty_packet_with_valid_fcs)
+  };
+  return create_suite("PPPOS", tests, sizeof(tests)/sizeof(testfunc), pppos_setup, pppos_teardown);
+}
+
+#endif /* PPP_SUPPORT && PPPOS_SUPPORT */
diff --git a/test/unit/ppp/test_pppos.h b/test/unit/ppp/test_pppos.h
new file mode 100644
index 00000000..56b3b0cb
--- /dev/null
+++ b/test/unit/ppp/test_pppos.h
@@ -0,0 +1,13 @@
+#ifndef LWIP_HDR_TEST_PPPOS_H
+#define LWIP_HDR_TEST_PPPOS_H
+
+#include "../lwip_check.h"
+#include "netif/ppp/ppp.h"
+
+#if PPP_SUPPORT && PPPOS_SUPPORT
+
+Suite* pppos_suite(void);
+
+#endif /* PPP_SUPPORT && PPPOS_SUPPORT */
+
+#endif /* LWIP_HDR_TEST_PPPOS_H */
-- 
2.25.1

