diff mbox series

[1/2] sparse: fix broken 'memcpy-max-count' check

Message ID 256de5b4-7bb7-8259-c220-8a9c9dc785b1@ramsayjones.plus.com (mailing list archive)
State New
Headers show
Series [1/2] sparse: fix broken 'memcpy-max-count' check | expand

Commit Message

Ramsay Jones Sept. 27, 2021, 11:43 p.m. UTC
commit a69f8d70 ("ptrlist: use ptr_list_nth() instead of linearize_ptr_\
list()", 2021-02-14) replaced a call to a local helper with a more generic
ptr_list function. The local function, argument(), was used to retrieve
the 'argno' argument to a function call, counting the arguments from one.
This call was replaced by the generic ptr_list_nth() function, which
accessed the ptr_list counting from zero. The 'argno' passed to the call to
argument() was 3 (the byte count), which when passed to ptr_list_nth()
was attempting to access the 4th (non-existent) argument. (The resulting
null pointer was then passed to check_byte_count() function, which had
an null-pointer check and so did not dereference the null pointer). This
effectively disabled the memcpy-max-count check.

In order to fix the check, change the 'argno' of 3 to the 'index' of 2.
Also, add a simple regression test.

Signed-off-by: Ramsay Jones <ramsay@ramsayjones.plus.com>
---
 sparse.c                    |  2 +-
 validation/byte-count-max.c | 28 ++++++++++++++++++++++++++++
 2 files changed, 29 insertions(+), 1 deletion(-)
 create mode 100644 validation/byte-count-max.c
diff mbox series

Patch

diff --git a/sparse.c b/sparse.c
index 9d62d4fe..e7cc6f55 100644
--- a/sparse.c
+++ b/sparse.c
@@ -165,7 +165,7 @@  static void check_byte_count(struct instruction *insn, pseudo_t count)
 
 static void check_memset(struct instruction *insn)
 {
-	check_byte_count(insn, ptr_list_nth(insn->arguments, 3));
+	check_byte_count(insn, ptr_list_nth(insn->arguments, 2));
 }
 
 #define check_memcpy check_memset
diff --git a/validation/byte-count-max.c b/validation/byte-count-max.c
new file mode 100644
index 00000000..0555a505
--- /dev/null
+++ b/validation/byte-count-max.c
@@ -0,0 +1,28 @@ 
+typedef unsigned long int size_t;
+typedef unsigned long ulong;
+
+extern void *memset(void *s, int c, size_t n);
+extern void *memcpy(void *dest, void *src, size_t n);
+extern ulong copy_to_user(void *to, const void *from, ulong count);
+extern ulong copy_from_user(void *to, const void *from, ulong count);
+
+static void func (char *s)
+{
+	char d[250000];
+
+	memset(d, 0, 250000);
+	memcpy(d, s, 250000);
+	copy_to_user(s, d, 250000);
+	copy_from_user(d, s, 250000);
+}
+
+/*
+ * check-name: byte-count-max
+ *
+ * check-error-start
+byte-count-max.c:13:15: warning: memset with byte count of 250000
+byte-count-max.c:14:15: warning: memcpy with byte count of 250000
+byte-count-max.c:15:21: warning: copy_to_user with byte count of 250000
+byte-count-max.c:16:23: warning: copy_from_user with byte count of 250000
+ * check-error-end
+ */