dwarf_next_cfi and intern_new_cie used slightly different methods
parsing the CIE augmentation data. Make sure both only read
augmentation data when it is there.

        * libdw/cie.c (intern_new_cie): Check 'z' is the first char of
        the augmentation. Only read augmentation data if
        cie->sized_augmentation_data is set.
        * libdw/dwarf_next_cfi.c (dwarf_next_cfi): Check limit for 'R'.

https://sourceware.org/bugzilla/show_bug.cgi?id=34387

Reported-by: Karan Kurani <[email protected]>
Signed-off-by: Mark Wielaard <[email protected]>
---
 libdw/cie.c            | 28 ++++++++++++++++++----------
 libdw/dwarf_next_cfi.c |  2 ++
 2 files changed, 20 insertions(+), 10 deletions(-)

diff --git a/libdw/cie.c b/libdw/cie.c
index 9753d9b97027..052a704ec2d8 100644
--- a/libdw/cie.c
+++ b/libdw/cie.c
@@ -74,21 +74,25 @@ intern_new_cie (Dwarf_CFI *cache, Dwarf_Off offset, const 
Dwarf_CIE *info)
 
   /* Grok the augmentation string and its data.  */
   const uint8_t *data = info->augmentation_data;
-  for (const char *ap = info->augmentation; *ap != '\0'; ++ap)
+  const char *ap = info->augmentation;
+  /* If present, 'z' must be the first char.  */
+  if (*ap == 'z')
+    {
+      cie->sized_augmentation_data = true;
+      ap++;
+    }
+  for (; *ap != '\0'; ++ap)
     {
       uint8_t encoding;
       switch (*ap)
        {
-       case 'z':
-         cie->sized_augmentation_data = true;
-         continue;
-
        case 'S':
          cie->signal_frame = true;
          continue;
 
        case 'L':               /* LSDA pointer encoding byte.  */
-         cie->lsda_encoding = *data++;
+         if (cie->sized_augmentation_data)
+           cie->lsda_encoding = *data++;
          if (!cie->sized_augmentation_data)
            cie->fde_augmentation_data_size
              += encoded_value_size (&cache->data->d, cache->e_ident,
@@ -96,13 +100,17 @@ intern_new_cie (Dwarf_CFI *cache, Dwarf_Off offset, const 
Dwarf_CIE *info)
          continue;
 
        case 'R':               /* FDE address encoding byte.  */
-         cie->fde_encoding = *data++;
+         if (cie->sized_augmentation_data)
+           cie->fde_encoding = *data++;
          continue;
 
        case 'P':               /* Skip personality routine.  */
-         encoding = *data++;
-         data += encoded_value_size (&cache->data->d, cache->e_ident,
-                                     encoding, data);
+         if (cie->sized_augmentation_data)
+           {
+             encoding = *data++;
+             data += encoded_value_size (&cache->data->d, cache->e_ident,
+                                         encoding, data);
+           }
          continue;
 
        default:
diff --git a/libdw/dwarf_next_cfi.c b/libdw/dwarf_next_cfi.c
index 5bb74b8a0d66..4ac64554023b 100644
--- a/libdw/dwarf_next_cfi.c
+++ b/libdw/dwarf_next_cfi.c
@@ -228,6 +228,8 @@ dwarf_next_cfi (const unsigned char e_ident[],
              if (sized_augmentation)
                {
                  /* Skip FDE address encoding byte.  */
+                 if (bytes >= limit)
+                   goto invalid;
                  bytes++;
                  continue;
                }
-- 
2.55.0

Reply via email to