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