Skip to content

Commit

Permalink
Fix @/! when stack is empty
Browse files Browse the repository at this point in the history
Both loading from the memory (@) and storing (!) require popping the
address from the stack.  If it's empty, POP_D() will yield NaN -- making
the conversion to int32_t yield an out-of-bounds value. Handle this
condition.

This also gets rid of the STORE() and LOAD() macro, that were only used
inside one function each.
  • Loading branch information
lpereira committed Jan 28, 2025
1 parent f6e9852 commit 645f161
Showing 1 changed file with 10 additions and 20 deletions.
30 changes: 10 additions & 20 deletions src/samples/forthsalon/forth.c
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ struct forth_ctx {
size_t pos;
} r_stack, d_stack;

double memory[64];
double memory[16];

bool is_inside_word_def;
};
Expand Down Expand Up @@ -126,20 +126,6 @@ struct forth_vars {
} \
v; \
})
#define LOAD(addr_) \
({ \
size_t v = (size_t)(int32_t)(addr_); \
if (v > N_ELEMENTS(ctx->memory)) \
return false; \
ctx->memory[v]; \
})
#define STORE(addr_, value_) \
({ \
size_t v = (size_t)(int32_t)(addr_); \
if (v > N_ELEMENTS(ctx->memory)) \
return false; \
ctx->memory[v] = (value_); \
})

#if DUMP_CODE
static void dump_code(const struct forth_code *code)
Expand Down Expand Up @@ -662,16 +648,20 @@ BUILTIN("r@")

BUILTIN("@")
{
double slot = POP_D();
PUSH_D(LOAD(slot));
int32_t slot = (int32_t)POP_D();
if (UNLIKELY(slot < 0))
return false;
PUSH_D(ctx->memory[slot % (int32_t)N_ELEMENTS(ctx->memory)]);
return true;
}

BUILTIN("!")
{
double v1 = POP_D();
double v2 = POP_D();
STORE(v2, v1);
double v = POP_D();
int32_t slot = (int32_t)POP_D();
if (UNLIKELY(slot < 0))
return false;
ctx->memory[slot % (int32_t)N_ELEMENTS(ctx->memory)] = v;
return true;
}

Expand Down

0 comments on commit 645f161

Please sign in to comment.