Re: [Rpm-maint] [PATCH] debugedit: Check .debug_str index is valid before use.

2018-03-12 Thread Panu Matilainen

On 03/12/2018 03:27 PM, Mark Wielaard wrote:

Hi Panu,

On Mon, 2018-03-12 at 14:07 +0200, Panu Matilainen wrote:

Actually, this breaks a bunch of testcases:

139: rpmbuild debuginfo subpackages multiple FAILED
(rpmbuild.at:973)
140: rpmbuild debuginfo subpackages multiple unique  FAILED
(rpmbuild.at:1058)
141: rpmbuild debuginfo subpackages multiple unique debugsource FAILED
(rpmbuild.at:1143)
142: rpmbuild debuginfo subpackages multiple excluded FAILED
(rpmbuild.at:1231)
143: rpmbuild debuginfo subpackages multiple excluded FAILED
(rpmbuild.at:1296)

They're all failing with messages like this:

/home/pmatilai/repos/rpm/tests/testing/usr/lib/rpm/debugedit:
/home/pmatilai/repos/rpm/tests/testing/build/BUILDROOT/test-1.0-1.x86_64/bin/hello2:
Bad string pointer index 678 for unit name


That is embarrassing. I was sure I got zero FAIL on the testsuite
before sending the patch. But now I see the same (on Fedora 27).

It might be because ./tests/testing/usr/lib/rpm/debugedit doesn't seem
to be regenerated by the build. So you only see it on a fully fresh
build, not on an incremental one.


Yup, the logic to update the test root contents is far from perfect...
'rm -rf tests/testing' works for forcing the issue though.



This is an interesting bug, because it was latent. We were already
accessing a bad string before, but for some reason we got away with it.

This code walks over the DIE tree in two phases. In phase zero we want
to collect the comp_dir (either from the DW_AT_comp_dir or the
DW_AT_name of the compile unit). The bug happens in phase 1, when we
don't need to collect the comp_dir. But we still do, wrongly using the
old string table... So the error is kind of correct.

Fix attached, which looks a bit funny, but really only wraps the
affected code in an if (phase == 0) block.


Ack, thanks for the explanation and the fast fix! Applied.

- Panu -



Cheers,

Mark



___
Rpm-maint mailing list
Rpm-maint@lists.rpm.org
http://lists.rpm.org/mailman/listinfo/rpm-maint


Re: [Rpm-maint] [PATCH] debugedit: Check .debug_str index is valid before use.

2018-03-12 Thread Mark Wielaard
Hi Panu,

On Mon, 2018-03-12 at 14:07 +0200, Panu Matilainen wrote:
> Actually, this breaks a bunch of testcases:
> 
> 139: rpmbuild debuginfo subpackages multiple FAILED 
> (rpmbuild.at:973)
> 140: rpmbuild debuginfo subpackages multiple unique  FAILED 
> (rpmbuild.at:1058)
> 141: rpmbuild debuginfo subpackages multiple unique debugsource FAILED 
> (rpmbuild.at:1143)
> 142: rpmbuild debuginfo subpackages multiple excluded FAILED 
> (rpmbuild.at:1231)
> 143: rpmbuild debuginfo subpackages multiple excluded FAILED 
> (rpmbuild.at:1296)
> 
> They're all failing with messages like this:
> 
> /home/pmatilai/repos/rpm/tests/testing/usr/lib/rpm/debugedit: 
> /home/pmatilai/repos/rpm/tests/testing/build/BUILDROOT/test-1.0-1.x86_64/bin/hello2:
>  
> Bad string pointer index 678 for unit name

That is embarrassing. I was sure I got zero FAIL on the testsuite
before sending the patch. But now I see the same (on Fedora 27).

It might be because ./tests/testing/usr/lib/rpm/debugedit doesn't seem
to be regenerated by the build. So you only see it on a fully fresh
build, not on an incremental one.

This is an interesting bug, because it was latent. We were already
accessing a bad string before, but for some reason we got away with it.

This code walks over the DIE tree in two phases. In phase zero we want
to collect the comp_dir (either from the DW_AT_comp_dir or the
DW_AT_name of the compile unit). The bug happens in phase 1, when we
don't need to collect the comp_dir. But we still do, wrongly using the
old string table... So the error is kind of correct.

Fix attached, which looks a bit funny, but really only wraps the
affected code in an if (phase == 0) block.

Cheers,

MarkFrom 8e6eb541067da7848b600b95c6ff8c3bad5c1f0d Mon Sep 17 00:00:00 2001
From: Mark Wielaard 
Date: Mon, 12 Mar 2018 14:16:15 +0100
Subject: [PATCH] debugedit: Only try to collect comp_dir in phase zero.

edit_attributes is run twice. Once for phase zero in which all strings are
collected. Then then for phase one in which the strings are rewritten. In
phase zero we also try to collect the comp_dir (either from the
DW_AT_comp_dir or the DW_AT_name of the compile unit). We were also
collecting the comp_dir is phase 1, which is unnecessary, and would not
actually work, since we would be using to old string table index for that,
which had already been rewritten.

Caught by the new string table index checks.

Signed-off-by: Mark Wielaard 
---
 tools/debugedit.c | 52 ++--
 1 file changed, 30 insertions(+), 22 deletions(-)

diff --git a/tools/debugedit.c b/tools/debugedit.c
index 6c71cbcbe..84568dd29 100644
--- a/tools/debugedit.c
+++ b/tools/debugedit.c
@@ -1539,14 +1539,18 @@ edit_attributes (DSO *dso, unsigned char *ptr, struct abbrev_tag *t, int phase)
 		{
 		  const char *dir;
 		  size_t idx = do_read_32_relocated (ptr);
-		  if (idx >= debug_sections[DEBUG_STR].size)
-		error (1, 0,
-			   "%s: Bad string pointer index %zd for comp_dir",
-			   dso->filename, idx);
-		  dir = (char *) debug_sections[DEBUG_STR].data + idx;
+		  /* In phase zero we collect the comp_dir.  */
+		  if (phase == 0)
+		{
+		  if (idx >= debug_sections[DEBUG_STR].size)
+			error (1, 0,
+			   "%s: Bad string pointer index %zd for comp_dir",
+			   dso->filename, idx);
+		  dir = (char *) debug_sections[DEBUG_STR].data + idx;
 
-		  free (comp_dir);
-		  comp_dir = strdup (dir);
+		  free (comp_dir);
+		  comp_dir = strdup (dir);
+		}
 
 		  if (dest_dir != NULL && phase == 0)
 		{
@@ -1566,25 +1570,29 @@ edit_attributes (DSO *dso, unsigned char *ptr, struct abbrev_tag *t, int phase)
 		 unit. If starting with / it is a full path name.
 		 Note that we don't handle DW_FORM_string in this
 		 case.  */
-	  char *name;
 	  size_t idx = do_read_32_relocated (ptr);
-	  if (idx >= debug_sections[DEBUG_STR].size)
-		error (1, 0,
-		   "%s: Bad string pointer index %zd for unit name",
-		   dso->filename, idx);
-	  name = (char *) debug_sections[DEBUG_STR].data + idx;
-	  if (*name == '/' && comp_dir == NULL)
-		{
-		  char *enddir = strrchr (name, '/');
 
-		  if (enddir != name)
+	  /* In phase zero we will look for a comp_dir to use.  */
+	  if (phase == 0)
+		{
+		  if (idx >= debug_sections[DEBUG_STR].size)
+		error (1, 0,
+			   "%s: Bad string pointer index %zd for unit name",
+			   dso->filename, idx);
+		  char *name = (char *) debug_sections[DEBUG_STR].data + idx;
+		  if (*name == '/' && comp_dir == NULL)
 		{
-		  comp_dir = malloc (enddir - name + 1);
-		  memcpy (comp_dir, name, enddir - name);
-		  comp_dir [enddir - name] = '\0';
+		  char *enddir = strrchr (name, '/');
+
+		  if (enddir != name)
+			{
+			  comp_dir = malloc (enddir - name + 1);
+			  memcpy (comp_dir, name, enddir - name);
+			  comp_dir [enddir - name] = '\0';
+			}
+		  else
+			comp_dir = strdup ("/");
 		}
-		  else
-		com

Re: [Rpm-maint] [PATCH] debugedit: Check .debug_str index is valid before use.

2018-03-12 Thread Panu Matilainen

On 03/09/2018 04:24 PM, Panu Matilainen wrote:

On 03/07/2018 05:25 PM, Mark Wielaard wrote:

debugedit would blindly use an .debug_str index from the .debug_info or
.debug_line sections assuming it would result in a valid string. Which
would crash and burn if the DWARF data was bogus when the string was
used. So check whenever converting an string index into a char pointer
so we can produce a more helpful error message.

https://bugzilla.redhat.com/show_bug.cgi?id=1543912

Signed-off-by: Mark Wielaard 
---
  tools/debugedit.c | 14 ++
  1 file changed, 14 insertions(+)

diff --git a/tools/debugedit.c b/tools/debugedit.c
index 57cd830..6c71cbc 100644
--- a/tools/debugedit.c
+++ b/tools/debugedit.c
@@ -820,6 +820,9 @@ record_file_string_entry_idx (struct strings 
*strings, size_t old_idx)

    struct stridxentry *entry = string_find_new_entry (strings, old_idx);
    if (entry != NULL)
  {
+  if (old_idx >= debug_sections[DEBUG_STR].size)
+    error (1, 0, "Bad string pointer index %zd", old_idx);
+
    Strent *strent;
    const char *old_str = (char *)debug_sections[DEBUG_STR].data + 
old_idx;

    const char *file = skip_dir_prefix (old_str, base_dir);
@@ -870,6 +873,9 @@ record_existing_string_entry_idx (struct strings 
*strings, size_t old_idx)

    struct stridxentry *entry = string_find_new_entry (strings, old_idx);
    if (entry != NULL)
  {
+  if (old_idx >= debug_sections[DEBUG_STR].size)
+    error (1, 0, "Bad string pointer index %zd", old_idx);
+
    const char *str = (char *)debug_sections[DEBUG_STR].data + 
old_idx;

    Strent *strent = strtab_add_len (strings->str_tab,
 str, strlen (str) + 1);
@@ -1533,6 +1539,10 @@ edit_attributes (DSO *dso, unsigned char *ptr, 
struct abbrev_tag *t, int phase)

  {
    const char *dir;
    size_t idx = do_read_32_relocated (ptr);
+  if (idx >= debug_sections[DEBUG_STR].size)
+    error (1, 0,
+   "%s: Bad string pointer index %zd for comp_dir",
+   dso->filename, idx);
    dir = (char *) debug_sections[DEBUG_STR].data + idx;
    free (comp_dir);
@@ -1558,6 +1568,10 @@ edit_attributes (DSO *dso, unsigned char *ptr, 
struct abbrev_tag *t, int phase)

   case.  */
    char *name;
    size_t idx = do_read_32_relocated (ptr);
+  if (idx >= debug_sections[DEBUG_STR].size)
+    error (1, 0,
+   "%s: Bad string pointer index %zd for unit name",
+   dso->filename, idx);
    name = (char *) debug_sections[DEBUG_STR].data + idx;
    if (*name == '/' && comp_dir == NULL)
  {



I was somewhat tempted to mumble something about putting these 
common-looking checks into a function but ... meh, it's Friday :P


Applied, thanks for the patch!


Actually, this breaks a bunch of testcases:

139: rpmbuild debuginfo subpackages multiple FAILED 
(rpmbuild.at:973)
140: rpmbuild debuginfo subpackages multiple unique  FAILED 
(rpmbuild.at:1058)
141: rpmbuild debuginfo subpackages multiple unique debugsource FAILED 
(rpmbuild.at:1143)
142: rpmbuild debuginfo subpackages multiple excluded FAILED 
(rpmbuild.at:1231)
143: rpmbuild debuginfo subpackages multiple excluded FAILED 
(rpmbuild.at:1296)


They're all failing with messages like this:

/home/pmatilai/repos/rpm/tests/testing/usr/lib/rpm/debugedit: 
/home/pmatilai/repos/rpm/tests/testing/build/BUILDROOT/test-1.0-1.x86_64/bin/hello2: 
Bad string pointer index 678 for unit name


- Panu -

___
Rpm-maint mailing list
Rpm-maint@lists.rpm.org
http://lists.rpm.org/mailman/listinfo/rpm-maint


Re: [Rpm-maint] [PATCH] debugedit: Check .debug_str index is valid before use.

2018-03-09 Thread Panu Matilainen

On 03/07/2018 05:25 PM, Mark Wielaard wrote:

debugedit would blindly use an .debug_str index from the .debug_info or
.debug_line sections assuming it would result in a valid string. Which
would crash and burn if the DWARF data was bogus when the string was
used. So check whenever converting an string index into a char pointer
so we can produce a more helpful error message.

https://bugzilla.redhat.com/show_bug.cgi?id=1543912

Signed-off-by: Mark Wielaard 
---
  tools/debugedit.c | 14 ++
  1 file changed, 14 insertions(+)

diff --git a/tools/debugedit.c b/tools/debugedit.c
index 57cd830..6c71cbc 100644
--- a/tools/debugedit.c
+++ b/tools/debugedit.c
@@ -820,6 +820,9 @@ record_file_string_entry_idx (struct strings *strings, 
size_t old_idx)
struct stridxentry *entry = string_find_new_entry (strings, old_idx);
if (entry != NULL)
  {
+  if (old_idx >= debug_sections[DEBUG_STR].size)
+   error (1, 0, "Bad string pointer index %zd", old_idx);
+
Strent *strent;
const char *old_str = (char *)debug_sections[DEBUG_STR].data + old_idx;
const char *file = skip_dir_prefix (old_str, base_dir);
@@ -870,6 +873,9 @@ record_existing_string_entry_idx (struct strings *strings, 
size_t old_idx)
struct stridxentry *entry = string_find_new_entry (strings, old_idx);
if (entry != NULL)
  {
+  if (old_idx >= debug_sections[DEBUG_STR].size)
+   error (1, 0, "Bad string pointer index %zd", old_idx);
+
const char *str = (char *)debug_sections[DEBUG_STR].data + old_idx;
Strent *strent = strtab_add_len (strings->str_tab,
   str, strlen (str) + 1);
@@ -1533,6 +1539,10 @@ edit_attributes (DSO *dso, unsigned char *ptr, struct 
abbrev_tag *t, int phase)
{
  const char *dir;
  size_t idx = do_read_32_relocated (ptr);
+ if (idx >= debug_sections[DEBUG_STR].size)
+   error (1, 0,
+  "%s: Bad string pointer index %zd for comp_dir",
+  dso->filename, idx);
  dir = (char *) debug_sections[DEBUG_STR].data + idx;
  
  		  free (comp_dir);

@@ -1558,6 +1568,10 @@ edit_attributes (DSO *dso, unsigned char *ptr, struct 
abbrev_tag *t, int phase)
 case.  */
  char *name;
  size_t idx = do_read_32_relocated (ptr);
+ if (idx >= debug_sections[DEBUG_STR].size)
+   error (1, 0,
+  "%s: Bad string pointer index %zd for unit name",
+  dso->filename, idx);
  name = (char *) debug_sections[DEBUG_STR].data + idx;
  if (*name == '/' && comp_dir == NULL)
{



I was somewhat tempted to mumble something about putting these 
common-looking checks into a function but ... meh, it's Friday :P


Applied, thanks for the patch!

- Panu -
___
Rpm-maint mailing list
Rpm-maint@lists.rpm.org
http://lists.rpm.org/mailman/listinfo/rpm-maint