diff --git a/src/hash.c b/src/hash.c
index bd3892e..67f0018 100644
--- a/src/hash.c
+++ b/src/hash.c
@@ -16,6 +16,7 @@ this program. If not, see . */
#include "makeint.h"
#include "hash.h"
+#include
#define CALLOC(t, n) ((t *) xcalloc (sizeof (t) * (n)))
#define MALLOC(t, n) ((t *) xmalloc (sizeof (t) * (n)))
@@ -410,10 +411,13 @@ unsigned jhash(unsigned const char *k, int length)
#ifdef WORDS_BIGENDIAN
/* The ifs are ordered from the first byte in memory to the last. */
-#define sum_up_to_nul(r, p, flag) \
+#define sum_up_to_nul(r, p, plen, flag) \
do { \
- unsigned int val; \
- memcpy(&val, (p), 4); \
+ unsigned int val = 0; \
+ size_t vsz = sizeof (val); \
+ size_t pn = (plen); \
+ size_t n = pn < vsz ? pn : vsz; \
+ memcpy(&val, (p), n); \
if ((val & 0xFF000000) == 0) \
flag = 1; \
else if ((val & 0xFF0000) == 0) \
@@ -427,11 +431,14 @@ unsigned jhash(unsigned const char *k, int length)
/* First detect the presence of zeroes. If there is none, we can
sum the 4 bytes directly. Otherwise, the ifs are ordered as in the
big endian case, from the first byte in memory to the last. */
-#define sum_up_to_nul(r, p, flag) \
+#define sum_up_to_nul(r, p, plen, flag) \
do { \
- unsigned int val; \
+ unsigned int val = 0; \
+ size_t vsz = sizeof (val); \
+ size_t pn = (plen); \
+ size_t n = pn < vsz ? pn : vsz; \
unsigned int zeroes; \
- memcpy(&val, (p), 4); \
+ memcpy(&val, (p), n); \
zeroes = ((val - 0x01010101) & ~val); \
if (!(zeroes & 0x80808080)) \
r += val; \
@@ -454,24 +461,31 @@ unsigned jhash_string(unsigned const char *k)
unsigned int a, b, c;
unsigned int have_nul = 0;
unsigned const char *start = k;
+ size_t klen = strlen(k);
/* Set up the internal state */
a = b = c = JHASH_INITVAL;
/* All but the last block: affect some 32 bits of (a,b,c) */
for (;;) {
- sum_up_to_nul(a, k, have_nul);
+ sum_up_to_nul(a, k, klen, have_nul);
if (have_nul)
break;
k += 4;
- sum_up_to_nul(b, k, have_nul);
+ assert (klen >= 4);
+ klen -= 4;
+ sum_up_to_nul(b, k, klen, have_nul);
if (have_nul)
break;
k += 4;
- sum_up_to_nul(c, k, have_nul);
+ assert (klen >= 4);
+ klen -= 4;
+ sum_up_to_nul(c, k, klen, have_nul);
if (have_nul)
break;
k += 4;
+ assert (klen >= 4);
+ klen -= 4;
jhash_mix(a, b, c);
}