libclamav: replace qsort implementation and optimize its common usage (bb#1721)

0.96
Tomasz Kojm 16 years ago
parent bc794573c7
commit 424d41d344
  1. 5
      ChangeLog
  2. 2
      libclamav/Makefile.am
  3. 22
      libclamav/Makefile.in
  4. 7
      libclamav/matcher-bm.c
  5. 2
      libclamav/others.h
  6. 80
      libclamav/others_common.c
  7. 164
      libclamav/qsort.c
  8. 7
      libclamav/readdb.c

@ -1,3 +1,8 @@
Mon Nov 16 19:26:53 CET 2009 (tk)
---------------------------------
* libclamav: replace qsort implementation and optimize its common
usage (bb#1721)
Tue Nov 10 19:29:18 CET 2009 (tk)
---------------------------------
* clamd, clamscan: add support for OfficialDatabaseOnly/--official-db-only

@ -78,6 +78,7 @@ libclamav_internal_utils_la_SOURCES=str.c\
md5.h\
others_common.c \
others.h \
qsort.c \
regex/strlcpy.c \
regex/regcomp.c \
regex/regerror.c \
@ -98,6 +99,7 @@ libclamav_internal_utils_nothreads_la_SOURCES=str.c\
md5.h\
others_common.c \
others.h \
qsort.c \
regex/strlcpy.c \
regex/regcomp.c \
regex/regerror.c \

@ -210,6 +210,7 @@ am_libclamav_internal_utils_la_OBJECTS = \
libclamav_internal_utils_la-str.lo \
libclamav_internal_utils_la-md5.lo \
libclamav_internal_utils_la-others_common.lo \
libclamav_internal_utils_la-qsort.lo \
libclamav_internal_utils_la-strlcpy.lo \
libclamav_internal_utils_la-regcomp.lo \
libclamav_internal_utils_la-regerror.lo \
@ -226,6 +227,7 @@ am_libclamav_internal_utils_nothreads_la_OBJECTS = \
libclamav_internal_utils_nothreads_la-str.lo \
libclamav_internal_utils_nothreads_la-md5.lo \
libclamav_internal_utils_nothreads_la-others_common.lo \
libclamav_internal_utils_nothreads_la-qsort.lo \
libclamav_internal_utils_nothreads_la-strlcpy.lo \
libclamav_internal_utils_nothreads_la-regcomp.lo \
libclamav_internal_utils_nothreads_la-regerror.lo \
@ -510,6 +512,7 @@ libclamav_internal_utils_la_SOURCES = str.c\
md5.h\
others_common.c \
others.h \
qsort.c \
regex/strlcpy.c \
regex/regcomp.c \
regex/regerror.c \
@ -529,6 +532,7 @@ libclamav_internal_utils_nothreads_la_SOURCES = str.c\
md5.h\
others_common.c \
others.h \
qsort.c \
regex/strlcpy.c \
regex/regcomp.c \
regex/regerror.c \
@ -688,6 +692,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libclamav_internal_utils_la-md5.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libclamav_internal_utils_la-others_common.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libclamav_internal_utils_la-qsort.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libclamav_internal_utils_la-regcomp.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libclamav_internal_utils_la-regerror.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libclamav_internal_utils_la-regexec.Plo@am__quote@
@ -696,6 +701,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libclamav_internal_utils_la-strlcpy.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libclamav_internal_utils_nothreads_la-md5.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libclamav_internal_utils_nothreads_la-others_common.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libclamav_internal_utils_nothreads_la-qsort.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libclamav_internal_utils_nothreads_la-regcomp.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libclamav_internal_utils_nothreads_la-regerror.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libclamav_internal_utils_nothreads_la-regexec.Plo@am__quote@
@ -1615,6 +1621,14 @@ libclamav_internal_utils_la-others_common.lo: others_common.c
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libclamav_internal_utils_la_CFLAGS) $(CFLAGS) -c -o libclamav_internal_utils_la-others_common.lo `test -f 'others_common.c' || echo '$(srcdir)/'`others_common.c
libclamav_internal_utils_la-qsort.lo: qsort.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libclamav_internal_utils_la_CFLAGS) $(CFLAGS) -MT libclamav_internal_utils_la-qsort.lo -MD -MP -MF $(DEPDIR)/libclamav_internal_utils_la-qsort.Tpo -c -o libclamav_internal_utils_la-qsort.lo `test -f 'qsort.c' || echo '$(srcdir)/'`qsort.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libclamav_internal_utils_la-qsort.Tpo $(DEPDIR)/libclamav_internal_utils_la-qsort.Plo
@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='qsort.c' object='libclamav_internal_utils_la-qsort.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libclamav_internal_utils_la_CFLAGS) $(CFLAGS) -c -o libclamav_internal_utils_la-qsort.lo `test -f 'qsort.c' || echo '$(srcdir)/'`qsort.c
libclamav_internal_utils_la-strlcpy.lo: regex/strlcpy.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libclamav_internal_utils_la_CFLAGS) $(CFLAGS) -MT libclamav_internal_utils_la-strlcpy.lo -MD -MP -MF $(DEPDIR)/libclamav_internal_utils_la-strlcpy.Tpo -c -o libclamav_internal_utils_la-strlcpy.lo `test -f 'regex/strlcpy.c' || echo '$(srcdir)/'`regex/strlcpy.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libclamav_internal_utils_la-strlcpy.Tpo $(DEPDIR)/libclamav_internal_utils_la-strlcpy.Plo
@ -1679,6 +1693,14 @@ libclamav_internal_utils_nothreads_la-others_common.lo: others_common.c
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libclamav_internal_utils_nothreads_la_CFLAGS) $(CFLAGS) -c -o libclamav_internal_utils_nothreads_la-others_common.lo `test -f 'others_common.c' || echo '$(srcdir)/'`others_common.c
libclamav_internal_utils_nothreads_la-qsort.lo: qsort.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libclamav_internal_utils_nothreads_la_CFLAGS) $(CFLAGS) -MT libclamav_internal_utils_nothreads_la-qsort.lo -MD -MP -MF $(DEPDIR)/libclamav_internal_utils_nothreads_la-qsort.Tpo -c -o libclamav_internal_utils_nothreads_la-qsort.lo `test -f 'qsort.c' || echo '$(srcdir)/'`qsort.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libclamav_internal_utils_nothreads_la-qsort.Tpo $(DEPDIR)/libclamav_internal_utils_nothreads_la-qsort.Plo
@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='qsort.c' object='libclamav_internal_utils_nothreads_la-qsort.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libclamav_internal_utils_nothreads_la_CFLAGS) $(CFLAGS) -c -o libclamav_internal_utils_nothreads_la-qsort.lo `test -f 'qsort.c' || echo '$(srcdir)/'`qsort.c
libclamav_internal_utils_nothreads_la-strlcpy.lo: regex/strlcpy.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libclamav_internal_utils_nothreads_la_CFLAGS) $(CFLAGS) -MT libclamav_internal_utils_nothreads_la-strlcpy.lo -MD -MP -MF $(DEPDIR)/libclamav_internal_utils_nothreads_la-strlcpy.Tpo -c -o libclamav_internal_utils_nothreads_la-strlcpy.lo `test -f 'regex/strlcpy.c' || echo '$(srcdir)/'`regex/strlcpy.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libclamav_internal_utils_nothreads_la-strlcpy.Tpo $(DEPDIR)/libclamav_internal_utils_nothreads_la-strlcpy.Plo

@ -140,11 +140,6 @@ int cli_bm_init(struct cli_matcher *root)
return CL_SUCCESS;
}
static int qcompare(const void *a, const void *b)
{
return *(const uint32_t *)a - *(const uint32_t *)b;
}
int cli_bm_initoff(const struct cli_matcher *root, struct cli_bm_off *data, fmap_t *map)
{
int ret;
@ -195,7 +190,7 @@ int cli_bm_initoff(const struct cli_matcher *root, struct cli_bm_off *data, fmap
if(info.exeinfo.section)
free(info.exeinfo.section);
cli_qsort(data->offtab, data->cnt, sizeof(uint32_t), qcompare);
cli_qsort(data->offtab, data->cnt, sizeof(uint32_t), NULL);
return CL_SUCCESS;
}

@ -407,7 +407,7 @@ int cli_checklimits(const char *, cli_ctx *, unsigned long, unsigned long, unsig
int cli_updatelimits(cli_ctx *, unsigned long);
unsigned long cli_getsizelimit(cli_ctx *, unsigned long);
int cli_matchregex(const char *str, const char *regex);
void cli_qsort(void *basep, size_t nelems, size_t size, int (*comp)(const void *, const void *));
void cli_qsort(void *a, size_t n, size_t es, int (*cmp)(const void *, const void *));
/* symlink behaviour */
#define CLI_FTW_FOLLOW_FILE_SYMLINK 0x01

@ -834,83 +834,3 @@ int cli_regcomp(regex_t *preg, const char *pattern, int cflags)
}
return cli_regcomp_real(preg, pattern, cflags);
}
/* Public domain qsort implementation by Raymond Gardner and Paul Edwards */
#define SWAP(a, b) (qsort_swap((char *)(a), (char *)(b), size))
#define COMP(a, b) ((*comp)((void *)(a), (void *)(b)))
#define T 7 /* subfiles of T or fewer elements will
* be sorted by a simple insertion sort
* T must be at least 3
*/
static void qsort_swap(char *a, char *b, size_t nbytes)
{
char tmp;
do {
tmp = *a;
*a++ = *b;
*b++ = tmp;
} while(--nbytes);
}
void cli_qsort(void *basep, size_t nelems, size_t size, int (*comp)(const void *, const void *))
{
char *stack[40], **sp;
char *i, *j, *limit;
size_t thresh;
char *base;
base = (char *) basep;
thresh = T * size;
sp = stack;
limit = base + nelems * size;
while(1) {
if(limit - base > thresh) {
SWAP(((((size_t) (limit - base)) / size) / 2) * size + base, base);
i = base + size;
j = limit - size;
if(COMP(i, j) > 0)
SWAP(i, j);
if(COMP(base, j) > 0)
SWAP(base, j);
if(COMP(i, base) > 0)
SWAP(i, base);
while(1) {
do
i += size;
while(COMP(i, base) < 0);
do
j -= size;
while(COMP(j, base) > 0);
if(i > j)
break;
SWAP(i, j);
}
SWAP(base, j);
if(j - base > limit - i) {
sp[0] = base;
sp[1] = j;
base = i;
} else {
sp[0] = i;
sp[1] = limit;
limit = j;
}
sp += 2;
} else {
for(j = base, i = j + size; i < limit; j = i, i += size)
for(; COMP(j, j + size) > 0; j -= size) {
SWAP(j, j+size);
if(j == base)
break;
}
if(sp != stack) {
sp -= 2;
base = sp[0];
limit = sp[1];
} else
break;
}
}
}

@ -0,0 +1,164 @@
/*-
* Copyright (c) 1992, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <stdlib.h>
#include "platform.h"
#include "cltypes.h"
static inline char *med3(char *, char *, char *, int (*)(const void *, const void *));
static inline void swapfunc(char *, char *, int, int);
/*
* Qsort routine from Bentley & McIlroy's "Engineering a Sort Function".
*/
#define swapcode(TYPE, parmi, parmj, n) { \
long i = (n) / sizeof (TYPE); \
register TYPE *pi = (TYPE *) (parmi); \
register TYPE *pj = (TYPE *) (parmj); \
do { \
register TYPE t = *pi; \
*pi++ = *pj; \
*pj++ = t; \
} while (--i > 0); \
}
#define SWAPINIT(a, es) swaptype = ((char *)a - (char *)0) % sizeof(long) || \
es % sizeof(long) ? 2 : es == sizeof(long)? 0 : 1;
static inline void
swapfunc(a, b, n, swaptype)
char *a, *b;
int n, swaptype;
{
if(swaptype <= 1)
swapcode(long, a, b, n)
else
swapcode(char, a, b, n)
}
#define swap(a, b) \
if (swaptype == 0) { \
long t = *(long *)(a); \
*(long *)(a) = *(long *)(b); \
*(long *)(b) = t; \
} else \
swapfunc(a, b, es, swaptype)
#define vecswap(a, b, n) if ((n) > 0) swapfunc(a, b, n, swaptype)
#define CMP(a, b) (cmp ? (cmp(a, b)) : ((int)(*(const uint32_t *)a - *(const uint32_t *)b)))
static inline char *
med3(a, b, c, cmp)
char *a, *b, *c;
int (*cmp)(const void *, const void *);
{
return CMP(a, b) < 0 ?
(CMP(b, c) < 0 ? b : (CMP(a, c) < 0 ? c : a ))
:(CMP(b, c) > 0 ? b : (CMP(a, c) < 0 ? a : c ));
}
void cli_qsort(void *a, size_t n, size_t es, int (*cmp)(const void *, const void *))
{
char *pa, *pb, *pc, *pd, *pl, *pm, *pn;
int d, r, swaptype, swap_cnt;
loop: SWAPINIT(a, es);
swap_cnt = 0;
if (n < 7) {
for (pm = a + es; pm < (char *) a + n * es; pm += es)
for (pl = pm; pl > (char *) a && CMP(pl - es, pl) > 0;
pl -= es)
swap(pl, pl - es);
return;
}
pm = a + (n / 2) * es;
if (n > 7) {
pl = a;
pn = a + (n - 1) * es;
if (n > 40) {
d = (n / 8) * es;
pl = med3(pl, pl + d, pl + 2 * d, cmp);
pm = med3(pm - d, pm, pm + d, cmp);
pn = med3(pn - 2 * d, pn - d, pn, cmp);
}
pm = med3(pl, pm, pn, cmp);
}
swap(a, pm);
pa = pb = a + es;
pc = pd = a + (n - 1) * es;
for (;;) {
while (pb <= pc && (r = CMP(pb, a)) <= 0) {
if (r == 0) {
swap_cnt = 1;
swap(pa, pb);
pa += es;
}
pb += es;
}
while (pb <= pc && (r = CMP(pc, a)) >= 0) {
if (r == 0) {
swap_cnt = 1;
swap(pc, pd);
pd -= es;
}
pc -= es;
}
if (pb > pc)
break;
swap(pb, pc);
swap_cnt = 1;
pb += es;
pc -= es;
}
if (swap_cnt == 0) { /* Switch to insertion sort */
for (pm = a + es; pm < (char *) a + n * es; pm += es)
for (pl = pm; pl > (char *) a && CMP(pl - es, pl) > 0;
pl -= es)
swap(pl, pl - es);
return;
}
pn = a + n * es;
r = MIN(pa - (char *)a, pb - pa);
vecswap(a, pb - r, r);
r = MIN(pd - pc, pn - pd - es);
vecswap(pb, pn - r, r);
if ((r = pb - pa) > es)
cli_qsort(a, r / es, es, cmp);
if ((r = pd - pc) > es) {
/* Iterate rather than recurse to save stack space */
a = pn - r;
n = r / es;
goto loop;
}
/* cli_qsort(pn - r, r / es, es, cmp);*/
}

@ -1238,11 +1238,6 @@ static int cli_loadign(FILE *fs, struct cl_engine *engine, unsigned int options,
return CL_SUCCESS;
}
static int scomp(const void *a, const void *b)
{
return *(const uint32_t *)a - *(const uint32_t *)b;
}
#define MD5_HDB 0
#define MD5_MDB 1
#define MD5_FP 2
@ -2211,7 +2206,7 @@ static void cli_md5db_build(struct cli_matcher* root)
root->soff_len = cli_hashset_toarray(&root->md5_sizes_hs, &root->soff);
#endif
cli_hashset_destroy(&root->md5_sizes_hs);
cli_qsort(root->soff, root->soff_len, sizeof(uint32_t), scomp);
cli_qsort(root->soff, root->soff_len, sizeof(uint32_t), NULL);
}
}

Loading…
Cancel
Save