Handle endianess during MZ format parsing (#2937)

Fixes test/db/formats/pe/jman, test/db/formats/mz/chkdsk and
test/db/formats/mz/cblp0 on big endian machines.
This commit is contained in:
Anton Kochkov 2022-08-20 03:12:27 +08:00 committed by GitHub
parent d1feb6cea3
commit fa29f1bc9f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -198,6 +198,24 @@ void *rz_bin_mz_free(struct rz_bin_mz_obj_t *bin) {
return NULL;
}
static bool read_mz_header(MZ_image_dos_header *mz, RzBuffer *buf) {
ut64 offset = 0;
return rz_buf_read_le16_offset(buf, &offset, &mz->signature) &&
rz_buf_read_le16_offset(buf, &offset, &mz->bytes_in_last_block) &&
rz_buf_read_le16_offset(buf, &offset, &mz->blocks_in_file) &&
rz_buf_read_le16_offset(buf, &offset, &mz->num_relocs) &&
rz_buf_read_le16_offset(buf, &offset, &mz->header_paragraphs) &&
rz_buf_read_le16_offset(buf, &offset, &mz->min_extra_paragraphs) &&
rz_buf_read_le16_offset(buf, &offset, &mz->max_extra_paragraphs) &&
rz_buf_read_le16_offset(buf, &offset, &mz->ss) &&
rz_buf_read_le16_offset(buf, &offset, &mz->sp) &&
rz_buf_read_le16_offset(buf, &offset, &mz->checksum) &&
rz_buf_read_le16_offset(buf, &offset, &mz->ip) &&
rz_buf_read_le16_offset(buf, &offset, &mz->cs) &&
rz_buf_read_le16_offset(buf, &offset, &mz->reloc_table_offset) &&
rz_buf_read_le16_offset(buf, &offset, &mz->overlay_number);
}
static int rz_bin_mz_init_hdr(struct rz_bin_mz_obj_t *bin) {
int relocations_size, dos_file_size;
MZ_image_dos_header *mz;
@ -205,9 +223,7 @@ static int rz_bin_mz_init_hdr(struct rz_bin_mz_obj_t *bin) {
RZ_LOG_ERROR("Cannot allocate MZ_image_dos_header");
return false;
}
bin->dos_header = mz;
// TODO: read field by field to avoid endian and alignment issues
if (rz_buf_read_at(bin->b, 0, (ut8 *)mz, sizeof(*mz)) == -1) {
if (!read_mz_header(mz, bin->b)) {
RZ_LOG_ERROR("Cannot read MZ_image_dos_header\n");
return false;
}
@ -224,6 +240,7 @@ static int rz_bin_mz_init_hdr(struct rz_bin_mz_obj_t *bin) {
mz->bytes_in_last_block;
}
bin->dos_header = mz;
bin->dos_file_size = dos_file_size;
if (dos_file_size > bin->size) {
return false;
@ -263,14 +280,19 @@ static int rz_bin_mz_init_hdr(struct rz_bin_mz_obj_t *bin) {
}
}
if (relocations_size > 0) {
if (!(bin->relocation_entries = malloc(relocations_size))) {
RZ_LOG_ERROR("Cannot allocate dos relocation entries");
return false;
}
if (rz_buf_read_at(bin->b, bin->dos_header->reloc_table_offset,
(ut8 *)bin->relocation_entries, relocations_size) == -1) {
RZ_LOG_ERROR("Cannot read dos relocation entries\n");
if (relocations_size == 0) {
return true;
}
if (!(bin->relocation_entries = malloc(relocations_size))) {
RZ_LOG_ERROR("Cannot allocate dos relocation entries");
return false;
}
ut64 offset = bin->dos_header->reloc_table_offset;
int i;
for (i = 0; i < relocations_size / sizeof(MZ_image_relocation_entry); i++) {
MZ_image_relocation_entry *mz_rel_entry = bin->relocation_entries + i;
if (!rz_buf_read_le16_offset(bin->b, &offset, &mz_rel_entry->offset) ||
!rz_buf_read_le16_offset(bin->b, &offset, &mz_rel_entry->segment)) {
RZ_FREE(bin->relocation_entries);
return false;
}