#endif
/* Report failure */
-#define FAIL do { VTRACE(("FAIL: %d\n", __LINE__)); return 0; } while (0)
+#define FAIL do { VTRACE(("FAIL: %d\n", __LINE__)); return -1; } while (0)
/* Extract opcode, argument, or skip count from code array */
#define GET_OP \
skip = *code; \
VTRACE(("%lu (skip to %p)\n", \
(unsigned long)skip, code+skip)); \
- if (skip-adj > (uintptr_t)(end - code)) \
+ if (skip-adj > (uintptr_t)(end - code)) \
FAIL; \
code++; \
} while (0)
}
}
- return 1;
+ return 0;
}
+/* Returns 0 on success, -1 on failure, and 1 if the last op is JUMP. */
static int
_validate_inner(SRE_CODE *code, SRE_CODE *end, Py_ssize_t groups)
{
case SRE_OP_IN_LOC_IGNORE:
GET_SKIP;
/* Stop 1 before the end; we check the FAILURE below */
- if (!_validate_charset(code, code+skip-2))
+ if (_validate_charset(code, code+skip-2))
FAIL;
if (code[skip-2] != SRE_OP_FAILURE)
FAIL;
}
/* Validate the charset */
if (flags & SRE_INFO_CHARSET) {
- if (!_validate_charset(code, newcode-1))
+ if (_validate_charset(code, newcode-1))
FAIL;
if (newcode[-1] != SRE_OP_FAILURE)
FAIL;
if (skip == 0)
break;
/* Stop 2 before the end; we check the JUMP below */
- if (!_validate_inner(code, code+skip-3, groups))
+ if (_validate_inner(code, code+skip-3, groups))
FAIL;
code += skip-3;
/* Check that it ends with a JUMP, and that each JUMP
else if (code+skip-1 != target)
FAIL;
}
+ if (code != target)
+ FAIL;
}
break;
FAIL;
if (max > SRE_MAXREPEAT)
FAIL;
- if (!_validate_inner(code, code+skip-4, groups))
+ if (_validate_inner(code, code+skip-4, groups))
FAIL;
code += skip-4;
GET_OP;
FAIL;
if (max > SRE_MAXREPEAT)
FAIL;
- if (!_validate_inner(code, code+skip-3, groups))
+ if (_validate_inner(code, code+skip-3, groups))
FAIL;
code += skip-3;
GET_OP;
case SRE_OP_ATOMIC_GROUP:
{
GET_SKIP;
- if (!_validate_inner(code, code+skip-2, groups))
+ if (_validate_inner(code, code+skip-2, groups))
FAIL;
code += skip-2;
GET_OP;
to allow arbitrary jumps anywhere in the code; so we just look
for a JUMP opcode preceding our skip target.
*/
- if (skip >= 3 && skip-3 < (uintptr_t)(end - code) &&
- code[skip-3] == SRE_OP_JUMP)
- {
- VTRACE(("both then and else parts present\n"));
- if (!_validate_inner(code+1, code+skip-3, groups))
- FAIL;
+ VTRACE(("then part:\n"));
+ int rc = _validate_inner(code+1, code+skip-1, groups);
+ if (rc == 1) {
+ VTRACE(("else part:\n"));
code += skip-2; /* Position after JUMP, at <skipno> */
GET_SKIP;
- if (!_validate_inner(code, code+skip-1, groups))
- FAIL;
- code += skip-1;
- }
- else {
- VTRACE(("only a then part present\n"));
- if (!_validate_inner(code+1, code+skip-1, groups))
- FAIL;
- code += skip-1;
+ rc = _validate_inner(code, code+skip-1, groups);
}
+ if (rc)
+ FAIL;
+ code += skip-1;
break;
case SRE_OP_ASSERT:
if (arg & 0x80000000)
FAIL; /* Width too large */
/* Stop 1 before the end; we check the SUCCESS below */
- if (!_validate_inner(code+1, code+skip-2, groups))
+ if (_validate_inner(code+1, code+skip-2, groups))
FAIL;
code += skip-2;
GET_OP;
FAIL;
break;
+ case SRE_OP_JUMP:
+ if (code + 1 != end)
+ FAIL;
+ VTRACE(("JUMP: %d\n", __LINE__));
+ return 1;
+
default:
FAIL;
}
VTRACE(("okay\n"));
- return 1;
+ return 0;
}
static int
static int
_validate(PatternObject *self)
{
- if (!_validate_outer(self->code, self->code+self->codesize, self->groups))
+ if (_validate_outer(self->code, self->code+self->codesize, self->groups))
{
PyErr_SetString(PyExc_RuntimeError, "invalid SRE code");
return 0;