1
Fork 0
mirror of https://git.savannah.gnu.org/git/guile.git synced 2025-05-20 11:40:18 +02:00

Fix hashing of vectors to run in bounded time.

* libguile/hash.c (SCM_MIN): New macro.
  (scm_hasher): In vector case, do nothing if d is 0.  Make sure to
  recurse with a reduced d.  Move the loop out of the 'if'.
This commit is contained in:
Mark H Weaver 2014-01-11 10:18:40 -05:00
parent 0e18163366
commit cc1cd04f81

View file

@ -1,5 +1,5 @@
/* Copyright (C) 1995, 1996, 1997, 2000, 2001, 2003, 2004, 2006, 2008, /* Copyright (C) 1995, 1996, 1997, 2000, 2001, 2003, 2004, 2006, 2008,
* 2009, 2010, 2011, 2012 Free Software Foundation, Inc. * 2009, 2010, 2011, 2012, 2014 Free Software Foundation, Inc.
* *
* This library is free software; you can redistribute it and/or * This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License * modify it under the terms of the GNU Lesser General Public License
@ -45,6 +45,7 @@
extern double floor(); extern double floor();
#endif #endif
#define SCM_MIN(A, B) ((A) < (B) ? (A) : (B))
unsigned long unsigned long
scm_string_hash (const unsigned char *str, size_t len) scm_string_hash (const unsigned char *str, size_t len)
@ -228,31 +229,34 @@ scm_hasher(SCM obj, unsigned long n, size_t d)
return scm_i_struct_hash (obj, n, d); return scm_i_struct_hash (obj, n, d);
case scm_tc7_wvect: case scm_tc7_wvect:
case scm_tc7_vector: case scm_tc7_vector:
{ if (d > 0)
size_t len = SCM_SIMPLE_VECTOR_LENGTH (obj); {
if (len > 5) size_t len, i, d2;
{ unsigned long h;
size_t i = d/2;
unsigned long h = 1; len = SCM_SIMPLE_VECTOR_LENGTH (obj);
while (i--) if (len > 5)
{ {
SCM elt = SCM_SIMPLE_VECTOR_REF (obj, h % len); i = d / 2;
h = ((h << 8) + (scm_hasher (elt, n, 2))) % n; h = 1;
} d2 = SCM_MIN (2, d - 1);
return h; }
} else
else {
{ i = len;
size_t i = len; h = n - 1;
unsigned long h = (n)-1; d2 = (d - 1) / len;
while (i--) }
{
SCM elt = SCM_SIMPLE_VECTOR_REF (obj, h % len); while (i--)
h = ((h << 8) + (scm_hasher (elt, n, d/len))) % n; {
} SCM elt = SCM_SIMPLE_VECTOR_REF (obj, h % len);
return h; h = ((h << 8) + (scm_hasher (elt, n, d2))) % n;
} }
} return h;
}
else
return 1;
case scm_tcs_cons_imcar: case scm_tcs_cons_imcar:
case scm_tcs_cons_nimcar: case scm_tcs_cons_nimcar:
if (d) return (scm_hasher (SCM_CAR (obj), n, d/2) if (d) return (scm_hasher (SCM_CAR (obj), n, d/2)