Print this page
5688 ELF tools need to be more careful with dwarf data

@@ -535,11 +535,12 @@
         fde_count = 0;
 
         for (APLIST_TRAVERSE(ofl->ofl_unwind, idx, osp)) {
                 uchar_t         *data;
                 size_t          size;
-                uint64_t        off = 0;
+                uint64_t        off = 0, ujunk;
+                int64_t         sjunk;
                 uint_t          cieRflag = 0, ciePflag = 0;
                 Shdr            *shdr;
 
                 /*
                  * remember first UNWIND section to

@@ -599,47 +600,93 @@
                                 ndx += strlen(cieaugstr) + 1;
 
                                 /*
                                  * calign & dalign
                                  */
-                                (void) uleb_extract(&data[off], &ndx);
-                                (void) sleb_extract(&data[off], &ndx);
+                                if (uleb_extract(&data[off], &ndx,
+                                    size - off, &ujunk) == DW_OVERFLOW) {
+                                        ld_eprintf(ofl, ERR_FATAL,
+                                            MSG_INTL(MSG_SCN_DWFOVRFLW),
+                                            ofl->ofl_name,
+                                            osp->os_name);
+                                        return (S_ERROR);
+                                }
+
+                                if (sleb_extract(&data[off], &ndx,
+                                    size - off, &sjunk) == DW_OVERFLOW) {
+                                        ld_eprintf(ofl, ERR_FATAL,
+                                            MSG_INTL(MSG_SCN_DWFOVRFLW),
+                                            ofl->ofl_name,
+                                            osp->os_name);
+                                        return (S_ERROR);
+                                }
 
                                 /*
                                  * retreg
                                  */
-                                if (cieversion == 1)
+                                if (cieversion == 1) {
                                         ndx++;
-                                else
-                                        (void) uleb_extract(&data[off], &ndx);
+                                } else {
+                                        if (uleb_extract(&data[off], &ndx,
+                                            size - off, &ujunk) ==
+                                            DW_OVERFLOW) {
+                                                ld_eprintf(ofl, ERR_FATAL,
+                                                    MSG_INTL(MSG_SCN_DWFOVRFLW),
+                                                    ofl->ofl_name,
+                                                    osp->os_name);
+                                                return (S_ERROR);
+                                        }
+                                }
                                 /*
                                  * we walk through the augmentation
                                  * section now looking for the Rflag
                                  */
                                 for (cieaugndx = 0; cieaugstr[cieaugndx];
                                     cieaugndx++) {
                                         /* BEGIN CSTYLED */
                                         switch (cieaugstr[cieaugndx]) {
                                         case 'z':
                                             /* size */
-                                            (void) uleb_extract(&data[off],
-                                                &ndx);
+                                            if (uleb_extract(&data[off],
+                                                &ndx, size - off, &ujunk) ==
+                                                DW_OVERFLOW) {
+                                                ld_eprintf(ofl, ERR_FATAL,
+                                                    MSG_INTL(MSG_SCN_DWFOVRFLW),
+                                                    ofl->ofl_name,
+                                                    osp->os_name);
+                                                return (S_ERROR);
+                                            }
                                             break;
                                         case 'P':
                                             /* personality */
                                             ciePflag = data[off + ndx];
                                             ndx++;
                                                 /*
                                                  * Just need to extract the
                                                  * value to move on to the next
                                                  * field.
                                                  */
-                                            (void) dwarf_ehe_extract(
-                                                &data[off],
-                                                &ndx, ciePflag,
+                                            switch (dwarf_ehe_extract(
+                                                &data[off], size - off,
+                                                &ndx, &ujunk, ciePflag,
                                                 ofl->ofl_dehdr->e_ident, B_FALSE,
-                                                shdr->sh_addr, off + ndx, 0);
+                                                shdr->sh_addr, off + ndx, 0)) {
+                                            case DW_OVERFLOW:
+                                                ld_eprintf(ofl, ERR_FATAL,
+                                                    MSG_INTL(MSG_SCN_DWFOVRFLW),
+                                                    ofl->ofl_name,
+                                                    osp->os_name);
+                                                return (S_ERROR);
+                                            case DW_BAD_ENCODING:
+                                                ld_eprintf(ofl, ERR_FATAL,
+                                                    MSG_INTL(MSG_SCN_DWFBADENC),
+                                                    ofl->ofl_name,
+                                                    osp->os_name, ciePflag);
+                                                return (S_ERROR);
+                                            case DW_SUCCESS:
+                                                break;
+                                            }
                                             break;
                                         case 'R':
                                             /* code encoding */
                                             cieRflag = data[off + ndx];
                                             ndx++;

@@ -659,15 +706,29 @@
 
                                 if (ofl->ofl_osgot != NULL)
                                         gotaddr =
                                             ofl->ofl_osgot->os_shdr->sh_addr;
 
-                                initloc = dwarf_ehe_extract(&data[off],
-                                    &ndx, cieRflag, ofl->ofl_dehdr->e_ident,
-                                    B_FALSE,
-                                    shdr->sh_addr, off + ndx,
-                                    gotaddr);
+                                switch (dwarf_ehe_extract(&data[off],
+                                    size - off, &ndx, &initloc, cieRflag,
+                                    ofl->ofl_dehdr->e_ident, B_FALSE,
+                                    shdr->sh_addr, off + ndx, gotaddr)) {
+                                case DW_OVERFLOW:
+                                        ld_eprintf(ofl, ERR_FATAL,
+                                            MSG_INTL(MSG_SCN_DWFOVRFLW),
+                                            ofl->ofl_name,
+                                            osp->os_name);
+                                        return (S_ERROR);
+                                case DW_BAD_ENCODING:
+                                        ld_eprintf(ofl, ERR_FATAL,
+                                            MSG_INTL(MSG_SCN_DWFBADENC),
+                                            ofl->ofl_name,
+                                            osp->os_name, cieRflag);
+                                        return (S_ERROR);
+                                case DW_SUCCESS:
+                                        break;
+                                }
 
                                 /*
                                  * Ignore FDEs with initloc set to 0.
                                  * initloc will not be 0 unless this FDE was
                                  * abandoned due to GNU linkonce processing.