diff --git a/librz/arch/cpus/c166-c166-generic.sdb.txt b/librz/arch/cpus/c166-c166-generic.sdb.txt index 3b09a75435d..d1f8b673325 100644 --- a/librz/arch/cpus/c166-c166-generic.sdb.txt +++ b/librz/arch/cpus/c166-c166-generic.sdb.txt @@ -37,9 +37,9 @@ IDX1.comment=MAC Address Pointer 1 ADEIC=io ADEIC.address=0xff9a ADEIC.comment=A/D Converter Overrun Error Interrupt Control Register -SYSCON=io -SYSCON.address=0xff0c -SYSCON.comment=CPU System Configuration Register +BUSCON0=io +BUSCON0.address=0xff0c +BUSCON0.comment=Bus Configuration Register 0 (Stack Pointer Segment Register [SPSEG]) VECSEG=io VECSEG.address=0xff12 VECSEG.comment=Bus Configuration Register 0 @@ -313,9 +313,6 @@ CCM7.comment=CAPCOM Mode Control Register 7 CP=io CP.address=0xfe10 CP.comment=CPU Context Pointer Register -R1=io -R1.address=0xfe12 -R1.comment=General Purpose Word Register R1 CRIC=io CRIC.address=0xff6a CRIC.comment=GPT2 CAPREL Interrupt Ctrl. Register diff --git a/librz/arch/isa/c166/c166_disas.c b/librz/arch/isa/c166/c166_disas.c index 6ddac794776..63445aa1d3d 100644 --- a/librz/arch/isa/c166/c166_disas.c +++ b/librz/arch/isa/c166/c166_disas.c @@ -352,8 +352,7 @@ const char *c166_extx_names[] = { }; RZ_API void c166_activate_ext(RZ_NONNULL C166State *state, ut32 addr, C166ExtState ext) { - // rz_return_if_fail(state->ext.i == 0); // realy need? - rz_return_if_fail(ext.i <= 3); + rz_return_if_fail(ext.i <= 4); state->ext = ext; state->last_addr = addr; } diff --git a/librz/bin/format/omf/omf.c b/librz/bin/format/omf/omf.c index 671fd852175..17510784a03 100644 --- a/librz/bin/format/omf/omf.c +++ b/librz/bin/format/omf/omf.c @@ -23,18 +23,25 @@ static bool is_valid_omf_type(ut8 type) { return true; } } - // RZ_LOG_ERROR("Invalid record type\n"); return false; } bool rz_bin_checksum_omf_ok(const ut8 *buf, ut64 buf_size) { ut8 checksum = 0; + if (!buf) { + RZ_LOG_ERROR("Invalid record (buf is null)\n"); + return false; + } if (buf_size < 3) { RZ_LOG_ERROR("Invalid record (too short)\n"); return false; } ut16 size = rz_read_le16(buf + 1); + if (size == 0 || size > UINT16_MAX) { + RZ_LOG_ERROR("Invalid record (untrusted value)\n"); + return false; + } if (buf_size < size + 3) { RZ_LOG_ERROR("Invalid record (too short)\n"); return false; diff --git a/librz/bin/format/omf/omf.h b/librz/bin/format/omf/omf.h index a7dd5f33e4d..4b9cacc2af1 100644 --- a/librz/bin/format/omf/omf.h +++ b/librz/bin/format/omf/omf.h @@ -224,7 +224,7 @@ typedef enum omf_ityp_t { /** * Used to specify an object file as input for L166. */ - ITYP_COMMANDLINE = 0x05, ///< Commandline descriptor. + ITYP_INVOCATION_LINE = 0xFF, ///< Invocation Line descriptor. /** * Contains the invocation line to the translator * including all invocation controls. @@ -719,6 +719,7 @@ typedef struct { typedef struct { ut8 bits; + ut64 base_addr; ut8 modinfo; int TI_INDEX; int SEC_INDEX; diff --git a/librz/bin/format/omf/omf166.c b/librz/bin/format/omf/omf166.c index cb241d697f3..47bef15b500 100644 --- a/librz/bin/format/omf/omf166.c +++ b/librz/bin/format/omf/omf166.c @@ -147,8 +147,6 @@ RZ_API const char *name_of_ti(const rz_bin_omf166_obj *obj, const ut16 ti_index) return NULL; } } - rz_warn_if_reached(); - return NULL; } const char *name_of_iTyp(ut8 iTyp) { @@ -168,11 +166,11 @@ const char *name_of_iTyp(ut8 iTyp) { case ITYP_OBJECT_INPUTFILE: { return "Object-Inputfile"; } - case ITYP_COMMANDLINE: { - return "Commandline"; + case ITYP_INVOCATION_LINE: { + return "InvocationLine"; } default: { - rz_warn_if_reached(); + RZ_LOG_WARN("UNKNOWN iTyp (%x).\n", iTyp); return "UNKNOWN"; } } @@ -323,7 +321,7 @@ static ut16 omf166_get_idx(const ut8 *buf, const size_t buf_size) { return ret; } -static bool load_omf166_lnames(const rz_bin_omf166_obj *obj, const OMF_record *record, const ut8 *buf, const size_t buf_size, ut64 global_ct) { +static bool load_omf166_lnames(const rz_bin_omf166_obj *obj, const OMF_record *record, const ut8 *buf, const size_t buf_size) { ut32 tmp_size = 0; ut32 ct_name = 0; @@ -380,8 +378,9 @@ static int load_omf166_global_sym_record(const rz_bin_omf166_obj *obj, const OMF ct++; base = rz_read_le32_offset(buf, &ct); } - } else + } else { base = rz_read_le32_offset(buf, &ct); + } if (record->size <= ct) { RZ_LOG_ERROR("Invalid sym record (bad size)\n"); @@ -396,7 +395,13 @@ static int load_omf166_global_sym_record(const rz_bin_omf166_obj *obj, const OMF sym->rec_type = record->type; sym->base = base; sym->n = rz_read_le8_offset(buf, &ct); - rz_str_ncpy(sym->name2, (const char *)&buf[ct], sym->n + 1); + if (ct + sym->n + 1 > buf_size) { + RZ_LOG_ERROR("Invalid sym record (overflow)\n"); + RZ_FREE(sym); + continue; + } + memcpy(sym->name2, buf + ct, sym->n); + sym->name2[sym->n] = '\0'; ct += sym->n; sym->offset = rz_read_le16_offset(buf, &ct); @@ -454,7 +459,7 @@ static int load_omf_data(const rz_bin_omf166_obj *obj, const ut8 *buf, const siz return true; } -static int load_omf_blkdef(const rz_bin_omf166_obj *obj, const ut8 *buf, const size_t buf_size, ut64 global_ct) { +static int load_omf_blkdef(const rz_bin_omf166_obj *obj, const ut8 *buf, const size_t buf_size) { size_t ct = 3; OMF_blocks *block = RZ_NEW0(OMF_blocks); if (!block) { @@ -470,7 +475,13 @@ static int load_omf_blkdef(const rz_bin_omf166_obj *obj, const ut8 *buf, const s } block->n = rz_read_le8_offset(buf, &ct); - rz_str_ncpy(block->name, (const char *)&buf[ct], block->n + 1); + if (ct + block->n + 1 > buf_size) { + RZ_LOG_ERROR("Invalid record (overflow)\n"); + RZ_FREE(block); + return true; + } + memcpy(block->name, buf + ct, block->n); + block->name[block->n] = '\0'; ct += block->n; block->BlockOffset16 = rz_read_le16_offset(buf, &ct); @@ -488,7 +499,7 @@ static int load_omf_blkdef(const rz_bin_omf166_obj *obj, const ut8 *buf, const s return true; } -static int load_comment_data(const rz_bin_omf166_obj *obj, const ut8 *buf, const OMF_record *record, ut64 global_ct) { +static int load_comment_data(const rz_bin_omf166_obj *obj, const ut8 *buf, const OMF_record *record) { if (!(obj && obj->coments_vec)) { return false; } @@ -504,17 +515,13 @@ static int load_comment_data(const rz_bin_omf166_obj *obj, const ut8 *buf, const comment->nopurge = (ComTyp_b1 & 0x80) >> 7; comment->is_filename = (ComTyp_b2 == 0x4b); comment->n = record->size + 3 - ct; - rz_str_ncpy(comment->text, - (const char *)&buf[ct], comment->n); + memcpy(comment->text, buf + ct, comment->n); + comment->text[comment->n] = '\0'; rz_pvector_push(obj->coments_vec, comment); return true; } static int load_grpdef_data(const rz_bin_omf166_obj *obj, const ut8 *buf, const OMF_record *record, ut64 global_ct) { - if (!obj) { - return false; - } - /* * Group Definition Record - Used to combine sections * @@ -531,12 +538,6 @@ static int load_grpdef_data(const rz_bin_omf166_obj *obj, const ut8 *buf, const static int load_deplst_data(const ut8 *buf, const OMF_record *record) { #if RZ_BUILD_DEBUG size_t ct = 3; - const ut8 some_byte = rz_read_le8_offset(buf, &ct); - (void)some_byte; - const ut8 info_n = rz_read_le8_offset(buf, &ct); - char info[255] = RZ_EMPTY; - rz_str_ncpy(info, (const char *)&buf[ct], info_n + 1); - ct += info_n; while (ct < record->size) { /** * iTyp | Mark8 | Time32 | Name(s) @@ -550,8 +551,12 @@ static int load_deplst_data(const ut8 *buf, const OMF_record *record) { In case of iTyp 4, more than one pathname may be specified. */ const ut8 iTyp = rz_read_le8_offset(buf, &ct); - const ut8 Mark8 = rz_read_le8_offset(buf, &ct); - const ut32 Time32 = rz_read_le32_offset(buf, &ct); + ut8 Mark8 = 0; + ut32 Time32 = 0; + if (iTyp != ITYP_INVOCATION_LINE) { + Mark8 = rz_read_le8_offset(buf, &ct); + Time32 = rz_read_le32_offset(buf, &ct); + } const ut8 n = rz_read_le8_offset(buf, &ct); char pathname[255] = RZ_EMPTY; rz_str_ncpy(pathname, @@ -597,7 +602,7 @@ static int load_linnum_data(const rz_bin_omf166_obj *obj, const ut8 *buf, const return true; } -static int load_omf_pedata(const rz_bin_omf166_obj *obj, const ut8 *buf, const OMF_record *record, const ut64 global_ct) { +static int load_omf_pedata(rz_bin_omf166_obj *obj, const ut8 *buf, const OMF_record *record, const ut64 global_ct) { if (!(obj && obj->pe_vec)) { return false; } @@ -622,6 +627,10 @@ static int load_omf_pedata(const rz_bin_omf166_obj *obj, const ut8 *buf, const O */ pe->size = pe->psize = record->size - 1 - (ct - 3); pe->paddr = global_ct + ct; + + if (pe->isVector) { + obj->base_addr = (ut32)pe->SegmentNumber8 << 16; + } rz_pvector_push(obj->pe_vec, pe); return true; } @@ -838,6 +847,8 @@ static int load_omf_typnew(rz_bin_omf166_obj *obj, const ut8 *buf) { */ const ut16 raw_count = rz_read_le16_offset(buf, &cct); if (raw_count == 0 || raw_count > UINT16_MAX) { + RZ_LOG_ERROR("Invalid component count (untrusted value)\n"); + RZ_FREE(newtype); return false; } newtype->label = rz_str_dup("COMPONENT_LIST_DESCRIPTOR"); @@ -860,7 +871,8 @@ static int load_omf_typnew(rz_bin_omf166_obj *obj, const ut8 *buf) { component->REP8 = rz_read_le8_offset(buf, &cct); component->POS8 = rz_read_le8_offset(buf, &cct); component->n = rz_read_le8_offset(buf, &cct); - rz_str_ncpy(component->name, (const char *)&buf[cct], component->n + 1); + memcpy(component->name, buf + cct, component->n); + component->name[component->n] = '\0'; cct += component->n; } break; @@ -912,10 +924,10 @@ static int load_omf_typnew(rz_bin_omf166_obj *obj, const ut8 *buf) { newtype->descriptor.struct_union.member_ti = rz_read_le16_offset(buf, &cct); newtype->descriptor.struct_union.n = rz_read_le8_offset(buf, &cct); - rz_str_ncpy( - newtype->descriptor.struct_union.tagname, - (const char *)&buf[cct], - newtype->descriptor.struct_union.n + 1); + memcpy(newtype->descriptor.struct_union.tagname, + buf + cct, + newtype->descriptor.struct_union.n); + newtype->descriptor.struct_union.tagname[newtype->descriptor.struct_union.n] = '\0'; newtype->label = rz_str_dup(newtype->descriptor.struct_union.tagname); break; } @@ -944,7 +956,7 @@ static int rz_bin_format_omf166_load_content(rz_bin_omf166_obj *obj, OMF_record switch (record->type) { case OMF166_LNAMES: { - return load_omf166_lnames(obj, record, buf, buf_size, global_ct); + return load_omf166_lnames(obj, record, buf, buf_size); } case OMF166_GLBDEF: case OMF166_LOCSYM: @@ -953,7 +965,7 @@ static int rz_bin_format_omf166_load_content(rz_bin_omf166_obj *obj, OMF_record return load_omf166_global_sym_record(obj, record, buf, buf_size); } case OMF166_BLKDEF: { - return load_omf_blkdef(obj, buf, buf_size, global_ct); + return load_omf_blkdef(obj, buf, buf_size); } case OMF166_VECTAB: case OMF166_PEDATA: { @@ -963,8 +975,13 @@ static int rz_bin_format_omf166_load_content(rz_bin_omf166_obj *obj, OMF_record case OMF166_THEADR: { char name[255] = RZ_EMPTY; size_t offset = 3; - ut8 n = rz_read_le8_offset(buf, &offset); - rz_str_ncpy(name, (const char *)&buf[offset], n + 1); + const ut8 n = rz_read_le8_offset(buf, &offset); + if (n + 1 + offset > buf_size) { + RZ_LOG_WARN("File may be corrupted (Overflow detected).\n"); + } else { + memcpy(name, buf + offset, n); + name[n] = '\0'; + } RZ_LOG_DEBUG("load_omf = %s = [0x%08" PFMT64x "] (%05d) `%s`\n", record->type == OMF166_THEADR ? "THEADR" : "LHEADR", global_ct, @@ -999,7 +1016,7 @@ static int rz_bin_format_omf166_load_content(rz_bin_omf166_obj *obj, OMF_record return true; } case OMF166_COMMENT: { - return load_comment_data(obj, buf, record, global_ct); + return load_comment_data(obj, buf, record); } case OMF166_GRPDEF: { return load_grpdef_data(obj, buf, record, global_ct); @@ -1039,7 +1056,12 @@ static int rz_bin_format_omf166_load_content(rz_bin_omf166_obj *obj, OMF_record while (record->size - 1 > left) { char name[255] = RZ_EMPTY; const ut8 n = rz_read_le8_offset(buf, &left); - rz_str_ncpy(name, (const char *)&buf[left], n + 1); + if (n + 1 + left > buf_size) { + RZ_LOG_WARN("File may be corrupted (Overflow detected).\n"); + } else { + memcpy(name, buf + left, n); + name[n] = '\0'; + } left += n; } return true; @@ -1056,6 +1078,11 @@ static int rz_bin_format_omf166_load_content(rz_bin_omf166_obj *obj, OMF_record case OMF166_UNKNOWN4: { return load_omf_unk4(buf, buf_size, record, global_ct); } + case OMF166_SSKDEF: { + RZ_LOG_DEBUG("load_omf: [%05d] [0x%08" PFMT64x "] 0x%02x (%" PFMTSZu ")\n", + record->size, global_ct, record->type, buf_size); + return true; + } default: { RZ_LOG_DEBUG("load_omf: [%05d] [0x%08" PFMT64x "] 0x%02x (%" PFMTSZu ")\t", record->size, global_ct, record->type, buf_size); @@ -1083,6 +1110,8 @@ static OMF_record *rz_bin_format_omf166_load_record(rz_bin_omf166_obj *obj, cons new->type = rz_read_le8_offset(buf, &offset); const ut16 raw_count = rz_read_le16_offset(buf, &offset); if (raw_count == 0 || raw_count > UINT16_MAX) { + RZ_LOG_ERROR("Invalid record (untrusted value)\n"); + RZ_FREE(new); return false; } new->size = raw_count; diff --git a/librz/bin/p/bin_c166.c b/librz/bin/p/bin_c166.c index 1bc0f60aae6..d842795d1ec 100644 --- a/librz/bin/p/bin_c166.c +++ b/librz/bin/p/bin_c166.c @@ -35,7 +35,7 @@ rz_bin_c166_obj *rz_bin_format_c166_load(const ut8 *buf, ut64 size) { return NULL; } const ut8 c = rz_read_le8(buf + 1); - ret->base_addr = c << 16 | 0x000000; + ret->base_addr = (ut32)c << 16; return ret; } @@ -111,7 +111,7 @@ static RzPVector /**/ *entries(RzBinFile *bf) { if (!bf || !bf->o || !bf->o->bin_obj) { return NULL; } - rz_bin_c166_obj *obj = bf->o->bin_obj; + const rz_bin_c166_obj *obj = bf->o->bin_obj; RzPVector *ret; RzBinAddr *addr; @@ -158,6 +158,11 @@ static RzBinAddr *binsym(RzBinFile *bf, RzBinSpecialSymbol type) { } } +static ut64 baddr(RzBinFile *bf) { + const rz_bin_c166_obj *obj = (rz_bin_c166_obj *)bf->o->bin_obj; + return obj->base_addr; +} + struct rz_bin_plugin_t rz_bin_plugin_c166 = { .name = "c166", .desc = "Siemens/Infineon C166 family microcontroller binary", @@ -171,6 +176,7 @@ struct rz_bin_plugin_t rz_bin_plugin_c166 = { .info = &info, .binsym = &binsym, .strings = &strings, + .baddr = baddr }; #ifndef RZ_PLUGIN_INCORE diff --git a/librz/bin/p/bin_omf166.c b/librz/bin/p/bin_omf166.c index f05eb7faef9..a94f7761b4d 100644 --- a/librz/bin/p/bin_omf166.c +++ b/librz/bin/p/bin_omf166.c @@ -100,6 +100,8 @@ static bool check_buffer(RzBuffer *b) { static RzPVector /**/ *entries(RzBinFile *bf) { RzPVector *ret; RzBinAddr *addr; + rz_bin_omf166_obj *obj = (rz_bin_omf166_obj *)bf->o->bin_obj; + if (!((ret = rz_pvector_new(free)))) { return NULL; } @@ -108,7 +110,7 @@ static RzPVector /**/ *entries(RzBinFile *bf) { return NULL; } addr->type = RZ_BIN_SPECIAL_SYMBOL_ENTRY; - addr->vaddr = 0xC00000; + addr->vaddr = obj->base_addr; rz_pvector_push(ret, addr); return ret; } @@ -180,8 +182,8 @@ static RzPVector /**/ *sections(RzBinFile *bf) { new->name = rz_str_newf("%s_%s", name, class_name); new->size = new->vsize = section->Seclen; new->vaddr = (section->SegmentNumber8 << 16) + section->offset; - new->has_strings = (section->Type == 1) ? true : false; - new->is_data = (section->Type == 1) ? true : false; + new->has_strings = section->Type != 2; + new->is_data = section->Type != 2; new->is_segment = 0; new->perm = c166_get_perms_from_class(section->class_index); rz_pvector_push(ret, new); @@ -217,6 +219,9 @@ static RzPVector /**/ *symbols(RzBinFile *bf) { } RzPVector *ret = rz_pvector_new((RzPVectorFree)rz_bin_symbol_free); + if (!ret) { + return NULL; + } rz_pvector_sort(obj->symbols_vec, offset_cmp, NULL); void **it; rz_pvector_foreach (obj->symbols_vec, it) { @@ -371,6 +376,7 @@ static RzBinInfo *info(RzBinFile *bf) { ret->rclass = rz_str_dup("OMF166"); ret->compiler = rz_str_dup("keil"); ret->os = rz_str_dup("c166"); + ret->cpu = rz_str_dup("c166-generic"); ret->machine = rz_str_dup("Siemens/Infineon C166 family microcontroller"); ret->arch = rz_str_dup("c166"); ret->big_endian = false; @@ -395,6 +401,7 @@ static RzPVector /**/ *strings(RzBinFile *bf) { static RzBinAddr *binsym(RzBinFile *bf, RzBinSpecialSymbol type) { RzBinAddr *ptr = NULL; + rz_bin_omf166_obj *obj = (rz_bin_omf166_obj *)bf->o->bin_obj; switch (type) { case RZ_BIN_SPECIAL_SYMBOL_ENTRY: @@ -404,7 +411,7 @@ static RzBinAddr *binsym(RzBinFile *bf, RzBinSpecialSymbol type) { return NULL; } ptr->type = RZ_BIN_SPECIAL_SYMBOL_ENTRY; - ptr->vaddr = 0xC00000; + ptr->vaddr = obj->base_addr; return ptr; case RZ_BIN_SPECIAL_SYMBOL_MAIN: if (!((ptr = RZ_NEW0(RzBinAddr)))) { @@ -421,6 +428,11 @@ static RzBinAddr *binsym(RzBinFile *bf, RzBinSpecialSymbol type) { } } +static ut64 baddr(RzBinFile *bf) { + rz_bin_omf166_obj *obj = (rz_bin_omf166_obj *)bf->o->bin_obj; + return obj->base_addr; +} + RzBinPlugin rz_bin_plugin_omf166 = { .name = "omf166", .desc = "OMF166 (Object Module Format by Siemens)", @@ -438,6 +450,7 @@ RzBinPlugin rz_bin_plugin_omf166 = { .info = &info, .strings = &strings, .get_vaddr = &get_vaddr, + .baddr = baddr }; #ifndef RZ_PLUGIN_INCORE diff --git a/test/db/analysis/c166 b/test/db/analysis/c166 index 480687411e6..7b1f00c2717 100644 --- a/test/db/analysis/c166 +++ b/test/db/analysis/c166 @@ -311,20 +311,20 @@ EXPECT=< 0x00c0001c 9ab7fe70 jnb 0xff6e, _getkey ; Getkey.c:22 ; 0xc0001c ; [09] -rw- section size 12 named PR_GETKEY_FCODE +| @=-> 0x00c0001c 9ab7fe70 jnb S0RIC.7, _getkey ; Getkey.c:22 ; 0xc0001c ; [09] -rw- section size 12 named PR_GETKEY_FCODE | | 0x00c00020 f2f4b2fe mov r4, 0xfe06:0x3eb2 ; Getkey.c:26 -| | 0x00c00024 7eb7 bclr 0xff6e ; Getkey.c:27 +| | 0x00c00024 7eb7 bclr S0RIC.7 ; Getkey.c:27 \ | 0x00c00026 db00 rets ; Getkey.c:28 / sym.isr_vec_0x28(); \ ,==< 0x00c00028 fac07a00 jmps Class_B_trap ; 0xc0007a ; "\r\xff\xff\xff\xff\xff\xfa\xc0\x80\U00000012\xa5Z\xa5\xa5р\xe6\xea" || ;-- section.C_CLRMEMSEC_UNKNOWN: - || 0x00c0002c 1a800400 bfldh 0xff00, #0x00, #0x04 ; [26] -r-- section size 24 named C_CLRMEMSEC_UNKNOWN + || 0x00c0002c 1a800400 bfldh P0L, #0x00, #0x04 ; [26] -r-- section size 24 named C_CLRMEMSEC_UNKNOWN || 0x00c00030 40c2 cmp r12, r2 - || 0x00c00032 0fa0 bset 0xff40.0 - || 0x00c00034 04005cc2 add 0xfe06:0x025c, 0xfe00 - || 0x00c00038 03000000 addb 0xfe00, 0xfe00:0x0000 + || 0x00c00032 0fa0 bset T2CON.0 + || 0x00c00034 04005cc2 add 0xfe06:0x025c, DPP0 + || 0x00c00038 03000000 addb DPP0, 0xfe00:0x0000 || 0x00c0003c 0080 add r8, r0 - || 0x00c0003e 04005bc2 add 0xfe06:0x025b, 0xfe00 + || 0x00c0003e 04005bc2 add 0xfe06:0x025b, DPP0 || 0x00c00042 0000 add r0, r0 || ;-- section.C_LIB_NCONST_NCONST: || 0x00c00044 0000 add r0, r0 ; [19] -r-- section size 48 named C_LIB_NCONST_NCONST @@ -338,13 +338,13 @@ EXPECT=<