summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStefan Adolfsson <sadolfsson@chromium.org>2018-05-25 14:47:38 +0200
committerchrome-bot <chrome-bot@chromium.org>2018-08-22 08:16:02 -0700
commite7bff8f8804e23680ff1fe57062c70debe856d21 (patch)
tree04fc7efd12b0cc5a129a2957a11dbe66f9dbd802
parente8252556d52f897f2ea443e1cdd1bb0ebf7174ab (diff)
downloadchrome-ec-e7bff8f8804e23680ff1fe57062c70debe856d21.tar.gz
CEC: Add unit tests for buffer handling
Makes sure that we don't have and that we don't introduce buffer overflows in the CEC buffer handling. Signed-off-by: Stefan Adolfsson <sadolfsson@chromium.org> BUG=b:80288314 BRANCH=none TEST=make -j runtests Change-Id: Iad5f79add99e2582e60f0d11ed53a27ac67e8b8c Reviewed-on: https://chromium-review.googlesource.com/1073415 Commit-Ready: Stefan Adolfsson <sadolfsson@chromium.org> Tested-by: Stefan Adolfsson <sadolfsson@chromium.org> Reviewed-by: Randall Spangler <rspangler@chromium.org> Reviewed-by: Zhongze Hu <frankhu@google.com>
-rw-r--r--include/cec.h4
-rw-r--r--test/build.mk2
-rw-r--r--test/cec.c132
-rw-r--r--test/cec.tasklist19
-rw-r--r--test/test_config.h4
5 files changed, 159 insertions, 2 deletions
diff --git a/include/cec.h b/include/cec.h
index d16378917f..f5d7b01ebe 100644
--- a/include/cec.h
+++ b/include/cec.h
@@ -16,12 +16,12 @@
/* CEC message during transfer */
struct cec_msg_transfer {
- /* The CEC message */
- uint8_t buf[MAX_CEC_MSG_LEN];
/* Bit offset */
uint8_t bit;
/* Byte offset */
uint8_t byte;
+ /* The CEC message */
+ uint8_t buf[MAX_CEC_MSG_LEN];
};
/*
diff --git a/test/build.mk b/test/build.mk
index 967231684e..4fffada544 100644
--- a/test/build.mk
+++ b/test/build.mk
@@ -18,6 +18,7 @@ test-list-host += battery_get_params_smart
test-list-host += bklight_lid
test-list-host += bklight_passthru
test-list-host += button
+test-list-host += cec
test-list-host += charge_manager
test-list-host += charge_manager_drp_charging
test-list-host += charge_ramp
@@ -73,6 +74,7 @@ battery_get_params_smart-y=battery_get_params_smart.o
bklight_lid-y=bklight_lid.o
bklight_passthru-y=bklight_passthru.o
button-y=button.o
+cec-y=cec.o
charge_manager-y=charge_manager.o
charge_manager_drp_charging-y=charge_manager.o
charge_ramp-y+=charge_ramp.o
diff --git a/test/cec.c b/test/cec.c
new file mode 100644
index 0000000000..3487ec1df4
--- /dev/null
+++ b/test/cec.c
@@ -0,0 +1,132 @@
+/* Copyright 2018 The Chromium OS Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ *
+ * Test the buffer handling of HDMI CEC
+ */
+
+#include <string.h>
+
+#include "cec.h"
+#include "test_util.h"
+
+struct overflow_msg {
+ struct cec_msg_transfer transfer;
+ uint8_t overflow_detector;
+} overflow_msg;
+/* Ensure the overflow detector is located directly after the buffer */
+BUILD_ASSERT(offsetof(struct overflow_msg, overflow_detector) ==
+ offsetof(struct cec_msg_transfer, buf) + MAX_CEC_MSG_LEN);
+
+
+struct overflow_circbuf {
+ struct cec_rx_cb circbuf;
+ uint8_t overflow_detector[CEC_CIRCBUF_SIZE];
+} overflow_circbuf;
+/* Ensure the overflow detector is located directly after the buffer */
+BUILD_ASSERT(offsetof(struct overflow_circbuf, overflow_detector) ==
+ offsetof(struct cec_rx_cb, buf) + CEC_CIRCBUF_SIZE);
+
+
+static struct cec_rx_cb *circbuf;
+
+/* Tests */
+static int test_msg_overflow(void)
+{
+ int i;
+
+ /* Overwrite the buffer by 1 byte */
+ for (i = 0; i < (MAX_CEC_MSG_LEN+1)*8; i++) {
+ msgt_set_bit(&overflow_msg.transfer, 1);
+ msgt_inc_bit(&overflow_msg.transfer);
+ }
+
+ /* Make sure we actually wrote the whole buffer with ones */
+ for (i = 0; i < MAX_CEC_MSG_LEN; i++)
+ TEST_ASSERT(overflow_msg.transfer.buf[i] == 0xff);
+
+ /* Verify that the attempt to overflow the buffer did not succeed */
+ TEST_ASSERT(overflow_msg.overflow_detector == 0);
+
+ /* The full indicator is when byte reaches MAX_CEC_MSG_LEN */
+ TEST_ASSERT(overflow_msg.transfer.byte == MAX_CEC_MSG_LEN);
+
+ /* Check that the indicator stays the same if we write another byte */
+ for (i = 0; i < 8; i++) {
+ msgt_set_bit(&overflow_msg.transfer, 1);
+ msgt_inc_bit(&overflow_msg.transfer);
+ }
+ TEST_ASSERT(overflow_msg.transfer.byte == MAX_CEC_MSG_LEN);
+
+ return EC_SUCCESS;
+}
+
+
+
+static int verify_no_circbuf_overflow(void)
+{
+ int i;
+
+ for (i = 0; i < CEC_CIRCBUF_SIZE; i++) {
+ if (overflow_circbuf.overflow_detector[i] != 0)
+ return EC_ERROR_OVERFLOW;
+ }
+ return EC_SUCCESS;
+}
+
+
+static void clear_circbuf(void)
+{
+ memset(circbuf, 0, sizeof(struct cec_rx_cb));
+
+}
+
+static int fill_queue(uint8_t *msg, int msg_size)
+{
+ int i;
+
+ /*
+ * Fill the queue. Every push adds the message and one extra byte for
+ * the length field. The maximum data we can add is one less than
+ * CEC_CIRCBUF_SIZE since write_pointer==read_pointer is used to
+ * indicate an empty buffer
+ */
+ clear_circbuf();
+
+ for (i = 0; i < (CEC_CIRCBUF_SIZE - 1)/(msg_size + 1); i++)
+ TEST_ASSERT(rx_circbuf_push(circbuf, msg, msg_size) == 0);
+
+ /* Now the queue should be full */
+ TEST_ASSERT(rx_circbuf_push(circbuf, msg, msg_size)
+ == EC_ERROR_OVERFLOW);
+
+ /* Verify nothing was written outside of the queue */
+ TEST_ASSERT(verify_no_circbuf_overflow() == EC_SUCCESS);
+
+ return EC_SUCCESS;
+}
+
+static int test_circbuf_overflow(void)
+{
+ uint8_t msg[CEC_CIRCBUF_SIZE];
+
+ memset(msg, 0xff, sizeof(msg));
+
+ TEST_ASSERT(fill_queue(msg, 1) == EC_SUCCESS);
+ TEST_ASSERT(fill_queue(msg, 2) == EC_SUCCESS);
+ TEST_ASSERT(fill_queue(msg, 3) == EC_SUCCESS);
+ TEST_ASSERT(fill_queue(msg, MAX_CEC_MSG_LEN) == EC_SUCCESS);
+
+ return EC_SUCCESS;
+}
+
+void run_test(void)
+{
+ circbuf = &overflow_circbuf.circbuf;
+
+ RUN_TEST(test_msg_overflow);
+
+ RUN_TEST(test_circbuf_overflow);
+
+ test_print_result();
+}
diff --git a/test/cec.tasklist b/test/cec.tasklist
new file mode 100644
index 0000000000..7015e106a9
--- /dev/null
+++ b/test/cec.tasklist
@@ -0,0 +1,19 @@
+/* Copyright 2018 The Chromium OS Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ *
+ * Test the buffer handling of HDMI CEC
+ */
+
+/**
+ * List of enabled tasks in the priority order
+ *
+ * The first one has the lowest priority.
+ *
+ * For each task, use the macro TASK_TEST(n, r, d, s) where :
+ * 'n' in the name of the task
+ * 'r' in the main routine of the task
+ * 'd' in an opaque parameter passed to the routine at startup
+ * 's' is the stack size in bytes; must be a multiple of 8
+ */
+#define CONFIG_TEST_TASK_LIST /* No test task */
diff --git a/test/test_config.h b/test/test_config.h
index 8efe426e38..be1068ac33 100644
--- a/test/test_config.h
+++ b/test/test_config.h
@@ -167,6 +167,10 @@ int ncp15wb_calculate_temp(uint16_t adc);
#define I2C_PORT_CHARGER 0
#endif
+#ifdef TEST_CEC
+#define CONFIG_CEC
+#endif
+
#ifdef TEST_LIGHTBAR
#define CONFIG_I2C
#define CONFIG_I2C_MASTER