[COMMITTED] libdw: Only read CIE augmentation data if it is there

Mark Wielaard mark@klomp.org
Sat Jul 11 15:44:54 GMT 2026


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 <karankurani3k@gmail.com>
Signed-off-by: Mark Wielaard <mark@klomp.org>
---
 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



More information about the Elfutils-devel mailing list