mirror of
https://github.com/janet-lang/janet
synced 2026-07-02 09:38:50 +00:00
Add oob read checks in peg bytecode unmarshal.
These checks run before any references to rule[x] to avoid reading beyond the end of the buffer. This needs to happen inline, not only at the end of the loop where we check if we landed on the correct ending index.
This commit is contained in:
@@ -1630,6 +1630,8 @@ static size_t size_padded(size_t offset, size_t size) {
|
||||
return x - (x % size);
|
||||
}
|
||||
|
||||
#define OVERFLOW_CHECK(n) do { if (i > blen - (n)) goto bad; } while (0) /* overflow */
|
||||
|
||||
static void *peg_unmarshal(JanetMarshalContext *ctx) {
|
||||
size_t bytecode_len = janet_unmarshal_size(ctx);
|
||||
uint32_t num_constants = (uint32_t) janet_unmarshal_int(ctx);
|
||||
@@ -1682,6 +1684,7 @@ static void *peg_unmarshal(JanetMarshalContext *ctx) {
|
||||
op_flags[i] |= 0x02;
|
||||
switch (instr) {
|
||||
case RULE_LITERAL:
|
||||
OVERFLOW_CHECK(1); /* We only read rule[1] */
|
||||
i += 2 + ((rule[1] + 3) >> 2);
|
||||
break;
|
||||
case RULE_DEBUG:
|
||||
@@ -1708,6 +1711,7 @@ static void *peg_unmarshal(JanetMarshalContext *ctx) {
|
||||
break;
|
||||
case RULE_LOOK:
|
||||
/* [offset, rule] */
|
||||
OVERFLOW_CHECK(3);
|
||||
if (rule[2] >= blen) goto bad;
|
||||
op_flags[rule[2]] |= 0x1;
|
||||
i += 3;
|
||||
@@ -1716,7 +1720,9 @@ static void *peg_unmarshal(JanetMarshalContext *ctx) {
|
||||
case RULE_SEQUENCE:
|
||||
/* [len, rules...] */
|
||||
{
|
||||
OVERFLOW_CHECK(2);
|
||||
uint32_t len = rule[1];
|
||||
OVERFLOW_CHECK(2 + len);
|
||||
for (uint32_t j = 0; j < len; j++) {
|
||||
if (rule[2 + j] >= blen) goto bad;
|
||||
op_flags[rule[2 + j]] |= 0x1;
|
||||
@@ -1728,6 +1734,7 @@ static void *peg_unmarshal(JanetMarshalContext *ctx) {
|
||||
case RULE_IFNOT:
|
||||
case RULE_LENPREFIX:
|
||||
/* [rule_a, rule_b (b if not a)] */
|
||||
OVERFLOW_CHECK(3);
|
||||
if (rule[1] >= blen) goto bad;
|
||||
if (rule[2] >= blen) goto bad;
|
||||
op_flags[rule[1]] |= 0x01;
|
||||
@@ -1736,6 +1743,7 @@ static void *peg_unmarshal(JanetMarshalContext *ctx) {
|
||||
break;
|
||||
case RULE_BETWEEN:
|
||||
/* [lo, hi, rule] */
|
||||
OVERFLOW_CHECK(4);
|
||||
if (rule[3] >= blen) goto bad;
|
||||
op_flags[rule[3]] |= 0x01;
|
||||
i += 4;
|
||||
@@ -1751,11 +1759,13 @@ static void *peg_unmarshal(JanetMarshalContext *ctx) {
|
||||
break;
|
||||
case RULE_CONSTANT:
|
||||
/* [constant, tag] */
|
||||
OVERFLOW_CHECK(3);
|
||||
if (rule[1] >= clen) goto bad;
|
||||
i += 3;
|
||||
break;
|
||||
case RULE_CAPTURE_NUM:
|
||||
/* [rule, base, tag] */
|
||||
OVERFLOW_CHECK(4);
|
||||
if (rule[1] >= blen) goto bad;
|
||||
op_flags[rule[1]] |= 0x01;
|
||||
i += 4;
|
||||
@@ -1765,6 +1775,7 @@ static void *peg_unmarshal(JanetMarshalContext *ctx) {
|
||||
case RULE_CAPTURE:
|
||||
case RULE_UNREF:
|
||||
/* [rule, tag] */
|
||||
OVERFLOW_CHECK(3);
|
||||
if (rule[1] >= blen) goto bad;
|
||||
op_flags[rule[1]] |= 0x01;
|
||||
i += 3;
|
||||
@@ -1773,6 +1784,7 @@ static void *peg_unmarshal(JanetMarshalContext *ctx) {
|
||||
case RULE_MATCHTIME:
|
||||
case RULE_MATCHSPLICE:
|
||||
/* [rule, constant, tag] */
|
||||
OVERFLOW_CHECK(4);
|
||||
if (rule[1] >= blen) goto bad;
|
||||
if (rule[2] >= clen) goto bad;
|
||||
op_flags[rule[1]] |= 0x01;
|
||||
@@ -1782,6 +1794,7 @@ static void *peg_unmarshal(JanetMarshalContext *ctx) {
|
||||
case RULE_TIL:
|
||||
case RULE_SPLIT:
|
||||
/* [rule, rule] */
|
||||
OVERFLOW_CHECK(3);
|
||||
if (rule[1] >= blen) goto bad;
|
||||
if (rule[2] >= blen) goto bad;
|
||||
op_flags[rule[1]] |= 0x01;
|
||||
@@ -1795,17 +1808,20 @@ static void *peg_unmarshal(JanetMarshalContext *ctx) {
|
||||
case RULE_TO:
|
||||
case RULE_THRU:
|
||||
/* [rule] */
|
||||
OVERFLOW_CHECK(2);
|
||||
if (rule[1] >= blen) goto bad;
|
||||
op_flags[rule[1]] |= 0x01;
|
||||
i += 2;
|
||||
break;
|
||||
case RULE_READINT:
|
||||
/* [ width | (endianness << 5) | (signedness << 6), tag ] */
|
||||
OVERFLOW_CHECK(3);
|
||||
if (rule[1] > JANET_MAX_READINT_WIDTH) goto bad;
|
||||
i += 3;
|
||||
break;
|
||||
case RULE_NTH:
|
||||
/* [nth, rule, tag] */
|
||||
OVERFLOW_CHECK(4);
|
||||
if (rule[2] >= blen) goto bad;
|
||||
op_flags[rule[2]] |= 0x01;
|
||||
i += 4;
|
||||
@@ -1835,6 +1851,8 @@ bad:
|
||||
janet_panic("invalid peg bytecode");
|
||||
}
|
||||
|
||||
#undef OVERFLOW_CHECK
|
||||
|
||||
static int cfun_peg_getter(JanetAbstract a, Janet key, Janet *out);
|
||||
static Janet peg_next(void *p, Janet key);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user