diff --git a/include/vm/internals/reader.h b/include/vm/internals/reader.h index 8764cd7..dbfd276 100644 --- a/include/vm/internals/reader.h +++ b/include/vm/internals/reader.h @@ -7,6 +7,8 @@ #include #include +extern char internal_error[256]; + bool vm_rd_char(FILE *fd, size_t count, char *outbuf); bool vm_rd_u16(FILE *fd, size_t count, uint16_t *outbuf); bool vm_rd_word(FILE *fd, size_t count, size_t *outbuf); diff --git a/src/compiler/fzl_writer.c b/src/compiler/fzl_writer.c index 38e4e48..c9994d0 100644 --- a/src/compiler/fzl_writer.c +++ b/src/compiler/fzl_writer.c @@ -2,7 +2,6 @@ #include #include #include -#include #include #include #include @@ -14,11 +13,11 @@ char wrlast_err[256]; fzl_writer_t *fzl_mkwriter(const char *filepath) { if (strlen(filepath) < 1) - return NULL; + return nullptr; fzl_writer_t *writer = malloc(sizeof(fzl_writer_t)); if (!writer) - return NULL; + return nullptr; writer->filepath = filepath; @@ -38,7 +37,7 @@ int fzl_write(fzl_writer_t *writer, fzl_gen_t *gen) return -1; } - const char hdr[5] = {'F', 'Z', 'L', 0x0, 0x2}; + constexpr char hdr[5] = {'F', 'Z', 'L', 0x0, 0x2}; fwrite(hdr, sizeof(char), 5, fd); fwrite(&gen->consts->size, sizeof(uint16_t), 1, fd); fwrite(&gen->extern_libs_count, sizeof(uint16_t), 1, fd); diff --git a/src/vm/fzl_vm.c b/src/vm/fzl_vm.c index bb46ab3..b3d2d0c 100644 --- a/src/vm/fzl_vm.c +++ b/src/vm/fzl_vm.c @@ -1,11 +1,8 @@ -#include #include #include #include #include -#include #include -#include #include #include #include @@ -16,11 +13,10 @@ #include char last_err[256]; +char internal_error[256]; size_t last_jmp_ip = 0; size_t total_jmp_on_same = 0; -static char *expect_hdr = "FZL\0\2"; - fzl_vm_t *fzl_mkvm(fzl_vm_reader_t *reader) { if (!reader) diff --git a/src/vm/fzl_vm_reader.c b/src/vm/fzl_vm_reader.c index 09bbdbe..037c467 100644 --- a/src/vm/fzl_vm_reader.c +++ b/src/vm/fzl_vm_reader.c @@ -35,8 +35,12 @@ fzl_vm_reader_t *fzl_vm_mkreader(char *filepath) void wr_validation_err(char *section) { - snprintf(reader_err, sizeof(reader_err), - "init error - section '%s' is not valid", section); + if (internal_error[0]) + snprintf(reader_err, sizeof(reader_err), "init error - section '%s': %s", + section, internal_error); + else + snprintf(reader_err, sizeof(reader_err), + "init error - section '%s' is not valid", section); } bool fzl_vm_read(fzl_vm_reader_t *reader) @@ -137,7 +141,26 @@ void fzl_vm_freereader(fzl_vm_reader_t *reader) free(reader->extern_libs); if (reader->extern_types) + { + for (uint16_t i = 0; i < reader->extern_types_count; i++) + { + free(reader->extern_types[i].name); + + if (reader->extern_types[i].kind == FZL_EXTERN_KIND_STRUCT) + { + fzl_extern_struct_field_t *fields = + reader->extern_types[i].structure.fields; + for (uint16_t j = 0; j < reader->extern_types[i].structure.fields_count; + j++) + { + if (fields[j].name) + free(fields[j].name); + } + } + } + free(reader->extern_types); + } if (reader->extern_fns) free(reader->extern_fns); diff --git a/src/vm/main.c b/src/vm/main.c index 8f91556..2b55e0a 100644 --- a/src/vm/main.c +++ b/src/vm/main.c @@ -161,6 +161,7 @@ int main(int argc, char **argv) } free(args); + fzl_vm_freereader(reader); fzl_freevm(vm); return 0; diff --git a/src/vm/reader/utility.c b/src/vm/reader/utility.c index 0054bac..3f16d50 100644 --- a/src/vm/reader/utility.c +++ b/src/vm/reader/utility.c @@ -10,7 +10,7 @@ bool vm_rd_char(FILE *fd, size_t count, char *o) if (!fd || !o) return false; - return fread(o, sizeof(char), count, fd) == (sizeof(char) * count); + return fread(o, sizeof(char), count, fd) == count; } // Read 16-byte uints with red bytes check @@ -19,7 +19,7 @@ bool vm_rd_u16(FILE *fd, size_t count, uint16_t *o) if (!fd || !o) return false; - return fread(o, sizeof(uint16_t), count, fd) == (sizeof(uint16_t) * count); + return fread(o, sizeof(uint16_t), count, fd) == count; } // Read machine word-size uints with red bytes check @@ -28,5 +28,5 @@ bool vm_rd_word(FILE *fd, size_t count, size_t *o) if (!fd || !o) return false; - return fread(o, sizeof(size_t), count, fd) == (sizeof(size_t) * count); + return fread(o, sizeof(size_t), count, fd) == count; } diff --git a/src/vm/reader/vm_rd_consts.c b/src/vm/reader/vm_rd_consts.c index 593f7e5..4245d7b 100644 --- a/src/vm/reader/vm_rd_consts.c +++ b/src/vm/reader/vm_rd_consts.c @@ -3,6 +3,7 @@ #include #include #include +#include #include #include #include @@ -19,7 +20,10 @@ bool vm_rd_consts(fzl_vm_reader_t *reader, FILE *fd) reader->consts = malloc(sizeof(fzl_value_t) * consts_count); if (!reader->consts) + { + snprintf(internal_error, sizeof(internal_error), "out of memory"); return false; + } memset(reader->consts, 0, sizeof(fzl_value_t) * consts_count); @@ -31,19 +35,32 @@ bool vm_rd_consts(fzl_vm_reader_t *reader, FILE *fd) memset(contents, 0, sizeof(contents)); ok = vm_rd_u16(fd, 1, &const_size); - if (!ok || const_size < 1) + if (!ok) + { + snprintf(internal_error, sizeof(internal_error), + "failed to read size of const #%u", i); return false; + } ok = vm_rd_char(fd, const_size, contents); if (!ok) + { + snprintf(internal_error, sizeof(internal_error), + "failed to read const #%u", i); return false; + } - char *val = malloc(sizeof(char) * const_size); + char *val = malloc(sizeof(char) * const_size + 1); if (!val) + { + snprintf(internal_error, sizeof(internal_error), + "out of memory on const #%u allocation", i); return false; + } - memset(val, 0, sizeof(char) * const_size); + memset(val, 0, sizeof(char) * const_size + 1); memcpy(val, contents, sizeof(char) * const_size); + reader->consts[i] = (fzl_value_t){ .type = FZL_TYPE_STRING, .as.s.value = val, .as.s.length = const_size}; } diff --git a/src/vm/reader/vm_rd_extern_libs.c b/src/vm/reader/vm_rd_extern_libs.c index d924c39..a6698db 100644 --- a/src/vm/reader/vm_rd_extern_libs.c +++ b/src/vm/reader/vm_rd_extern_libs.c @@ -1,6 +1,7 @@ #include #include #include +#include #include #include #include @@ -17,7 +18,10 @@ bool vm_rd_extern_libs(fzl_vm_reader_t *reader, FILE *fd) reader->extern_libs = malloc(sizeof(char *) * libs_count); if (!reader->extern_libs) + { + snprintf(internal_error, sizeof(internal_error), "out of memory"); return false; + } memset(reader->extern_libs, 0, sizeof(char *) * libs_count); @@ -30,17 +34,29 @@ bool vm_rd_extern_libs(fzl_vm_reader_t *reader, FILE *fd) ok = vm_rd_u16(fd, 1, &name_sz); if (!ok || name_sz < 1) + { + snprintf(internal_error, sizeof(internal_error), + "failed to read lib #%u name size", i); return false; + } ok = vm_rd_char(fd, name_sz, name); if (!ok) + { + snprintf(internal_error, sizeof(internal_error), + "failed to read lib #%u name", i); return false; + } - char *val = malloc(sizeof(char) * name_sz); + char *val = malloc(sizeof(char) * name_sz + 1); if (!val) + { + snprintf(internal_error, sizeof(internal_error), + "out of memory on lib #%u name allocation", i); return false; + } - memset(val, 0, sizeof(char) * name_sz); + memset(val, 0, sizeof(char) * name_sz + 1); memcpy(val, name, sizeof(char) * name_sz); reader->extern_libs[i] = val; } diff --git a/src/vm/reader/vm_rd_extern_types.c b/src/vm/reader/vm_rd_extern_types.c index ca644a7..f1a1728 100644 --- a/src/vm/reader/vm_rd_extern_types.c +++ b/src/vm/reader/vm_rd_extern_types.c @@ -20,7 +20,10 @@ bool vm_rd_extern_types(fzl_vm_reader_t *reader, FILE *fd) reader->extern_types = malloc(sizeof(fzl_extern_type_t) * types_count); if (!reader->extern_types) + { + snprintf(internal_error, sizeof(internal_error), "out of memory"); return false; + } memset(reader->extern_types, 0, sizeof(fzl_extern_type_t) * types_count); @@ -31,27 +34,50 @@ bool vm_rd_extern_types(fzl_vm_reader_t *reader, FILE *fd) uint16_t lib_slot; if (!vm_rd_u16(fd, 1, &lib_slot)) + { + snprintf(internal_error, sizeof(internal_error), + "failed to read lib slot of type #%u", i); return false; + } + type->lib_slot = lib_slot; char kind; if (!vm_rd_char(fd, 1, &kind)) + { + snprintf(internal_error, sizeof(internal_error), + "failed to read type #%u kind", i); return false; + } + type->kind = (fzl_extern_kind_t)kind; uint16_t name_sz; if (!vm_rd_u16(fd, 1, &name_sz) || name_sz < 1) + { + snprintf(internal_error, sizeof(internal_error), + "failed to read type #%u name size", i); return false; + } if (!vm_rd_char(fd, name_sz, namebuf)) + { + snprintf(internal_error, sizeof(internal_error), + "failed to read type #%u name", i); return false; + } - char *val = malloc(sizeof(char) * name_sz); + char *val = malloc(sizeof(char) * name_sz + 1); if (!val) + { + snprintf(internal_error, sizeof(internal_error), + "out of memory on type #%u name allocation", i); return false; + } + type->name = val; - memset(val, 0, sizeof(char) * name_sz); + memset(val, 0, sizeof(char) * name_sz + 1); memcpy(val, namebuf, sizeof(char) * name_sz); if (type->kind == FZL_EXTERN_KIND_HANDLE) @@ -66,21 +92,36 @@ bool vm_rd_extern_types(fzl_vm_reader_t *reader, FILE *fd) char is_primitive; if (!vm_rd_char(fd, 1, &is_primitive)) + { + snprintf(internal_error, sizeof(internal_error), + "failed to read type #%u primitivity flag", i); return false; + } + typeref->is_primitive = (bool)is_primitive; if ((bool)is_primitive) { char primitive; if (!vm_rd_char(fd, 1, &primitive)) + { + snprintf(internal_error, sizeof(internal_error), + "failed to read type #%u primitive", i); return false; + } + typeref->primitive = (fzl_type_t)primitive; } else { uint16_t slot; if (!vm_rd_u16(fd, 1, &slot)) + { + snprintf(internal_error, sizeof(internal_error), + "failed to read type #%u slot index", i); return false; + } + typeref->type_slot = slot; } @@ -88,16 +129,28 @@ bool vm_rd_extern_types(fzl_vm_reader_t *reader, FILE *fd) } if (type->kind != FZL_EXTERN_KIND_STRUCT) + { + snprintf(internal_error, sizeof(internal_error), "unknown type #%u kind", + i); return false; + } uint16_t fields_count; if (!vm_rd_u16(fd, 1, &fields_count)) + { + snprintf(internal_error, sizeof(internal_error), + "failed to read type #%u structure fields count", i); return false; + } fzl_extern_struct_field_t *fields = malloc(sizeof(fzl_extern_struct_field_t) * fields_count); if (!fields) + { + snprintf(internal_error, sizeof(internal_error), + "out of memory on type #%u structure fields allocation", i); return false; + } memset(fields, 0, sizeof(fzl_extern_struct_field_t) * fields_count); type->structure.fields = fields; @@ -109,22 +162,38 @@ bool vm_rd_extern_types(fzl_vm_reader_t *reader, FILE *fd) char has_name; if (!vm_rd_char(fd, 1, &has_name)) + { + snprintf(internal_error, sizeof(internal_error), + "failed to read type #%u field #%u name exists flag", i, j); return false; + } if (has_name) { memset(namebuf, 0, sizeof(namebuf)); if (!vm_rd_u16(fd, 1, &name_sz)) + { + snprintf(internal_error, sizeof(internal_error), + "failed to read type #%u field #%u name size", i, j); return false; + } if (!vm_rd_char(fd, name_sz, namebuf)) + { + snprintf(internal_error, sizeof(internal_error), + "failed to read type #%u field #%u name", i, j); return false; + } - char *fval = malloc(sizeof(char) * name_sz); + char *fval = malloc(sizeof(char) * name_sz + 1); if (!fval) + { + snprintf(internal_error, sizeof(internal_error), + "out of memory on type #%u field #%u name allocation", i, j); return false; + } - memset(fval, 0, sizeof(char) * name_sz); + memset(fval, 0, sizeof(char) * name_sz + 1); memcpy(fval, namebuf, sizeof(char) * name_sz); f->name = fval; @@ -132,21 +201,36 @@ bool vm_rd_extern_types(fzl_vm_reader_t *reader, FILE *fd) char is_primitive; if (!vm_rd_char(fd, 1, &is_primitive)) + { + snprintf(internal_error, sizeof(internal_error), + "failed to read type #%u flag #%u primitivity flag", i, j); return false; + } + f->type.is_primitive = (bool)is_primitive; if (f->type.is_primitive) { char ftype; if (!vm_rd_char(fd, 1, &ftype)) + { + snprintf(internal_error, sizeof(internal_error), + "failed to read type #%u field #%u primitive", i, j); return false; + } + f->type.primitive = (fzl_type_t)ftype; } else { uint16_t fslot; if (!vm_rd_u16(fd, 1, &fslot)) + { + snprintf(internal_error, sizeof(internal_error), + "failed to read type #%u field #%u slot index", i, j); return false; + } + f->type.type_slot = fslot; } } diff --git a/src/vm/reader/vm_rd_header.c b/src/vm/reader/vm_rd_header.c index bf14fe7..6f226a0 100644 --- a/src/vm/reader/vm_rd_header.c +++ b/src/vm/reader/vm_rd_header.c @@ -13,8 +13,7 @@ bool vm_rd_header(fzl_vm_reader_t *reader, FILE *fd) return false; char chkbuf[5]; - bool ok = vm_rd_char(fd, 5, chkbuf); - if (!ok) + if (!vm_rd_char(fd, 5, chkbuf)) return false; if (memcmp(chkbuf, hdr, hdr_size) != 0) diff --git a/src/vm/reader/vm_rd_ops.c b/src/vm/reader/vm_rd_ops.c index 9e5938c..30126bb 100644 --- a/src/vm/reader/vm_rd_ops.c +++ b/src/vm/reader/vm_rd_ops.c @@ -15,13 +15,20 @@ bool vm_rd_ops(fzl_vm_reader_t *reader, FILE *fd) reader->ops = malloc(sizeof(size_t) * ops_count); if (!reader->ops) + { + snprintf(internal_error, sizeof(internal_error), "out of memory"); return false; + } for (size_t i = 0; i < ops_count; i++) { size_t opcode; if (!vm_rd_word(fd, 1, &opcode)) + { + snprintf(internal_error, sizeof(internal_error), + "failed to read opcode #%zu", i); return false; + } reader->ops[i] = opcode; } diff --git a/src/vm/reader/vm_rd_sections_sz.c b/src/vm/reader/vm_rd_sections_sz.c index 5fbe407..e9b57de 100644 --- a/src/vm/reader/vm_rd_sections_sz.c +++ b/src/vm/reader/vm_rd_sections_sz.c @@ -1,6 +1,5 @@ -#include -#include #include +#include // Reader sizes section bool vm_rd_sections_sz(fzl_vm_reader_t *reader, FILE *fd) @@ -8,22 +7,40 @@ bool vm_rd_sections_sz(fzl_vm_reader_t *reader, FILE *fd) if (!reader || !fd) return false; - bool ok = vm_rd_u16(fd, 1, (uint16_t *)&reader->consts_count); - if (!ok) + if (!vm_rd_u16(fd, 1, &reader->consts_count)) + { + snprintf(internal_error, sizeof(internal_error), + "failed to read constants table size"); return false; + } - ok = vm_rd_u16(fd, 1, &reader->extern_libs_count); - if (!ok) + if (!vm_rd_u16(fd, 1, &reader->extern_libs_count)) + { + snprintf(internal_error, sizeof(internal_error), + "failed to read external libs count"); return false; + } - ok = vm_rd_u16(fd, 1, &reader->extern_types_count); - if (!ok) + if (!vm_rd_u16(fd, 1, &reader->extern_types_count)) + { + snprintf(internal_error, sizeof(internal_error), + "failed to read external types count"); return false; + } - ok = vm_rd_u16(fd, 1, &reader->extern_fns_count); - if (!ok) + if (!vm_rd_u16(fd, 1, &reader->extern_fns_count)) + { + snprintf(internal_error, sizeof(internal_error), + "failed to read external functions count"); return false; + } - ok = vm_rd_word(fd, 1, &reader->ops_count); - return ok; + if (!vm_rd_word(fd, 1, &reader->ops_count)) + { + snprintf(internal_error, sizeof(internal_error), + "failed to read opcodes count"); + return false; + } + + return true; }