diff --git a/libclamav/elf.c b/libclamav/elf.c index 19edfe346..5ce6c8bed 100644 --- a/libclamav/elf.c +++ b/libclamav/elf.c @@ -99,8 +99,8 @@ static uint64_t cli_rawaddr64(uint64_t vaddr, struct elf_program_hdr64 *ph, uint } /* Return converted endian-fixed header, or error code */ -static int cli_elf_fileheader(cli_ctx *ctx, fmap_t *map, union elf_file_hdr *file_hdr, - uint8_t *do_convert, uint8_t *is64) +static cl_error_t cli_elf_fileheader(cli_ctx *ctx, fmap_t *map, union elf_file_hdr *file_hdr, + uint8_t *do_convert, uint8_t *is64) { uint8_t format64, conv; @@ -306,8 +306,8 @@ static int cli_elf_ph32(cli_ctx *ctx, fmap_t *map, struct cli_exe_info *elfinfo, } /* Read 64-bit program headers */ -static int cli_elf_ph64(cli_ctx *ctx, fmap_t *map, struct cli_exe_info *elfinfo, - struct elf_file_hdr64 *file_hdr, uint8_t conv) +static cl_error_t cli_elf_ph64(cli_ctx *ctx, fmap_t *map, struct cli_exe_info *elfinfo, + struct elf_file_hdr64 *file_hdr, uint8_t conv) { struct elf_program_hdr64 *program_hdr = NULL; uint16_t phnum, phentsize; @@ -791,11 +791,11 @@ cl_error_t cli_scanelf(cli_ctx *ctx) /* ELF header parsing only * Returns 0 on success, -1 on error */ -int cli_elfheader(cli_ctx *ctx, struct cli_exe_info *elfinfo) +cl_error_t cli_elfheader(cli_ctx *ctx, struct cli_exe_info *elfinfo) { union elf_file_hdr file_hdr; uint8_t conv = 0, is64 = 0; - int ret; + cl_error_t ret = CL_SUCCESS; cli_dbgmsg("in cli_elfheader\n"); @@ -806,8 +806,8 @@ int cli_elfheader(cli_ctx *ctx, struct cli_exe_info *elfinfo) } ret = cli_elf_fileheader(NULL, ctx->fmap, &file_hdr, &conv, &is64); - if (ret != CL_CLEAN) { - return -1; + if (ret != CL_SUCCESS) { + goto done; } /* Program headers and Entry */ @@ -816,8 +816,8 @@ int cli_elfheader(cli_ctx *ctx, struct cli_exe_info *elfinfo) } else { ret = cli_elf_ph32(NULL, ctx->fmap, elfinfo, &(file_hdr.hdr32.hdr), conv); } - if (ret != CL_CLEAN) { - return -1; + if (ret != CL_SUCCESS) { + goto done; } /* Section Headers */ @@ -826,11 +826,13 @@ int cli_elfheader(cli_ctx *ctx, struct cli_exe_info *elfinfo) } else { ret = cli_elf_sh32(NULL, ctx->fmap, elfinfo, &(file_hdr.hdr32.hdr), conv); } - if (ret != CL_CLEAN) { - return -1; + if (ret != CL_SUCCESS) { + goto done; } - return 0; +done: + + return ret; } /* diff --git a/libclamav/elf.h b/libclamav/elf.h index 014f4e6eb..6cb8267e0 100644 --- a/libclamav/elf.h +++ b/libclamav/elf.h @@ -145,7 +145,7 @@ struct elf_section_hdr64 { cl_error_t cli_scanelf(cli_ctx *ctx); -int cli_elfheader(cli_ctx *ctx, struct cli_exe_info *elfinfo); +cl_error_t cli_elfheader(cli_ctx *ctx, struct cli_exe_info *elfinfo); cl_error_t cli_unpackelf(cli_ctx *ctx); diff --git a/libclamav/macho.c b/libclamav/macho.c index 97f09e198..038c9a23d 100644 --- a/libclamav/macho.c +++ b/libclamav/macho.c @@ -169,8 +169,6 @@ struct macho_fat_arch { }; #define RETURN_BROKEN \ - if (matcher) \ - return -1; \ if (SCAN_HEURISTIC_BROKEN) { \ if (CL_VIRUS == cli_append_potentially_unwanted(ctx, "Heuristics.Broken.Executable")) \ return CL_VIRUS; \ @@ -197,7 +195,7 @@ static uint32_t cli_rawaddr(uint32_t vaddr, struct cli_exe_section *sects, uint1 return vaddr - sects[i].rva + sects[i].raw; } -int cli_scanmacho(cli_ctx *ctx, struct cli_exe_info *fileinfo) +cl_error_t cli_scanmacho(cli_ctx *ctx, struct cli_exe_info *fileinfo) { struct macho_hdr hdr; struct macho_load_cmd load_cmd; @@ -205,7 +203,8 @@ int cli_scanmacho(cli_ctx *ctx, struct cli_exe_info *fileinfo) struct macho_segment_cmd64 segment_cmd64; struct macho_section section; struct macho_section64 section64; - unsigned int i, j, sect = 0, conv, m64, nsects, matcher = 0; + unsigned int i, j, sect = 0, conv, m64, nsects; + bool get_fileinfo = false; unsigned int arch = 0, ep = 0, err; struct cli_exe_section *sections = NULL; char name[16]; @@ -213,7 +212,7 @@ int cli_scanmacho(cli_ctx *ctx, struct cli_exe_info *fileinfo) ssize_t at; if (fileinfo) { - matcher = 1; + get_fileinfo = true; // TODO This code assumes fileinfo->offset == 0, which might not always // be the case. For now just print this debug message and continue on @@ -224,7 +223,7 @@ int cli_scanmacho(cli_ctx *ctx, struct cli_exe_info *fileinfo) if (fmap_readn(map, &hdr, 0, sizeof(hdr)) != sizeof(hdr)) { cli_dbgmsg("cli_scanmacho: Can't read header\n"); - return matcher ? -1 : CL_EFORMAT; + return CL_EFORMAT; } at = sizeof(hdr); @@ -242,44 +241,44 @@ int cli_scanmacho(cli_ctx *ctx, struct cli_exe_info *fileinfo) m64 = 1; } else { cli_dbgmsg("cli_scanmacho: Incorrect magic\n"); - return matcher ? -1 : CL_EFORMAT; + return CL_EFORMAT; } switch (EC32(hdr.cpu_type, conv)) { case 7: - if (!matcher) + if (!get_fileinfo) cli_dbgmsg("MACHO: CPU Type: Intel 32-bit\n"); arch = 1; break; case 7 | 0x1000000: - if (!matcher) + if (!get_fileinfo) cli_dbgmsg("MACHO: CPU Type: Intel 64-bit\n"); break; case 12: - if (!matcher) + if (!get_fileinfo) cli_dbgmsg("MACHO: CPU Type: ARM\n"); break; case 14: - if (!matcher) + if (!get_fileinfo) cli_dbgmsg("MACHO: CPU Type: SPARC\n"); break; case 18: - if (!matcher) + if (!get_fileinfo) cli_dbgmsg("MACHO: CPU Type: POWERPC 32-bit\n"); arch = 2; break; case 18 | 0x1000000: - if (!matcher) + if (!get_fileinfo) cli_dbgmsg("MACHO: CPU Type: POWERPC 64-bit\n"); arch = 3; break; default: - if (!matcher) + if (!get_fileinfo) cli_dbgmsg("MACHO: CPU Type: ** UNKNOWN ** (%u)\n", EC32(hdr.cpu_type, conv)); break; } - if (!matcher) switch (EC32(hdr.filetype, conv)) { + if (!get_fileinfo) switch (EC32(hdr.filetype, conv)) { case 0x1: /* MH_OBJECT */ cli_dbgmsg("MACHO: Filetype: Relocatable object file\n"); break; @@ -311,7 +310,7 @@ int cli_scanmacho(cli_ctx *ctx, struct cli_exe_info *fileinfo) cli_dbgmsg("MACHO: Filetype: ** UNKNOWN ** (0x%x)\n", EC32(hdr.filetype, conv)); } - if (!matcher) { + if (!get_fileinfo) { cli_dbgmsg("MACHO: Number of load commands: %u\n", EC32(hdr.ncmds, conv)); cli_dbgmsg("MACHO: Size of load commands: %u\n", EC32(hdr.sizeofcmds, conv)); } @@ -362,7 +361,7 @@ int cli_scanmacho(cli_ctx *ctx, struct cli_exe_info *fileinfo) strncpy(name, segment_cmd.segname, sizeof(name)); name[sizeof(name) - 1] = '\0'; } - if (!matcher) { + if (!get_fileinfo) { cli_dbgmsg("MACHO: Segment name: %s\n", name); cli_dbgmsg("MACHO: Number of sections: %u\n", nsects); } @@ -372,14 +371,14 @@ int cli_scanmacho(cli_ctx *ctx, struct cli_exe_info *fileinfo) RETURN_BROKEN; } if (!nsects) { - if (!matcher) + if (!get_fileinfo) cli_dbgmsg("MACHO: ------------------\n"); continue; } sections = (struct cli_exe_section *)cli_realloc2(sections, (sect + nsects) * sizeof(struct cli_exe_section)); if (!sections) { cli_errmsg("cli_scanmacho: Can't allocate memory for 'sections'\n"); - return matcher ? -1 : CL_EMEM; + return CL_EMEM; } for (j = 0; j < nsects; j++) { @@ -417,7 +416,7 @@ int cli_scanmacho(cli_ctx *ctx, struct cli_exe_info *fileinfo) strncpy(name, section.sectname, sizeof(name)); name[sizeof(name) - 1] = '\0'; } - if (!matcher) { + if (!get_fileinfo) { cli_dbgmsg("MACHO: --- Section %u ---\n", sect); cli_dbgmsg("MACHO: Name: %s\n", name); cli_dbgmsg("MACHO: Virtual address: 0x%x\n", (unsigned int)sections[sect].rva); @@ -428,7 +427,7 @@ int cli_scanmacho(cli_ctx *ctx, struct cli_exe_info *fileinfo) } sect++; } - if (!matcher) + if (!get_fileinfo) cli_dbgmsg("MACHO: ------------------\n"); } else if (arch && (load_cmd.cmd == 0x4 || load_cmd.cmd == 0x5)) { /* LC_(UNIX)THREAD */ @@ -477,7 +476,7 @@ int cli_scanmacho(cli_ctx *ctx, struct cli_exe_info *fileinfo) default: cli_errmsg("cli_scanmacho: Invalid arch setting!\n"); free(sections); - return matcher ? -1 : CL_EARG; + return CL_EARG; } } else { if (EC32(load_cmd.cmdsize, conv) > sizeof(load_cmd)) @@ -486,32 +485,32 @@ int cli_scanmacho(cli_ctx *ctx, struct cli_exe_info *fileinfo) } if (ep) { - if (!matcher) + if (!get_fileinfo) cli_dbgmsg("Entry Point: 0x%x\n", ep); if (sections) { ep = cli_rawaddr(ep, sections, sect, &err); if (err) { cli_dbgmsg("cli_scanmacho: Can't calculate EP offset\n"); free(sections); - return matcher ? -1 : CL_EFORMAT; + return CL_EFORMAT; } - if (!matcher) + if (!get_fileinfo) cli_dbgmsg("Entry Point file offset: %u\n", ep); } } - if (matcher) { + if (get_fileinfo) { fileinfo->ep = ep; fileinfo->nsections = sect; fileinfo->sections = sections; - return 0; } else { free(sections); - return CL_SUCCESS; } + + return CL_SUCCESS; } -int cli_machoheader(cli_ctx *ctx, struct cli_exe_info *fileinfo) +cl_error_t cli_machoheader(cli_ctx *ctx, struct cli_exe_info *fileinfo) { return cli_scanmacho(ctx, fileinfo); } @@ -520,7 +519,7 @@ cl_error_t cli_scanmacho_unibin(cli_ctx *ctx) { struct macho_fat_header fat_header; struct macho_fat_arch fat_arch; - unsigned int conv, i, matcher = 0; + unsigned int conv, i; cl_error_t ret = CL_SUCCESS; fmap_t *map = ctx->fmap; ssize_t at; diff --git a/libclamav/macho.h b/libclamav/macho.h index cf763c5dc..ffb99c8b1 100644 --- a/libclamav/macho.h +++ b/libclamav/macho.h @@ -26,8 +26,8 @@ #include "execs.h" #include "fmap.h" -int cli_scanmacho(cli_ctx *ctx, struct cli_exe_info *fileinfo); -int cli_machoheader(cli_ctx *ctx, struct cli_exe_info *fileinfo); +cl_error_t cli_scanmacho(cli_ctx *ctx, struct cli_exe_info *fileinfo); +cl_error_t cli_machoheader(cli_ctx *ctx, struct cli_exe_info *fileinfo); cl_error_t cli_scanmacho_unibin(cli_ctx *ctx); cl_error_t cli_unpackmacho(cli_ctx *ctx); diff --git a/libclamav/matcher.c b/libclamav/matcher.c index d5b96e0b8..52d0d0013 100644 --- a/libclamav/matcher.c +++ b/libclamav/matcher.c @@ -346,7 +346,7 @@ cl_error_t cli_scan_buff(const unsigned char *buffer, uint32_t length, uint32_t * offdata[2]: max shift * offdata[3]: section number */ -cl_error_t cli_caloff(const char *offstr, const struct cli_target_info *info, unsigned int target, uint32_t *offdata, uint32_t *offset_min, uint32_t *offset_max) +cl_error_t cli_caloff(const char *offstr, const struct cli_target_info *info, cli_target_t target, uint32_t *offdata, uint32_t *offset_min, uint32_t *offset_max) { char offcpy[65] = {0}; unsigned int n = 0, val = 0; @@ -453,7 +453,7 @@ cl_error_t cli_caloff(const char *offstr, const struct cli_target_info *info, un if (offdata[0] != CLI_OFF_ANY && offdata[0] != CLI_OFF_ABSOLUTE && offdata[0] != CLI_OFF_EOF_MINUS && offdata[0] != CLI_OFF_MACRO) { - if (target != 1 && target != 6 && target != 9) { + if (target != TARGET_PE && target != TARGET_ELF && target != TARGET_MACHO) { cli_errmsg("cli_caloff: Invalid offset type for target %u\n", target); return CL_EMALFDB; } @@ -533,22 +533,27 @@ void cli_targetinfo_init(struct cli_target_info *info) cli_exe_info_init(&(info->exeinfo), 0); } -void cli_targetinfo(struct cli_target_info *info, unsigned int target, cli_ctx *ctx) +void cli_targetinfo(struct cli_target_info *info, cli_target_t target, cli_ctx *ctx) { - int (*einfo)(cli_ctx *, struct cli_exe_info *) = NULL; + cl_error_t (*einfo)(cli_ctx *, struct cli_exe_info *) = NULL; info->fsize = ctx->fmap->len; - if (target == 1) - einfo = cli_pe_targetinfo; - else if (target == 6) - einfo = cli_elfheader; - else if (target == 9) - einfo = cli_machoheader; - else - return; + switch (target) { + case TARGET_PE: + einfo = cli_pe_targetinfo; + break; + case TARGET_ELF: + einfo = cli_elfheader; + break; + case TARGET_MACHO: + einfo = cli_machoheader; + break; + default: + return; + } - if (einfo(ctx, &info->exeinfo)) + if (CL_SUCCESS != einfo(ctx, &info->exeinfo)) info->status = -1; else info->status = 1; diff --git a/libclamav/matcher.h b/libclamav/matcher.h index 8e2d946ea..e139c0e90 100644 --- a/libclamav/matcher.h +++ b/libclamav/matcher.h @@ -203,11 +203,29 @@ struct cli_cdb { struct cli_cdb *next; }; +typedef enum { + TARGET_GENERIC = 0, + TARGET_PE = 1, + TARGET_OLE2 = 2, + TARGET_HTML = 3, + TARGET_MAIL = 4, + TARGET_GRAPHICS = 5, + TARGET_ELF = 6, + TARGET_ASCII = 7, + TARGET_NOT_USED = 8, + TARGET_MACHO = 9, + TARGET_PDF = 10, + TARGET_FLASH = 11, + TARGET_JAVA = 12, + TARGET_INTERNAL = 13, + TARGET_OTHER = 14, +} cli_target_t; + #define CLI_MAX_TARGETS 10 /* maximum filetypes for a specific target */ struct cli_mtarget { cli_file_t target[CLI_MAX_TARGETS]; const char *name; - uint8_t idx; /* idx of matcher */ + cli_target_t idx; /* idx of matcher */ uint8_t ac_only; uint8_t enable_prefiltering; uint8_t target_count; /* must be synced with non-zero values in the target array */ @@ -216,21 +234,21 @@ struct cli_mtarget { #define CLI_MTARGETS 15 static const struct cli_mtarget cli_mtargets[CLI_MTARGETS] = { /* All types for target, name, idx, ac_only, pre-filtering?, # of types */ - {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, "GENERIC", 0, 0, 1, 1}, - {{CL_TYPE_MSEXE, 0, 0, 0, 0, 0, 0, 0, 0, 0}, "PE", 1, 0, 1, 1}, - {{CL_TYPE_MSOLE2, 0, 0, 0, 0, 0, 0, 0, 0, 0}, "OLE2", 2, 1, 0, 1}, - {{CL_TYPE_HTML, 0, 0, 0, 0, 0, 0, 0, 0, 0}, "HTML", 3, 1, 0, 1}, - {{CL_TYPE_MAIL, 0, 0, 0, 0, 0, 0, 0, 0, 0}, "MAIL", 4, 1, 1, 1}, - {{CL_TYPE_GRAPHICS, CL_TYPE_GIF, CL_TYPE_PNG, CL_TYPE_JPEG, CL_TYPE_TIFF, 0, 0, 0, 0, 0}, "GRAPHICS", 5, 1, 0, 5}, - {{CL_TYPE_ELF, 0, 0, 0, 0, 0, 0, 0, 0, 0}, "ELF", 6, 1, 0, 1}, - {{CL_TYPE_TEXT_ASCII, 0, 0, 0, 0, 0, 0, 0, 0, 0}, "ASCII", 7, 1, 1, 1}, - {{CL_TYPE_ERROR, 0, 0, 0, 0, 0, 0, 0, 0, 0}, "NOT USED", 8, 1, 0, 1}, - {{CL_TYPE_MACHO, CL_TYPE_MACHO_UNIBIN, 0, 0, 0, 0, 0, 0, 0, 0}, "MACH-O", 9, 1, 0, 2}, - {{CL_TYPE_PDF, 0, 0, 0, 0, 0, 0, 0, 0, 0}, "PDF", 10, 1, 0, 1}, - {{CL_TYPE_SWF, 0, 0, 0, 0, 0, 0, 0, 0, 0}, "FLASH", 11, 1, 0, 1}, - {{CL_TYPE_JAVA, 0, 0, 0, 0, 0, 0, 0, 0, 0}, "JAVA", 12, 1, 0, 1}, - {{CL_TYPE_INTERNAL, 0, 0, 0, 0, 0, 0, 0, 0, 0}, "INTERNAL", 13, 1, 0, 1}, - {{CL_TYPE_OTHER, 0, 0, 0, 0, 0, 0, 0, 0, 0}, "OTHER", 14, 1, 0, 1}}; + {{CL_TYPE_ANY, 0, 0, 0, 0, 0, 0, 0, 0, 0}, "GENERIC", TARGET_GENERIC, 0, 1, 1}, + {{CL_TYPE_MSEXE, 0, 0, 0, 0, 0, 0, 0, 0, 0}, "PE", TARGET_PE, 0, 1, 1}, + {{CL_TYPE_MSOLE2, 0, 0, 0, 0, 0, 0, 0, 0, 0}, "OLE2", TARGET_OLE2, 1, 0, 1}, + {{CL_TYPE_HTML, 0, 0, 0, 0, 0, 0, 0, 0, 0}, "HTML", TARGET_HTML, 1, 0, 1}, + {{CL_TYPE_MAIL, 0, 0, 0, 0, 0, 0, 0, 0, 0}, "MAIL", TARGET_MAIL, 1, 1, 1}, + {{CL_TYPE_GRAPHICS, CL_TYPE_GIF, CL_TYPE_PNG, CL_TYPE_JPEG, CL_TYPE_TIFF, 0, 0, 0, 0, 0}, "GRAPHICS", TARGET_GRAPHICS, 1, 0, 5}, + {{CL_TYPE_ELF, 0, 0, 0, 0, 0, 0, 0, 0, 0}, "ELF", TARGET_ELF, 1, 0, 1}, + {{CL_TYPE_TEXT_ASCII, 0, 0, 0, 0, 0, 0, 0, 0, 0}, "ASCII", TARGET_ASCII, 1, 1, 1}, + {{CL_TYPE_ERROR, 0, 0, 0, 0, 0, 0, 0, 0, 0}, "NOT USED", TARGET_NOT_USED, 1, 0, 1}, + {{CL_TYPE_MACHO, CL_TYPE_MACHO_UNIBIN, 0, 0, 0, 0, 0, 0, 0, 0}, "MACH-O", TARGET_MACHO, 1, 0, 2}, + {{CL_TYPE_PDF, 0, 0, 0, 0, 0, 0, 0, 0, 0}, "PDF", TARGET_PDF, 1, 0, 1}, + {{CL_TYPE_SWF, 0, 0, 0, 0, 0, 0, 0, 0, 0}, "FLASH", TARGET_FLASH, 1, 0, 1}, + {{CL_TYPE_JAVA, 0, 0, 0, 0, 0, 0, 0, 0, 0}, "JAVA", TARGET_JAVA, 1, 0, 1}, + {{CL_TYPE_INTERNAL, 0, 0, 0, 0, 0, 0, 0, 0, 0}, "INTERNAL", TARGET_INTERNAL, 1, 0, 1}, + {{CL_TYPE_OTHER, 0, 0, 0, 0, 0, 0, 0, 0, 0}, "OTHER", TARGET_OTHER, 1, 0, 1}}; // clang-format off diff --git a/libclamav/pe.c b/libclamav/pe.c index bc31aac2a..f5dcea993 100644 --- a/libclamav/pe.c +++ b/libclamav/pe.c @@ -2775,7 +2775,7 @@ int cli_scanpe(cli_ctx *ctx) char *dest = NULL; int ndesc; cl_error_t ret = CL_SUCCESS; - cli_peheader_error_t peheader_ret; + cl_error_t peheader_ret; int upack = 0; size_t fsize; struct cli_bc_ctx *bc_ctx; @@ -2829,34 +2829,39 @@ int cli_scanpe(cli_ctx *ctx) // successfully on Windows, we need to relax our PE parsing standards so // that we make sure the executable gets scanned appropriately -#define PE_HDR_PARSE_FAIL_CONSEQUENCE "won't attempt .mdb / .imp / PE-specific BC rule matching or exe unpacking\n" + switch (peheader_ret) { + case CL_EFORMAT: + ret = CL_SUCCESS; + if (DETECT_BROKEN_PE) { + ret = cli_append_potentially_unwanted(ctx, "Heuristics.Broken.Executable"); + } + cli_dbgmsg("cli_scanpe: PE header appears broken - won't attempt .mdb / .imp / PE-specific BC rule matching or exe unpacking\n"); + cli_exe_info_destroy(peinfo); + return ret; - if (CLI_PEHEADER_RET_BROKEN_PE == peheader_ret) { - ret = CL_SUCCESS; - if (DETECT_BROKEN_PE) { - ret = cli_append_potentially_unwanted(ctx, "Heuristics.Broken.Executable"); - } - cli_dbgmsg("cli_scanpe: PE header appears broken - " PE_HDR_PARSE_FAIL_CONSEQUENCE); - cli_exe_info_destroy(peinfo); - return ret; + case CL_ERROR: + ret = CL_SUCCESS; + cli_dbgmsg("cli_scanpe: An error occurred when parsing the PE header - won't attempt .mdb / .imp / PE-specific BC rule matching or exe unpacking\n"); + cli_exe_info_destroy(peinfo); + return ret; - } else if (CLI_PEHEADER_RET_JSON_TIMEOUT == peheader_ret) { - cli_dbgmsg("cli_scanpe: JSON creation timed out - " PE_HDR_PARSE_FAIL_CONSEQUENCE); - cli_exe_info_destroy(peinfo); - return CL_ETIMEOUT; + case CL_ETIMEOUT: + ret = CL_ETIMEOUT; + cli_dbgmsg("cli_scanpe: JSON creation timed out - won't attempt .mdb / .imp / PE-specific BC rule matching or exe unpacking\n"); + cli_exe_info_destroy(peinfo); + return ret; - } else if (CLI_PEHEADER_RET_GENERIC_ERROR == peheader_ret) { - cli_dbgmsg("cli_scanpe: An error occurred when parsing the PE header - " PE_HDR_PARSE_FAIL_CONSEQUENCE); - cli_exe_info_destroy(peinfo); - return CL_SUCCESS; + default: + break; } if (!peinfo->is_pe32plus) { /* PE */ - if (DCONF & PE_CONF_UPACK) + if (DCONF & PE_CONF_UPACK) { upack = (EC16(peinfo->file_hdr.SizeOfOptionalHeader) == 0x148); + } } - for (i = 0; i < peinfo->nsections; i++) { + for (i = 0; i < peinfo->nsections; i++) { if (peinfo->sections[i].rsz) { /* Don't bother with virtual only sections */ // TODO Regarding the commented out check below: // This used to check that the section name was NULL, but now that @@ -4428,7 +4433,7 @@ int cli_scanpe(cli_ctx *ctx) return CL_SUCCESS; } -cli_peheader_error_t cli_pe_targetinfo(cli_ctx *ctx, struct cli_exe_info *peinfo) +cl_error_t cli_pe_targetinfo(cli_ctx *ctx, struct cli_exe_info *peinfo) { return cli_peheader(ctx->fmap, peinfo, CLI_PEHEADER_OPT_EXTRACT_VINFO, NULL); } @@ -4461,10 +4466,9 @@ cli_peheader_error_t cli_pe_targetinfo(cli_ctx *ctx, struct cli_exe_info *peinfo * rsz is just set to 0 for it. * @param ctx The overarching cli_ctx. This is required with certain opts, but * optional otherwise. - * @return If the PE header is parsed successfully, CLI_PEHEADER_RET_SUCCESS - * is returned. If it seems like the PE is broken, - * CLI_PEHEADER_RET_BROKEN_PE is returned. Otherwise, one of the - * other error codes is returned. + * @return If the PE header is parsed successfully, CL_SUCCESS is returned. + * If it seems like the PE is broken, CL_EFORMAT is returned. + * Otherwise, one of the other error codes is returned. * The caller MUST destroy peinfo, regardless of what this function * returns. * @@ -4491,8 +4495,10 @@ cli_peheader_error_t cli_pe_targetinfo(cli_ctx *ctx, struct cli_exe_info *peinfo * * TODO Same as above but with JSON creation */ -cli_peheader_error_t cli_peheader(fmap_t *map, struct cli_exe_info *peinfo, uint32_t opts, cli_ctx *ctx) +cl_error_t cli_peheader(fmap_t *map, struct cli_exe_info *peinfo, uint32_t opts, cli_ctx *ctx) { + cl_error_t ret = CL_ERROR; + uint16_t e_magic; /* DOS signature ("MZ") */ const char *archtype = NULL, *subsystem = NULL; time_t timestamp; @@ -4514,7 +4520,6 @@ cli_peheader_error_t cli_peheader(fmap_t *map, struct cli_exe_info *peinfo, uint int native = 0; size_t read; - cli_peheader_error_t ret = CLI_PEHEADER_RET_GENERIC_ERROR; #if HAVE_JSON int toval = 0; struct json_object *pe_json = NULL; @@ -4548,7 +4553,7 @@ cli_peheader_error_t cli_peheader(fmap_t *map, struct cli_exe_info *peinfo, uint if (fmap_readn(map, &(peinfo->e_lfanew), peinfo->offset + 58 + sizeof(e_magic), sizeof(peinfo->e_lfanew)) != sizeof(peinfo->e_lfanew)) { /* truncated header? */ cli_dbgmsg("cli_peheader: Unable to read e_lfanew - truncated header?\n"); - ret = CLI_PEHEADER_RET_BROKEN_PE; + ret = CL_EFORMAT; goto done; } @@ -4743,7 +4748,7 @@ cli_peheader_error_t cli_peheader(fmap_t *map, struct cli_exe_info *peinfo, uint cli_dbgmsg("cli_peheader: Invalid NumberOfSections (0)\n"); } } - ret = CLI_PEHEADER_RET_BROKEN_PE; + ret = CL_EFORMAT; goto done; } @@ -4776,14 +4781,14 @@ cli_peheader_error_t cli_peheader(fmap_t *map, struct cli_exe_info *peinfo, uint pe_add_heuristic_property(ctx, "BadOptionalHeaderSize"); } #endif - ret = CLI_PEHEADER_RET_BROKEN_PE; + ret = CL_EFORMAT; goto done; } at = peinfo->offset + peinfo->e_lfanew + sizeof(struct pe_image_file_hdr); if (fmap_readn(map, &(peinfo->pe_opt.opt32), at, sizeof(struct pe_image_optional_hdr32)) != sizeof(struct pe_image_optional_hdr32)) { cli_dbgmsg("cli_peheader: Can't read optional file header\n"); - ret = CLI_PEHEADER_RET_BROKEN_PE; + ret = CL_EFORMAT; goto done; } stored_opt_hdr_size = sizeof(struct pe_image_optional_hdr32); @@ -4802,13 +4807,13 @@ cli_peheader_error_t cli_peheader(fmap_t *map, struct cli_exe_info *peinfo, uint pe_add_heuristic_property(ctx, "BadOptionalHeaderSizePE32Plus"); } #endif - ret = CLI_PEHEADER_RET_BROKEN_PE; + ret = CL_EFORMAT; goto done; } if (fmap_readn(map, (void *)(((size_t) & (peinfo->pe_opt.opt64)) + sizeof(struct pe_image_optional_hdr32)), at, OPT_HDR_SIZE_DIFF) != OPT_HDR_SIZE_DIFF) { cli_dbgmsg("cli_peheader: Can't read additional optional file header bytes\n"); - ret = CLI_PEHEADER_RET_BROKEN_PE; + ret = CL_EFORMAT; goto done; } @@ -4991,7 +4996,7 @@ cli_peheader_error_t cli_peheader(fmap_t *map, struct cli_exe_info *peinfo, uint if (!native && (!salign || (salign % 0x1000))) { cli_dbgmsg("cli_peheader: Bad section alignment\n"); if (opts & CLI_PEHEADER_OPT_STRICT_ON_PE_ERRORS) { - ret = CLI_PEHEADER_RET_BROKEN_PE; + ret = CL_EFORMAT; goto done; } } @@ -4999,7 +5004,7 @@ cli_peheader_error_t cli_peheader(fmap_t *map, struct cli_exe_info *peinfo, uint if (!native && (!falign || (falign % 0x200))) { cli_dbgmsg("cli_peheader: Bad file alignment\n"); if (opts & CLI_PEHEADER_OPT_STRICT_ON_PE_ERRORS) { - ret = CLI_PEHEADER_RET_BROKEN_PE; + ret = CL_EFORMAT; goto done; } } @@ -5029,7 +5034,7 @@ cli_peheader_error_t cli_peheader(fmap_t *map, struct cli_exe_info *peinfo, uint if (opt_hdr_size < (stored_opt_hdr_size + data_dirs_size)) { cli_dbgmsg("cli_peheader: SizeOfOptionalHeader too small (doesn't include data dir size)\n"); - ret = CLI_PEHEADER_RET_BROKEN_PE; + ret = CL_EFORMAT; goto done; } @@ -5080,7 +5085,7 @@ cli_peheader_error_t cli_peheader(fmap_t *map, struct cli_exe_info *peinfo, uint read = fmap_readn(map, section_hdrs, at, peinfo->nsections * sizeof(struct pe_image_section_hdr)); if ((read == (size_t)-1) || (read != peinfo->nsections * sizeof(struct pe_image_section_hdr))) { cli_dbgmsg("cli_peheader: Can't read section header - possibly broken PE file\n"); - ret = CLI_PEHEADER_RET_BROKEN_PE; + ret = CL_EFORMAT; goto done; } at += sizeof(struct pe_image_section_hdr) * peinfo->nsections; @@ -5126,7 +5131,7 @@ cli_peheader_error_t cli_peheader(fmap_t *map, struct cli_exe_info *peinfo, uint if (opts & CLI_PEHEADER_OPT_REMOVE_MISSING_SECTIONS) { if (peinfo->nsections == 1) { - ret = CLI_PEHEADER_RET_BROKEN_PE; + ret = CL_EFORMAT; goto done; } @@ -5169,7 +5174,7 @@ cli_peheader_error_t cli_peheader(fmap_t *map, struct cli_exe_info *peinfo, uint add_section_info(ctx, &peinfo->sections[i]); if (cli_json_timeout_cycle_check(ctx, &toval) != CL_SUCCESS) { - ret = CLI_PEHEADER_RET_JSON_TIMEOUT; + ret = CL_ETIMEOUT; goto done; } } @@ -5213,7 +5218,7 @@ cli_peheader_error_t cli_peheader(fmap_t *map, struct cli_exe_info *peinfo, uint if (!salign || (section->urva % salign)) { /* Bad section alignment */ cli_dbgmsg("cli_peheader: Broken PE - section's VirtualAddress is misaligned\n"); if (opts & CLI_PEHEADER_OPT_STRICT_ON_PE_ERRORS) { - ret = CLI_PEHEADER_RET_BROKEN_PE; + ret = CL_EFORMAT; goto done; } } @@ -5222,7 +5227,7 @@ cli_peheader_error_t cli_peheader(fmap_t *map, struct cli_exe_info *peinfo, uint // section? Why the exception for uraw? if (section->urva >> 31 || section->uvsz >> 31 || (section->rsz && section->uraw >> 31) || peinfo->sections[i].ursz >> 31) { cli_dbgmsg("cli_peheader: Found PE values with sign bit set\n"); - ret = CLI_PEHEADER_RET_BROKEN_PE; + ret = CL_EFORMAT; goto done; } @@ -5230,7 +5235,7 @@ cli_peheader_error_t cli_peheader(fmap_t *map, struct cli_exe_info *peinfo, uint if (section->urva != peinfo->hdr_size) { /* Bad first section RVA */ cli_dbgmsg("cli_peheader: First section doesn't start immediately after the header\n"); if (opts & CLI_PEHEADER_OPT_STRICT_ON_PE_ERRORS) { - ret = CLI_PEHEADER_RET_BROKEN_PE; + ret = CL_EFORMAT; goto done; } } @@ -5241,7 +5246,7 @@ cli_peheader_error_t cli_peheader(fmap_t *map, struct cli_exe_info *peinfo, uint if (section->urva - peinfo->sections[i - 1].urva != peinfo->sections[i - 1].vsz) { /* No holes, no overlapping, no virtual disorder */ cli_dbgmsg("cli_peheader: Virtually misplaced section (wrong order, overlapping, non contiguous)\n"); if (opts & CLI_PEHEADER_OPT_STRICT_ON_PE_ERRORS) { - ret = CLI_PEHEADER_RET_BROKEN_PE; + ret = CL_EFORMAT; goto done; } } @@ -5268,7 +5273,7 @@ cli_peheader_error_t cli_peheader(fmap_t *map, struct cli_exe_info *peinfo, uint // TODO Should this offset include peinfo->offset? if (!(peinfo->ep = cli_rawaddr(peinfo->vep, peinfo->sections, peinfo->nsections, &err, fsize, peinfo->hdr_size)) && err) { cli_dbgmsg("cli_peheader: Broken PE file - Can't map EntryPoint to a file offset\n"); - ret = CLI_PEHEADER_RET_BROKEN_PE; + ret = CL_EFORMAT; goto done; } @@ -5277,7 +5282,7 @@ cli_peheader_error_t cli_peheader(fmap_t *map, struct cli_exe_info *peinfo, uint cli_jsonint(pe_json, "EntryPointOffset", peinfo->ep); if (cli_json_timeout_cycle_check(ctx, &toval) != CL_SUCCESS) { - ret = CLI_PEHEADER_RET_JSON_TIMEOUT; + ret = CL_ETIMEOUT; goto done; } } @@ -5480,7 +5485,7 @@ cli_peheader_error_t cli_peheader(fmap_t *map, struct cli_exe_info *peinfo, uint // Do final preperations for peinfo to be passed back peinfo->is_dll = is_dll; - ret = CLI_PEHEADER_RET_SUCCESS; + ret = CL_SUCCESS; done: /* In the fail case, peinfo will get destroyed by the caller */ @@ -5546,7 +5551,7 @@ cl_error_t cli_check_auth_header(cli_ctx *ctx, struct cli_exe_info *peinfo) peinfo = &_peinfo; cli_exe_info_init(peinfo, 0); - if (cli_peheader(ctx->fmap, peinfo, CLI_PEHEADER_OPT_NONE, NULL) != CLI_PEHEADER_RET_SUCCESS) { + if (CL_SUCCESS != cli_peheader(ctx->fmap, peinfo, CLI_PEHEADER_OPT_NONE, NULL)) { cli_exe_info_destroy(peinfo); return CL_EFORMAT; } @@ -5800,7 +5805,7 @@ cl_error_t cli_genhash_pe(cli_ctx *ctx, unsigned int class, int type, stats_sect // if so, use that to avoid having to re-parse the header cli_exe_info_init(peinfo, 0); - if (cli_peheader(ctx->fmap, peinfo, CLI_PEHEADER_OPT_NONE, NULL) != CLI_PEHEADER_RET_SUCCESS) { + if (cli_peheader(ctx->fmap, peinfo, CLI_PEHEADER_OPT_NONE, NULL) != CL_SUCCESS) { cli_exe_info_destroy(peinfo); return CL_EFORMAT; } diff --git a/libclamav/pe.h b/libclamav/pe.h index 8c144fd93..b2f491a80 100644 --- a/libclamav/pe.h +++ b/libclamav/pe.h @@ -87,15 +87,8 @@ enum { #define CLI_PEHEADER_OPT_STRICT_ON_PE_ERRORS 0x8 #define CLI_PEHEADER_OPT_REMOVE_MISSING_SECTIONS 0x10 -typedef enum cli_peheader_error { - CLI_PEHEADER_RET_SUCCESS = 0, - CLI_PEHEADER_RET_GENERIC_ERROR = -1, - CLI_PEHEADER_RET_BROKEN_PE = -2, - CLI_PEHEADER_RET_JSON_TIMEOUT = -3 -} cli_peheader_error_t; - -cli_peheader_error_t cli_pe_targetinfo(cli_ctx *ctx, struct cli_exe_info *peinfo); -cli_peheader_error_t cli_peheader(fmap_t *map, struct cli_exe_info *peinfo, uint32_t opts, cli_ctx *ctx); +cl_error_t cli_pe_targetinfo(cli_ctx *ctx, struct cli_exe_info *peinfo); +cl_error_t cli_peheader(fmap_t *map, struct cli_exe_info *peinfo, uint32_t opts, cli_ctx *ctx); cl_error_t cli_check_auth_header(cli_ctx *ctx, struct cli_exe_info *peinfo); cl_error_t cli_genhash_pe(cli_ctx *ctx, unsigned int class, int type, stats_section_t *hashes); diff --git a/libclamav/readdb.c b/libclamav/readdb.c index 1354193a7..344e531db 100644 --- a/libclamav/readdb.c +++ b/libclamav/readdb.c @@ -127,7 +127,7 @@ char *cli_virname(const char *virname, unsigned int official) cl_error_t cli_sigopts_handler(struct cli_matcher *root, const char *virname, const char *hexsig, uint8_t sigopts, uint16_t rtype, uint16_t type, - const char *offset, uint8_t target, const uint32_t *lsigid, unsigned int options) + const char *offset, const uint32_t *lsigid, unsigned int options) { char *hexcpy, *start, *end, *mid; unsigned int i; @@ -191,7 +191,7 @@ cl_error_t cli_sigopts_handler(struct cli_matcher *root, const char *virname, co return CL_EMALFDB; } - ret = cli_add_content_match_pattern(root, virname, hexcpy, sigopts, rtype, type, offset, target, lsigid, options); + ret = cli_add_content_match_pattern(root, virname, hexcpy, sigopts, rtype, type, offset, lsigid, options); free(hexcpy); return ret; } @@ -203,7 +203,7 @@ cl_error_t cli_sigopts_handler(struct cli_matcher *root, const char *virname, co if (start != end && mid && (*(++mid) == '#' || !strncmp(mid, ">>", 2) || !strncmp(mid, "<<", 2) || !strncmp(mid, "0#", 2))) { /* TODO byte compare currently does not have support for sigopts, pass through */ - ret = cli_add_content_match_pattern(root, virname, hexcpy, sigopts, rtype, type, offset, target, lsigid, options); + ret = cli_add_content_match_pattern(root, virname, hexcpy, sigopts, rtype, type, offset, lsigid, options); free(hexcpy); return ret; } @@ -300,7 +300,7 @@ cl_error_t cli_sigopts_handler(struct cli_matcher *root, const char *virname, co } /* NOCASE sigopt is handled in cli_ac_addsig */ - ret = cli_add_content_match_pattern(root, virname, hexovr, sigopts, rtype, type, offset, target, lsigid, options); + ret = cli_add_content_match_pattern(root, virname, hexovr, sigopts, rtype, type, offset, lsigid, options); free(hexovr); if (ret != CL_SUCCESS || !(sigopts & ACPATT_OPTION_ASCII)) { free(hexcpy); @@ -312,7 +312,7 @@ cl_error_t cli_sigopts_handler(struct cli_matcher *root, const char *virname, co } /* ASCII sigopt; NOCASE sigopt is handled in cli_ac_addsig */ - ret = cli_add_content_match_pattern(root, virname, hexcpy, sigopts, rtype, type, offset, target, lsigid, options); + ret = cli_add_content_match_pattern(root, virname, hexcpy, sigopts, rtype, type, offset, lsigid, options); free(hexcpy); return ret; } @@ -426,7 +426,7 @@ done: } cl_error_t readdb_parse_ldb_subsignature(struct cli_matcher *root, const char *virname, char *hexsig, - const char *offset, uint8_t target, const uint32_t *lsigid, unsigned int options, + const char *offset, const uint32_t *lsigid, unsigned int options, int current_subsig_index, int num_subsigs, struct cli_lsig_tdb *tdb) { cl_error_t status = CL_EPARSE; @@ -615,9 +615,9 @@ cl_error_t readdb_parse_ldb_subsignature(struct cli_matcher *root, const char *v sig = (subtokens_count % 2) ? subtokens[0] : subtokens[1]; if (subsig_opts) { - ret = cli_sigopts_handler(root, virname, sig, subsig_opts, 0, 0, offset, target, lsigid, options); + ret = cli_sigopts_handler(root, virname, sig, subsig_opts, 0, 0, offset, lsigid, options); } else { - ret = cli_add_content_match_pattern(root, virname, sig, 0, 0, 0, offset, target, lsigid, options); + ret = cli_add_content_match_pattern(root, virname, sig, 0, 0, 0, offset, lsigid, options); } if (CL_SUCCESS != ret) { @@ -647,13 +647,12 @@ done: * @param hexsig The string containing the regex * @param subsig_opts Content match pattern options. See ACPATT_* macros in matcher-ac.h. * @param offset The string offset where the pattern starts - * @param target The clamav target type. * @param lsigid An array of 2 uint32_t numbers: lsig_id and subsig_id. May be NULL for testing. * @param options Database options. See CL_DB_* macros in clamav.h. * @return cl_error_t */ static cl_error_t readdb_parse_yara_string(struct cli_matcher *root, const char *virname, char *hexsig, uint8_t subsig_opts, - const char *offset, uint8_t target, const uint32_t *lsigid, unsigned int options) + const char *offset, const uint32_t *lsigid, unsigned int options) { cl_error_t status = CL_EPARSE; cl_error_t ret; @@ -669,9 +668,9 @@ static cl_error_t readdb_parse_yara_string(struct cli_matcher *root, const char * Looks like an AC/BM content match subsignature. */ if (subsig_opts) { - ret = cli_sigopts_handler(root, virname, hexsig, subsig_opts, 0, 0, offset, target, lsigid, options); + ret = cli_sigopts_handler(root, virname, hexsig, subsig_opts, 0, 0, offset, lsigid, options); } else { - ret = cli_add_content_match_pattern(root, virname, hexsig, 0, 0, 0, offset, target, lsigid, options); + ret = cli_add_content_match_pattern(root, virname, hexsig, 0, 0, 0, offset, lsigid, options); } } @@ -700,14 +699,13 @@ done: * @param rtype * @param type * @param offset The string offset where the pattern starts - * @param target The clamav target type. * @param lsigid An array of 2 uint32_t numbers: lsig_id and subsig_id. May be NULL for testing. * @param options Database options. See CL_DB_* macros in clamav.h. * @return cl_error_t */ cl_error_t cli_add_content_match_pattern(struct cli_matcher *root, const char *virname, const char *hexsig, uint8_t sigopts, uint16_t rtype, uint16_t type, - const char *offset, uint8_t target, const uint32_t *lsigid, unsigned int options) + const char *offset, const uint32_t *lsigid, unsigned int options) { struct cli_bm_patt *bm_new; char *pt, *hexcpy, *n, l, r; @@ -747,7 +745,7 @@ cl_error_t cli_add_content_match_pattern(struct cli_matcher *root, const char *v } strcat(hexcpy, ++wild); - ret = cli_add_content_match_pattern(root, virname, hexcpy, sigopts, rtype, type, offset, target, lsigid, options); + ret = cli_add_content_match_pattern(root, virname, hexcpy, sigopts, rtype, type, offset, lsigid, options); free(hexcpy); return ret; @@ -1275,7 +1273,7 @@ static cl_error_t cli_loaddb(FILE *fs, struct cl_engine *engine, unsigned int *s if (*pt == '=') continue; - if (CL_SUCCESS != (ret = cli_add_content_match_pattern(root, start, pt, 0, 0, 0, "*", 0, NULL, options))) { + if (CL_SUCCESS != (ret = cli_add_content_match_pattern(root, start, pt, 0, 0, 0, "*", NULL, options))) { cli_dbgmsg("cli_loaddb: cli_add_content_match_pattern failed on line %d\n", line); ret = CL_EMALFDB; break; @@ -1584,7 +1582,7 @@ static int cli_loadndb(FILE *fs, struct cl_engine *engine, unsigned int *signo, const char *sig, *virname, *offset, *pt; struct cli_matcher *root; int line = 0, sigs = 0, ret = 0, tokens_count; - unsigned short target; + cli_target_t target; unsigned int phish = options & CL_DB_PHISHING; UNUSEDPARAM(dbname); @@ -1661,19 +1659,19 @@ static int cli_loadndb(FILE *fs, struct cl_engine *engine, unsigned int *signo, ret = CL_EMALFDB; break; } - target = (unsigned short)atoi(pt); + target = (cli_target_t)atoi(pt); - if (target >= CLI_MTARGETS) { - cli_dbgmsg("Not supported target type in signature for %s\n", virname); + if (target >= CLI_MTARGETS || target < 0) { + cli_dbgmsg("Not supported target type (%d) in signature for %s\n", (int)target, virname); continue; } - root = engine->root[target]; + root = engine->root[(size_t)target]; offset = tokens[2]; sig = tokens[3]; - if (CL_SUCCESS != (ret = cli_add_content_match_pattern(root, virname, sig, 0, 0, 0, offset, target, NULL, options))) { + if (CL_SUCCESS != (ret = cli_add_content_match_pattern(root, virname, sig, 0, 0, 0, offset, NULL, options))) { ret = CL_EMALFDB; break; } @@ -2018,13 +2016,13 @@ static inline int init_tdb(struct cli_lsig_tdb *tdb, struct cl_engine *engine, c return CL_BREAK; } - if ((tdb->icongrp1 || tdb->icongrp2) && tdb->target[0] != 1) { + if ((tdb->icongrp1 || tdb->icongrp2) && tdb->target[0] != TARGET_PE) { FREE_TDB_P(tdb); cli_errmsg("init_tdb: IconGroup is only supported in PE (target 1) signatures\n"); return CL_EMALFDB; } - if ((tdb->ep || tdb->nos) && tdb->target[0] != 1 && tdb->target[0] != 6 && tdb->target[0] != 9) { + if ((tdb->ep || tdb->nos) && tdb->target[0] != TARGET_PE && tdb->target[0] != TARGET_ELF && tdb->target[0] != TARGET_MACHO) { FREE_TDB_P(tdb); cli_errmsg("init_tdb: EntryPoint/NumberOfSections is only supported in PE/ELF/Mach-O signatures\n"); return CL_EMALFDB; @@ -2047,7 +2045,6 @@ static cl_error_t load_oneldb(char *buffer, int chkpua, struct cl_engine *engine struct cli_ac_lsig *lsig = NULL; char *tokens[LDB_TOKENS + 1]; int i, subsigs, tokens_count; - unsigned short target = 0; struct cli_matcher *root; struct cli_lsig_tdb tdb; uint32_t lsigid[2]; @@ -2186,7 +2183,7 @@ static cl_error_t load_oneldb(char *buffer, int chkpua, struct cl_engine *engine lsigid[1] = i; // handle each LDB subsig - ret = readdb_parse_ldb_subsignature(root, virname, tokens[3 + i], "*", target, lsigid, options, i, subsigs, &tdb); + ret = readdb_parse_ldb_subsignature(root, virname, tokens[3 + i], "*", lsigid, options, i, subsigs, &tdb); if (CL_SUCCESS != ret) { cli_errmsg("cli_loadldb: failed to parse subsignature %d in %s\n", i, virname); status = ret; @@ -2496,7 +2493,7 @@ static int cli_loadftm(FILE *fs, struct cl_engine *engine, unsigned int options, magictype = atoi(tokens[0]); if (magictype == 1) { /* A-C */ - if (CL_SUCCESS != (ret = cli_add_content_match_pattern(engine->root[0], tokens[3], tokens[2], 0, rtype, type, tokens[1], 0, NULL, options))) + if (CL_SUCCESS != (ret = cli_add_content_match_pattern(engine->root[0], tokens[3], tokens[2], 0, rtype, type, tokens[1], NULL, options))) break; } else if ((magictype == 0) || (magictype == 4)) { /* memcmp() */ @@ -3802,7 +3799,7 @@ static int yara_hexstr_verify(YR_STRING *string, const char *hexstr, uint32_t *l } /* Long Check: Attempt to load hexstr */ - if (CL_SUCCESS != (ret = cli_sigopts_handler(engine->test_root, "test-hex", hexstr, 0, 0, 0, "*", 0, lsigid, options))) { + if (CL_SUCCESS != (ret = cli_sigopts_handler(engine->test_root, "test-hex", hexstr, 0, 0, 0, "*", lsigid, options))) { if (ret == CL_EMALFDB) { cli_warnmsg("load_oneyara[verify]: recovered from database loading error\n"); /* TODO: if necessary, reset testing matcher if error occurs */ @@ -3831,7 +3828,6 @@ static int load_oneyara(YR_RULE *rule, int chkpua, struct cl_engine *engine, uns uint32_t lsigid[2]; struct cli_matcher *root; struct cli_ac_lsig **newtable, *lsig, *tsig = NULL; - unsigned short target = 0; char *logic = NULL, *target_str = NULL; char *newident = NULL; /* size_t lsize; */ // only used in commented out code @@ -4312,7 +4308,7 @@ static int load_oneyara(YR_RULE *rule, int chkpua, struct cl_engine *engine, uns (ytable.table[i]->sigopts & ACPATT_OPTION_ASCII) ? "a" : ""); ret = readdb_parse_yara_string(root, newident, ytable.table[i]->hexstr, ytable.table[i]->sigopts, - ytable.table[i]->offset, target, lsigid, options); + ytable.table[i]->offset, lsigid, options); if (CL_SUCCESS != ret) { root->ac_lsigs--; FREE_TDB(tdb); diff --git a/libclamav/readdb.h b/libclamav/readdb.h index f6f33efe2..d0b76877b 100644 --- a/libclamav/readdb.h +++ b/libclamav/readdb.h @@ -140,14 +140,13 @@ char *cli_virname(const char *virname, unsigned int official); * @param rtype * @param type * @param offset - * @param target * @param lsigid * @param options * @return cl_error_t */ cl_error_t cli_sigopts_handler(struct cli_matcher *root, const char *virname, const char *hexsig, uint8_t sigopts, uint16_t rtype, uint16_t type, - const char *offset, uint8_t target, const uint32_t *lsigid, unsigned int options); + const char *offset, const uint32_t *lsigid, unsigned int options); /** * @brief Parse body-based patterns that DO NOT have subsignature modifiers. @@ -162,14 +161,13 @@ cl_error_t cli_sigopts_handler(struct cli_matcher *root, const char *virname, co * @param rtype * @param type * @param offset - * @param target * @param lsigid * @param options * @return cl_error_t */ cl_error_t cli_add_content_match_pattern(struct cli_matcher *root, const char *virname, const char *hexsig, uint8_t sigopts, uint16_t rtype, uint16_t type, - const char *offset, uint8_t target, const uint32_t *lsigid, unsigned int options); + const char *offset, const uint32_t *lsigid, unsigned int options); /** * @brief Parse a subsignature from a logical signature. @@ -188,7 +186,6 @@ cl_error_t cli_add_content_match_pattern(struct cli_matcher *root, const char *v * @param virname * @param hexsig * @param offset - * @param target * @param lsigid An array of 2 uint32_t numbers: lsig_id and subsig_id. May be NULL for testing. * @param options * @param current_subsig_index @@ -197,7 +194,7 @@ cl_error_t cli_add_content_match_pattern(struct cli_matcher *root, const char *v * @return cl_error_t */ cl_error_t readdb_parse_ldb_subsignature(struct cli_matcher *root, const char *virname, char *hexsig, - const char *offset, uint8_t target, const uint32_t *lsigid, unsigned int options, + const char *offset, const uint32_t *lsigid, unsigned int options, int current_subsig_index, int num_subsigs, struct cli_lsig_tdb *tdb); cl_error_t cli_load(const char *filename, struct cl_engine *engine, unsigned int *signo, unsigned int options, struct cli_dbio *dbio); diff --git a/libclamav/regex_list.c b/libclamav/regex_list.c index 6fae820b7..df689134e 100644 --- a/libclamav/regex_list.c +++ b/libclamav/regex_list.c @@ -757,7 +757,6 @@ static cl_error_t add_pattern_suffix(void *cbdata, const char *suffix, size_t su struct regex_matcher *matcher = cbdata; struct regex_list *regex = NULL; const struct cli_element *el = NULL; - void *tmp_matcher = NULL; /* save original address if OOM occurs */ cl_error_t ret = CL_SUCCESS; if (NULL == matcher) { @@ -802,9 +801,8 @@ static cl_error_t add_pattern_suffix(void *cbdata, const char *suffix, size_t su list_add_tail(&matcher->suffix_regexes[(size_t)el->data], regex); } else { /* new suffix */ - size_t n = matcher->suffix_cnt; - el = cli_hashtab_insert(&matcher->suffix_hash, suffix, suffix_len, (cli_element_data)n); - tmp_matcher = matcher->suffix_regexes; /* save the current value before cli_realloc() */ + size_t n = matcher->suffix_cnt; + el = cli_hashtab_insert(&matcher->suffix_hash, suffix, suffix_len, (cli_element_data)n); CLI_REALLOC(matcher->suffix_regexes, (n + 1) * sizeof(*matcher->suffix_regexes), cli_errmsg("add_pattern_suffix: Unable to reallocate memory for matcher->suffix_regexes\n"); diff --git a/libclamav/regex_suffix.c b/libclamav/regex_suffix.c index 2eeb3cc91..b65d501e2 100644 --- a/libclamav/regex_suffix.c +++ b/libclamav/regex_suffix.c @@ -329,6 +329,7 @@ static struct node *parse_regex(const uint8_t *p, size_t *last) /* next char is escaped, advance pointer * and let fall-through handle it */ ++*last; + /* fall-through */ default: right = make_leaf(p[*last]); v = make_node(concat, v, right); @@ -479,7 +480,7 @@ cl_error_t cli_regex2suffix(const char *pattern, regex_t *preg, suffix_callback cli_errmsg("cli_regex2suffix: unable to strdup regex.pattern"); rc = REG_ESPACE); - n = parse_regex(pattern, &last); + n = parse_regex((const uint8_t *)pattern, &last); if (!n) { rc = REG_ESPACE; goto done; diff --git a/sigtool/sigtool.c b/sigtool/sigtool.c index 970ac655c..a414592d6 100644 --- a/sigtool/sigtool.c +++ b/sigtool/sigtool.c @@ -195,7 +195,7 @@ static int hashpe(const char *filename, unsigned int class, int type) goto done; } - if (cli_add_content_match_pattern(engine->root[0], "test", "deadbeef", 0, 0, 0, "*", 0, NULL, 0) != CL_SUCCESS) { + if (cli_add_content_match_pattern(engine->root[0], "test", "deadbeef", 0, 0, 0, "*", NULL, 0) != CL_SUCCESS) { mprintf(LOGG_ERROR, "hashpe: Can't parse signature\n"); goto done; } @@ -2096,7 +2096,7 @@ static void matchsig(char *sig, const char *offset, int fd) goto done; } - if (readdb_parse_ldb_subsignature(engine->root[0], "test", sig, "*", 0, NULL, 0, 0, 1, &tdb) != CL_SUCCESS) { + if (readdb_parse_ldb_subsignature(engine->root[0], "test", sig, "*", NULL, 0, 0, 1, &tdb) != CL_SUCCESS) { mprintf(LOGG_ERROR, "matchsig: Can't parse signature\n"); goto done; } @@ -3313,7 +3313,7 @@ static int dumpcerts(const struct optstruct *opts) goto done; } - if (cli_add_content_match_pattern(engine->root[0], "test", "deadbeef", 0, 0, 0, "*", 0, NULL, 0) != CL_SUCCESS) { + if (cli_add_content_match_pattern(engine->root[0], "test", "deadbeef", 0, 0, 0, "*", NULL, 0) != CL_SUCCESS) { mprintf(LOGG_ERROR, "dumpcerts: Can't parse signature\n"); goto done; } diff --git a/sigtool/vba.c b/sigtool/vba.c index 6dc4167b7..e9852a7a5 100644 --- a/sigtool/vba.c +++ b/sigtool/vba.c @@ -77,7 +77,7 @@ cli_ctx *convenience_ctx(int fd) goto done; } - if (cli_add_content_match_pattern(engine->root[0], "test", "deadbeef", 0, 0, 0, "*", 0, NULL, 0) != CL_SUCCESS) { + if (cli_add_content_match_pattern(engine->root[0], "test", "deadbeef", 0, 0, 0, "*", NULL, 0) != CL_SUCCESS) { printf("convenience_ctx: Can't parse signature\n"); goto done; } diff --git a/unit_tests/check_matchers.c b/unit_tests/check_matchers.c index f208b4bd3..e0595f81a 100644 --- a/unit_tests/check_matchers.c +++ b/unit_tests/check_matchers.c @@ -220,7 +220,7 @@ START_TEST(test_ac_scanbuff) ck_assert_msg(ret == CL_SUCCESS, "cli_ac_init() failed"); for (i = 0; ac_testdata[i].data; i++) { - ret = cli_add_content_match_pattern(root, ac_testdata[i].virname, ac_testdata[i].hexsig, 0, 0, 0, "*", 0, NULL, 0); + ret = cli_add_content_match_pattern(root, ac_testdata[i].virname, ac_testdata[i].hexsig, 0, 0, 0, "*", NULL, 0); ck_assert_msg(ret == CL_SUCCESS, "cli_add_content_match_pattern failed"); } @@ -263,7 +263,7 @@ START_TEST(test_ac_scanbuff_allscan) ck_assert_msg(ret == CL_SUCCESS, "cli_ac_init() failed"); for (i = 0; ac_testdata[i].data; i++) { - ret = cli_add_content_match_pattern(root, ac_testdata[i].virname, ac_testdata[i].hexsig, 0, 0, 0, "*", 0, NULL, 0); + ret = cli_add_content_match_pattern(root, ac_testdata[i].virname, ac_testdata[i].hexsig, 0, 0, 0, "*", NULL, 0); ck_assert_msg(ret == CL_SUCCESS, "cli_add_content_match_pattern failed"); } @@ -315,7 +315,7 @@ START_TEST(test_ac_scanbuff_ex) ck_assert_msg(ret == CL_SUCCESS, "[ac_ex] cli_ac_init() failed"); for (i = 0; ac_sigopts_testdata[i].data; i++) { - ret = cli_sigopts_handler(root, ac_sigopts_testdata[i].virname, ac_sigopts_testdata[i].hexsig, ac_sigopts_testdata[i].sigopts, 0, 0, ac_sigopts_testdata[i].offset, 0, NULL, 0); + ret = cli_sigopts_handler(root, ac_sigopts_testdata[i].virname, ac_sigopts_testdata[i].hexsig, ac_sigopts_testdata[i].sigopts, 0, 0, ac_sigopts_testdata[i].offset, NULL, 0); ck_assert_msg(ret == CL_SUCCESS, "[ac_ex] cli_sigopts_handler() failed"); } @@ -358,7 +358,7 @@ START_TEST(test_ac_scanbuff_allscan_ex) ck_assert_msg(ret == CL_SUCCESS, "[ac_ex] cli_ac_init() failed"); for (i = 0; ac_sigopts_testdata[i].data; i++) { - ret = cli_sigopts_handler(root, ac_sigopts_testdata[i].virname, ac_sigopts_testdata[i].hexsig, ac_sigopts_testdata[i].sigopts, 0, 0, ac_sigopts_testdata[i].offset, 0, NULL, 0); + ret = cli_sigopts_handler(root, ac_sigopts_testdata[i].virname, ac_sigopts_testdata[i].hexsig, ac_sigopts_testdata[i].sigopts, 0, 0, ac_sigopts_testdata[i].offset, NULL, 0); ck_assert_msg(ret == CL_SUCCESS, "[ac_ex] cli_sigopts_handler() failed"); } @@ -413,11 +413,11 @@ START_TEST(test_bm_scanbuff) ret = cli_bm_init(root); ck_assert_msg(ret == CL_SUCCESS, "cli_bm_init() failed"); - ret = cli_add_content_match_pattern(root, "Sig1", "deadbabe", 0, 0, 0, "*", 0, NULL, 0); + ret = cli_add_content_match_pattern(root, "Sig1", "deadbabe", 0, 0, 0, "*", NULL, 0); ck_assert_msg(ret == CL_SUCCESS, "cli_add_content_match_pattern failed"); - ret = cli_add_content_match_pattern(root, "Sig2", "deadbeef", 0, 0, 0, "*", 0, NULL, 0); + ret = cli_add_content_match_pattern(root, "Sig2", "deadbeef", 0, 0, 0, "*", NULL, 0); ck_assert_msg(ret == CL_SUCCESS, "cli_add_content_match_pattern failed"); - ret = cli_add_content_match_pattern(root, "Sig3", "babedead", 0, 0, 0, "*", 0, NULL, 0); + ret = cli_add_content_match_pattern(root, "Sig3", "babedead", 0, 0, 0, "*", NULL, 0); ck_assert_msg(ret == CL_SUCCESS, "cli_add_content_match_pattern failed"); ctx.options->general &= ~CL_SCAN_GENERAL_ALLMATCHES; /* make sure all-match is disabled */ @@ -442,11 +442,11 @@ START_TEST(test_bm_scanbuff_allscan) ret = cli_bm_init(root); ck_assert_msg(ret == CL_SUCCESS, "cli_bm_init() failed"); - ret = cli_add_content_match_pattern(root, "Sig1", "deadbabe", 0, 0, 0, "*", 0, NULL, 0); + ret = cli_add_content_match_pattern(root, "Sig1", "deadbabe", 0, 0, 0, "*", NULL, 0); ck_assert_msg(ret == CL_SUCCESS, "cli_add_content_match_pattern failed"); - ret = cli_add_content_match_pattern(root, "Sig2", "deadbeef", 0, 0, 0, "*", 0, NULL, 0); + ret = cli_add_content_match_pattern(root, "Sig2", "deadbeef", 0, 0, 0, "*", NULL, 0); ck_assert_msg(ret == CL_SUCCESS, "cli_add_content_match_pattern failed"); - ret = cli_add_content_match_pattern(root, "Sig3", "babedead", 0, 0, 0, "*", 0, NULL, 0); + ret = cli_add_content_match_pattern(root, "Sig3", "babedead", 0, 0, 0, "*", NULL, 0); ck_assert_msg(ret == CL_SUCCESS, "cli_add_content_match_pattern failed"); ctx.options->general |= CL_SCAN_GENERAL_ALLMATCHES; /* enable all-match */ @@ -484,7 +484,7 @@ START_TEST(test_pcre_scanbuff) strncat(hexsig, PCRE_BYPASS, hexlen); strncat(hexsig, pcre_testdata[i].hexsig, hexlen); - ret = readdb_parse_ldb_subsignature(root, pcre_testdata[i].virname, hexsig, pcre_testdata[i].offset, 0, NULL, 0, 0, 0, NULL); + ret = readdb_parse_ldb_subsignature(root, pcre_testdata[i].virname, hexsig, pcre_testdata[i].offset, NULL, 0, 0, 0, NULL); ck_assert_msg(ret == CL_SUCCESS, "[pcre] readdb_parse_ldb_subsignature failed"); free(hexsig); } @@ -538,7 +538,7 @@ START_TEST(test_pcre_scanbuff_allscan) strncat(hexsig, PCRE_BYPASS, hexlen); strncat(hexsig, pcre_testdata[i].hexsig, hexlen); - ret = readdb_parse_ldb_subsignature(root, pcre_testdata[i].virname, hexsig, pcre_testdata[i].offset, 0, NULL, 0, 0, 1, NULL); + ret = readdb_parse_ldb_subsignature(root, pcre_testdata[i].virname, hexsig, pcre_testdata[i].offset, NULL, 0, 0, 1, NULL); ck_assert_msg(ret == CL_SUCCESS, "[pcre] readdb_parse_ldb_subsignature failed"); free(hexsig); }