aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlan Modra <amodra@gmail.com>2021-05-15 15:06:28 +0930
committerAlan Modra <amodra@gmail.com>2021-05-15 15:09:01 +0930
commit46d1214d887cdd2979fec2344cda1720abbbd33f (patch)
tree21481cb28334fad48ebabe585cbcb2eca50417c2
parentc03df92247333e5bf65bc663fab80fe7a87c0370 (diff)
downloadgdb-46d1214d887cdd2979fec2344cda1720abbbd33f.zip
gdb-46d1214d887cdd2979fec2344cda1720abbbd33f.tar.gz
gdb-46d1214d887cdd2979fec2344cda1720abbbd33f.tar.bz2
get_line_filename_and_dirname
* dwarf.c (get_line_filename_and_dirname): Delete initial_length_size. Simplify length sanity check, and check for too small lengths. Constrain data reads to header length. Avoid pointer UB.
-rw-r--r--binutils/ChangeLog6
-rw-r--r--binutils/dwarf.c37
2 files changed, 28 insertions, 15 deletions
diff --git a/binutils/ChangeLog b/binutils/ChangeLog
index b4f1af1..ecf389a 100644
--- a/binutils/ChangeLog
+++ b/binutils/ChangeLog
@@ -1,5 +1,11 @@
2021-05-15 Alan Modra <amodra@gmail.com>
+ * dwarf.c (get_line_filename_and_dirname): Delete initial_length_size.
+ Simplify length sanity check, and check for too small lengths.
+ Constrain data reads to header length. Avoid pointer UB.
+
+2021-05-15 Alan Modra <amodra@gmail.com>
+
* dwarf.c (display_debug_macinfo): Print strings that might not
be zero terminated with %*s. Don't bump curr if unterminated.
diff --git a/binutils/dwarf.c b/binutils/dwarf.c
index d184e52..9d78291 100644
--- a/binutils/dwarf.c
+++ b/binutils/dwarf.c
@@ -5827,7 +5827,7 @@ get_line_filename_and_dirname (dwarf_vma line_offset,
{
struct dwarf_section *section = &debug_displays [line].section;
unsigned char *hdrptr, *dirtable, *file_name;
- unsigned int offset_size, initial_length_size;
+ unsigned int offset_size;
unsigned int version, opcode_base;
dwarf_vma length, diridx;
const unsigned char * end;
@@ -5847,16 +5847,14 @@ get_line_filename_and_dirname (dwarf_vma line_offset,
/* This section is 64-bit DWARF 3. */
SAFE_BYTE_GET_AND_INC (length, hdrptr, 8, end);
offset_size = 8;
- initial_length_size = 12;
}
else
- {
- offset_size = 4;
- initial_length_size = 4;
- }
- if (length + initial_length_size < length
- || length + initial_length_size > section->size)
+ offset_size = 4;
+
+ if (length > (size_t) (end - hdrptr)
+ || length < 2 + offset_size + 1 + 3 + 1)
return NULL;
+ end = hdrptr + length;
SAFE_BYTE_GET_AND_INC (version, hdrptr, 2, end);
if (version != 2 && version != 3 && version != 4)
@@ -5867,18 +5865,19 @@ get_line_filename_and_dirname (dwarf_vma line_offset,
hdrptr += 3; /* Skip default_is_stmt, line_base, line_range. */
SAFE_BYTE_GET_AND_INC (opcode_base, hdrptr, 1, end);
- if (opcode_base == 0)
+ if (opcode_base == 0
+ || opcode_base - 1 >= (size_t) (end - hdrptr))
return NULL;
hdrptr += opcode_base - 1;
- if (hdrptr >= end)
- return NULL;
dirtable = hdrptr;
/* Skip over dirname table. */
while (*hdrptr != '\0')
{
- hdrptr += strnlen ((char *) hdrptr, end - hdrptr) + 1;
+ hdrptr += strnlen ((char *) hdrptr, end - hdrptr);
+ if (hdrptr < end)
+ hdrptr++;
if (hdrptr >= end)
return NULL;
}
@@ -5887,7 +5886,9 @@ get_line_filename_and_dirname (dwarf_vma line_offset,
/* Now skip over preceding filename table entries. */
for (; hdrptr < end && *hdrptr != '\0' && fileidx > 1; fileidx--)
{
- hdrptr += strnlen ((char *) hdrptr, end - hdrptr) + 1;
+ hdrptr += strnlen ((char *) hdrptr, end - hdrptr);
+ if (hdrptr < end)
+ hdrptr++;
SKIP_ULEB (hdrptr, end);
SKIP_ULEB (hdrptr, end);
SKIP_ULEB (hdrptr, end);
@@ -5896,14 +5897,20 @@ get_line_filename_and_dirname (dwarf_vma line_offset,
return NULL;
file_name = hdrptr;
- hdrptr += strnlen ((char *) hdrptr, end - hdrptr) + 1;
+ hdrptr += strnlen ((char *) hdrptr, end - hdrptr);
+ if (hdrptr < end)
+ hdrptr++;
if (hdrptr >= end)
return NULL;
READ_ULEB (diridx, hdrptr, end);
if (diridx == 0)
return file_name;
for (; dirtable < end && *dirtable != '\0' && diridx > 1; diridx--)
- dirtable += strnlen ((char *) dirtable, end - dirtable) + 1;
+ {
+ dirtable += strnlen ((char *) dirtable, end - dirtable);
+ if (dirtable < end)
+ dirtable++;
+ }
if (dirtable >= end || *dirtable == '\0')
return NULL;
*dir_name = dirtable;