]> git.ipfire.org Git - thirdparty/make.git/commitdiff
* strcache.c (add_hugestring): [SV 46832] Support huge strings.
authorPaul Smith <psmith@gnu.org>
Mon, 29 Feb 2016 03:07:50 +0000 (22:07 -0500)
committerPaul Smith <psmith@gnu.org>
Mon, 29 Feb 2016 06:35:02 +0000 (01:35 -0500)
The strcache was limited to strings of length 65535 or less,
because the length is kept in an unsigned short.  To support
huge strings add a new simple linked list, which we don't try
to hash.

strcache.c

index ec0f0a57172188aa136773b1bd8904077fd931c3..6dcf2bc6c8fcf754078a4bfa874345a5086e9f9e 100644 (file)
@@ -134,6 +134,26 @@ add_string (const char *str, unsigned int len)
   return res;
 }
 
+/* For strings too large for the strcache, we just save them in a list.  */
+struct hugestring {
+  struct hugestring *next;  /* The next string.  */
+  char buffer[1];           /* The string.  */
+};
+
+static struct hugestring *hugestrings = NULL;
+
+static const char *
+add_hugestring (const char *str, unsigned int len)
+{
+  struct hugestring *new = xmalloc (sizeof (struct hugestring) + len);
+  memcpy (new->buffer, str, len);
+  new->buffer[len] = '\0';
+
+  new->next = hugestrings;
+  hugestrings = new;
+
+  return new->buffer;
+}
 
 /* Hash table of strings in the cache.  */
 
@@ -159,11 +179,19 @@ static struct hash_table strings;
 static unsigned long total_adds = 0;
 
 static const char *
-add_hash (const char *str, int len)
+add_hash (const char *str, unsigned int len)
 {
+  char *const *slot;
+  const char *key;
+
+  /* If it's too large for the string cache, just copy it.
+     We don't bother trying to match these.  */
+  if (len > USHRT_MAX - 1)
+    return add_hugestring (str, len);
+
   /* Look up the string in the hash.  If it's there, return it.  */
-  char *const *slot = (char *const *) hash_find_slot (&strings, str);
-  const char *key = *slot;
+  slot = (char *const *) hash_find_slot (&strings, str);
+  key = *slot;
 
   /* Count the total number of add operations we performed.  */
   ++total_adds;
@@ -190,6 +218,13 @@ strcache_iscached (const char *str)
     if (str >= sp->buffer && str < sp->buffer + sp->end)
       return 1;
 
+  {
+    struct hugestring *hp;
+    for (hp = hugestrings; hp != 0; hp = hp->next)
+      if (str == hp->buffer)
+        return 1;
+  }
+
   return 0;
 }