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.