Patchwork [libfortran] Fix PR 54736, memory corruption with GFORTRAN_CONVERT_UNIT

login
register
mail settings
Submitter Thomas Koenig
Date Sept. 29, 2012, 6:01 p.m.
Message ID <50673770.7030502@netcologne.de>
Download mbox | patch
Permalink /patch/188040/
State New
Headers show

Comments

Thomas Koenig - Sept. 29, 2012, 6:01 p.m.
Hello world,

the attached patch fixes the PR.  The logic for processing
GFORTRAN_CONVERT_UNIT had been quite wrong.  I have checked
that the original test case, plus a few more, no longer cause
assertion failures or memory corruption (also checked with
valgrind).  No test case because it is not possible to set
environment variables from the testsuite.

Regression-tested.  OK for trunk?

I would also like to backport this to 4.7, and maybe 4.6.  What
do you think?

	Thomas

2012-09-29  Thomas K├Ânig  <tkoenig@gcc.gnu.org>

	PR libfortran/54736
	* runtime/environ.c (search_unit):  Correct logic
	for binary search.
	(mark_single):  Fix index errors.

Patch

Index: runtime/environ.c
===================================================================
--- runtime/environ.c	(Revision 191649)
+++ runtime/environ.c	(Arbeitskopie)
@@ -459,21 +459,34 @@  search_unit (int unit, int *ip)
 {
   int low, high, mid;
 
-  low = -1;
-  high = n_elist;
+  if (n_elist == 0)
+    {
+      *ip = 0;
+      return 0;
+    }
+
+  low = 0;
+  high = n_elist - 1;
   while (high - low > 1)
     {
       mid = (low + high) / 2;
-      if (unit <= elist[mid].unit)
+      if (unit == elist[mid].unit)
+	{
+	  *ip = mid;
+	  return 1;
+	}
+      else if (unit > elist[mid].unit)
+	low = mid;
+      else
 	high = mid;
-      else
-	low = mid;
     }
-  *ip = high;
-  if (elist[high].unit == unit)
-    return 1;
+
+  if (unit > elist[high].unit)
+    *ip = high;
   else
-    return 0;
+    *ip = low;
+
+  return 0;
 }
 
 /* This matches a keyword.  If it is found, return the token supplied,
@@ -588,13 +601,13 @@  mark_single (int unit)
     }
   if (search_unit (unit, &i))
     {
-      elist[unit].conv = endian;
+      elist[i].conv = endian;
     }
   else
     {
-      for (j=n_elist; j>=i; j--)
+      for (j=n_elist-1; j>=i; j--)
 	elist[j+1] = elist[j];
-    
+
       n_elist += 1;
       elist[i].unit = unit;
       elist[i].conv = endian;