tinyvm/libtvm/tvm.c
Adygzhy Ondar 1911acb84f tvm_vm_create(): fix possible NULL pointer dereferencing.
if calloc() doesn't allocate memory for struct tvm_ctx,
there may be NULL pointer dereferencing, i.e. vm->mem, vm->prog.
So the vm pointer verification must be before it is used.

Also, there is the same situation with vm->mem and stack creation.
2017-10-28 14:00:01 +03:00

89 lines
1.8 KiB
C

#include <tvm/tvm.h>
#include <tvm/tvm_lexer.h>
#include <tvm/tvm_parser.h>
struct tvm_ctx *tvm_vm_create()
{
struct tvm_ctx *vm =
(struct tvm_ctx *)calloc(1, sizeof(struct tvm_ctx));
if (!vm)
return NULL;
vm->mem = tvm_mem_create(MIN_MEMORY_SIZE);
vm->prog = tvm_prog_create();
if (!vm->mem || !vm->prog) {
tvm_vm_destroy(vm);
return NULL;
}
tvm_stack_create(vm->mem, MIN_STACK_SIZE);
return vm;
}
int tvm_vm_interpret(struct tvm_ctx *vm, char *filename)
{
FILE *filp = NULL;
int source_length = 0;
/* Attempt to open the file.
* If the file cannot be opened, try once more.
*/
if (filename) {
for (int i = 0; i < 2; i++) {
if (!filp)
filp = tvm_fopen(filename, ".vm", "r");
}
}
if (!filp) {
printf("File was not found, or does not exist. Unable to interpret.\n");
return 1;
}
source_length = tvm_flength(filp);
char *source = calloc(source_length, sizeof(char));
tvm_fcopy(source, source_length, filp);
fclose(filp);
int err = tvm_preprocess(&source, &source_length, vm->prog->defines);
/* The preprocessor encountered a problem. */
if (err < 0)
return 1;
struct tvm_lexer_ctx *lexer_ctx = lexer_create();
tvm_lex(lexer_ctx, source, vm->prog->defines);
free(source);
if (tvm_parse_labels(vm, (const char ***)lexer_ctx->tokens) != 0)
return 1;
if (tvm_parse_program(vm, (const char ***)lexer_ctx->tokens) != 0)
return 1;
tvm_lexer_destroy(lexer_ctx);
return 0;
}
void tvm_vm_run(struct tvm_ctx *vm)
{
int *instr_idx = &vm->mem->registers[0x8].i32;
*instr_idx = vm->prog->start;
for (; vm->prog->instr[*instr_idx] != -0x1; ++(*instr_idx))
tvm_step(vm, instr_idx);
}
void tvm_vm_destroy(struct tvm_ctx *vm)
{
if (vm && vm->mem)
tvm_mem_destroy(vm->mem);
if (vm && vm->prog)
tvm_prog_destroy(vm->prog);
if (vm)
free(vm);
}