]> granicus.if.org Git - postgresql/commitdiff
Fix busted TRANSLATE() code --- it coredumped due to pfree()'ing the
authorTom Lane <tgl@sss.pgh.pa.us>
Wed, 15 Mar 2000 17:24:18 +0000 (17:24 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
Wed, 15 Mar 2000 17:24:18 +0000 (17:24 +0000)
wrong pointer.

src/backend/utils/adt/oracle_compat.c

index b18cbf4a2080fec955339953203d441e6f89c230..36524798823fde171cc3a5101c759eff6f10130c 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *     Edmund Mergl <E.Mergl@bawue.de>
  *
- *     $Id: oracle_compat.c,v 1.21 2000/03/14 23:06:37 thomas Exp $
+ *     $Id: oracle_compat.c,v 1.22 2000/03/15 17:24:18 tgl Exp $
  *
  */
 
@@ -500,64 +500,76 @@ substr(text *string, int4 m, int4 n)
  *
  * Purpose:
  *
- *      Returns string after replacing all occurences of from with
- *      the corresponding character in to. TRANSLATE will not remove
- *       characters.
- *      Modified to work with strings rather than single character
- *       for the substitution arguments.
- *      Modifications from Edwin Ramirez <ramirez@doc.mssm.edu>.
+ *      Returns string after replacing all occurrences of characters in from
+ *      with the corresponding character in to.  If from is longer than to,
+ *      occurrences of the extra characters in from are deleted.
+ *      Improved by Edwin Ramirez <ramirez@doc.mssm.edu>.
  *
  ********************************************************************/
 
 text *
 translate(text *string, text *from, text *to)
 {
-       text   *ret;
-       char   *ptr_ret, *from_ptr, *to_ptr;
-       char   *source, *target, *temp, rep;
+       text   *result;
+       char   *from_ptr, *to_ptr;
+       char   *source, *target;
        int             m, fromlen, tolen, retlen, i;
 
-       if ((string == (text *) NULL) ||
-               ((m = VARSIZE(string) - VARHDRSZ) <= 0))
-               return string;
+       if (string == (text *) NULL ||
+               from == (text *) NULL ||
+               to == (text *) NULL)
+               return (text *) NULL;
 
-       target   = (char *) palloc(VARSIZE(string) - VARHDRSZ);
-       source   = VARDATA(string);
-       temp     = target;
+       if ((m = VARSIZE(string) - VARHDRSZ) <= 0)
+               return string;
 
        fromlen = VARSIZE(from) - VARHDRSZ;
        from_ptr = VARDATA(from);
        tolen = VARSIZE(to) - VARHDRSZ;
-       to_ptr   = VARDATA(to);
+       to_ptr = VARDATA(to);
+
+       result = (text *) palloc(VARSIZE(string));
+
+       source = VARDATA(string);
+       target = VARDATA(result);
        retlen = 0;
-       while (m--)
+
+       while (m-- > 0)
        {
-               rep = *source;
-               for(i=0;i<fromlen;i++) {
-            if(from_ptr[i] == *source)  {
-                               if(i < tolen) {
-                                       rep = to_ptr[i];
-                               } else {
-                                       rep = 0;
-                               }
+               char    rep = *source++;
+
+               for (i = 0; i < fromlen; i++)
+               {
+            if (from_ptr[i] == rep)
                                break;
-            }
                }
-               if(rep != 0) {
-            *target++ = rep;
-            retlen++;
+               if (i < fromlen)
+               {
+                       if (i < tolen)
+                       {
+                               /* substitute */
+                               *target++ = to_ptr[i];
+                               retlen++;
+                       }
+                       else
+                       {
+                               /* discard */
+                       }
+               }
+               else
+               {
+                       /* no match, so copy */
+                       *target++ = rep;
+                       retlen++;
                }
-               source++;
        }
 
-       ret = (text *) palloc(retlen + VARHDRSZ);
-       VARSIZE(ret) = retlen + VARHDRSZ;
-       ptr_ret = VARDATA(ret);
-       for(i=0;i<retlen;i++) {
-               *ptr_ret++ = temp[i];
-       }
-       pfree(target);
-       return ret;
-}
+       VARSIZE(result) = retlen + VARHDRSZ;
+       /*
+        * There may be some wasted space in the result if deletions occurred,
+        * but it's not worth reallocating it; the function result probably
+        * won't live long anyway.
+        */
 
-/* EOF */
+       return result;
+}