diff mbox series

sparc64: avoid stringop-overread warning to access Machine description datas

Message ID 20210428212823.3741332-1-romain.naour@gmail.com
State New
Headers show
Series sparc64: avoid stringop-overread warning to access Machine description datas | expand

Commit Message

Romain Naour April 28, 2021, 9:28 p.m. UTC
gcc-11 warns about what appears to be an out-of-range array access but
stop the build due to -Werror added to cflags:

arch/sparc/kernel/mdesc.c: In function 'mdesc_node_by_name':
arch/sparc/kernel/mdesc.c:647:22: error: 'strcmp' reading 1 or more bytes from a region of size 0 [-Werror=stringop-overread]
  647 |                 if (!strcmp(names + ep[ret].name_offset, name))
      |                      ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
arch/sparc/kernel/mdesc.c:77:33: note: at offset 16 into source object 'mdesc' of size 16
   77 |         struct mdesc_hdr        mdesc;
      |                                 ^~~~~
arch/sparc/kernel/mdesc.c: In function 'mdesc_get_property':
arch/sparc/kernel/mdesc.c:692:22: error: 'strcmp' reading 1 or more bytes from a region of size 0 [-Werror=stringop-overread]
  692 |                 if (!strcmp(names + ep->name_offset, name)) {
      |                      ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
arch/sparc/kernel/mdesc.c:77:33: note: at offset 16 into source object 'mdesc' of size 16
   77 |         struct mdesc_hdr        mdesc;
      |                                 ^~~~~
arch/sparc/kernel/mdesc.c: In function 'mdesc_next_arc':
arch/sparc/kernel/mdesc.c:719:21: error: 'strcmp' reading 1 or more bytes from a region of size 0 [-Werror=stringop-overread]
  719 |                 if (strcmp(names + ep->name_offset, arc_type))
      |                     ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
arch/sparc/kernel/mdesc.c:77:33: note: at offset 16 into source object 'mdesc' of size 16
   77 |         struct mdesc_hdr        mdesc;
      |                                 ^~~~~
cc1: all warnings being treated as errors

The issue was initially reported to gcc [1] where it was analized.
As suggested, change the struct mdesc_elem * accesses from the end
of mdesc to those from the beginning of the data array.

Update the prototype of node_block(), name_block() and data_block()
since the code really seems to want to do is to compute the address
somewhere into the chunk pointed to by hp.

[1] https://gcc.gnu.org/bugzilla/show_bug.cgi?id=100262

Signed-off-by: Romain Naour <romain.naour@gmail.com>
---
 arch/sparc/kernel/mdesc.c | 37 +++++++++++++++++++++----------------
 1 file changed, 21 insertions(+), 16 deletions(-)
diff mbox series

Patch

diff --git a/arch/sparc/kernel/mdesc.c b/arch/sparc/kernel/mdesc.c
index 8e645ddac58e..3403555aa1e2 100644
--- a/arch/sparc/kernel/mdesc.c
+++ b/arch/sparc/kernel/mdesc.c
@@ -75,6 +75,7 @@  struct mdesc_handle {
 	refcount_t		refcnt;
 	unsigned int		handle_size;
 	struct mdesc_hdr	mdesc;
+	char			data[];
 };
 
 typedef int (*mdesc_node_info_get_f)(struct mdesc_handle *, u64,
@@ -610,26 +611,30 @@  int mdesc_get_node_info(struct mdesc_handle *hp, u64 node,
 }
 EXPORT_SYMBOL(mdesc_get_node_info);
 
-static struct mdesc_elem *node_block(struct mdesc_hdr *mdesc)
+static struct mdesc_elem *node_block(struct mdesc_handle *hp)
 {
-	return (struct mdesc_elem *) (mdesc + 1);
+	return (struct mdesc_elem *) hp + offsetof(struct mdesc_handle, data);
 }
 
-static void *name_block(struct mdesc_hdr *mdesc)
+static void *name_block(struct mdesc_handle *hp)
 {
-	return ((void *) node_block(mdesc)) + mdesc->node_sz;
+	struct mdesc_hdr *mdesc = &hp->mdesc;
+
+	return ((void *) node_block(hp)) + mdesc->node_sz;
 }
 
-static void *data_block(struct mdesc_hdr *mdesc)
+static void *data_block(struct mdesc_handle *hp)
 {
-	return ((void *) name_block(mdesc)) + mdesc->name_sz;
+	struct mdesc_hdr *mdesc = &hp->mdesc;
+
+	return ((void *) name_block(hp)) + mdesc->name_sz;
 }
 
 u64 mdesc_node_by_name(struct mdesc_handle *hp,
 		       u64 from_node, const char *name)
 {
-	struct mdesc_elem *ep = node_block(&hp->mdesc);
-	const char *names = name_block(&hp->mdesc);
+	struct mdesc_elem *ep = node_block(hp);
+	const char *names = name_block(hp);
 	u64 last_node = hp->mdesc.node_sz / 16;
 	u64 ret;
 
@@ -657,15 +662,15 @@  EXPORT_SYMBOL(mdesc_node_by_name);
 const void *mdesc_get_property(struct mdesc_handle *hp, u64 node,
 			       const char *name, int *lenp)
 {
-	const char *names = name_block(&hp->mdesc);
+	const char *names = name_block(hp);
 	u64 last_node = hp->mdesc.node_sz / 16;
-	void *data = data_block(&hp->mdesc);
+	void *data = data_block(hp);
 	struct mdesc_elem *ep;
 
 	if (node == MDESC_NODE_NULL || node >= last_node)
 		return NULL;
 
-	ep = node_block(&hp->mdesc) + node;
+	ep = node_block(hp) + node;
 	ep++;
 	for (; ep->tag != MD_NODE_END; ep++) {
 		void *val = NULL;
@@ -702,8 +707,8 @@  EXPORT_SYMBOL(mdesc_get_property);
 
 u64 mdesc_next_arc(struct mdesc_handle *hp, u64 from, const char *arc_type)
 {
-	struct mdesc_elem *ep, *base = node_block(&hp->mdesc);
-	const char *names = name_block(&hp->mdesc);
+	struct mdesc_elem *ep, *base = node_block(hp);
+	const char *names = name_block(hp);
 	u64 last_node = hp->mdesc.node_sz / 16;
 
 	if (from == MDESC_NODE_NULL || from >= last_node)
@@ -728,7 +733,7 @@  EXPORT_SYMBOL(mdesc_next_arc);
 
 u64 mdesc_arc_target(struct mdesc_handle *hp, u64 arc)
 {
-	struct mdesc_elem *ep, *base = node_block(&hp->mdesc);
+	struct mdesc_elem *ep, *base = node_block(hp);
 
 	ep = base + arc;
 
@@ -738,8 +743,8 @@  EXPORT_SYMBOL(mdesc_arc_target);
 
 const char *mdesc_node_name(struct mdesc_handle *hp, u64 node)
 {
-	struct mdesc_elem *ep, *base = node_block(&hp->mdesc);
-	const char *names = name_block(&hp->mdesc);
+	struct mdesc_elem *ep, *base = node_block(hp);
+	const char *names = name_block(hp);
 	u64 last_node = hp->mdesc.node_sz / 16;
 
 	if (node == MDESC_NODE_NULL || node >= last_node)