summaryrefslogtreecommitdiffstats
path: root/meta/recipes-devtools/binutils/binutils/CVE-2020-16593.patch
blob: c7c7829261eb03c38bc9969dc9e308a4d82084d3 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
From aec72fda3b320c36eb99fc1c4cf95b10fc026729 Mon Sep 17 00:00:00 2001
From: Alan Modra <amodra@gmail.com>
Date: Thu, 16 Apr 2020 17:49:38 +0930
Subject: [PATCH] PR25827, Null pointer dereferencing in scan_unit_for_symbols

    PR 25827
    * dwarf2.c (scan_unit_for_symbols): Wrap overlong lines.  Don't
    strdup(0).

Upstream-Status: Backport
https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=aec72fda3b320c36eb99fc1c4cf95b10fc026729
CVE: CVE-2020-16593 
Signed-off-by: Armin Kuster <akuster@mvista.com>


Index: git/bfd/dwarf2.c
===================================================================
--- git.orig/bfd/dwarf2.c
+++ git/bfd/dwarf2.c
@@ -295,12 +295,12 @@ struct comp_unit
 /* This data structure holds the information of an abbrev.  */
 struct abbrev_info
 {
-  unsigned int number;		/* Number identifying abbrev.  */
-  enum dwarf_tag tag;		/* DWARF tag.  */
-  int has_children;		/* Boolean.  */
-  unsigned int num_attrs;	/* Number of attributes.  */
-  struct attr_abbrev *attrs;	/* An array of attribute descriptions.  */
-  struct abbrev_info *next;	/* Next in chain.  */
+  unsigned int         number;     /* Number identifying abbrev.  */
+  enum dwarf_tag       tag;        /* DWARF tag.  */
+  bfd_boolean          has_children;   /* TRUE if the abbrev has children.  */
+  unsigned int         num_attrs;  /* Number of attributes.  */
+  struct attr_abbrev * attrs;      /* An array of attribute descriptions.  */
+  struct abbrev_info * next;       /* Next in chain.  */
 };
 
 struct attr_abbrev
@@ -1487,6 +1487,8 @@ struct varinfo
 {
   /* Pointer to previous variable in list of all variables */
   struct varinfo *prev_var;
+  /* The offset of the varinfo from the start of the unit.  */
+  bfd_uint64_t unit_offset;
   /* Source location file name */
   char *file;
   /* Source location line number */
@@ -1497,7 +1499,7 @@ struct varinfo
   /* Where the symbol is defined */
   asection *sec;
   /* Is this a stack variable? */
-  unsigned int stack: 1;
+  bfd_boolean stack;
 };
 
 /* Return TRUE if NEW_LINE should sort after LINE.  */
@@ -2871,7 +2873,7 @@ lookup_symbol_in_variable_table (struct
   struct varinfo* each;
 
   for (each = unit->variable_table; each; each = each->prev_var)
-    if (each->stack == 0
+    if (! each->stack
 	&& each->file != NULL
 	&& each->name != NULL
 	&& each->addr == addr
@@ -3166,6 +3168,20 @@ read_rangelist (struct comp_unit *unit,
   return TRUE;
 }
 
+static struct varinfo *
+lookup_var_by_offset (bfd_uint64_t offset, struct varinfo * table)
+{
+  while (table)
+    {
+      if (table->unit_offset == offset)
+   return table;
+      table = table->prev_var;
+    }
+
+  return NULL;
+}
+
+
 /* DWARF2 Compilation unit functions.  */
 
 /* Scan over each die in a comp. unit looking for functions to add
@@ -3202,6 +3218,9 @@ scan_unit_for_symbols (struct comp_unit
       bfd_vma low_pc = 0;
       bfd_vma high_pc = 0;
       bfd_boolean high_pc_relative = FALSE;
+      bfd_uint64_t current_offset;
+       
+      current_offset = info_ptr - unit->info_ptr_unit;
 
       /* PR 17512: file: 9f405d9d.  */
       if (info_ptr >= info_ptr_end)
@@ -3234,12 +3253,13 @@ scan_unit_for_symbols (struct comp_unit
 	  goto fail;
 	}
 
-      var = NULL;
       if (abbrev->tag == DW_TAG_subprogram
 	  || abbrev->tag == DW_TAG_entry_point
 	  || abbrev->tag == DW_TAG_inlined_subroutine)
 	{
 	  bfd_size_type amt = sizeof (struct funcinfo);
+
+      var = NULL;
 	  func = (struct funcinfo *) bfd_zalloc (abfd, amt);
 	  if (func == NULL)
 	    goto fail;
@@ -3268,13 +3288,15 @@ scan_unit_for_symbols (struct comp_unit
 	      if (var == NULL)
 		goto fail;
 	      var->tag = abbrev->tag;
-	      var->stack = 1;
+	      var->stack = TRUE;
 	      var->prev_var = unit->variable_table;
 	      unit->variable_table = var;
+          var->unit_offset = current_offset;
 	      /* PR 18205: Missing debug information can cause this
 		 var to be attached to an already cached unit.  */
 	    }
-
+	  else
+	    var = NULL;
 	  /* No inline function in scope at this nesting level.  */
 	  nested_funcs[nesting_level].func = 0;
 	}
@@ -3362,6 +3384,33 @@ scan_unit_for_symbols (struct comp_unit
 	    {
 	      switch (attr.name)
 		{
+       case DW_AT_specification:
+         if (attr.u.val)
+           {
+             struct varinfo * spec_var;
+
+             spec_var = lookup_var_by_offset (attr.u.val,
+                              unit->variable_table);
+             if (spec_var == NULL)
+           {
+             _bfd_error_handler (_("DWARF error: could not find "
+                       "variable specification "
+                       "at offset %lx"),
+                         (unsigned long) attr.u.val);
+             break;
+           }
+
+             if (var->name == NULL)
+           var->name = spec_var->name;
+             if (var->file == NULL && spec_var->file != NULL)
+           var->file = strdup (spec_var->file);
+             if (var->line == 0)
+           var->line = spec_var->line;
+             if (var->sec == NULL)
+           var->sec = spec_var->sec;
+           }
+         break;
+
 		case DW_AT_name:
 		  if (is_str_attr (attr.form))
 		    var->name = attr.u.str;
@@ -3378,7 +3427,7 @@ scan_unit_for_symbols (struct comp_unit
 
 		case DW_AT_external:
 		  if (attr.u.val != 0)
-		    var->stack = 0;
+		    var->stack = FALSE;
 		  break;
 
 		case DW_AT_location:
@@ -3392,7 +3441,7 @@ scan_unit_for_symbols (struct comp_unit
 		      if (attr.u.blk->data != NULL
 			  && *attr.u.blk->data == DW_OP_addr)
 			{
-			  var->stack = 0;
+			  var->stack = FALSE;
 
 			  /* Verify that DW_OP_addr is the only opcode in the
 			     location, in which case the block size will be 1
@@ -3888,7 +3937,7 @@ comp_unit_hash_info (struct dwarf2_debug
        each_var = each_var->prev_var)
     {
       /* Skip stack vars and vars with no files or names.  */
-      if (each_var->stack == 0
+      if (! each_var->stack
 	  && each_var->file != NULL
 	  && each_var->name != NULL)
 	/* There is no need to copy name string into hash table as
Index: git/bfd/ChangeLog
===================================================================
--- git.orig/bfd/ChangeLog
+++ git/bfd/ChangeLog
@@ -1,3 +1,9 @@
+2020-04-16  Alan Modra  <amodra@gmail.com>
+
+       PR 25827
+       * dwarf2.c (scan_unit_for_symbols): Wrap overlong lines.  Don't
+       strdup(0).
+
 2021-05-03  Alan Modra  <amodra@gmail.com>
 
 	PR 27755