]> granicus.if.org Git - postgresql/commitdiff
Fix string comparison in jsonpath
authorAlexander Korotkov <akorotkov@postgresql.org>
Mon, 12 Aug 2019 03:19:19 +0000 (06:19 +0300)
committerAlexander Korotkov <akorotkov@postgresql.org>
Mon, 12 Aug 2019 03:26:13 +0000 (06:26 +0300)
Take into account pg_server_to_any() may return input string "as is".

Reported-by: Andrew Dunstan, Thomas Munro
Discussion: https://postgr.es/m/0ed83a33-d900-466a-880a-70ef456c721f%402ndQuadrant.com
Author: Alexander Korotkov, Thomas Munro
Backpatch-through: 12

src/backend/utils/adt/jsonpath_exec.c

index 4a0de4fe95a616ee6f61d0719f539f2f96ff9d09..72bc5eab6cb09374fb49138b5d3b6c33b2286457 100644 (file)
@@ -2020,16 +2020,37 @@ compareStrings(const char *mbstr1, int mblen1,
        }
        else
        {
-               /* We have to convert other encodings to UTF-8 first, then compare. */
-               char       *utf8str1 = pg_server_to_any(mbstr1, mblen1, PG_UTF8),
-                                  *utf8str2 = pg_server_to_any(mbstr2, mblen2, PG_UTF8);
-               int                     cmp;
+               char       *utf8str1,
+                                  *utf8str2;
+               int                     cmp,
+                                       utf8len1,
+                                       utf8len2;
 
-               cmp = binaryCompareStrings(utf8str1, strlen(utf8str1),
-                                                                  utf8str2, strlen(utf8str2));
+               /*
+                * We have to convert other encodings to UTF-8 first, then compare.
+                * Input strings may be not null-terminated and pg_server_to_any() may
+                * return them "as is".  So, use strlen() only if there is real
+                * conversion.
+                */
+               utf8str1 = pg_server_to_any(mbstr1, mblen1, PG_UTF8);
+               utf8str2 = pg_server_to_any(mbstr2, mblen2, PG_UTF8);
+               utf8len1 = (mbstr1 == utf8str1) ? mblen1 : strlen(utf8str1);
+               utf8len2 = (mbstr2 == utf8str2) ? mblen2 : strlen(utf8str2);
+
+               cmp = binaryCompareStrings(utf8str1, utf8len1, utf8str2, utf8len2);
+
+               /*
+                * If pg_server_to_any() did no real conversion, then we actually
+                * compared original strings.  So, we already done.
+                */
+               if (mbstr1 == utf8str1 && mbstr2 == utf8str2)
+                       return cmp;
 
-               pfree(utf8str1);
-               pfree(utf8str2);
+               /* Free memory if needed */
+               if (mbstr1 != utf8str1)
+                       pfree(utf8str1);
+               if (mbstr2 != utf8str2)
+                       pfree(utf8str2);
 
                /*
                 * When all Unicode codepoints are equal, return result of binary