diff --git a/clamd/session.c b/clamd/session.c index a14109c223..92a7a8fb7e 100644 --- a/clamd/session.c +++ b/clamd/session.c @@ -191,13 +191,15 @@ int command(client_conn_t *conn, int *virus) { int desc = conn->sd; struct cl_engine *engine = conn->engine; - struct cl_scan_options *options = conn->options; + struct cl_scan_options options; const struct optstruct *opts = conn->opts; enum scan_type type = TYPE_INIT; int maxdirrec; int ret = 0; int flags = CLI_FTW_STD; + memcpy(&options, conn->options, sizeof(struct cl_scan_options)); + struct scan_cb_data scandata; struct cli_ftw_cbdata data; unsigned ok, error, total; @@ -218,7 +220,7 @@ int command(client_conn_t *conn, int *virus) scandata.group = conn->group; scandata.odesc = desc; scandata.conn = conn; - scandata.options = options; + scandata.options = &options; scandata.engine = engine; scandata.opts = opts; scandata.thr_pool = conn->thrpool; @@ -296,7 +298,7 @@ int command(client_conn_t *conn, int *virus) conn_reply_error(conn, "FILDES: didn't receive file descriptor."); return 1; } else { - ret = scanfd(conn, NULL, engine, options, opts, desc, 0); + ret = scanfd(conn, NULL, engine, &options, opts, desc, 0); if (ret == CL_VIRUS) { *virus = 1; ret = 0; @@ -327,7 +329,7 @@ int command(client_conn_t *conn, int *virus) return 0; case COMMAND_INSTREAMSCAN: thrmgr_setactivetask(NULL, "INSTREAM"); - ret = scanfd(conn, NULL, engine, options, opts, desc, 1); + ret = scanfd(conn, NULL, engine, &options, opts, desc, 1); if (ret == CL_VIRUS) { *virus = 1; ret = 0; diff --git a/unit_tests/clamd_test.py b/unit_tests/clamd_test.py index 0bee5d5619..76cb5eb674 100644 --- a/unit_tests/clamd_test.py +++ b/unit_tests/clamd_test.py @@ -512,3 +512,48 @@ def test_clamd_09_clamdscan_ExcludePath(self): self.run_clamdscan('{}'.format(TC.path_tmp), expected_ec=1, expected_out=expected_out, unexpected_out=unexpected_out, use_valgrind=True) + + def test_clamd_10_allmatch_not_sticky(self): + ''' + Verify that a scanning without allmatch does not use allmatch mode, after scanning with allmatch. + This is a regression test for an issue where the allmatch scan option is sticky and any scans after an allmatch scan become an allmatch scan. + ''' + self.step_name('Testing clamdscan --allmatch is not sticky') + + # Get a list of Path()'s of each of signature file + test_path = TC.path_source / 'unit_tests' / 'input' / 'pe_allmatch' + database_files = list(test_path.glob('alert-sigs/*')) + + test_exe = test_path / 'test.exe' + + # Copy them to the database directory before starting ClamD + for db in database_files: + shutil.copy(str(db), str(TC.path_db)) + + # + # Start ClamD + # + self.start_clamd() + + poll = self.proc.poll() + assert poll == None # subprocess is alive if poll() returns None + + # Try first without --allmatch + output = self.execute_command('{clamdscan} -c {clamd_config} --wait --ping 10 {test_exe}'.format( + clamdscan=TC.clamdscan, clamd_config=TC.clamd_config, test_exe=test_exe)) + assert output.ec == 1 + assert output.out.count('FOUND') == 1 + + + # Next, try WITH --allmatch + output = self.execute_command('{clamdscan} -c {clamd_config} --allmatch {test_exe}'.format( + clamdscan=TC.clamdscan, clamd_config=TC.clamd_config, test_exe=test_exe)) + assert output.ec == 1 + assert output.out.count('FOUND') > 1 + + + # Try again without --allmatch + output = self.execute_command('{clamdscan} -c {clamd_config} {test_exe}'.format( + clamdscan=TC.clamdscan, clamd_config=TC.clamd_config, test_exe=test_exe)) + assert output.ec == 1 + assert output.out.count('FOUND') == 1