From: Alan Modra Date: Sat, 15 May 2021 05:36:28 +0000 (+0930) Subject: get_line_filename_and_dirname X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=46d1214d887cdd2979fec2344cda1720abbbd33f;p=binutils-gdb.git 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. --- diff --git a/binutils/ChangeLog b/binutils/ChangeLog index b4f1af1957b..ecf389af9fd 100644 --- a/binutils/ChangeLog +++ b/binutils/ChangeLog @@ -1,3 +1,9 @@ +2021-05-15 Alan Modra + + * 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 * dwarf.c (display_debug_macinfo): Print strings that might not diff --git a/binutils/dwarf.c b/binutils/dwarf.c index d184e5289ed..9d782912208 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;