diff options
| author | Paul Eggert | 2016-11-26 00:19:08 -0800 |
|---|---|---|
| committer | Paul Eggert | 2016-11-26 00:20:26 -0800 |
| commit | b7f3a3055c92010afde318c1108b02e4424a3bac (patch) | |
| tree | 87c216fe495dc9fb716a5c05759911b746a29657 /src | |
| parent | caec5c06caa854a5e9d2001bd8ef7199a0b7540c (diff) | |
| download | emacs-b7f3a3055c92010afde318c1108b02e4424a3bac.tar.gz emacs-b7f3a3055c92010afde318c1108b02e4424a3bac.zip | |
Don't access pointers to freed storage in regex.c
Remove __BOUNDED_POINTERS__ code, which does not work with
-fcheck-pointer-bound and which has undefined behavior anyway.
Problem found when trying to port to gcc -fcheck-pointer-bounds.
(This code was removed from glibc and gnulib regex.c many years ago.)
* src/regex.c (ELSE_EXTEND_BUFFER_HIGH_BOUND): Remove.
(EXTEND_BUFFER): Use a more-portable approach that avoids
undefined behavior due to inspecting pointers to freed storage.
Diffstat (limited to 'src')
| -rw-r--r-- | src/regex.c | 51 |
1 files changed, 15 insertions, 36 deletions
diff --git a/src/regex.c b/src/regex.c index 1c6c9e5c18b..afd0d180316 100644 --- a/src/regex.c +++ b/src/regex.c | |||
| @@ -1644,28 +1644,6 @@ static int analyze_first (re_char *p, re_char *pend, | |||
| 1644 | reset the pointers that pointed into the old block to point to the | 1644 | reset the pointers that pointed into the old block to point to the |
| 1645 | correct places in the new one. If extending the buffer results in it | 1645 | correct places in the new one. If extending the buffer results in it |
| 1646 | being larger than MAX_BUF_SIZE, then flag memory exhausted. */ | 1646 | being larger than MAX_BUF_SIZE, then flag memory exhausted. */ |
| 1647 | #if __BOUNDED_POINTERS__ | ||
| 1648 | # define SET_HIGH_BOUND(P) (__ptrhigh (P) = __ptrlow (P) + bufp->allocated) | ||
| 1649 | # define MOVE_BUFFER_POINTER(P) \ | ||
| 1650 | (__ptrlow (P) = new_buffer + (__ptrlow (P) - old_buffer), \ | ||
| 1651 | SET_HIGH_BOUND (P), \ | ||
| 1652 | __ptrvalue (P) = new_buffer + (__ptrvalue (P) - old_buffer)) | ||
| 1653 | # define ELSE_EXTEND_BUFFER_HIGH_BOUND \ | ||
| 1654 | else \ | ||
| 1655 | { \ | ||
| 1656 | SET_HIGH_BOUND (b); \ | ||
| 1657 | SET_HIGH_BOUND (begalt); \ | ||
| 1658 | if (fixup_alt_jump) \ | ||
| 1659 | SET_HIGH_BOUND (fixup_alt_jump); \ | ||
| 1660 | if (laststart) \ | ||
| 1661 | SET_HIGH_BOUND (laststart); \ | ||
| 1662 | if (pending_exact) \ | ||
| 1663 | SET_HIGH_BOUND (pending_exact); \ | ||
| 1664 | } | ||
| 1665 | #else | ||
| 1666 | # define MOVE_BUFFER_POINTER(P) ((P) = new_buffer + ((P) - old_buffer)) | ||
| 1667 | # define ELSE_EXTEND_BUFFER_HIGH_BOUND | ||
| 1668 | #endif | ||
| 1669 | #define EXTEND_BUFFER() \ | 1647 | #define EXTEND_BUFFER() \ |
| 1670 | do { \ | 1648 | do { \ |
| 1671 | unsigned char *old_buffer = bufp->buffer; \ | 1649 | unsigned char *old_buffer = bufp->buffer; \ |
| @@ -1674,23 +1652,24 @@ static int analyze_first (re_char *p, re_char *pend, | |||
| 1674 | bufp->allocated <<= 1; \ | 1652 | bufp->allocated <<= 1; \ |
| 1675 | if (bufp->allocated > MAX_BUF_SIZE) \ | 1653 | if (bufp->allocated > MAX_BUF_SIZE) \ |
| 1676 | bufp->allocated = MAX_BUF_SIZE; \ | 1654 | bufp->allocated = MAX_BUF_SIZE; \ |
| 1655 | ptrdiff_t b_off = b - old_buffer; \ | ||
| 1656 | ptrdiff_t begalt_off = begalt - old_buffer; \ | ||
| 1657 | bool fixup_alt_jump_set = !!fixup_alt_jump; \ | ||
| 1658 | bool laststart_set = !!laststart; \ | ||
| 1659 | bool pending_exact_set = !!pending_exact; \ | ||
| 1660 | ptrdiff_t fixup_alt_jump_off, laststart_off, pending_exact_off; \ | ||
| 1661 | if (fixup_alt_jump_set) fixup_alt_jump_off = fixup_alt_jump - old_buffer; \ | ||
| 1662 | if (laststart_set) laststart_off = laststart - old_buffer; \ | ||
| 1663 | if (pending_exact_set) pending_exact_off = pending_exact - old_buffer; \ | ||
| 1677 | RETALLOC (bufp->buffer, bufp->allocated, unsigned char); \ | 1664 | RETALLOC (bufp->buffer, bufp->allocated, unsigned char); \ |
| 1678 | if (bufp->buffer == NULL) \ | 1665 | if (bufp->buffer == NULL) \ |
| 1679 | return REG_ESPACE; \ | 1666 | return REG_ESPACE; \ |
| 1680 | /* If the buffer moved, move all the pointers into it. */ \ | 1667 | unsigned char *new_buffer = bufp->buffer; \ |
| 1681 | if (old_buffer != bufp->buffer) \ | 1668 | b = new_buffer + b_off; \ |
| 1682 | { \ | 1669 | begalt = new_buffer + begalt_off; \ |
| 1683 | unsigned char *new_buffer = bufp->buffer; \ | 1670 | if (fixup_alt_jump_set) fixup_alt_jump = new_buffer + fixup_alt_jump_off; \ |
| 1684 | MOVE_BUFFER_POINTER (b); \ | 1671 | if (laststart_set) laststart = new_buffer + laststart_off; \ |
| 1685 | MOVE_BUFFER_POINTER (begalt); \ | 1672 | if (pending_exact_set) pending_exact = new_buffer + pending_exact_off; \ |
| 1686 | if (fixup_alt_jump) \ | ||
| 1687 | MOVE_BUFFER_POINTER (fixup_alt_jump); \ | ||
| 1688 | if (laststart) \ | ||
| 1689 | MOVE_BUFFER_POINTER (laststart); \ | ||
| 1690 | if (pending_exact) \ | ||
| 1691 | MOVE_BUFFER_POINTER (pending_exact); \ | ||
| 1692 | } \ | ||
| 1693 | ELSE_EXTEND_BUFFER_HIGH_BOUND \ | ||
| 1694 | } while (0) | 1673 | } while (0) |
| 1695 | 1674 | ||
| 1696 | 1675 | ||