Commit 616f2fe2 authored by Serhiy Storchaka's avatar Serhiy Storchaka

Issue #17016: Get rid of possible pointer wraparounds and integer overflows

in the re module.  Patch by Nickolai Zeldovich.
parent c2a4f6b6
...@@ -1130,6 +1130,7 @@ Milan Zamazal ...@@ -1130,6 +1130,7 @@ Milan Zamazal
Artur Zaprzala Artur Zaprzala
Mike Zarnstorff Mike Zarnstorff
Siebren van der Zee Siebren van der Zee
Nickolai Zeldovich
Uwe Zessin Uwe Zessin
Cheng Zhang Cheng Zhang
Tarek Ziadé Tarek Ziadé
......
...@@ -25,6 +25,9 @@ Core and Builtins ...@@ -25,6 +25,9 @@ Core and Builtins
Library Library
------- -------
- Issue #17016: Get rid of possible pointer wraparounds and integer overflows
in the re module. Patch by Nickolai Zeldovich.
- Issue #17536: Add to webbrowser's browser list: xdg-open, gvfs-open, - Issue #17536: Add to webbrowser's browser list: xdg-open, gvfs-open,
www-browser, x-www-browser, chromium browsers, iceweasel, iceape. www-browser, x-www-browser, chromium browsers, iceweasel, iceape.
......
...@@ -686,7 +686,7 @@ do { \ ...@@ -686,7 +686,7 @@ do { \
alloc_pos = state->data_stack_base; \ alloc_pos = state->data_stack_base; \
TRACE(("allocating %s in %d (%d)\n", \ TRACE(("allocating %s in %d (%d)\n", \
SFY(type), alloc_pos, sizeof(type))); \ SFY(type), alloc_pos, sizeof(type))); \
if (state->data_stack_size < alloc_pos+sizeof(type)) { \ if (sizeof(type) > state->data_stack_size - alloc_pos) { \
int j = data_stack_grow(state, sizeof(type)); \ int j = data_stack_grow(state, sizeof(type)); \
if (j < 0) return j; \ if (j < 0) return j; \
if (ctx_pos != -1) \ if (ctx_pos != -1) \
...@@ -706,7 +706,7 @@ do { \ ...@@ -706,7 +706,7 @@ do { \
do { \ do { \
TRACE(("copy data in %p to %d (%d)\n", \ TRACE(("copy data in %p to %d (%d)\n", \
data, state->data_stack_base, size)); \ data, state->data_stack_base, size)); \
if (state->data_stack_size < state->data_stack_base+size) { \ if (size > state->data_stack_size - state->data_stack_base) { \
int j = data_stack_grow(state, size); \ int j = data_stack_grow(state, size); \
if (j < 0) return j; \ if (j < 0) return j; \
if (ctx_pos != -1) \ if (ctx_pos != -1) \
...@@ -1028,7 +1028,7 @@ entrance: ...@@ -1028,7 +1028,7 @@ entrance:
TRACE(("|%p|%p|REPEAT_ONE %d %d\n", ctx->pattern, ctx->ptr, TRACE(("|%p|%p|REPEAT_ONE %d %d\n", ctx->pattern, ctx->ptr,
ctx->pattern[1], ctx->pattern[2])); ctx->pattern[1], ctx->pattern[2]));
if (ctx->ptr + ctx->pattern[1] > end) if (ctx->pattern[1] > end - ctx->ptr)
RETURN_FAILURE; /* cannot match */ RETURN_FAILURE; /* cannot match */
state->ptr = ctx->ptr; state->ptr = ctx->ptr;
...@@ -1111,7 +1111,7 @@ entrance: ...@@ -1111,7 +1111,7 @@ entrance:
TRACE(("|%p|%p|MIN_REPEAT_ONE %d %d\n", ctx->pattern, ctx->ptr, TRACE(("|%p|%p|MIN_REPEAT_ONE %d %d\n", ctx->pattern, ctx->ptr,
ctx->pattern[1], ctx->pattern[2])); ctx->pattern[1], ctx->pattern[2]));
if (ctx->ptr + ctx->pattern[1] > end) if (ctx->pattern[1] > end - ctx->ptr)
RETURN_FAILURE; /* cannot match */ RETURN_FAILURE; /* cannot match */
state->ptr = ctx->ptr; state->ptr = ctx->ptr;
...@@ -2784,7 +2784,7 @@ _compile(PyObject* self_, PyObject* args) ...@@ -2784,7 +2784,7 @@ _compile(PyObject* self_, PyObject* args)
skip = *code; \ skip = *code; \
VTRACE(("%lu (skip to %p)\n", \ VTRACE(("%lu (skip to %p)\n", \
(unsigned long)skip, code+skip)); \ (unsigned long)skip, code+skip)); \
if (code+skip-adj < code || code+skip-adj > end)\ if (skip-adj > end-code) \
FAIL; \ FAIL; \
code++; \ code++; \
} while (0) } while (0)
...@@ -2817,7 +2817,7 @@ _validate_charset(SRE_CODE *code, SRE_CODE *end) ...@@ -2817,7 +2817,7 @@ _validate_charset(SRE_CODE *code, SRE_CODE *end)
case SRE_OP_CHARSET: case SRE_OP_CHARSET:
offset = 32/sizeof(SRE_CODE); /* 32-byte bitmap */ offset = 32/sizeof(SRE_CODE); /* 32-byte bitmap */
if (code+offset < code || code+offset > end) if (offset > end-code)
FAIL; FAIL;
code += offset; code += offset;
break; break;
...@@ -2825,7 +2825,7 @@ _validate_charset(SRE_CODE *code, SRE_CODE *end) ...@@ -2825,7 +2825,7 @@ _validate_charset(SRE_CODE *code, SRE_CODE *end)
case SRE_OP_BIGCHARSET: case SRE_OP_BIGCHARSET:
GET_ARG; /* Number of blocks */ GET_ARG; /* Number of blocks */
offset = 256/sizeof(SRE_CODE); /* 256-byte table */ offset = 256/sizeof(SRE_CODE); /* 256-byte table */
if (code+offset < code || code+offset > end) if (offset > end-code)
FAIL; FAIL;
/* Make sure that each byte points to a valid block */ /* Make sure that each byte points to a valid block */
for (i = 0; i < 256; i++) { for (i = 0; i < 256; i++) {
...@@ -2834,7 +2834,7 @@ _validate_charset(SRE_CODE *code, SRE_CODE *end) ...@@ -2834,7 +2834,7 @@ _validate_charset(SRE_CODE *code, SRE_CODE *end)
} }
code += offset; code += offset;
offset = arg * 32/sizeof(SRE_CODE); /* 32-byte bitmap times arg */ offset = arg * 32/sizeof(SRE_CODE); /* 32-byte bitmap times arg */
if (code+offset < code || code+offset > end) if (offset > end-code)
FAIL; FAIL;
code += offset; code += offset;
break; break;
...@@ -2985,11 +2985,11 @@ _validate_inner(SRE_CODE *code, SRE_CODE *end, Py_ssize_t groups) ...@@ -2985,11 +2985,11 @@ _validate_inner(SRE_CODE *code, SRE_CODE *end, Py_ssize_t groups)
GET_ARG; prefix_len = arg; GET_ARG; prefix_len = arg;
GET_ARG; /* prefix skip */ GET_ARG; /* prefix skip */
/* Here comes the prefix string */ /* Here comes the prefix string */
if (code+prefix_len < code || code+prefix_len > newcode) if (prefix_len > newcode-code)
FAIL; FAIL;
code += prefix_len; code += prefix_len;
/* And here comes the overlap table */ /* And here comes the overlap table */
if (code+prefix_len < code || code+prefix_len > newcode) if (prefix_len > newcode-code)
FAIL; FAIL;
/* Each overlap value should be < prefix_len */ /* Each overlap value should be < prefix_len */
for (i = 0; i < prefix_len; i++) { for (i = 0; i < prefix_len; i++) {
...@@ -3118,7 +3118,7 @@ _validate_inner(SRE_CODE *code, SRE_CODE *end, Py_ssize_t groups) ...@@ -3118,7 +3118,7 @@ _validate_inner(SRE_CODE *code, SRE_CODE *end, Py_ssize_t groups)
to allow arbitrary jumps anywhere in the code; so we just look to allow arbitrary jumps anywhere in the code; so we just look
for a JUMP opcode preceding our skip target. for a JUMP opcode preceding our skip target.
*/ */
if (skip >= 3 && code+skip-3 >= code && if (skip >= 3 && skip-3 < end-code &&
code[skip-3] == SRE_OP_JUMP) code[skip-3] == SRE_OP_JUMP)
{ {
VTRACE(("both then and else parts present\n")); VTRACE(("both then and else parts present\n"));
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment