Fix heap limit checking overflow bug in pcre2_dfa_match().

This commit is contained in:
Philip.Hazel 2018-10-22 16:47:55 +00:00
parent c796bb85a1
commit 951bc4b9ff
2 changed files with 24 additions and 16 deletions

View File

@ -48,6 +48,10 @@ minimum of zero, an incorrect "match must start with this character" could be
recorded. Example: /(?&xxx)*ABC(?<xxx>XYZ)/ would (incorrectly) expect 'A' to recorded. Example: /(?&xxx)*ABC(?<xxx>XYZ)/ would (incorrectly) expect 'A' to
be the first character of a match. be the first character of a match.
12. The heap limit checking code in pcre2_dfa_match() could suffer from
overflow if the heap limit was set very large. This could cause incorrect "heap
limit exceeded" errors.
Version 10.32 10-September-2018 Version 10.32 10-September-2018
------------------------------- -------------------------------

View File

@ -319,8 +319,8 @@ finding the minimum heap requirement for a match. */
typedef struct RWS_anchor { typedef struct RWS_anchor {
struct RWS_anchor *next; struct RWS_anchor *next;
unsigned int size; /* Number of ints */ uint32_t size; /* Number of ints */
unsigned int free; /* Number of ints */ uint32_t free; /* Number of ints */
} RWS_anchor; } RWS_anchor;
#define RWS_ANCHOR_SIZE (sizeof(RWS_anchor)/sizeof(int)) #define RWS_ANCHOR_SIZE (sizeof(RWS_anchor)/sizeof(int))
@ -416,20 +416,24 @@ if (rws->next != NULL)
new = rws->next; new = rws->next;
} }
/* All sizes are in units of sizeof(int), except for mb->heaplimit, which is in /* Sizes in the RWS_anchor blocks are in units of sizeof(int), but
kibibytes. */ mb->heap_limit and mb->heap_used are in kibibytes. Play carefully, to avoid
overflow. */
else else
{ {
unsigned int newsize = rws->size * 2; uint32_t newsize = (rws->size >= UINT32_MAX/2)? UINT32_MAX/2 : rws->size * 2;
unsigned int heapleft = (unsigned int) uint32_t newsizeK = newsize/(1024/sizeof(int));
(((1024/sizeof(int))*mb->heap_limit - mb->heap_used));
if (newsize > heapleft) newsize = heapleft; if (newsizeK + mb->heap_used > mb->heap_limit)
newsizeK = mb->heap_limit - mb->heap_used;
newsize = newsizeK*(1024/sizeof(int));
if (newsize < RWS_RSIZE + ovecsize + RWS_ANCHOR_SIZE) if (newsize < RWS_RSIZE + ovecsize + RWS_ANCHOR_SIZE)
return PCRE2_ERROR_HEAPLIMIT; return PCRE2_ERROR_HEAPLIMIT;
new = mb->memctl.malloc(newsize*sizeof(int), mb->memctl.memory_data); new = mb->memctl.malloc(newsize*sizeof(int), mb->memctl.memory_data);
if (new == NULL) return PCRE2_ERROR_NOMEMORY; if (new == NULL) return PCRE2_ERROR_NOMEMORY;
mb->heap_used += newsize; mb->heap_used += newsizeK;
new->next = NULL; new->next = NULL;
new->size = newsize; new->size = newsize;
rws->next = new; rws->next = new;