[PATCH] debugedit: Don't use alloca and sanity check line table dir/file counts

Mark Wielaard mark@klomp.org
Tue Sep 1 17:18:37 GMT 2026


read_dwarf4_line would use alloca to store the (temporary) directory
table, which could overflow the stack. Use malloc instead. Also sanity
check the directory/file count (in both read_dwarf4_line, where value
is always at least one and read_dwarf5_line, where zero is a valid
value).

	* tools/debugedit.c (read_dwarf4_line): Initialize dirt to
	NULL, make value and dirt_cnt an uint64_t, sanitize value
	and malloc result, fee on return.
	(read_dwarf5_line_entries): Make entry_count a size_t, check
	entry_count is not zero, sanitize entry_count.

Signed-off-by: Mark Wielaard <mark@klomp.org>
---
 tools/debugedit.c | 37 ++++++++++++++++++++++++++++---------
 1 file changed, 28 insertions(+), 9 deletions(-)

diff --git a/tools/debugedit.c b/tools/debugedit.c
index 4d7e2b66da76..502fa2126e77 100644
--- a/tools/debugedit.c
+++ b/tools/debugedit.c
@@ -1990,8 +1990,8 @@ static bool
 read_dwarf4_line (DSO *dso, unsigned char *ptr, char *comp_dir,
 		  struct line_table *table)
 {
-  unsigned char **dirt;
-  uint32_t value, dirt_cnt;
+  unsigned char **dirt = NULL;
+  uint64_t value, dirt_cnt;
   size_t comp_dir_len = !comp_dir ? 0 : strlen (comp_dir);
   unsigned char *dir = ptr;
 
@@ -2020,7 +2020,15 @@ read_dwarf4_line (DSO *dso, unsigned char *ptr, char *comp_dir,
       ++value;
     }
 
-  dirt = (unsigned char **) alloca (value * sizeof (unsigned char *));
+  if (value > SIZE_MAX / sizeof (unsigned char *))
+    error (1, 0, "%s: Too many dirs in debug_line", dso->filename);
+  dirt = (unsigned char **) malloc (value * sizeof (unsigned char *));
+  if (dirt == NULL)
+    {
+      error (0, errno, "%s: Could not allocate debug_line dirs",
+	     dso->filename);
+      return false;
+    }
   dirt[0] = (unsigned char *) ".";
   dirt_cnt = 1;
   ptr = dir;
@@ -2043,8 +2051,9 @@ read_dwarf4_line (DSO *dso, unsigned char *ptr, char *comp_dir,
 
       if (value >= dirt_cnt)
 	{
-	  error (0, 0, "%s: Wrong directory table index %u",
+	  error (0, 0, "%s: Wrong directory table index %" PRIu64,
 		 dso->filename, value);
+	  free (dirt);
 	  return false;
 	}
       file_len = strlen (file);
@@ -2068,6 +2077,7 @@ read_dwarf4_line (DSO *dso, unsigned char *ptr, char *comp_dir,
       if (s == NULL)
 	{
 	  error (0, ENOMEM, "%s: Reading file table", dso->filename);
+	  free (dirt);
 	  return false;
 	}
       if (*file == '/')
@@ -2126,6 +2136,7 @@ read_dwarf4_line (DSO *dso, unsigned char *ptr, char *comp_dir,
       read_uleb128 (ptr);
     }
 
+  free (dirt);
   return true;
 }
 
@@ -2153,17 +2164,25 @@ read_dwarf5_line_entries (DSO *dso, unsigned char **ptrp,
 
   /* directories_count */
   /* file_names_count */
-  unsigned entry_count = read_uleb128 (*ptrp);
+  size_t entry_count = read_uleb128 (*ptrp);
 
   bool collecting_dirs = phase == 0 && *dirs == NULL;
   bool writing_files = phase == 0 && *dirs != NULL;
   if (collecting_dirs)
     {
       *ndir = entry_count;
-      *dirs = malloc (entry_count * sizeof (char *));
-      if (*dirs == NULL)
-	error (1, errno, "%s: Could not allocate debug_line dirs",
-	       dso->filename);
+      if (entry_count > 0)
+	{
+	  if (entry_count > SIZE_MAX / sizeof (char *))
+	    error (1, 0, "%s: Too many dirs/names in debug_line",
+		   dso->filename);
+	  *dirs = malloc (entry_count * sizeof (char *));
+	  if (*dirs == NULL)
+	    error (1, errno, "%s: Could not allocate debug_line dirs",
+		   dso->filename);
+	}
+      else
+	*dirs = NULL;
     }
 
   /* directories */
-- 
2.55.0



More information about the Debugedit mailing list