# --- SDE-COPYRIGHT-NOTE-BEGIN ---
# This copyright note is auto-generated by ./scripts/Create-CopyPatch.
#
# Filename: package/.../make/make-3.82-0007-copy-on-expand.patch
# Copyright (C) 2012 The OpenSDE Project
#
# More information can be found in the files COPYING and README.
#
# This patch file is dual-licensed. It is available under the license the
# patched project is licensed under, as long as it is an OpenSource license
# as defined at http://www.opensource.org/ (e.g. BSD, X11) or under the terms
# of the GNU General Public License as published by the Free Software
# Foundation; either version 2 of the License, or (at your option) any later
# version.
# --- SDE-COPYRIGHT-NOTE-END ---

From 3d11dcdc977ef7db3897663b806fe08856ca4190 Mon Sep 17 00:00:00 2001
From: Christian Wiese <chris@opensde.org>
Date: Mon, 22 Oct 2012 18:05:12 +0200
Subject: [PATCH] copy on expand

ChangeLog:

2011-08-29  Paul Smith  <psmith@gnu.org>

       * expand.c (variable_expand_string): Always allocate a new buffer
       for a string we're expanding.  The string we're working on can get
       freed while we work on it (for example if it's the value of a
       variable which modifies itself using an eval operation).
       See Savannah patch #7534 for the original report by Lubomir Rintel.

tests/ChangeLog:

2011-08-29  Paul Smith  <psmith@gnu.org>

       * scripts/features/varnesting: Test resetting of variables while
       expanding them.  See Savannah patch #7534
---
 expand.c                          |   20 +++++----------
 tests/scripts/features/varnesting |   47 +++++++++++++++++++------------------
 2 files changed, 31 insertions(+), 36 deletions(-)

diff --git a/expand.c b/expand.c
index 2315b06..9aeaa13 100644
--- a/expand.c
+++ b/expand.c
@@ -197,7 +197,7 @@ variable_expand_string (char *line, const char *string, long length)
 {
   struct variable *v;
   const char *p, *p1;
-  char *abuf = NULL;
+  char *save;
   char *o;
   unsigned int line_offset;
 
@@ -212,16 +212,11 @@ variable_expand_string (char *line, const char *string, long length)
       return (variable_buffer);
     }
 
-  /* If we want a subset of the string, allocate a temporary buffer for it.
-     Most of the functions we use here don't work with length limits.  */
-  if (length > 0 && string[length] != '\0')
-    {
-      abuf = xmalloc(length+1);
-      memcpy(abuf, string, length);
-      abuf[length] = '\0';
-      string = abuf;
-    }
-  p = string;
+  /* We need a copy of STRING: due to eval, it's possible that it will get
+     freed as we process it (it might be the value of a variable that's reset
+     for example).  Also having a nil-terminated string is handy.  */
+  save = length < 0 ? xstrdup (string) : xstrndup (string, length);
+  p = save;
 
   while (1)
     {
@@ -411,8 +406,7 @@ variable_expand_string (char *line, const char *string, long length)
       ++p;
     }
 
-  if (abuf)
-    free (abuf);
+  free (save);
 
   variable_buffer_output (o, "", 1);
   return (variable_buffer + line_offset);
diff --git a/tests/scripts/features/varnesting b/tests/scripts/features/varnesting
index 15d5071..d8f3ffb 100644
--- a/tests/scripts/features/varnesting
+++ b/tests/scripts/features/varnesting
@@ -1,29 +1,30 @@
-$description = "The following test creates a makefile to ...";
+#                                                                    -*-perl-*-
+$description = "Test recursive variables";
 
 $details = "";
 
-open(MAKEFILE,"> $makefile");
-
-# The Contents of the MAKEFILE ...
-
-print MAKEFILE "x = variable1\n"
-              ."variable2 := Hello\n"
-              ."y = \$(subst 1,2,\$(x))\n"
-              ."z = y\n"
-              ."a := \$(\$(\$(z)))\n"
-              ."all: \n"
-              ."\t\@echo \$(a)\n";
-
-# END of Contents of MAKEFILE
-
-close(MAKEFILE);
-
-&run_make_with_options($makefile,"",&get_logfile);
-
-# Create the answer to what should be produced by this Makefile
-$answer = "Hello\n";
-
-&compare_output($answer,&get_logfile(1));
+run_make_test('
+x = variable1
+variable2 := Hello
+y = $(subst 1,2,$(x))
+z = y
+a := $($($(z)))
+all: 
+	@echo $(a)
+',
+              '', "Hello\n");
+
+# This tests resetting the value of a variable while expanding it.
+# You may only see problems with this if you're using valgrind or
+# some other memory checker that poisons freed memory.
+# See Savannah patch #7534
+
+run_make_test('
+VARIABLE = $(eval VARIABLE := echo hi)$(VARIABLE)
+wololo:
+	@$(VARIABLE)
+',
+              '', "hi\n");
 
 1;
 
-- 
1.7.2.3