diff --git a/libclamav/bytecode.c b/libclamav/bytecode.c index 4a04a24bc..599b3360c 100644 --- a/libclamav/bytecode.c +++ b/libclamav/bytecode.c @@ -25,6 +25,7 @@ #endif #include +#include #include "dconf.h" #include "clamav.h" #include "others.h" @@ -110,11 +111,36 @@ static int cli_bytecode_context_reset(struct cli_bc_ctx *ctx) ctx->tempfile = NULL; ctx->outfd = 0; } + if (ctx->jsnormdir) { + char fullname[1025]; + cli_ctx *cctx = ctx->ctx; + int fd, ret = CL_CLEAN; + + if (!ctx->found) { + snprintf(fullname, 1024, "%s"PATHSEP"javascript", ctx->jsnormdir); + fd = open(fullname, O_RDONLY|O_BINARY); + if(fd >= 0) { + ret = cli_scandesc(fd, cctx, CL_TYPE_HTML, 0, NULL, AC_SCAN_VIR); + if (ret == CL_CLEAN) { + lseek(fd, 0, SEEK_SET); + ret = cli_scandesc(fd, cctx, CL_TYPE_TEXT_ASCII, 0, NULL, AC_SCAN_VIR); + } + close(fd); + } + } + if (!cctx || !cctx->engine->keeptmp) { + cli_rmdirs(ctx->jsnormdir); + } + free(ctx->jsnormdir); + if (ret != CL_CLEAN) + ctx->found = 1; + } ctx->numParams = 0; ctx->funcid = 0; ctx->file_size = 0; ctx->off = 0; ctx->written = 0; + ctx->jsnormwritten = 0; #if USE_MPOOL if (ctx->mpool) { mpool_destroy(ctx->mpool); @@ -140,6 +166,13 @@ static int cli_bytecode_context_reset(struct cli_bc_ctx *ctx) free(ctx->hashsets); ctx->hashsets = NULL; ctx->nhashsets = 0; + + for (i=0;injsnorms;i++) + cli_bcapi_jsnorm_done(ctx, i); + free(ctx->jsnorms); + ctx->jsnorms = NULL; + ctx->njsnorms = 0; + ctx->jsnormdir = NULL; return CL_SUCCESS; } diff --git a/libclamav/bytecode_api.c b/libclamav/bytecode_api.c index b1f2c25fb..f71aef894 100644 --- a/libclamav/bytecode_api.c +++ b/libclamav/bytecode_api.c @@ -42,6 +42,7 @@ #include "pe.h" #include "disasm.h" #include "scanners.h" +#include "jsparse/js-norm.h" uint32_t cli_bcapi_test1(struct cli_bc_ctx *ctx, uint32_t a, uint32_t b) { @@ -817,3 +818,80 @@ int32_t cli_bcapi_bytecode_rt_error(struct cli_bc_ctx *ctx , int32_t id) return 0; } +int32_t cli_bcapi_jsnorm_init(struct cli_bc_ctx *ctx, int32_t from) +{ + struct parser_state *state; + struct bc_jsnorm *b; + unsigned n = ctx->njsnorms + 1; + if (!get_buffer(ctx, from)) { + cli_dbgmsg("bytecode api: jsnorm_init: invalid buffers!\n"); + return -1; + } + state = cli_js_init(); + if (!state) + return -1; + b = cli_realloc(ctx->jsnorms, sizeof(*ctx->jsnorms)*n); + if (!b) { + cli_js_destroy(state); + return -1; + } + ctx->jsnorms = b; + ctx->njsnorms = n; + b = &b[n-1]; + b->from = from; + b->state = state; + if (!ctx->jsnormdir) { + cli_ctx *cctx = (cli_ctx*)ctx->ctx; + ctx->jsnormdir = cli_gentemp(cctx ? cctx->engine->tmpdir : NULL); + if (ctx->jsnormdir) { + if (mkdir(ctx->jsnormdir, 0700)) { + cli_dbgmsg("js: can't create temp dir %s\n", ctx->jsnormdir); + free(ctx->jsnormdir); + return CL_ETMPDIR; + } + } + } + return n-1; +} + +static struct bc_jsnorm *get_jsnorm(struct cli_bc_ctx *ctx, int32_t id) +{ + if (id < 0 || id >= ctx->njsnorms || !ctx->jsnorms) + return NULL; + return &ctx->jsnorms[id]; +} + +int32_t cli_bcapi_jsnorm_process(struct cli_bc_ctx *ctx, int32_t id) +{ + unsigned avail; + char *in; + cli_ctx *cctx = ctx->ctx; + struct bc_jsnorm *b = get_jsnorm(ctx, id); + if (!b || b->from == -1 || !b->state) + return -1; + + avail = cli_bcapi_buffer_pipe_read_avail(ctx, b->from); + in = cli_bcapi_buffer_pipe_read_get(ctx, b->from, avail); + if (!avail || !in) + return -1; + if (cctx && cli_checklimits("bytecode js api", cctx, ctx->jsnormwritten + avail, 0, 0)) + return -1; + cli_bcapi_buffer_pipe_read_stopped(ctx, b->from, avail); + cli_js_process_buffer(b->state, in, avail); + return 0; +} + +int32_t cli_bcapi_jsnorm_done(struct cli_bc_ctx *ctx , int32_t id) +{ + struct bc_jsnorm *b = get_jsnorm(ctx, id); + if (!b || b->from == -1) + return -1; + if (ctx->ctx && cli_updatelimits(ctx->ctx, ctx->jsnormwritten)) + return -1; + ctx->jsnormwritten = 0; + cli_js_parse_done(b->state); + cli_js_output(b->state, ctx->jsnormdir); + cli_js_destroy(b->state); + b->from = -1; + return 0; +} diff --git a/libclamav/bytecode_api.h b/libclamav/bytecode_api.h index 78ad03e1c..1fc2d5bcb 100644 --- a/libclamav/bytecode_api.h +++ b/libclamav/bytecode_api.h @@ -247,5 +247,9 @@ int32_t inflate_done(int32_t id); int32_t bytecode_rt_error(int32_t locationid); +int32_t jsnorm_init(int32_t from_buffer); +int32_t jsnorm_process(int32_t id); +int32_t jsnorm_done(int32_t id); + #endif #endif diff --git a/libclamav/bytecode_api_decl.c b/libclamav/bytecode_api_decl.c index a14feae8e..aac273bec 100644 --- a/libclamav/bytecode_api_decl.c +++ b/libclamav/bytecode_api_decl.c @@ -75,6 +75,9 @@ int32_t cli_bcapi_inflate_init(struct cli_bc_ctx *ctx , int32_t, int32_t, int32_ int32_t cli_bcapi_inflate_process(struct cli_bc_ctx *ctx , int32_t); int32_t cli_bcapi_inflate_done(struct cli_bc_ctx *ctx , int32_t); int32_t cli_bcapi_bytecode_rt_error(struct cli_bc_ctx *ctx , int32_t); +int32_t cli_bcapi_jsnorm_init(struct cli_bc_ctx *ctx , int32_t); +int32_t cli_bcapi_jsnorm_process(struct cli_bc_ctx *ctx , int32_t); +int32_t cli_bcapi_jsnorm_done(struct cli_bc_ctx *ctx , int32_t); const struct cli_apiglobal cli_globals[] = { /* Bytecode globals BEGIN */ @@ -187,7 +190,10 @@ const struct cli_apicall cli_apicalls[]={ {"inflate_init", 9, 0, 7}, {"inflate_process", 8, 13, 2}, {"inflate_done", 8, 14, 2}, - {"bytecode_rt_error", 8, 15, 2} + {"bytecode_rt_error", 8, 15, 2}, + {"jsnorm_init", 8, 16, 2}, + {"jsnorm_process", 8, 17, 2}, + {"jsnorm_done", 8, 18, 2} /* Bytecode APIcalls END */ }; const cli_apicall_int2 cli_apicalls0[] = { @@ -230,7 +236,10 @@ const cli_apicall_int1 cli_apicalls2[] = { (cli_apicall_int1)cli_bcapi_buffer_pipe_done, (cli_apicall_int1)cli_bcapi_inflate_process, (cli_apicall_int1)cli_bcapi_inflate_done, - (cli_apicall_int1)cli_bcapi_bytecode_rt_error + (cli_apicall_int1)cli_bcapi_bytecode_rt_error, + (cli_apicall_int1)cli_bcapi_jsnorm_init, + (cli_apicall_int1)cli_bcapi_jsnorm_process, + (cli_apicall_int1)cli_bcapi_jsnorm_done }; const cli_apicall_malloclike cli_apicalls3[] = { (cli_apicall_malloclike)cli_bcapi_malloc diff --git a/libclamav/bytecode_api_impl.h b/libclamav/bytecode_api_impl.h index f8f69975b..2ce547162 100644 --- a/libclamav/bytecode_api_impl.h +++ b/libclamav/bytecode_api_impl.h @@ -72,5 +72,8 @@ int32_t cli_bcapi_inflate_init(struct cli_bc_ctx *ctx , int32_t, int32_t, int32_ int32_t cli_bcapi_inflate_process(struct cli_bc_ctx *ctx , int32_t); int32_t cli_bcapi_inflate_done(struct cli_bc_ctx *ctx , int32_t); int32_t cli_bcapi_bytecode_rt_error(struct cli_bc_ctx *ctx , int32_t); +int32_t cli_bcapi_jsnorm_init(struct cli_bc_ctx *ctx , int32_t); +int32_t cli_bcapi_jsnorm_process(struct cli_bc_ctx *ctx , int32_t); +int32_t cli_bcapi_jsnorm_done(struct cli_bc_ctx *ctx , int32_t); #endif diff --git a/libclamav/bytecode_priv.h b/libclamav/bytecode_priv.h index eca766087..3187308a5 100644 --- a/libclamav/bytecode_priv.h +++ b/libclamav/bytecode_priv.h @@ -132,6 +132,11 @@ struct bc_inflate { int8_t needSync; }; +struct bc_jsnorm { + struct parser_state *state; + int32_t from; +}; + struct cli_bc_ctx { uint8_t timeout;/* must be first byte in struct! */ /* id and params of toplevel function called */ @@ -174,6 +179,10 @@ struct cli_bc_ctx { unsigned nbuffers; struct cli_hashset *hashsets; unsigned nhashsets; + struct bc_jsnorm* jsnorms; + unsigned njsnorms; + char *jsnormdir; + unsigned jsnormwritten; }; struct cli_all_bc; int cli_vm_execute(const struct cli_bc *bc, struct cli_bc_ctx *ctx, const struct cli_bc_func *func, const struct cli_bc_inst *inst);