Subject: Fix path canonicalization issues in debugedit This patch fixes multiple problems with path canonicalization in debugedit. This version of debugedit is taken from the dwarftools repository. --- tools/debugedit.c | 168 ++++++++++++++++++++++++++---------------------------- 1 file changed, 82 insertions(+), 86 deletions(-) Index: tools/debugedit.c =================================================================== --- tools/debugedit.c.orig +++ tools/debugedit.c @@ -157,7 +157,7 @@ strptr (DSO *dso, int sec, off_t offset) { if (data->d_buf && offset >= data->d_off - && offset < data->d_off + data->d_size) + && offset < data->d_off + (off_t)data->d_size) return (const char *) data->d_buf + (offset - data->d_off); } } @@ -471,13 +471,13 @@ has_prefix (const char *str, { int str_len; int prefix_len; - + str_len = strlen (str); prefix_len = strlen (prefix); if (str_len < prefix_len) return 0; - + return strncmp (str, prefix, prefix_len) == 0; } @@ -485,9 +485,10 @@ static int edit_dwarf2_line (DSO *dso, uint_32 off, char *comp_dir, int phase) { unsigned char *ptr = debug_sections[DEBUG_LINE].data, *dir; - unsigned char **dirt; + char **dirt; unsigned char *endsec = ptr + debug_sections[DEBUG_LINE].size; unsigned char *endcu, *endprol; + char line_base; unsigned char opcode_base; uint_32 value, dirt_cnt; size_t comp_dir_len = strlen (comp_dir); @@ -496,9 +497,9 @@ edit_dwarf2_line (DSO *dso, uint_32 off, if (phase != 0) return 0; - + ptr += off; - + endcu = ptr + 4; endcu += read_32 (ptr); if (endcu == ptr + 0xffffffff) @@ -521,7 +522,7 @@ edit_dwarf2_line (DSO *dso, uint_32 off, value); return 1; } - + endprol = ptr + 4; endprol += read_32 (ptr); if (endprol > endcu) @@ -530,26 +531,27 @@ edit_dwarf2_line (DSO *dso, uint_32 off, dso->filename); return 1; } - + + line_base = (char) (ptr[2] & 0xff); opcode_base = ptr[4]; ptr = dir = ptr + 4 + opcode_base; - + /* dir table: */ value = 1; while (*ptr != 0) { - ptr = strchr (ptr, 0) + 1; + ptr = (unsigned char *)strchr ((char *)ptr, 0) + 1; ++value; } - dirt = (unsigned char **) alloca (value * sizeof (unsigned char *)); + dirt = (char **) alloca (value * sizeof (char *)); dirt[0] = "."; dirt_cnt = 1; ptr = dir; while (*ptr != 0) { - dirt[dirt_cnt++] = ptr; - ptr = strchr (ptr, 0) + 1; + dirt[dirt_cnt++] = (char *)ptr; + ptr = (unsigned char *)strchr ((char *)ptr, 0) + 1; } ptr++; @@ -559,8 +561,8 @@ edit_dwarf2_line (DSO *dso, uint_32 off, char *s, *file; size_t file_len, dir_len; - file = ptr; - ptr = strchr (ptr, 0) + 1; + file = (char *)ptr; + ptr = (unsigned char *)strchr ((char *)ptr, 0) + 1; value = read_uleb128 (ptr); if (value >= dirt_cnt) @@ -629,7 +631,7 @@ edit_dwarf2_line (DSO *dso, uint_32 off, } free (s); - + read_uleb128 (ptr); read_uleb128 (ptr); } @@ -661,7 +663,7 @@ edit_dwarf2_line (DSO *dso, uint_32 off, if (dest_dir) { - unsigned char *srcptr, *buf = NULL; + char *srcptr, *srcstart, *buf = NULL; size_t base_len = strlen (base_dir); size_t dest_len = strlen (dest_dir); size_t shrank = 0; @@ -675,12 +677,16 @@ edit_dwarf2_line (DSO *dso, uint_32 off, ptr = dir; } else - ptr = srcptr = dir; - unsigned char *srcstart=srcptr; + { + ptr = dir; + srcptr = (char *)dir; + } + + srcstart = srcptr; while (*srcptr != 0) { - size_t len = strlen (srcptr) + 1; - const unsigned char *readptr = srcptr; + size_t len = strlen (srcptr); + const char *readptr = srcptr; if (*srcptr == '/' && has_prefix (srcptr, base_dir)) { @@ -689,39 +695,28 @@ edit_dwarf2_line (DSO *dso, uint_32 off, memcpy (ptr, dest_dir, dest_len); ptr += dest_len; readptr += base_len; - } + } srcptr += len; shrank += srcptr - readptr; - canonicalize_path (readptr, ptr); - len = strlen (ptr) + 1; + canonicalize_path (readptr, (char *)ptr); + len = strlen ((char *)ptr); + +#ifdef DEBUG + if ((srcptr - readptr) > len) + error(0, 0,"canonicalization unexpectedly shrank (%lu): \"%s\"\n", + (long unsigned int)(srcptr - readptr) - len, ptr); +#endif + shrank -= len; ptr += len; - elf_flagdata (debug_sections[DEBUG_STR].elf_data, - ELF_C_SET, ELF_F_DIRTY); - } - - if (shrank > 0) - { - if (--shrank == 0) - error (EXIT_FAILURE, 0, - "canonicalization unexpectedly shrank by one character"); - memset (ptr, 'X', shrank); - ptr += shrank; - *ptr++ = '\0'; + elf_flagdata (debug_sections[DEBUG_STR].elf_data, + ELF_C_SET, ELF_F_DIRTY); + ++ptr; + ++srcptr; } - if (abs_dir_cnt + abs_file_cnt != 0) - { - size_t len = (abs_dir_cnt + abs_file_cnt) * (base_len - dest_len); - - if (len == 1) - error (EXIT_FAILURE, 0, "-b arg has to be either the same length as -d arg, or more than 1 char shorter"); - memset (ptr, 'X', len - 1); - ptr += len - 1; - *ptr++ = '\0'; - } *ptr++ = '\0'; ++srcptr; @@ -741,21 +736,26 @@ edit_dwarf2_line (DSO *dso, uint_32 off, elf_flagdata (debug_sections[DEBUG_STR].elf_data, ELF_C_SET, ELF_F_DIRTY); } - else if (ptr != srcptr) + else if ((char *)ptr != srcptr) memmove (ptr, srcptr, len); srcptr += len; ptr += len; - dir = srcptr; + dir = (unsigned char *)srcptr; read_uleb128 (srcptr); read_uleb128 (srcptr); read_uleb128 (srcptr); if (ptr != dir) - memmove (ptr, dir, srcptr - dir); - ptr += srcptr - dir; + memmove (ptr, dir, (unsigned char *)srcptr - dir); + ptr += (unsigned char *)srcptr - dir; } *ptr = '\0'; free (buf); } + + ptr++; + /* fill the rest until the line number program starts with NOP opcode */ + memset(ptr, opcode_base - line_base, endprol - ptr); + /* don't touch the line number program */ return 0; } @@ -767,17 +767,13 @@ edit_attributes (DSO *dso, unsigned char int i; uint_32 list_offs; int found_list_offs; - unsigned char *comp_dir; - - comp_dir = NULL; - list_offs = 0; - found_list_offs = 0; + char *comp_dir = NULL; + for (i = 0; i < t->nattr; ++i) { uint_32 form = t->attr[i].form; uint_32 len = 0; int base_len, dest_len; - while (1) { @@ -791,56 +787,55 @@ edit_attributes (DSO *dso, unsigned char } if (t->attr[i].attr == DW_AT_comp_dir) - { + { if ( form == DW_FORM_string ) - { + { free (comp_dir); - comp_dir = strdup (ptr); - - if (phase == 1 && dest_dir && has_prefix (ptr, base_dir)) - { + comp_dir = strdup ((char *)ptr); + + if (phase == 1 && dest_dir + && has_prefix ((char *)ptr, base_dir)) + { base_len = strlen (base_dir); dest_len = strlen (dest_dir); - + memcpy (ptr, dest_dir, dest_len); if (dest_len < base_len) - { + { memset(ptr + dest_len, '/', base_len - dest_len); - - } + } elf_flagdata (debug_sections[DEBUG_INFO].elf_data, ELF_C_SET, ELF_F_DIRTY); - } - } - + } + } else if (form == DW_FORM_strp && debug_sections[DEBUG_STR].data) - { + { char *dir; - dir = debug_sections[DEBUG_STR].data - + do_read_32_relocated (ptr); + dir = (char *)debug_sections[DEBUG_STR].data + + do_read_32_relocated (ptr); free (comp_dir); comp_dir = strdup (dir); if (phase == 1 && dest_dir && has_prefix (dir, base_dir)) - { + { base_len = strlen (base_dir); dest_len = strlen (dest_dir); - + memcpy (dir, dest_dir, dest_len); if (dest_len < base_len) - { + { memmove (dir + dest_len, dir + base_len, strlen (dir + base_len) + 1); - } + } elf_flagdata (debug_sections[DEBUG_STR].elf_data, ELF_C_SET, ELF_F_DIRTY); - } - } - } + } + } + } else if ((t->tag == DW_TAG_compile_unit || t->tag == DW_TAG_partial_unit) && t->attr[i].attr == DW_AT_name @@ -848,9 +843,9 @@ edit_attributes (DSO *dso, unsigned char && debug_sections[DEBUG_STR].data) { char *name; - - name = debug_sections[DEBUG_STR].data - + do_read_32_relocated (ptr); + + name = (char *)debug_sections[DEBUG_STR].data + + do_read_32_relocated (ptr); if (*name == '/' && comp_dir == NULL) { char *enddir = strrchr (name, '/'); @@ -869,7 +864,7 @@ edit_attributes (DSO *dso, unsigned char { base_len = strlen (base_dir); dest_len = strlen (dest_dir); - + memcpy (name, dest_dir, dest_len); if (dest_len < base_len) { @@ -913,7 +908,7 @@ edit_attributes (DSO *dso, unsigned char ptr += 4; break; case DW_FORM_string: - ptr = strchr (ptr, '\0') + 1; + ptr = (unsigned char *)strchr ((char *)ptr, '\0') + 1; break; case DW_FORM_indirect: form = read_uleb128 (ptr); @@ -1470,10 +1465,11 @@ handle_build_id (DSO *dso, Elf_Data *bui const unsigned char * id = build_id->d_buf + build_id_offset; char hex[build_id_size * 2 + 1]; int n = snprintf (hex, 3, "%02" PRIx8, id[0]); + size_t size; assert (n == 2); - for (i = 1; i < build_id_size; ++i) + for (size = 1; size < build_id_size; ++size) { - n = snprintf (&hex[i * 2], 3, "%02" PRIx8, id[i]); + n = snprintf (&hex[size * 2], 3, "%02" PRIx8, id[size]); assert (n == 2); } puts (hex);